1use std::convert::TryFrom;
6use std::io::Cursor;
7
8use byteorder::ReadBytesExt;
9use byteorder::LE;
10use log::debug;
11use thiserror::Error;
12
13use crate::codec::vp8::bool_decoder::BoolDecoder;
14use crate::codec::vp8::bool_decoder::BoolDecoderError;
15use crate::codec::vp8::bool_decoder::BoolDecoderResult;
16use crate::codec::vp8::bool_decoder::BoolDecoderState;
17use crate::codec::vp8::probs::COEFF_DEFAULT_PROBS;
18use crate::codec::vp8::probs::COEFF_UPDATE_PROBS;
19use crate::codec::vp8::probs::KF_UV_MODE_PROBS;
20use crate::codec::vp8::probs::KF_Y_MODE_PROBS;
21use crate::codec::vp8::probs::MV_DEFAULT_PROBS;
22use crate::codec::vp8::probs::MV_UPDATE_PROBS;
23use crate::codec::vp8::probs::NK_UV_MODE_PROBS;
24use crate::codec::vp8::probs::NK_Y_MODE_PROBS;
25
26#[derive(Clone, Debug, Default, PartialEq, Eq)]
28pub struct QuantIndices {
29 pub y_ac_qi: u8,
32 pub y_dc_delta: i8,
35 pub y2_dc_delta: i8,
38 pub y2_ac_delta: i8,
41 pub uv_dc_delta: i8,
44 pub uv_ac_delta: i8,
47}
48
49#[derive(Clone, Debug, Default, PartialEq, Eq)]
50pub struct MbLfAdjustments {
51 pub loop_filter_adj_enable: bool,
54 pub mode_ref_lf_delta_update: bool,
57
58 pub ref_frame_delta: [i8; 4],
62 pub mb_mode_delta: [i8; 4],
65}
66
67#[derive(Clone, Debug, Default, PartialEq, Eq)]
68pub struct Segmentation {
69 pub segmentation_enabled: bool,
71 pub update_mb_segmentation_map: bool,
73 pub update_segment_feature_data: bool,
75
76 pub segment_feature_mode: bool,
80 pub quantizer_update_value: [i8; 4],
82 pub lf_update_value: [i8; 4],
84
85 pub segment_prob: [u8; 3],
88}
89
90#[derive(Clone, Debug, Default, PartialEq, Eq)]
91pub struct ModeProbs {
92 pub intra_16x16_prob: [u8; 4],
95 pub intra_chroma_prob: [u8; 3],
98}
99
100#[derive(Clone, Debug, Default, PartialEq, Eq)]
101pub struct Header {
102 pub key_frame: bool,
104 pub version: u8,
106 pub show_frame: bool,
108 pub data_chunk_size: u8,
110 pub first_part_size: u32,
113
114 pub width: u16,
116 pub height: u16,
118 pub horiz_scale_code: u8,
120 pub vert_scale_code: u8,
122 pub color_space: bool,
124 pub clamping_type: bool,
127 pub filter_type: bool,
129 pub loop_filter_level: u8,
131 pub sharpness_level: u8,
133 log2_nbr_of_dct_partitions: u8,
136
137 pub partition_size: [u32; 8],
138
139 pub quant_indices: QuantIndices,
141
142 pub refresh_entropy_probs: bool,
145 pub refresh_last: bool,
148
149 pub refresh_golden_frame: bool,
151 pub refresh_alternate_frame: bool,
154 pub copy_buffer_to_golden: u8,
156 pub copy_buffer_to_alternate: u8,
158 pub sign_bias_golden: bool,
160 pub sign_bias_alternate: bool,
163
164 pub coeff_prob: [[[[u8; 11]; 3]; 8]; 4],
166 pub mv_prob: [[u8; 19]; 2],
168
169 pub mb_no_coeff_skip: bool,
172 pub prob_skip_false: u8,
175 pub prob_intra: u8,
177 pub prob_last: u8,
180 pub prob_golden: u8,
183 pub mode_probs: ModeProbs,
185
186 pub bd_range: usize,
188 pub bd_value: usize,
190 pub bd_count: isize,
192
193 pub header_size: u32,
196}
197
198#[derive(Debug, Error)]
199pub enum ParseUncompressedChunkError {
200 #[error("invalid start code {0}")]
201 InvalidStartCode(u32),
202 #[error("I/O error: {0}")]
203 IoError(#[from] std::io::Error),
204}
205
206#[derive(Debug, Error)]
207pub enum ComputePartitionSizesError {
208 #[error("unexpected end of header")]
209 EndOfHeader,
210 #[error("partition size not fitting in a u32")]
211 PartitionTooLarge,
212}
213
214impl Header {
215 pub fn num_dct_partitions(&self) -> usize {
218 1 << self.log2_nbr_of_dct_partitions
219 }
220
221 pub fn frame_len(&self) -> usize {
223 std::iter::once(self.data_chunk_size as usize)
225 .chain(std::iter::once(self.first_part_size as usize))
227 .chain(std::iter::once(
229 self.num_dct_partitions().saturating_sub(1) * 3,
230 ))
231 .chain(
233 self.partition_size
234 .iter()
235 .take(self.num_dct_partitions())
236 .map(|s| *s as usize),
237 )
238 .sum()
239 }
240
241 fn parse_uncompressed_data_chunk(
243 bitstream: &[u8],
244 ) -> Result<Self, ParseUncompressedChunkError> {
245 debug!("Parsing VP8 uncompressed data chunk.");
246
247 let mut reader = Cursor::new(bitstream);
248
249 let frame_tag = reader.read_u24::<LE>()?;
250
251 let mut header = Header {
252 key_frame: (frame_tag & 0x1) == 0,
253 version: ((frame_tag >> 1) & 0x07) as u8,
254 show_frame: ((frame_tag >> 4) & 0x1) != 0,
255 first_part_size: (frame_tag >> 5) & 0x7ffff,
256 ..Default::default()
257 };
258
259 if header.key_frame {
260 let start_code = reader.read_u24::<LE>()?;
261
262 if start_code != 0x2a019d {
263 return Err(ParseUncompressedChunkError::InvalidStartCode(start_code));
264 }
265
266 let size_code = reader.read_u16::<LE>()?;
267 header.horiz_scale_code = (size_code >> 14) as u8;
268 header.width = size_code & 0x3fff;
269
270 let size_code = reader.read_u16::<LE>()?;
271 header.vert_scale_code = (size_code >> 14) as u8;
272 header.height = size_code & 0x3fff;
273 }
274
275 header.data_chunk_size = reader.position() as u8;
276
277 Ok(header)
278 }
279
280 fn compute_partition_sizes(&mut self, data: &[u8]) -> Result<(), ComputePartitionSizesError> {
281 let num_partitions = self.num_dct_partitions();
282 let mut part_size_ofs = self.first_part_size as usize;
283 let mut ofs = part_size_ofs + 3 * (num_partitions - 1);
284
285 if ofs > data.len() {
286 return Err(ComputePartitionSizesError::EndOfHeader);
287 }
288
289 for i in 0..num_partitions - 1 {
290 let b0 = u32::from(data[part_size_ofs]);
291 let b1 = u32::from(data[part_size_ofs + 1]) << 8;
292 let b2 = u32::from(data[part_size_ofs + 2]) << 16;
293
294 let part_size = b0 | b1 | b2;
295 part_size_ofs += 3;
296
297 self.partition_size[i] = part_size;
298 ofs += part_size as usize;
299 }
300
301 if ofs > data.len() {
302 return Err(ComputePartitionSizesError::EndOfHeader);
303 }
304
305 self.partition_size[num_partitions - 1] = u32::try_from(data.len() - ofs)
306 .map_err(|_| ComputePartitionSizesError::PartitionTooLarge)?;
307 Ok(())
308 }
309}
310
311pub struct Frame<'a> {
313 bitstream: &'a [u8],
315 frame_len: usize,
317 pub header: Header,
319}
320
321impl<'a> AsRef<[u8]> for Frame<'a> {
322 fn as_ref(&self) -> &[u8] {
323 &self.bitstream[..self.frame_len]
324 }
325}
326
327#[derive(Clone, Debug, PartialEq, Eq)]
329pub struct Parser {
330 segmentation: Segmentation,
332 mb_lf_adjust: MbLfAdjustments,
334 coeff_prob: [[[[u8; 11]; 3]; 8]; 4],
336 mv_prob: [[u8; 19]; 2],
338 mode_probs: ModeProbs,
340}
341
342#[derive(Debug, Error)]
343pub enum ParseFrameError {
344 #[error("error while parsing uncompressed chunk of frame: {0}")]
345 ParseUncompressedChunk(#[from] ParseUncompressedChunkError),
346 #[error("partition end {0} is bigger than bitstream length {1}")]
347 InvalidPartitionSize(usize, usize),
348 #[error("error while parsing frame header: {0}")]
349 ParseFrameHeader(#[from] BoolDecoderError),
350 #[error("error while computing frames partitions sizes: {0}")]
351 ComputePartitionSizes(#[from] ComputePartitionSizesError),
352 #[error("bitstream is shorter ({0} bytes) than computed length of frame {1}")]
353 BitstreamTooShort(usize, usize),
354}
355
356impl Parser {
357 pub fn segmentation(&self) -> &Segmentation {
358 &self.segmentation
359 }
360
361 pub fn mb_lf_adjust(&self) -> &MbLfAdjustments {
362 &self.mb_lf_adjust
363 }
364
365 fn mode_probs_init_defaults(mode_probs: &mut ModeProbs, key_frame: bool) {
366 if key_frame {
367 mode_probs.intra_16x16_prob = KF_Y_MODE_PROBS;
368 mode_probs.intra_chroma_prob = KF_UV_MODE_PROBS;
369 } else {
370 mode_probs.intra_16x16_prob = NK_Y_MODE_PROBS;
371 mode_probs.intra_chroma_prob = NK_UV_MODE_PROBS;
372 }
373 }
374
375 fn update_segmentation<T: AsRef<[u8]>>(
376 bd: &mut BoolDecoder<T>,
377 seg: &mut Segmentation,
378 ) -> BoolDecoderResult<()> {
379 seg.update_mb_segmentation_map = false;
380 seg.update_segment_feature_data = false;
381
382 seg.segmentation_enabled = bd.read_bool()?;
383 if !seg.segmentation_enabled {
384 return Ok(());
385 }
386
387 seg.update_mb_segmentation_map = bd.read_bool()?;
388 seg.update_segment_feature_data = bd.read_bool()?;
389
390 if seg.update_segment_feature_data {
391 seg.segment_feature_mode = bd.read_bool()?;
392
393 for value in seg.quantizer_update_value.iter_mut() {
394 let update = bd.read_bool()?;
395 if update {
396 *value = bd.read_sint(7)?;
397 } else {
398 *value = 0;
401 }
402 }
403
404 for value in seg.lf_update_value.iter_mut() {
405 let update = bd.read_bool()?;
406 if update {
407 *value = bd.read_sint(6)?;
408 } else {
409 *value = 0;
412 }
413 }
414
415 if seg.update_mb_segmentation_map {
416 for value in seg.segment_prob.iter_mut() {
417 let update = bd.read_bool()?;
418 if update {
419 *value = bd.read_uint(8)?;
420 } else {
421 *value = 255;
424 }
425 }
426 }
427 }
428
429 Ok(())
430 }
431
432 fn parse_mb_lf_adjustments<T: AsRef<[u8]>>(
433 bd: &mut BoolDecoder<T>,
434 adj: &mut MbLfAdjustments,
435 ) -> BoolDecoderResult<()> {
436 adj.mode_ref_lf_delta_update = false;
437
438 adj.loop_filter_adj_enable = bd.read_bool()?;
439 if !adj.loop_filter_adj_enable {
440 return Ok(());
441 }
442
443 adj.mode_ref_lf_delta_update = bd.read_bool()?;
444 if !adj.mode_ref_lf_delta_update {
445 return Ok(());
446 }
447
448 for value in adj.ref_frame_delta.iter_mut() {
449 let update = bd.read_bool()?;
450 if update {
451 *value = bd.read_sint(6)?;
452 }
453 }
454
455 for value in adj.mb_mode_delta.iter_mut() {
456 let update = bd.read_bool()?;
457 if update {
458 *value = bd.read_sint(6)?;
459 }
460 }
461
462 Ok(())
463 }
464
465 fn parse_quant_indices<T: AsRef<[u8]>>(
466 bd: &mut BoolDecoder<T>,
467 q: &mut QuantIndices,
468 ) -> BoolDecoderResult<()> {
469 q.y_ac_qi = bd.read_uint(7)?;
470
471 let y_dc_delta_present = bd.read_bool()?;
472
473 if y_dc_delta_present {
474 q.y_dc_delta = bd.read_sint(4)?;
475 } else {
476 q.y_dc_delta = 0;
477 }
478
479 let y2_dc_delta_present = bd.read_bool()?;
480 if y2_dc_delta_present {
481 q.y2_dc_delta = bd.read_sint(4)?;
482 } else {
483 q.y2_dc_delta = 0;
484 }
485
486 let y2_ac_delta_present = bd.read_bool()?;
487 if y2_ac_delta_present {
488 q.y2_ac_delta = bd.read_sint(4)?;
489 } else {
490 q.y2_ac_delta = 0;
491 }
492
493 let uv_dc_delta_present = bd.read_bool()?;
494 if uv_dc_delta_present {
495 q.uv_dc_delta = bd.read_sint(4)?;
496 } else {
497 q.uv_dc_delta = 0;
498 }
499
500 let uv_ac_delta_present = bd.read_bool()?;
501 if uv_ac_delta_present {
502 q.uv_ac_delta = bd.read_sint(4)?;
503 } else {
504 q.uv_ac_delta = 0;
505 }
506
507 Ok(())
508 }
509
510 fn parse_token_prob_update<T: AsRef<[u8]>>(
511 bd: &mut BoolDecoder<T>,
512 coeff_probs: &mut [[[[u8; 11]; 3]; 8]; 4],
513 ) -> BoolDecoderResult<()> {
514 for (i, vi) in coeff_probs.iter_mut().enumerate() {
515 for (j, vj) in vi.iter_mut().enumerate() {
516 for (k, vk) in vj.iter_mut().enumerate() {
517 for (l, prob) in vk.iter_mut().enumerate() {
518 let update = bd.read_bool_with_prob(COEFF_UPDATE_PROBS[i][j][k][l])?;
519 if update {
520 *prob = bd.read_uint(8)?;
521 }
522 }
523 }
524 }
525 }
526
527 Ok(())
528 }
529
530 fn parse_mv_prob_update<T: AsRef<[u8]>>(
531 bd: &mut BoolDecoder<T>,
532 mv_probs: &mut [[u8; 19]; 2],
533 ) -> BoolDecoderResult<()> {
534 for (i, vi) in mv_probs.iter_mut().enumerate() {
535 for (j, prob) in vi.iter_mut().enumerate() {
536 let update = bd.read_bool_with_prob(MV_UPDATE_PROBS[i][j])?;
537 if update {
538 let mv_prob_update = bd.read_uint::<u8>(7)?;
539
540 if mv_prob_update > 0 {
541 *prob = mv_prob_update << 1;
542 } else {
543 *prob = 1;
544 }
545 }
546 }
547 }
548
549 Ok(())
550 }
551
552 fn parse_frame_header(&mut self, data: &[u8], frame: &mut Header) -> BoolDecoderResult<()> {
553 debug!("Parsing VP8 frame header.");
554 let mut bd = BoolDecoder::new(data);
555
556 if frame.key_frame {
557 frame.color_space = bd.read_bool()?;
558 frame.clamping_type = bd.read_bool()?;
559 }
560
561 Parser::update_segmentation(&mut bd, &mut self.segmentation)?;
562
563 frame.filter_type = bd.read_bool()?;
564 frame.loop_filter_level = bd.read_uint(6)?;
565 frame.sharpness_level = bd.read_uint(3)?;
566
567 Parser::parse_mb_lf_adjustments(&mut bd, &mut self.mb_lf_adjust)?;
568
569 frame.log2_nbr_of_dct_partitions = bd.read_uint(2)?;
570
571 Parser::parse_quant_indices(&mut bd, &mut frame.quant_indices)?;
572
573 frame.copy_buffer_to_golden = 0;
574 frame.copy_buffer_to_alternate = 0;
575
576 if frame.key_frame {
577 frame.refresh_entropy_probs = bd.read_bool()?;
578
579 frame.refresh_last = true;
580 frame.refresh_golden_frame = true;
581 frame.refresh_alternate_frame = true;
582
583 Parser::mode_probs_init_defaults(&mut frame.mode_probs, true);
584 } else {
585 frame.refresh_golden_frame = bd.read_bool()?;
586 frame.refresh_alternate_frame = bd.read_bool()?;
587
588 if !frame.refresh_golden_frame {
589 frame.copy_buffer_to_golden = bd.read_uint(2)?;
590 }
591
592 if !frame.refresh_alternate_frame {
593 frame.copy_buffer_to_alternate = bd.read_uint(2)?;
594 }
595
596 frame.sign_bias_golden = bd.read_bool()?;
597 frame.sign_bias_alternate = bd.read_bool()?;
598 frame.refresh_entropy_probs = bd.read_bool()?;
599 frame.refresh_last = bd.read_bool()?;
600
601 frame.mode_probs = self.mode_probs.clone();
602 }
603
604 frame.coeff_prob = self.coeff_prob;
605 frame.mv_prob = self.mv_prob;
606
607 Parser::parse_token_prob_update(&mut bd, &mut frame.coeff_prob)?;
608
609 frame.mb_no_coeff_skip = bd.read_bool()?;
610 if frame.mb_no_coeff_skip {
611 frame.prob_skip_false = bd.read_uint(8)?;
612 }
613
614 if !frame.key_frame {
615 frame.prob_intra = bd.read_uint(8)?;
616 frame.prob_last = bd.read_uint(8)?;
617 frame.prob_golden = bd.read_uint(8)?;
618
619 let intra_16x16_prob_update_flag = bd.read_bool()?;
620 if intra_16x16_prob_update_flag {
621 for prob in frame.mode_probs.intra_16x16_prob.iter_mut() {
622 *prob = bd.read_uint(8)?;
623 }
624 }
625
626 let intra_chroma_prob_update_flag = bd.read_bool()?;
627 if intra_chroma_prob_update_flag {
628 for prob in frame.mode_probs.intra_chroma_prob.iter_mut() {
629 *prob = bd.read_uint(8)?;
630 }
631 }
632
633 Parser::parse_mv_prob_update(&mut bd, &mut frame.mv_prob)?;
634 }
635
636 if frame.refresh_entropy_probs {
637 self.coeff_prob = frame.coeff_prob;
638 self.mv_prob = frame.mv_prob;
639
640 if !frame.key_frame {
641 self.mode_probs = frame.mode_probs.clone();
642 }
643 }
644
645 frame.header_size = bd.pos() as u32;
646
647 let state: BoolDecoderState = bd.into();
648 frame.bd_range = state.range;
649 frame.bd_value = state.value;
650 frame.bd_count = state.count;
651
652 Ok(())
653 }
654
655 pub fn parse_frame<'a>(&mut self, bitstream: &'a [u8]) -> Result<Frame<'a>, ParseFrameError> {
657 let mut header = Header::parse_uncompressed_data_chunk(bitstream)?;
658 if header.key_frame {
659 *self = Default::default();
661 }
662
663 let first_part_end = header.data_chunk_size as usize + header.first_part_size as usize;
664
665 if first_part_end > bitstream.len() {
666 return Err(ParseFrameError::InvalidPartitionSize(
667 first_part_end,
668 bitstream.len(),
669 ));
670 }
671
672 let compressed_area = &bitstream[header.data_chunk_size as usize..];
673
674 self.parse_frame_header(compressed_area, &mut header)?;
675 header.compute_partition_sizes(compressed_area)?;
676
677 let frame_len = header.frame_len();
678 if frame_len > bitstream.as_ref().len() {
679 return Err(ParseFrameError::BitstreamTooShort(
680 bitstream.as_ref().len(),
681 frame_len,
682 ));
683 }
684
685 Ok(Frame {
686 bitstream,
687 frame_len,
688 header,
689 })
690 }
691}
692
693impl Default for Parser {
694 fn default() -> Self {
695 Self {
696 segmentation: Default::default(),
697 mb_lf_adjust: Default::default(),
698 coeff_prob: COEFF_DEFAULT_PROBS,
699 mv_prob: MV_DEFAULT_PROBS,
700 mode_probs: ModeProbs {
701 intra_16x16_prob: NK_Y_MODE_PROBS,
702 intra_chroma_prob: NK_UV_MODE_PROBS,
703 },
704 }
705 }
706}
707
708#[cfg(test)]
709mod tests {
710 use super::Parser;
711
712 const VP8_TEST_0_INTRA: &[u8] = include_bytes!("test_data/vp8-parser-test-0-intra.bin");
715 const VP8_TEST_0_INTER: &[u8] = include_bytes!("test_data/vp8-parser-test-0-inter.bin");
716
717 #[test]
718 fn gst_intra() {
719 let mut parser = Parser::default();
720 let frame = parser
721 .parse_frame(VP8_TEST_0_INTRA)
722 .expect("Parsing a intra frame failed");
723
724 assert!(frame.header.key_frame);
725
726 assert_eq!(frame.header.first_part_size, 234);
727 assert_eq!(frame.header.width, 176);
728 assert_eq!(frame.header.height, 144);
729
730 assert!(parser.mb_lf_adjust.loop_filter_adj_enable);
731 assert!(parser.mb_lf_adjust.mode_ref_lf_delta_update);
732
733 assert_eq!(parser.mb_lf_adjust.ref_frame_delta[0], 2);
734 assert_eq!(parser.mb_lf_adjust.ref_frame_delta[1], 0);
735 assert_eq!(parser.mb_lf_adjust.ref_frame_delta[2], -2);
736 assert_eq!(parser.mb_lf_adjust.ref_frame_delta[3], -2);
737
738 assert_eq!(parser.mb_lf_adjust.mb_mode_delta[0], 4);
739 assert_eq!(parser.mb_lf_adjust.mb_mode_delta[1], -2);
740 assert_eq!(parser.mb_lf_adjust.mb_mode_delta[2], 2);
741 assert_eq!(parser.mb_lf_adjust.mb_mode_delta[3], 4);
742
743 assert_eq!(frame.header.quant_indices.y_ac_qi, 4);
744 assert!(frame.header.mb_no_coeff_skip);
745
746 assert_eq!(frame.header.bd_range, 0xe8);
747 assert_eq!(frame.header.bd_value, 0x68);
748 assert_eq!(frame.header.bd_count, 1);
749 }
750
751 #[test]
752 fn gst_inter() {
753 let mut parser = Parser::default();
754 let frame = parser
755 .parse_frame(VP8_TEST_0_INTER)
756 .expect("Parsing a inter frame failed");
757
758 assert!(!frame.header.key_frame);
759
760 assert_eq!(frame.header.first_part_size, 98);
761 assert!(parser.mb_lf_adjust.loop_filter_adj_enable);
762 assert_eq!(frame.header.quant_indices.y_ac_qi, 4);
763
764 assert!(frame.header.refresh_entropy_probs);
765 assert!(frame.header.refresh_last);
766 assert!(frame.header.mb_no_coeff_skip);
767
768 assert_eq!(frame.header.prob_skip_false, 131);
769 assert_eq!(frame.header.prob_intra, 224);
770 assert_eq!(frame.header.prob_last, 233);
771 assert_eq!(frame.header.prob_golden, 1);
772
773 assert_eq!(frame.header.bd_range, 0x8e);
774 assert_eq!(frame.header.bd_value, 0x85);
775 assert_eq!(frame.header.bd_count, 5);
776 }
777}