libbitsub_core/pgs/
composition.rs1use super::segment::CompositionState;
4use crate::utils::BigEndianReader;
5
6#[derive(Debug, Clone, Copy, Default)]
8pub struct CompositionObject {
9 pub object_id: u16,
11 pub window_id: u8,
13 pub cropped_flag: u8,
15 pub x: u16,
17 pub y: u16,
19 pub crop_x: u16,
21 pub crop_y: u16,
23 pub crop_width: u16,
25 pub crop_height: u16,
27}
28
29impl CompositionObject {
30 #[inline]
32 pub fn has_cropping(&self) -> bool {
33 (self.cropped_flag & 0x80) != 0
34 }
35}
36
37#[derive(Debug, Clone)]
39pub struct PresentationCompositionSegment {
40 pub width: u16,
42 pub height: u16,
44 pub frame_rate: u8,
46 pub composition_number: u16,
48 pub composition_state: u8,
50 pub palette_update_flag: u8,
52 pub palette_id: u8,
54 pub composition_objects: Vec<CompositionObject>,
56}
57
58impl PresentationCompositionSegment {
59 pub fn parse(reader: &mut BigEndianReader, _length: usize) -> Option<Self> {
61 let width = reader.read_u16()?;
62 let height = reader.read_u16()?;
63 let frame_rate = reader.read_u8()?;
64 let composition_number = reader.read_u16()?;
65 let composition_state = reader.read_u8()?;
66 let palette_update_flag = reader.read_u8()?;
67 let palette_id = reader.read_u8()?;
68
69 let count = reader.read_u8()? as usize;
70 let mut composition_objects = Vec::with_capacity(count);
71
72 for _ in 0..count {
73 let object_id = reader.read_u16()?;
74 let window_id = reader.read_u8()?;
75 let cropped_flag = reader.read_u8()?;
76 let x = reader.read_u16()?;
77 let y = reader.read_u16()?;
78
79 let (crop_x, crop_y, crop_width, crop_height) = if (cropped_flag & 0x80) != 0 {
80 (
81 reader.read_u16()?,
82 reader.read_u16()?,
83 reader.read_u16()?,
84 reader.read_u16()?,
85 )
86 } else {
87 (0, 0, 0, 0)
88 };
89
90 composition_objects.push(CompositionObject {
91 object_id,
92 window_id,
93 cropped_flag,
94 x,
95 y,
96 crop_x,
97 crop_y,
98 crop_width,
99 crop_height,
100 });
101 }
102
103 Some(Self {
104 width,
105 height,
106 frame_rate,
107 composition_number,
108 composition_state,
109 palette_update_flag,
110 palette_id,
111 composition_objects,
112 })
113 }
114
115 pub fn get_composition_state(&self) -> Option<CompositionState> {
117 CompositionState::try_from(self.composition_state).ok()
118 }
119
120 #[inline]
122 pub fn is_epoch_start(&self) -> bool {
123 self.composition_state == CompositionState::EpochStart as u8
124 }
125
126 #[inline]
128 pub fn is_acquisition_point(&self) -> bool {
129 self.composition_state == CompositionState::AcquisitionPoint as u8
130 }
131
132 #[inline]
134 pub fn is_palette_update_only(&self) -> bool {
135 (self.palette_update_flag & 0x80) != 0
136 }
137}