1pub mod buffering_period;
2pub mod pic_timing;
3pub mod user_data_registered_itu_t_t35;
4
5use crate::rbsp::BitReaderError;
6use hex_slice::AsHex;
7use std::convert::TryFrom;
8use std::fmt::{Debug, Formatter};
9use std::io::BufRead;
10
11#[derive(Debug, Copy, Clone, PartialEq, Eq)]
12pub enum HeaderType {
13 BufferingPeriod,
14 PicTiming,
15 PanScanRect,
16 FillerPayload,
17 UserDataRegisteredItuTT35,
18 UserDataUnregistered,
19 RecoveryPoint,
20 DecRefPicMarkingRepetition,
21 SparePic,
22 SceneInfo,
23 SubSeqInfo,
24 SubSeqLayerCharacteristics,
25 SubSeqCharacteristics,
26 FullFrameFreeze,
27 FullFrameFreezeRelease,
28 FullFrameSnapshot,
29 ProgressiveRefinementSegmentStart,
30 ProgressiveRefinementSegmentEnd,
31 MotionConstrainedSliceGroupSet,
32 FilmGrainCharacteristics,
33 DeblockingFilterDisplayPreference,
34 StereoVideoInfo,
35 PostFilterHint,
36 ToneMappingInfo,
37 ScalabilityInfo,
38 SubPicScalableLayer,
39 NonRequiredLayerRep,
40 PriorityLayerInfo,
41 LayersNotPresent,
42 LayerDependencyChange,
43 ScalableNesting,
44 BaseLayerTemporalHrd,
45 QualityLayerIntegrityCheck,
46 RedundantPicProperty,
47 Tl0DepRepIndex,
48 TlSwitchingPoint,
49 ParallelDecodingInfo,
50 MvcScalableNesting,
51 ViewScalabilityInfo,
52 MultiviewSceneInfo,
53 MultiviewAcquisitionInfo,
54 NonRequiredViewComponent,
55 ViewDependencyChange,
56 OperationPointsNotPresent,
57 BaseViewTemporalHrd,
58 FramePackingArrangement,
59 MultiviewViewPosition,
60 DisplayOrientation,
61 MvcdScalableNesting,
62 MvcdViewScalabilityInfo,
63 DepthRepresentationInfo,
64 ThreeDimensionalReferenceDisplaysInfo,
65 DepthTiming,
66 DepthSamplingInfo,
67 ConstrainedDepthParameterSetIdentifier,
68 GreenMetadata,
69 MasteringDisplayColourVolume,
70 ColourRemappingInfo,
71 AlternativeTransferCharacteristics,
72 AlternativeDepthInfo,
73 ReservedSeiMessage(u32),
74}
75impl HeaderType {
76 fn from_id(id: u32) -> HeaderType {
77 match id {
78 0 => HeaderType::BufferingPeriod,
79 1 => HeaderType::PicTiming,
80 2 => HeaderType::PanScanRect,
81 3 => HeaderType::FillerPayload,
82 4 => HeaderType::UserDataRegisteredItuTT35,
83 5 => HeaderType::UserDataUnregistered,
84 6 => HeaderType::RecoveryPoint,
85 7 => HeaderType::DecRefPicMarkingRepetition,
86 8 => HeaderType::SparePic,
87 9 => HeaderType::SceneInfo,
88 10 => HeaderType::SubSeqInfo,
89 11 => HeaderType::SubSeqLayerCharacteristics,
90 12 => HeaderType::SubSeqCharacteristics,
91 13 => HeaderType::FullFrameFreeze,
92 14 => HeaderType::FullFrameFreezeRelease,
93 15 => HeaderType::FullFrameSnapshot,
94 16 => HeaderType::ProgressiveRefinementSegmentStart,
95 17 => HeaderType::ProgressiveRefinementSegmentEnd,
96 18 => HeaderType::MotionConstrainedSliceGroupSet,
97 19 => HeaderType::FilmGrainCharacteristics,
98 20 => HeaderType::DeblockingFilterDisplayPreference,
99 21 => HeaderType::StereoVideoInfo,
100 22 => HeaderType::PostFilterHint,
101 23 => HeaderType::ToneMappingInfo,
102 24 => HeaderType::ScalabilityInfo,
103 25 => HeaderType::SubPicScalableLayer,
104 26 => HeaderType::NonRequiredLayerRep,
105 27 => HeaderType::PriorityLayerInfo,
106 28 => HeaderType::LayersNotPresent,
107 29 => HeaderType::LayerDependencyChange,
108 30 => HeaderType::ScalableNesting,
109 31 => HeaderType::BaseLayerTemporalHrd,
110 32 => HeaderType::QualityLayerIntegrityCheck,
111 33 => HeaderType::RedundantPicProperty,
112 34 => HeaderType::Tl0DepRepIndex,
113 35 => HeaderType::TlSwitchingPoint,
114 36 => HeaderType::ParallelDecodingInfo,
115 37 => HeaderType::MvcScalableNesting,
116 38 => HeaderType::ViewScalabilityInfo,
117 39 => HeaderType::MultiviewSceneInfo,
118 40 => HeaderType::MultiviewAcquisitionInfo,
119 41 => HeaderType::NonRequiredViewComponent,
120 42 => HeaderType::ViewDependencyChange,
121 43 => HeaderType::OperationPointsNotPresent,
122 44 => HeaderType::BaseViewTemporalHrd,
123 45 => HeaderType::FramePackingArrangement,
124 46 => HeaderType::MultiviewViewPosition,
125 47 => HeaderType::DisplayOrientation,
126 48 => HeaderType::MvcdScalableNesting,
127 49 => HeaderType::MvcdViewScalabilityInfo,
128 50 => HeaderType::DepthRepresentationInfo,
129 51 => HeaderType::ThreeDimensionalReferenceDisplaysInfo,
130 52 => HeaderType::DepthTiming,
131 53 => HeaderType::DepthSamplingInfo,
132 54 => HeaderType::ConstrainedDepthParameterSetIdentifier,
133 56 => HeaderType::GreenMetadata,
134 137 => HeaderType::MasteringDisplayColourVolume,
135 142 => HeaderType::ColourRemappingInfo,
136 147 => HeaderType::AlternativeTransferCharacteristics,
137 188 => HeaderType::AlternativeDepthInfo,
138 _ => HeaderType::ReservedSeiMessage(id),
139 }
140 }
141}
142
143pub struct SeiReader<'a, R: BufRead + Clone> {
145 reader: R,
146 scratch: &'a mut Vec<u8>,
147 payloads_seen: usize,
148 done: bool,
149}
150
151impl<'a, R: BufRead + Clone> SeiReader<'a, R> {
152 pub fn from_rbsp_bytes(reader: R, scratch: &'a mut Vec<u8>) -> Self {
153 Self {
154 reader,
155 scratch,
156 payloads_seen: 0,
157 done: false,
158 }
159 }
160
161 pub fn next(&mut self) -> Result<Option<SeiMessage<'_>>, BitReaderError> {
166 if self.done {
167 return Ok(None);
168 }
169
170 self.done = true;
174 let payload_type = read_u32(&mut self.reader, "payload_type")?;
175
176 if payload_type == 0x80 && self.payloads_seen > 0 {
179 let buf = self
180 .reader
181 .fill_buf()
182 .map_err(|e| BitReaderError::ReaderErrorFor("payload_type", e))?;
183 if buf.is_empty() {
184 return Ok(None);
185 }
186 }
187 let payload_type = HeaderType::from_id(payload_type);
188 let payload_len = usize::try_from(read_u32(&mut self.reader, "payload_len")?).unwrap();
189
190 self.scratch.resize(payload_len, 0);
195 self.reader
196 .read_exact(&mut self.scratch)
197 .map_err(|e| BitReaderError::ReaderErrorFor("payload", e))?;
198
199 self.payloads_seen += 1;
200 self.done = false;
201 Ok(Some(SeiMessage {
202 payload_type,
203 payload: &self.scratch[..],
204 }))
205 }
206}
207
208#[derive(PartialEq, Eq)]
209pub struct SeiMessage<'a> {
210 pub payload_type: HeaderType,
211 pub payload: &'a [u8],
212}
213
214impl<'a> Debug for SeiMessage<'a> {
215 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
216 f.debug_struct("SeiMessage")
217 .field("payload_type", &self.payload_type)
218 .field("payload", &format!("{:02x}", self.payload.plain_hex(false)))
219 .finish()
220 }
221}
222
223fn read_u32<R: BufRead>(reader: &mut R, name: &'static str) -> Result<u32, BitReaderError> {
225 let mut acc = 0u32;
226 loop {
227 let mut buf = [0];
228 reader
229 .read_exact(&mut buf[..])
230 .map_err(|e| BitReaderError::ReaderErrorFor(name, e))?;
231 let byte = buf[0];
232 acc = acc.checked_add(u32::from(byte)).ok_or_else(|| {
233 BitReaderError::ReaderErrorFor(
234 name,
235 std::io::Error::new(std::io::ErrorKind::InvalidData, "overflowed u32"),
236 )
237 })?;
238 if byte != 0xFF {
239 return Ok(acc);
240 }
241 }
242}
243
244#[cfg(test)]
245mod test {
246 use crate::nal::{Nal, RefNal};
247
248 use super::*;
249
250 #[test]
251 fn it_works() {
252 let data = [
253 0x06, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x80, ];
264 let nal = RefNal::new(&data[..], &[], true);
265 let mut scratch = Vec::new();
266 let mut r = SeiReader::from_rbsp_bytes(nal.rbsp_bytes(), &mut scratch);
267 let m1 = r.next().unwrap().unwrap();
268 assert_eq!(m1.payload_type, HeaderType::PicTiming);
269 assert_eq!(m1.payload, &[0x01]);
270 let m2 = r.next().unwrap().unwrap();
271 assert_eq!(m2.payload_type, HeaderType::PanScanRect);
272 assert_eq!(m2.payload, &[0x02, 0x02]);
273 assert_eq!(r.next().unwrap(), None);
274 assert_eq!(r.next().unwrap(), None);
275 }
276}