1use crate::bit_reader::BitReader;
32use crate::BitstreamError;
33
34pub const START_CODE_PICTURE: u8 = 0x00;
38pub const START_CODE_SLICE_FIRST: u8 = 0x01;
40pub const START_CODE_SLICE_LAST: u8 = 0xAF;
42pub const START_CODE_SEQUENCE_HEADER: u8 = 0xB3;
44pub const START_CODE_EXTENSION: u8 = 0xB5;
46pub const START_CODE_SEQUENCE_END: u8 = 0xB7;
48pub const START_CODE_GROUP_OF_PICTURES: u8 = 0xB8;
50
51pub const EXTENSION_ID_SEQUENCE: u8 = 0x1;
53pub const EXTENSION_ID_PICTURE_CODING: u8 = 0x8;
56
57pub const DEFAULT_INTRA_QUANT: [u8; 64] = [
62 8, 16, 19, 22, 26, 27, 29, 34, 16, 16, 22, 24, 27, 29, 34, 37, 19, 22, 26, 27, 29, 34, 34, 38,
63 22, 22, 26, 27, 29, 34, 37, 40, 22, 26, 27, 29, 32, 35, 40, 48, 26, 27, 29, 32, 35, 40, 48, 58,
64 26, 27, 29, 34, 38, 46, 56, 69, 27, 29, 35, 38, 46, 56, 69, 83,
65];
66
67pub const DEFAULT_NON_INTRA_QUANT: [u8; 64] = [16; 64];
70
71const ZIGZAG_TO_RASTER: [u8; 64] = [
74 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20,
75 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59,
76 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63,
77];
78
79pub fn zigzag_to_raster_quant(zz: &[u8; 64]) -> [u8; 64] {
82 let mut out = [0u8; 64];
83 for (zz_idx, &raster_idx) in ZIGZAG_TO_RASTER.iter().enumerate() {
84 out[raster_idx as usize] = zz[zz_idx];
85 }
86 out
87}
88
89pub fn find_start_codes(buf: &[u8]) -> Vec<(u8, usize)> {
96 let mut out = Vec::new();
97 let mut i = 0;
98 let n = buf.len();
99 while i + 3 < n {
100 if buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1 {
101 out.push((buf[i + 3], i + 4));
102 i += 4;
103 } else {
104 i += 1;
105 }
106 }
107 out
108}
109
110pub fn find_first_slice(buf: &[u8]) -> Option<usize> {
115 let n = buf.len();
116 let mut i = 0;
117 while i + 3 < n {
118 if buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1 {
119 let code = buf[i + 3];
120 if (START_CODE_SLICE_FIRST..=START_CODE_SLICE_LAST).contains(&code) {
121 return Some(i);
122 }
123 i += 4;
124 } else {
125 i += 1;
126 }
127 }
128 None
129}
130
131#[derive(Debug, Clone, Default, PartialEq, Eq)]
135pub struct Mpeg2SequenceHeader {
136 pub horizontal_size: u32,
137 pub vertical_size: u32,
138 pub aspect_ratio_information: u8,
139 pub frame_rate_code: u8,
140 pub bit_rate: u32,
141 pub vbv_buffer_size: u32,
142 pub constrained_parameters_flag: bool,
143 pub intra_quantiser_matrix: Option<[u8; 64]>,
147 pub non_intra_quantiser_matrix: Option<[u8; 64]>,
149}
150
151impl Mpeg2SequenceHeader {
152 pub fn intra_quantizer_matrix_raster(&self) -> [u8; 64] {
155 zigzag_to_raster_quant(
156 self.intra_quantiser_matrix
157 .as_ref()
158 .unwrap_or(&DEFAULT_INTRA_QUANT),
159 )
160 }
161
162 pub fn non_intra_quantizer_matrix_raster(&self) -> [u8; 64] {
164 zigzag_to_raster_quant(
165 self.non_intra_quantiser_matrix
166 .as_ref()
167 .unwrap_or(&DEFAULT_NON_INTRA_QUANT),
168 )
169 }
170}
171
172#[derive(Debug, Clone, Default, PartialEq, Eq)]
174pub struct Mpeg2PictureHeader {
175 pub temporal_reference: u32,
176 pub picture_coding_type: u8,
178 pub vbv_delay: u32,
179 pub full_pel_forward_vector: u8,
181 pub full_pel_backward_vector: u8,
182 pub f_code: [[u8; 2]; 2],
183}
184
185#[derive(Debug, Clone, Default, PartialEq, Eq)]
187pub struct Mpeg2PictureCodingExtension {
188 pub f_code: [[u8; 2]; 2],
189 pub intra_dc_precision: u8,
190 pub picture_structure: u8,
191 pub top_field_first: u8,
192 pub frame_pred_frame_dct: u8,
193 pub concealment_motion_vectors: u8,
194 pub q_scale_type: u8,
195 pub intra_vlc_format: u8,
196 pub alternate_scan: u8,
197 pub repeat_first_field: u8,
198 pub chroma_420_type: u8,
199 pub progressive_frame: u8,
200}
201
202#[derive(Debug, Clone, Default, PartialEq, Eq)]
206pub struct Mpeg2SequenceExtension {
207 pub profile_and_level_indication: u8,
208 pub progressive_sequence: bool,
209 pub chroma_format: u8,
211 pub horizontal_size_extension: u8,
212 pub vertical_size_extension: u8,
213 pub bit_rate_extension: u32,
214 pub vbv_buffer_size_extension: u8,
215 pub low_delay: bool,
216 pub frame_rate_extension_n: u8,
217 pub frame_rate_extension_d: u8,
218}
219
220pub fn parse_sequence_header(bytes: &[u8]) -> Result<Mpeg2SequenceHeader, BitstreamError> {
225 if bytes.len() < 8 {
226 return Err(BitstreamError::unexpected_end(
227 "MPEG-2 sequence_header shorter than 8 bytes",
228 ));
229 }
230 let mut r = BitReader::new(bytes);
231 let mut s = Mpeg2SequenceHeader {
232 horizontal_size: r.u(12),
233 vertical_size: r.u(12),
234 aspect_ratio_information: r.u(4) as u8,
235 frame_rate_code: r.u(4) as u8,
236 bit_rate: r.u(18),
237 ..Mpeg2SequenceHeader::default()
238 };
239 let _marker_bit = r.u(1);
240 s.vbv_buffer_size = r.u(10);
241 s.constrained_parameters_flag = r.u(1) != 0;
242 let load_intra = r.u(1) != 0;
243 if load_intra {
244 let mut m = [0u8; 64];
245 for q in m.iter_mut() {
246 *q = r.u(8) as u8;
247 }
248 s.intra_quantiser_matrix = Some(m);
249 }
250 let load_non_intra = r.u(1) != 0;
251 if load_non_intra {
252 let mut m = [0u8; 64];
253 for q in m.iter_mut() {
254 *q = r.u(8) as u8;
255 }
256 s.non_intra_quantiser_matrix = Some(m);
257 }
258 Ok(s)
259}
260
261pub fn parse_picture_header(bytes: &[u8]) -> Result<Mpeg2PictureHeader, BitstreamError> {
264 if bytes.len() < 4 {
265 return Err(BitstreamError::unexpected_end(
266 "MPEG-2 picture_header shorter than 4 bytes",
267 ));
268 }
269 let mut r = BitReader::new(bytes);
270 let mut p = Mpeg2PictureHeader {
271 temporal_reference: r.u(10),
272 picture_coding_type: r.u(3) as u8,
273 vbv_delay: r.u(16),
274 ..Mpeg2PictureHeader::default()
275 };
276 if p.picture_coding_type == 2 || p.picture_coding_type == 3 {
277 p.full_pel_forward_vector = r.u(1) as u8;
279 let forward_f_code = r.u(3) as u8;
280 p.f_code[0][0] = forward_f_code;
281 p.f_code[0][1] = forward_f_code;
282 }
283 if p.picture_coding_type == 3 {
284 p.full_pel_backward_vector = r.u(1) as u8;
286 let backward_f_code = r.u(3) as u8;
287 p.f_code[1][0] = backward_f_code;
288 p.f_code[1][1] = backward_f_code;
289 }
290 Ok(p)
291}
292
293pub fn parse_picture_coding_extension(
297 bytes: &[u8],
298) -> Result<Mpeg2PictureCodingExtension, BitstreamError> {
299 if bytes.len() < 4 {
300 return Err(BitstreamError::unexpected_end(
301 "MPEG-2 picture_coding_extension shorter than 4 bytes",
302 ));
303 }
304 let mut r = BitReader::new(bytes);
305 let ext_id = r.u(4) as u8;
306 if ext_id != EXTENSION_ID_PICTURE_CODING {
307 return Err(BitstreamError::invalid(format!(
308 "MPEG-2 picture_coding_extension: ext_id={ext_id} != 8"
309 )));
310 }
311 let mut e = Mpeg2PictureCodingExtension::default();
312 e.f_code[0][0] = r.u(4) as u8;
313 e.f_code[0][1] = r.u(4) as u8;
314 e.f_code[1][0] = r.u(4) as u8;
315 e.f_code[1][1] = r.u(4) as u8;
316 e.intra_dc_precision = r.u(2) as u8;
317 e.picture_structure = r.u(2) as u8;
318 e.top_field_first = r.u(1) as u8;
319 e.frame_pred_frame_dct = r.u(1) as u8;
320 e.concealment_motion_vectors = r.u(1) as u8;
321 e.q_scale_type = r.u(1) as u8;
322 e.intra_vlc_format = r.u(1) as u8;
323 e.alternate_scan = r.u(1) as u8;
324 e.repeat_first_field = r.u(1) as u8;
325 e.chroma_420_type = r.u(1) as u8;
326 e.progressive_frame = r.u(1) as u8;
327 Ok(e)
328}
329
330pub fn parse_sequence_extension(bytes: &[u8]) -> Result<Mpeg2SequenceExtension, BitstreamError> {
334 if bytes.len() < 6 {
335 return Err(BitstreamError::unexpected_end(
336 "MPEG-2 sequence_extension shorter than 6 bytes",
337 ));
338 }
339 let mut r = BitReader::new(bytes);
340 let ext_id = r.u(4) as u8;
341 if ext_id != EXTENSION_ID_SEQUENCE {
342 return Err(BitstreamError::invalid(format!(
343 "MPEG-2 sequence_extension: ext_id={ext_id} != 1"
344 )));
345 }
346 let mut e = Mpeg2SequenceExtension {
347 profile_and_level_indication: r.u(8) as u8,
348 progressive_sequence: r.u(1) != 0,
349 chroma_format: r.u(2) as u8,
350 horizontal_size_extension: r.u(2) as u8,
351 vertical_size_extension: r.u(2) as u8,
352 bit_rate_extension: r.u(12),
353 ..Mpeg2SequenceExtension::default()
354 };
355 let _marker_bit = r.u(1);
356 e.vbv_buffer_size_extension = r.u(8) as u8;
357 e.low_delay = r.u(1) != 0;
358 e.frame_rate_extension_n = r.u(2) as u8;
359 e.frame_rate_extension_d = r.u(5) as u8;
360 Ok(e)
361}
362
363#[cfg(test)]
364mod tests {
365 use super::*;
366
367 #[test]
368 fn find_start_codes_locates_known_codes() {
369 let buf = [
370 0, 0, 1, 0xb3, 0xaa, 0xbb, 0, 0, 1, 0xb5, 0xcc, 0, 0, 1, 0x00, 0xdd, 0xee, 0, 0, 1, 0x01, 0xff, ];
375 let codes = find_start_codes(&buf);
376 assert_eq!(codes.len(), 4);
377 assert_eq!(codes[0].0, 0xb3);
378 assert_eq!(codes[1].0, 0xb5);
379 assert_eq!(codes[2].0, 0x00);
380 assert_eq!(codes[3].0, 0x01);
381 }
382
383 #[test]
384 fn find_first_slice_returns_offset_of_leading_zeros() {
385 let buf = [
386 0, 0, 1, 0xb3, 0xaa, 0, 0, 1, 0x00, 0xbb, 0, 0, 1, 0x01, 0xcc, ];
390 let off = find_first_slice(&buf).expect("slice present");
391 assert_eq!(off, 10);
392 }
393
394 #[test]
395 fn zigzag_inverse_roundtrip() {
396 let zz: [u8; 64] = std::array::from_fn(|i| (i + 1) as u8);
397 let raster = zigzag_to_raster_quant(&zz);
398 assert_eq!(raster[0], 1); assert_eq!(raster[1], 2);
400 assert_eq!(raster[8], 3);
401 }
402
403 #[test]
404 fn parse_sequence_header_too_short() {
405 assert!(matches!(
406 parse_sequence_header(&[0u8; 4]),
407 Err(BitstreamError::UnexpectedEnd(_))
408 ));
409 }
410
411 #[test]
412 fn parse_picture_coding_extension_rejects_wrong_ext_id() {
413 let bytes = [0x10, 0x00, 0x00, 0x00];
415 assert!(matches!(
416 parse_picture_coding_extension(&bytes),
417 Err(BitstreamError::InvalidData(_))
418 ));
419 }
420}