pgs_parse/
pgs_pcs_segment.rs1use std::rc::Rc;
8
9use crate::{pgs_memory_buffer::{BigEndian, ReadBytes}, pgs_segment_header::PgsSegmentHeader, Error, PgsMemoryBuffer, Result};
10
11#[derive(Debug, PartialEq)]
14pub enum PgsPcsObjectCroppedFlag {
15 ForceCroppedImage = 0x40,
16 Off = 0x00
17}
18
19impl From<u8> for PgsPcsObjectCroppedFlag {
20 fn from(value: u8) -> Self {
28 match value {
29 0x40 => PgsPcsObjectCroppedFlag::ForceCroppedImage,
30 _ => PgsPcsObjectCroppedFlag::Off
31 }
32 }
33}
34
35#[derive(Debug)]
38pub struct PgsPcsSegmentCompositionObjects {
39 pub object_id: u16,
40 pub window_id: u8,
41 pub object_cropped_flag: PgsPcsObjectCroppedFlag,
42 pub object_horizontal_position: u16,
43 pub object_vertical_position: u16,
44 pub object_cropping_horizontal_position: u16,
45 pub object_cropping_vertical_position: u16,
46 pub object_cropping_width: u16,
47 pub object_cropping_height_position: u16
48}
49
50impl PgsPcsSegmentCompositionObjects {
51 fn new() -> Self {
52 PgsPcsSegmentCompositionObjects {
53 object_id: 0,
54 window_id: 0,
55 object_cropped_flag: PgsPcsObjectCroppedFlag::Off,
56 object_horizontal_position: 0,
57 object_vertical_position: 0,
58 object_cropping_horizontal_position: 0,
59 object_cropping_vertical_position: 0,
60 object_cropping_width: 0,
61 object_cropping_height_position: 0
62 }
63 }
64}
65
66#[derive(Debug, Clone, Copy, PartialEq)]
69pub enum PgsPcsCompositionState {
70 EpochStart,
72 AcquisitionPoint,
74 Normal,
76}
77
78impl From<u8> for PgsPcsCompositionState {
79 fn from(value: u8) -> Self {
87 match value {
88 0x80 => PgsPcsCompositionState::EpochStart,
89 0x40 => PgsPcsCompositionState::AcquisitionPoint,
90 _ => PgsPcsCompositionState::Normal
91 }
92 }
93}
94
95#[derive(Debug)]
96pub struct PgsPcsSegment {
97 pub header: PgsSegmentHeader,
98 pub width: u16,
99 pub height: u16,
100 pub frame_rate: u8,
101 pub composition_number: u16,
102 pub composition_state: PgsPcsCompositionState,
103 pub palette_update_flag: u8,
104 pub palette_id: u8,
105 pub number_of_composition_objects: u8,
106 pub composition_objects: Vec<PgsPcsSegmentCompositionObjects>
107}
108
109impl PgsPcsSegment {
112 fn new(header: PgsSegmentHeader) -> Self {
113 PgsPcsSegment {
114 header,
115 width: 0,
116 height: 0,
117 frame_rate: 0x10,
118 composition_number: 0,
119 composition_state: PgsPcsCompositionState::Normal,
120 palette_update_flag: 0,
121 palette_id: 0,
122 number_of_composition_objects: 0,
123 composition_objects: Vec::new()
124 }
125 }
126
127 pub fn from_data(header: PgsSegmentHeader, data: &[u8]) -> Result<Rc<PgsPcsSegment>> {
135 if data.len() < header.segment_length as usize {
136 return Err(Error::InvalidSegmentDataLength);
137 }
138
139 let mut segment = PgsPcsSegment::new(header);
140
141 let mut buffer: PgsMemoryBuffer = PgsMemoryBuffer::from(data);
142 segment.width = buffer.read_u16::<BigEndian>()?;
143 segment.height = buffer.read_u16::<BigEndian>()?;
144 let _ = buffer.read_u8()?;
145 segment.composition_number = buffer.read_u16::<BigEndian>()?;
146 segment.composition_state = PgsPcsCompositionState::from(buffer.read_u8()?);
147 segment.palette_update_flag = buffer.read_u8()?;
148 segment.palette_id = buffer.read_u8()?;
149 segment.number_of_composition_objects = buffer.read_u8()?;
150
151 for _ in 0..segment.number_of_composition_objects {
152 let mut com_obj = PgsPcsSegmentCompositionObjects::new();
153 com_obj.object_id = buffer.read_u16::<BigEndian>()?;
154 com_obj.window_id = buffer.read_u8()?;
155 com_obj.object_cropped_flag = PgsPcsObjectCroppedFlag::from(buffer.read_u8()?);
156 com_obj.object_horizontal_position = buffer.read_u16::<BigEndian>()?;
157 com_obj.object_vertical_position = buffer.read_u16::<BigEndian>()?;
158 if com_obj.object_cropped_flag == PgsPcsObjectCroppedFlag::ForceCroppedImage {
159 com_obj.object_cropping_horizontal_position = buffer.read_u16::<BigEndian>()?;
160 com_obj.object_cropping_vertical_position = buffer.read_u16::<BigEndian>()?;
161 com_obj.object_cropping_width = buffer.read_u16::<BigEndian>()?;
162 com_obj.object_cropping_height_position = buffer.read_u16::<BigEndian>()?;
163 }
164
165 segment.composition_objects.push(com_obj);
166 }
167
168 Ok(Rc::new(segment))
169 }
170}
171
172impl Default for PgsPcsSegment {
173 fn default() -> Self {
174 Self::new(Default::default())
175 }
176}