1use anyhow::anyhow;
6use anyhow::Context;
7use bitreader::BitReader;
8use enumn::N;
9
10use crate::codec::vp9::lookups::AC_QLOOKUP;
11use crate::codec::vp9::lookups::AC_QLOOKUP_10;
12use crate::codec::vp9::lookups::AC_QLOOKUP_12;
13use crate::codec::vp9::lookups::DC_QLOOKUP;
14use crate::codec::vp9::lookups::DC_QLOOKUP_10;
15use crate::codec::vp9::lookups::DC_QLOOKUP_12;
16
17pub const REFS_PER_FRAME: usize = 3;
18
19pub const MAX_REF_LF_DELTAS: usize = 4;
20pub const MAX_MODE_LF_DELTAS: usize = 2;
21
22pub const INTRA_FRAME: usize = 0;
23pub const LAST_FRAME: usize = 1;
24pub const GOLDEN_FRAME: usize = 2;
25pub const ALTREF_FRAME: usize = 3;
26pub const MAX_REF_FRAMES: usize = 4;
27
28pub const MAX_SEGMENTS: usize = 8;
29pub const SEG_TREE_PROBS: usize = MAX_SEGMENTS - 1;
30pub const PREDICTION_PROBS: usize = 3;
31
32#[repr(u8)]
34pub enum SegLvl {
35 AltQ = 0,
36 AltL = 1,
37 RefFrame = 2,
38 LvlSkip = 3,
39}
40pub const SEG_LVL_MAX: usize = 4;
41
42pub const MAX_LOOP_FILTER: u32 = 63;
43
44pub const REF_FRAMES_LOG2: usize = 3;
45pub const REF_FRAMES: usize = 1 << REF_FRAMES_LOG2;
46
47pub const SUPERFRAME_MARKER: u32 = 0x06;
48pub const MAX_FRAMES_IN_SUPERFRAME: usize = 8;
49
50pub const FRAME_MARKER: u32 = 0x02;
51pub const SYNC_CODE: u32 = 0x498342;
52
53pub const MIN_TILE_WIDTH_B64: u32 = 4;
54pub const MAX_TILE_WIDTH_B64: u32 = 64;
55
56pub const NUM_REF_FRAMES: usize = 8;
58
59#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, N)]
60pub enum InterpolationFilter {
61 #[default]
62 EightTap = 0,
63 EightTapSmooth = 1,
64 EightTapSharp = 2,
65 Bilinear = 3,
66 Switchable = 4,
67}
68
69#[derive(Copy, Clone, Debug, PartialEq, Eq, N)]
70pub enum ReferenceFrameType {
71 Intra = 0,
72 Last = 1,
73 Golden = 2,
74 AltRef = 3,
75}
76
77#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, N)]
78
79pub enum FrameType {
80 #[default]
81 KeyFrame = 0,
82 InterFrame = 1,
83}
84
85#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, N)]
86pub enum Profile {
87 #[default]
88 Profile0 = 0,
89 Profile1 = 1,
90 Profile2 = 2,
91 Profile3 = 3,
92}
93
94#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, N)]
95pub enum BitDepth {
96 #[default]
97 Depth8 = 8,
98 Depth10 = 10,
99 Depth12 = 12,
100}
101
102#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, N)]
103pub enum ColorSpace {
104 #[default]
105 Unknown = 0,
106 Bt601 = 1,
107 Bt709 = 2,
108 Smpte170 = 3,
109 Smpte240 = 4,
110 Bt2020 = 5,
111 Reserved2 = 6,
112 CsSrgb = 7,
113}
114
115#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, N)]
116pub enum ColorRange {
117 #[default]
118 StudioSwing = 0,
119 FullSwing = 1,
120}
121
122#[derive(Clone, Debug, Default, PartialEq, Eq)]
123pub struct LoopFilterParams {
124 pub level: u8,
126 pub sharpness: u8,
130 pub delta_enabled: bool,
134 pub delta_update: bool,
138 pub update_ref_delta: [bool; MAX_REF_LF_DELTAS],
142 pub ref_deltas: [i8; MAX_REF_LF_DELTAS],
146 pub update_mode_delta: [bool; MAX_MODE_LF_DELTAS],
150 pub mode_deltas: [i8; MAX_MODE_LF_DELTAS],
154}
155
156#[derive(Clone, Debug, Default, PartialEq, Eq)]
157pub struct QuantizationParams {
158 pub base_q_idx: u8,
161 pub delta_q_y_dc: i8,
163 pub delta_q_uv_dc: i8,
165 pub delta_q_uv_ac: i8,
167}
168
169#[derive(Clone, Debug, Default, PartialEq, Eq)]
170pub struct SegmentationParams {
171 pub enabled: bool,
174 pub update_map: bool,
178 pub tree_probs: [u8; SEG_TREE_PROBS],
180 pub pred_probs: [u8; PREDICTION_PROBS],
182 pub temporal_update: bool,
187 pub update_data: bool,
191 pub abs_or_delta_update: bool,
195 feature_enabled: [[bool; SEG_LVL_MAX]; MAX_SEGMENTS],
199 feature_data: [[i16; SEG_LVL_MAX]; MAX_SEGMENTS],
201}
202
203impl SegmentationParams {
204 fn is_feature_enabled(&self, segment_id: u8, feature: SegLvl) -> bool {
206 self.feature_enabled[segment_id as usize][feature as usize]
207 }
208
209 fn is_feature_active(&self, segment_id: u8, feature: SegLvl) -> bool {
211 self.enabled && self.is_feature_enabled(segment_id, feature)
212 }
213
214 fn feature_data(&self, segment_id: u8, feature: SegLvl) -> i16 {
216 self.feature_data[segment_id as usize][feature as usize]
217 }
218}
219
220#[derive(Clone, Debug, Default, PartialEq, Eq)]
221pub struct Segmentation {
222 pub lvl_lookup: [[u8; MAX_MODE_LF_DELTAS]; MAX_REF_FRAMES],
224
225 pub luma_ac_quant_scale: i16,
227 pub luma_dc_quant_scale: i16,
229 pub chroma_ac_quant_scale: i16,
231 pub chroma_dc_quant_scale: i16,
233
234 pub reference_frame_enabled: bool,
236 pub reference_frame: i16,
238 pub reference_skip_enabled: bool,
240}
241
242impl Segmentation {
243 pub fn update_segmentation(segmentation: &mut [Segmentation; MAX_SEGMENTS], hdr: &Header) {
245 let lf = &hdr.lf;
246 let seg = &hdr.seg;
247
248 let n_shift = lf.level >> 5;
249
250 for segment_id in 0..MAX_SEGMENTS as u8 {
251 let luma_dc_quant_scale = hdr.get_dc_quant(segment_id, true);
252 let luma_ac_quant_scale = hdr.get_ac_quant(segment_id, true);
253 let chroma_dc_quant_scale = hdr.get_dc_quant(segment_id, false);
254 let chroma_ac_quant_scale = hdr.get_ac_quant(segment_id, false);
255
256 let mut lvl_lookup: [[u8; MAX_MODE_LF_DELTAS]; MAX_REF_FRAMES];
257
258 if lf.level == 0 {
259 lvl_lookup = Default::default()
260 } else {
261 let mut lvl_seg = i32::from(lf.level);
262
263 if hdr.seg.is_feature_active(segment_id, SegLvl::AltL) {
265 if seg.abs_or_delta_update {
266 lvl_seg = i32::from(seg.feature_data(segment_id, SegLvl::AltL));
267 } else {
268 lvl_seg += i32::from(seg.feature_data(segment_id, SegLvl::AltL));
269 }
270 }
271
272 let lvl_seg = lvl_seg.clamp(0, MAX_LOOP_FILTER as i32) as u8;
273
274 if !lf.delta_enabled {
275 lvl_lookup = [[lvl_seg; MAX_MODE_LF_DELTAS]; MAX_REF_FRAMES]
276 } else {
277 let intra_delta = lf.ref_deltas[INTRA_FRAME] as i32;
278 let mut intra_lvl = lvl_seg as i32 + (intra_delta << n_shift);
279
280 lvl_lookup = segmentation[segment_id as usize].lvl_lookup;
281 lvl_lookup[INTRA_FRAME][0] = intra_lvl.clamp(0, MAX_LOOP_FILTER as i32) as u8;
282
283 #[allow(clippy::needless_range_loop)]
286 for ref_ in LAST_FRAME..MAX_REF_FRAMES {
287 for mode in 0..MAX_MODE_LF_DELTAS {
288 let ref_delta = lf.ref_deltas[ref_] as i32;
289 let mode_delta = lf.mode_deltas[mode] as i32;
290
291 intra_lvl =
292 lvl_seg as i32 + (ref_delta << n_shift) + (mode_delta << n_shift);
293
294 lvl_lookup[ref_][mode] =
295 intra_lvl.clamp(0, MAX_LOOP_FILTER as i32) as u8;
296 }
297 }
298 }
299 }
300
301 segmentation[usize::from(segment_id)] = Segmentation {
302 lvl_lookup,
303 luma_ac_quant_scale,
304 luma_dc_quant_scale,
305 chroma_ac_quant_scale,
306 chroma_dc_quant_scale,
307 reference_frame_enabled: seg.is_feature_enabled(segment_id, SegLvl::RefFrame),
308 reference_frame: seg.feature_data(segment_id, SegLvl::RefFrame),
309 reference_skip_enabled: seg.is_feature_enabled(segment_id, SegLvl::LvlSkip),
310 }
311 }
312 }
313}
314
315#[derive(Clone, Debug, Default, PartialEq, Eq)]
316struct FrameSize {
317 width: u32,
318 height: u32,
319}
320
321pub struct Frame<'a> {
322 bitstream: &'a [u8],
324 pub header: Header,
326 offset: usize,
328 size: usize,
330}
331
332impl<'a> Frame<'a> {
333 pub fn new(bitstream: &'a [u8], header: Header, offset: usize, size: usize) -> Self {
334 Self {
335 bitstream,
336 header,
337 offset,
338 size,
339 }
340 }
341}
342
343impl<'a> AsRef<[u8]> for Frame<'a> {
344 fn as_ref(&self) -> &[u8] {
345 let data = self.bitstream;
346 &data[self.offset..self.offset + self.size]
347 }
348}
349
350#[derive(Clone, Debug, Default, PartialEq, Eq)]
352pub struct Header {
353 pub profile: Profile,
355 pub bit_depth: BitDepth,
357 pub subsampling_x: bool,
359 pub subsampling_y: bool,
361 pub color_space: ColorSpace,
363 pub color_range: ColorRange,
366 pub show_existing_frame: bool,
369 pub frame_to_show_map_idx: u8,
372 pub frame_type: FrameType,
374 pub show_frame: bool,
376 pub error_resilient_mode: bool,
378 pub width: u32,
380 pub height: u32,
382 pub render_and_frame_size_different: bool,
386 pub render_width: u32,
388 pub render_height: u32,
390 pub intra_only: bool,
393 pub reset_frame_context: u8,
395 pub refresh_frame_flags: u8,
398 pub ref_frame_idx: [u8; REFS_PER_FRAME],
403 pub ref_frame_sign_bias: [u8; 4],
408 pub allow_high_precision_mv: bool,
412 pub interpolation_filter: InterpolationFilter,
414 pub refresh_frame_context: bool,
419 pub frame_parallel_decoding_mode: bool,
421 pub frame_context_idx: u8,
423 pub lf: LoopFilterParams,
425 pub quant: QuantizationParams,
427 pub seg: SegmentationParams,
429 pub tile_cols_log2: u8,
433 pub tile_rows_log2: u8,
436 pub lossless: bool,
440 pub header_size_in_bytes: u16,
442 pub uncompressed_header_size_in_bytes: u16,
444}
445
446impl Header {
447 fn get_qindex(&self, segment_id: u8) -> u8 {
449 let base_q_idx = self.quant.base_q_idx;
450
451 if self.seg.is_feature_active(segment_id, SegLvl::AltQ) {
452 let mut data = self.seg.feature_data(segment_id, SegLvl::AltQ) as i32;
453
454 if !self.seg.abs_or_delta_update {
455 data += base_q_idx as i32;
456 }
457
458 data.clamp(0, 255) as u8
459 } else {
460 base_q_idx
461 }
462 }
463
464 fn get_dc_quant(&self, segment_id: u8, luma: bool) -> i16 {
466 let delta_q_dc = if luma {
467 self.quant.delta_q_y_dc
468 } else {
469 self.quant.delta_q_uv_dc
470 } as i32;
471 let qindex = self.get_qindex(segment_id);
472 let q_table_idx = (qindex as i32 + delta_q_dc).clamp(0, 255) as u8;
473
474 let table = match self.bit_depth {
475 BitDepth::Depth8 => &DC_QLOOKUP,
476 BitDepth::Depth10 => &DC_QLOOKUP_10,
477 BitDepth::Depth12 => &DC_QLOOKUP_12,
478 };
479
480 table[q_table_idx as usize]
481 }
482
483 fn get_ac_quant(&self, segment_id: u8, luma: bool) -> i16 {
485 let delta_q_ac = if luma { 0 } else { self.quant.delta_q_uv_ac } as i32;
486 let qindex = self.get_qindex(segment_id);
487 let q_table_idx = (qindex as i32 + delta_q_ac).clamp(0, 255) as u8;
488
489 let table = match self.bit_depth {
490 BitDepth::Depth8 => &AC_QLOOKUP,
491 BitDepth::Depth10 => &AC_QLOOKUP_10,
492 BitDepth::Depth12 => &AC_QLOOKUP_12,
493 };
494
495 table[q_table_idx as usize]
496 }
497}
498
499struct SuperframeHeader {
501 frames_in_superframe: u32,
505 frame_sizes: Vec<usize>,
508}
509
510#[derive(Clone, Debug, Default, PartialEq, Eq)]
512pub struct Parser {
513 bit_depth: BitDepth,
514 subsampling_x: bool,
515 subsampling_y: bool,
516 color_space: ColorSpace,
517 color_range: ColorRange,
518
519 mi_cols: u32,
520 mi_rows: u32,
521 sb64_cols: u32,
522 sb64_rows: u32,
523
524 lf: LoopFilterParams,
525 seg: SegmentationParams,
526
527 reference_frame_sz: [FrameSize; REF_FRAMES],
528}
529
530impl Parser {
531 fn parse_superframe_hdr(resource: impl AsRef<[u8]>) -> anyhow::Result<SuperframeHeader> {
532 let bitstream = resource.as_ref();
533
534 let mut reader = BitReader::new(&bitstream[bitstream.len() - 1..]);
536
537 let marker = reader.read_u32(3)?;
539
540 if marker != SUPERFRAME_MARKER {
541 return Ok(SuperframeHeader {
543 frames_in_superframe: 1,
544 frame_sizes: vec![bitstream.len()],
545 });
546 }
547
548 let bytes_per_framesize = reader.read_u32(2)? + 1;
549 let frames_in_superframe = reader.read_u32(3)? + 1;
550
551 if frames_in_superframe > MAX_FRAMES_IN_SUPERFRAME as u32 {
552 return Err(anyhow!(
553 "Broken stream: too many frames in superframe, expected a maximum of {:?}, found {:?}",
554 MAX_FRAMES_IN_SUPERFRAME,
555 frames_in_superframe
556 ));
557 }
558
559 let sz_index = 2 + frames_in_superframe * bytes_per_framesize;
560
561 let data = resource.as_ref();
562 let index_offset = data.len() - sz_index as usize;
563 let first_byte = data[index_offset];
564 let last_byte = *data
565 .last()
566 .ok_or_else(|| anyhow!("superframe header is empty"))?;
567
568 if first_byte != last_byte {
569 return Ok(SuperframeHeader {
571 frames_in_superframe: 1,
572 frame_sizes: vec![bitstream.len()],
573 });
574 }
575
576 let mut frame_sizes = vec![];
577 let mut reader = BitReader::new(&bitstream[index_offset..]);
578
579 let _ = reader.read_u32(8)?;
581
582 for _ in 0..frames_in_superframe {
583 let mut frame_size = 0;
584
585 for j in 0..bytes_per_framesize {
586 frame_size |= reader.read_u32(8)? << (j * 8);
587 }
588
589 frame_sizes.push(frame_size as usize);
590 }
591
592 Ok(SuperframeHeader {
593 frames_in_superframe,
594 frame_sizes,
595 })
596 }
597
598 fn read_signed_8(r: &mut BitReader, nbits: u8) -> bitreader::Result<i8> {
599 let value = r.read_u8(nbits)?;
600 let negative = r.read_bool()?;
601
602 if negative {
603 Ok(-(value as i8))
604 } else {
605 Ok(value as i8)
606 }
607 }
608
609 fn parse_frame_marker(r: &mut BitReader) -> anyhow::Result<()> {
610 let marker = r.read_u32(2)?;
611
612 if marker != FRAME_MARKER {
613 return Err(anyhow!(
614 "Broken stream: expected frame marker, found {:?}",
615 marker
616 ));
617 }
618
619 Ok(())
620 }
621
622 fn parse_profile(r: &mut BitReader) -> anyhow::Result<Profile> {
623 let low = r.read_u32(1)?;
624 let high = r.read_u32(1)?;
625
626 let profile = (high << 1) | low;
627
628 if profile == 3 {
629 let _ = r.read_bool()?;
631 }
632
633 Profile::n(profile).with_context(|| format!("Broken stream: invalid profile {:?}", profile))
634 }
635
636 fn parse_frame_sync_code(r: &mut BitReader) -> anyhow::Result<()> {
637 let sync_code = r.read_u32(24)?;
638
639 if sync_code != SYNC_CODE {
640 return Err(anyhow!(
641 "Broken stream: expected sync code == {:?}, found {:?}",
642 SYNC_CODE,
643 sync_code
644 ));
645 }
646
647 Ok(())
648 }
649
650 fn parse_color_config(&mut self, r: &mut BitReader, hdr: &mut Header) -> anyhow::Result<()> {
651 if matches!(hdr.profile, Profile::Profile2 | Profile::Profile3) {
652 let ten_or_twelve_bit = r.read_bool()?;
653 if ten_or_twelve_bit {
654 hdr.bit_depth = BitDepth::Depth12;
655 } else {
656 hdr.bit_depth = BitDepth::Depth10
657 }
658 } else {
659 hdr.bit_depth = BitDepth::Depth8;
660 }
661
662 let color_space = r.read_u32(3)?;
663 hdr.color_space = ColorSpace::n(color_space)
664 .with_context(|| format!("Broken stream: invalid color space: {:?}", color_space))?;
665
666 if !matches!(hdr.color_space, ColorSpace::CsSrgb) {
667 let color_range = r.read_u32(1)?;
668
669 hdr.color_range = ColorRange::n(color_range).with_context(|| {
670 format!("Broken stream: invalid color range: {:?}", color_range)
671 })?;
672
673 if matches!(hdr.profile, Profile::Profile1 | Profile::Profile3) {
674 hdr.subsampling_x = r.read_bool()?;
675 hdr.subsampling_y = r.read_bool()?;
676
677 let _ = r.read_bool()?;
679 } else {
680 hdr.subsampling_x = true;
681 hdr.subsampling_y = true;
682 }
683 } else {
684 hdr.color_range = ColorRange::FullSwing;
685 if matches!(hdr.profile, Profile::Profile1 | Profile::Profile3) {
686 hdr.subsampling_x = false;
687 hdr.subsampling_y = false;
688
689 let _ = r.read_bool()?;
691 }
692 }
693
694 self.bit_depth = hdr.bit_depth;
695 self.color_space = hdr.color_space;
696 self.subsampling_x = hdr.subsampling_x;
697 self.subsampling_y = hdr.subsampling_y;
698 self.color_range = hdr.color_range;
699
700 Ok(())
701 }
702
703 fn compute_image_size(&mut self, width: u32, height: u32) {
704 self.mi_cols = (width + 7) >> 3;
705 self.mi_rows = (height + 7) >> 3;
706 self.sb64_cols = (self.mi_cols + 7) >> 3;
707 self.sb64_rows = (self.mi_rows + 7) >> 3;
708 }
709
710 fn parse_frame_size(&mut self, r: &mut BitReader, hdr: &mut Header) -> bitreader::Result<()> {
711 hdr.width = r.read_u32(16)? + 1;
712 hdr.height = r.read_u32(16)? + 1;
713 self.compute_image_size(hdr.width, hdr.height);
714 Ok(())
715 }
716
717 fn parse_render_size(r: &mut BitReader, hdr: &mut Header) -> bitreader::Result<()> {
718 hdr.render_and_frame_size_different = r.read_bool()?;
719 if hdr.render_and_frame_size_different {
720 hdr.render_width = r.read_u32(16)? + 1;
721 hdr.render_height = r.read_u32(16)? + 1;
722 } else {
723 hdr.render_width = hdr.width;
724 hdr.render_height = hdr.height;
725 }
726
727 Ok(())
728 }
729
730 fn parse_frame_size_with_refs(
731 &mut self,
732 r: &mut BitReader,
733 hdr: &mut Header,
734 ) -> bitreader::Result<()> {
735 let mut found_ref = false;
736
737 for i in 0..REFS_PER_FRAME {
738 found_ref = r.read_bool()?;
739
740 if found_ref {
741 let idx = hdr.ref_frame_idx[i] as usize;
742 hdr.width = self.reference_frame_sz[idx].width;
743 hdr.height = self.reference_frame_sz[idx].height;
744 break;
745 }
746 }
747
748 if !found_ref {
749 self.parse_frame_size(r, hdr)?;
750 } else {
751 self.compute_image_size(hdr.width, hdr.height)
752 }
753
754 Self::parse_render_size(r, hdr)
755 }
756
757 fn read_interpolation_filter(r: &mut BitReader) -> bitreader::Result<InterpolationFilter> {
758 const LITERAL_TO_TYPE: [InterpolationFilter; 4] = [
759 InterpolationFilter::EightTapSmooth,
760 InterpolationFilter::EightTap,
761 InterpolationFilter::EightTapSharp,
762 InterpolationFilter::Bilinear,
763 ];
764
765 let is_filter_switchable = r.read_bool()?;
766
767 Ok(if is_filter_switchable {
768 InterpolationFilter::Switchable
769 } else {
770 let raw_interpolation_filter = r.read_u32(2)?;
771 LITERAL_TO_TYPE[raw_interpolation_filter as usize]
772 })
773 }
774
775 fn setup_past_independence(&mut self, hdr: &mut Header) {
776 self.seg.feature_enabled = Default::default();
777 self.seg.feature_data = Default::default();
778 self.seg.abs_or_delta_update = false;
779
780 self.lf.delta_enabled = true;
781 self.lf.ref_deltas[ReferenceFrameType::Intra as usize] = 1;
782 self.lf.ref_deltas[ReferenceFrameType::Last as usize] = 0;
783 self.lf.ref_deltas[ReferenceFrameType::Golden as usize] = -1;
784 self.lf.ref_deltas[ReferenceFrameType::AltRef as usize] = -1;
785
786 self.lf.mode_deltas = Default::default();
787 hdr.ref_frame_sign_bias = Default::default();
788 }
789
790 fn parse_loop_filter_params(
791 r: &mut BitReader,
792 lf: &mut LoopFilterParams,
793 ) -> bitreader::Result<()> {
794 lf.level = r.read_u8(6)?;
795 lf.sharpness = r.read_u8(3)?;
796 lf.delta_enabled = r.read_bool()?;
797
798 if lf.delta_enabled {
799 lf.delta_update = r.read_bool()?;
800 if lf.delta_update {
801 for i in 0..MAX_REF_LF_DELTAS {
802 lf.update_ref_delta[i] = r.read_bool()?;
803 if lf.update_ref_delta[i] {
804 lf.ref_deltas[i] = Self::read_signed_8(r, 6)?;
805 }
806 }
807
808 for i in 0..MAX_MODE_LF_DELTAS {
809 lf.update_mode_delta[i] = r.read_bool()?;
810 if lf.update_mode_delta[i] {
811 lf.mode_deltas[i] = Self::read_signed_8(r, 6)?;
812 }
813 }
814 }
815 }
816
817 Ok(())
818 }
819
820 fn read_delta_q(r: &mut BitReader, value: &mut i8) -> bitreader::Result<()> {
821 let delta_coded = r.read_bool()?;
822
823 if delta_coded {
824 *value = Self::read_signed_8(r, 4)?;
825 } else {
826 *value = 0;
827 }
828
829 Ok(())
830 }
831
832 fn parse_quantization_params(r: &mut BitReader, hdr: &mut Header) -> bitreader::Result<()> {
833 let quant = &mut hdr.quant;
834
835 quant.base_q_idx = r.read_u8(8)?;
836
837 Self::read_delta_q(r, &mut quant.delta_q_y_dc)?;
838 Self::read_delta_q(r, &mut quant.delta_q_uv_dc)?;
839 Self::read_delta_q(r, &mut quant.delta_q_uv_ac)?;
840
841 hdr.lossless = quant.base_q_idx == 0
842 && quant.delta_q_y_dc == 0
843 && quant.delta_q_uv_dc == 0
844 && quant.delta_q_uv_ac == 0;
845
846 Ok(())
847 }
848
849 fn read_prob(r: &mut BitReader) -> bitreader::Result<u8> {
850 let prob_coded = r.read_bool()?;
851
852 let prob = if prob_coded { r.read_u8(8)? } else { 255 };
853
854 Ok(prob)
855 }
856
857 fn parse_segmentation_params(
858 r: &mut BitReader,
859 seg: &mut SegmentationParams,
860 ) -> bitreader::Result<()> {
861 const SEGMENTATION_FEATURE_BITS: [u8; SEG_LVL_MAX] = [8, 6, 2, 0];
862 const SEGMENTATION_FEATURE_SIGNED: [bool; SEG_LVL_MAX] = [true, true, false, false];
863
864 seg.update_map = false;
865 seg.update_data = false;
866
867 seg.enabled = r.read_bool()?;
868
869 if !seg.enabled {
870 return Ok(());
871 }
872
873 seg.update_map = r.read_bool()?;
874
875 if seg.update_map {
876 for i in 0..SEG_TREE_PROBS {
877 seg.tree_probs[i] = Self::read_prob(r)?;
878 }
879
880 seg.temporal_update = r.read_bool()?;
881
882 for i in 0..PREDICTION_PROBS {
883 seg.pred_probs[i] = if seg.temporal_update {
884 Self::read_prob(r)?
885 } else {
886 255
887 };
888 }
889 }
890
891 seg.update_data = r.read_bool()?;
892
893 if seg.update_data {
894 seg.abs_or_delta_update = r.read_bool()?;
895 for i in 0..MAX_SEGMENTS {
896 for j in 0..SEG_LVL_MAX {
897 seg.feature_enabled[i][j] = r.read_bool()?;
898 if seg.feature_enabled[i][j] {
899 let bits_to_read = SEGMENTATION_FEATURE_BITS[j];
900 let mut feature_value = r.read_i16(bits_to_read)?;
901
902 if SEGMENTATION_FEATURE_SIGNED[j] {
903 let feature_sign = r.read_bool()?;
904
905 if feature_sign {
906 feature_value = -feature_value;
907 }
908 }
909
910 seg.feature_data[i][j] = feature_value;
911 }
912 }
913 }
914 }
915
916 Ok(())
917 }
918
919 fn calc_min_log2_tile_cols(sb64_cols: u32) -> u8 {
920 let mut min_log2 = 0;
921
922 while (MAX_TILE_WIDTH_B64 << min_log2) < sb64_cols {
923 min_log2 += 1;
924 }
925
926 min_log2
927 }
928
929 fn calc_max_log2_tile_cols(sb64_cols: u32) -> u8 {
930 let mut max_log2 = 1;
931
932 while (sb64_cols >> max_log2) >= MIN_TILE_WIDTH_B64 {
933 max_log2 += 1;
934 }
935
936 max_log2 - 1
937 }
938
939 fn parse_tile_info(&self, r: &mut BitReader, hdr: &mut Header) -> bitreader::Result<()> {
940 let max_log2_tile_cols = Self::calc_max_log2_tile_cols(self.sb64_cols);
941
942 hdr.tile_cols_log2 = Self::calc_min_log2_tile_cols(self.sb64_cols);
943
944 while hdr.tile_cols_log2 < max_log2_tile_cols {
945 let increment_tile_cols_log2 = r.read_bool()?;
946
947 if increment_tile_cols_log2 {
948 hdr.tile_cols_log2 += 1;
949 } else {
950 break;
951 }
952 }
953
954 hdr.tile_rows_log2 = r.read_u8(1)?;
955
956 if hdr.tile_rows_log2 > 0 {
957 let increment_tile_rows_log2 = r.read_bool()?;
958 hdr.tile_rows_log2 += increment_tile_rows_log2 as u8;
959 }
960
961 Ok(())
962 }
963
964 fn parse_frame_header(
965 &mut self,
966 resource: impl AsRef<[u8]>,
967 offset: usize,
968 ) -> anyhow::Result<Header> {
969 let data = &resource.as_ref()[offset..];
970 let mut r = BitReader::new(data);
971 let mut hdr = Header::default();
972
973 Self::parse_frame_marker(&mut r)?;
974 hdr.profile = Self::parse_profile(&mut r)?;
975
976 hdr.show_existing_frame = r.read_bool()?;
977
978 if hdr.show_existing_frame {
979 hdr.frame_to_show_map_idx = r.read_u8(3)?;
980 return Ok(hdr);
981 }
982
983 hdr.frame_type =
984 FrameType::n(r.read_u8(1)?).ok_or(anyhow!("Broken data: invalid frame type"))?;
985
986 hdr.show_frame = r.read_bool()?;
987 hdr.error_resilient_mode = r.read_bool()?;
988
989 let frame_is_intra;
990
991 if matches!(hdr.frame_type, FrameType::KeyFrame) {
992 Self::parse_frame_sync_code(&mut r)?;
993 self.parse_color_config(&mut r, &mut hdr)?;
994 self.parse_frame_size(&mut r, &mut hdr)?;
995 Self::parse_render_size(&mut r, &mut hdr)?;
996 hdr.refresh_frame_flags = 0xff;
997 frame_is_intra = true;
998 } else {
999 if !hdr.show_frame {
1000 hdr.intra_only = r.read_bool()?;
1001 }
1002
1003 frame_is_intra = hdr.intra_only;
1004
1005 if !hdr.error_resilient_mode {
1006 hdr.reset_frame_context = r.read_u8(2)?;
1007 } else {
1008 hdr.reset_frame_context = 0;
1009 }
1010
1011 if hdr.intra_only {
1012 Self::parse_frame_sync_code(&mut r)?;
1013
1014 if !matches!(hdr.profile, Profile::Profile0) {
1015 self.parse_color_config(&mut r, &mut hdr)?;
1016 } else {
1017 hdr.color_space = ColorSpace::Bt601;
1018 hdr.subsampling_x = true;
1019 hdr.subsampling_y = true;
1020 hdr.bit_depth = BitDepth::Depth8;
1021
1022 self.color_space = hdr.color_space;
1023 self.subsampling_x = hdr.subsampling_x;
1024 self.subsampling_y = hdr.subsampling_y;
1025 self.bit_depth = hdr.bit_depth;
1026 }
1027
1028 hdr.refresh_frame_flags = r.read_u8(8)?;
1029 self.parse_frame_size(&mut r, &mut hdr)?;
1030 Self::parse_render_size(&mut r, &mut hdr)?;
1031 } else {
1032 hdr.color_space = self.color_space;
1034 hdr.color_range = self.color_range;
1035 hdr.subsampling_x = self.subsampling_x;
1036 hdr.subsampling_y = self.subsampling_y;
1037 hdr.bit_depth = self.bit_depth;
1038
1039 hdr.refresh_frame_flags = r.read_u8(8)?;
1040
1041 for i in 0..REFS_PER_FRAME {
1042 hdr.ref_frame_idx[i] = r.read_u8(3)?;
1043 hdr.ref_frame_sign_bias[ReferenceFrameType::Last as usize + i] =
1044 r.read_u8(1)?;
1045 }
1046
1047 self.parse_frame_size_with_refs(&mut r, &mut hdr)?;
1048 hdr.allow_high_precision_mv = r.read_bool()?;
1049 hdr.interpolation_filter = Self::read_interpolation_filter(&mut r)?;
1050 }
1051 }
1052
1053 if !hdr.error_resilient_mode {
1054 hdr.refresh_frame_context = r.read_bool()?;
1055 hdr.frame_parallel_decoding_mode = r.read_bool()?;
1056 } else {
1057 hdr.refresh_frame_context = false;
1058 hdr.frame_parallel_decoding_mode = true;
1059 }
1060
1061 hdr.frame_context_idx = r.read_u8(2)?;
1062
1063 if frame_is_intra || hdr.error_resilient_mode {
1064 self.setup_past_independence(&mut hdr);
1065 }
1066
1067 Self::parse_loop_filter_params(&mut r, &mut self.lf)?;
1068 Self::parse_quantization_params(&mut r, &mut hdr)?;
1069 Self::parse_segmentation_params(&mut r, &mut self.seg)?;
1070 self.parse_tile_info(&mut r, &mut hdr)?;
1071
1072 hdr.header_size_in_bytes = r.read_u16(16)?;
1073
1074 hdr.lf = self.lf.clone();
1075 hdr.seg = self.seg.clone();
1076
1077 for i in 0..REF_FRAMES {
1078 let flag = 1 << i;
1079 if hdr.refresh_frame_flags & flag != 0 {
1080 self.reference_frame_sz[i].width = hdr.width;
1081 self.reference_frame_sz[i].height = hdr.height;
1082 }
1083 }
1084
1085 hdr.uncompressed_header_size_in_bytes = (r.position() as u16 + 7) / 8;
1086
1087 Ok(hdr)
1088 }
1089
1090 pub fn parse_frame<'a>(
1092 &mut self,
1093 bitstream: &'a [u8],
1094 offset: usize,
1095 size: usize,
1096 ) -> anyhow::Result<Frame<'a>> {
1097 let header = self.parse_frame_header(bitstream, offset)?;
1098
1099 Ok(Frame {
1100 header,
1101 bitstream,
1102 offset,
1103 size,
1104 })
1105 }
1106
1107 pub fn parse_chunk<'a>(&mut self, resource: &'a [u8]) -> anyhow::Result<Vec<Frame<'a>>> {
1110 let superframe_hdr = Parser::parse_superframe_hdr(resource)?;
1111 let mut offset = 0;
1112
1113 let mut frames = vec![];
1114
1115 for i in 0..superframe_hdr.frames_in_superframe {
1116 let frame_sz = superframe_hdr.frame_sizes[i as usize];
1117 let frame = self.parse_frame(resource, offset, frame_sz)?;
1118 offset += frame_sz;
1119 frames.push(frame);
1120 }
1121
1122 Ok(frames)
1123 }
1124}
1125
1126#[cfg(test)]
1127mod tests {
1128 use crate::codec::vp9::parser::BitDepth;
1129 use crate::codec::vp9::parser::ColorSpace;
1130 use crate::codec::vp9::parser::FrameType;
1131 use crate::codec::vp9::parser::InterpolationFilter;
1132 use crate::codec::vp9::parser::Parser;
1133 use crate::codec::vp9::parser::Profile;
1134 use crate::codec::vp9::parser::MAX_SEGMENTS;
1135 use crate::codec::vp9::parser::SEG_LVL_MAX;
1136 use crate::utils::IvfIterator;
1137
1138 #[test]
1139 fn test_parse_superframe() {
1140 const VP9_TEST_SUPERFRAME: &[u8] = include_bytes!("test_data/vp9-superframe.bin");
1142
1143 let mut parser = Parser::default();
1144 let frames = parser
1145 .parse_chunk(VP9_TEST_SUPERFRAME)
1146 .expect("Parsing a superframe failed");
1147
1148 assert_eq!(frames.len(), 2);
1149 assert_eq!(frames[0].offset, 0);
1150 assert_eq!(frames[0].size, 1333);
1151 assert_eq!(frames[1].offset, 1333);
1152 assert_eq!(frames[1].size, 214);
1153 }
1154
1155 #[test]
1156 fn test_parse_test25fps() {
1157 const TEST_STREAM: &[u8] = include_bytes!("test_data/test-25fps.vp9");
1159
1160 let mut parser = Parser::default();
1161 let ivf_iter = IvfIterator::new(TEST_STREAM);
1162
1163 for (frame_n, packet) in ivf_iter.enumerate() {
1164 let frames = parser
1165 .parse_chunk(packet.as_ref())
1166 .expect("Parsing a superframe failed");
1167
1168 if frame_n == 0 {
1169 assert_eq!(frames.len(), 1);
1170 let h = &frames[0].header;
1171
1172 assert!(matches!(h.profile, Profile::Profile0));
1173 assert!(matches!(h.bit_depth, BitDepth::Depth8));
1174
1175 assert!(h.subsampling_x);
1176 assert!(h.subsampling_y);
1177
1178 assert!(matches!(h.color_space, ColorSpace::Unknown));
1179 assert!(matches!(
1180 h.color_range,
1181 crate::codec::vp9::parser::ColorRange::StudioSwing
1182 ));
1183
1184 assert!(!h.show_existing_frame);
1185 assert_eq!(h.frame_to_show_map_idx, 0);
1186
1187 assert!(matches!(h.frame_type, FrameType::KeyFrame));
1188 assert!(h.show_frame);
1189 assert!(!h.error_resilient_mode);
1190
1191 assert_eq!(h.width, 320);
1192 assert_eq!(h.height, 240);
1193
1194 assert!(!h.render_and_frame_size_different);
1195
1196 assert_eq!(h.render_width, 320);
1197 assert_eq!(h.render_height, 240);
1198
1199 assert!(!h.intra_only);
1200 assert_eq!(h.reset_frame_context, 0);
1201
1202 assert_eq!(h.refresh_frame_flags, 0xff);
1203 assert_eq!(h.ref_frame_idx, [0, 0, 0]);
1204 assert_eq!(h.ref_frame_sign_bias, [0, 0, 0, 0]);
1205
1206 assert!(!h.allow_high_precision_mv);
1207 assert!(matches!(
1208 h.interpolation_filter,
1209 InterpolationFilter::EightTap
1210 ));
1211
1212 assert!(h.refresh_frame_context);
1213 assert!(h.frame_parallel_decoding_mode);
1214 assert_eq!(h.frame_context_idx, 0);
1215
1216 let lf = &h.lf;
1217 assert_eq!(lf.level, 9);
1218 assert_eq!(lf.sharpness, 0);
1219
1220 assert!(lf.delta_enabled);
1221 assert!(lf.delta_update);
1222
1223 assert_eq!(lf.update_ref_delta, [true, false, true, true]);
1224 assert_eq!(lf.ref_deltas, [1, 0, -1, -1]);
1225
1226 assert_eq!(lf.update_mode_delta, [false, false]);
1227
1228 let q = &h.quant;
1229
1230 assert_eq!(q.base_q_idx, 65);
1231 assert_eq!(q.delta_q_y_dc, 0);
1232 assert_eq!(q.delta_q_uv_dc, 0);
1233 assert_eq!(q.delta_q_uv_ac, 0);
1234
1235 let s = &h.seg;
1236
1237 assert!(!s.enabled);
1238 assert!(!s.update_map);
1239 assert_eq!(s.tree_probs, [0, 0, 0, 0, 0, 0, 0]);
1240 assert_eq!(s.pred_probs, [0, 0, 0]);
1241 assert!(!s.temporal_update);
1242 assert!(!s.update_data);
1243 assert!(!s.abs_or_delta_update);
1244 assert_eq!(s.feature_enabled, [[false; SEG_LVL_MAX]; MAX_SEGMENTS]);
1245 assert_eq!(s.feature_data, [[0; SEG_LVL_MAX]; MAX_SEGMENTS]);
1246
1247 assert_eq!(h.tile_cols_log2, 0);
1248 assert_eq!(h.tile_rows_log2, 0);
1249 assert_eq!(h.header_size_in_bytes, 120);
1250
1251 assert!(!h.lossless);
1252 } else if frame_n == 1 {
1253 assert_eq!(frames.len(), 2);
1254
1255 assert_eq!(frames[0].offset, 0);
1256 assert_eq!(frames[0].size, 2390);
1257 assert_eq!(frames[1].offset, 2390);
1258 assert_eq!(frames[1].size, 108);
1259
1260 let h = &frames[0].header;
1261
1262 assert!(matches!(h.profile, Profile::Profile0));
1263 assert!(matches!(h.bit_depth, BitDepth::Depth8));
1264
1265 assert!(h.subsampling_x);
1266 assert!(h.subsampling_y);
1267
1268 assert!(matches!(h.color_space, ColorSpace::Unknown));
1269 assert!(matches!(
1270 h.color_range,
1271 crate::codec::vp9::parser::ColorRange::StudioSwing
1272 ));
1273
1274 assert!(!h.show_existing_frame);
1275 assert_eq!(h.frame_to_show_map_idx, 0);
1276
1277 assert!(matches!(h.frame_type, FrameType::InterFrame));
1278 assert!(!h.show_frame);
1279 assert!(!h.error_resilient_mode);
1280
1281 assert_eq!(h.width, 320);
1282 assert_eq!(h.height, 240);
1283
1284 assert!(!h.render_and_frame_size_different);
1285
1286 assert_eq!(h.render_width, 320);
1287 assert_eq!(h.render_height, 240);
1288
1289 assert!(!h.intra_only);
1290 assert_eq!(h.reset_frame_context, 0);
1291
1292 assert_eq!(h.refresh_frame_flags, 4);
1293 assert_eq!(h.ref_frame_idx, [0, 1, 2]);
1294 assert_eq!(h.ref_frame_sign_bias, [0, 0, 0, 0]);
1295
1296 assert!(h.allow_high_precision_mv);
1297 assert!(matches!(
1298 h.interpolation_filter,
1299 InterpolationFilter::EightTap
1300 ));
1301
1302 assert!(h.refresh_frame_context);
1303 assert!(h.frame_parallel_decoding_mode);
1304 assert_eq!(h.frame_context_idx, 1);
1305
1306 let lf = &h.lf;
1307 assert_eq!(lf.level, 15);
1308 assert_eq!(lf.sharpness, 0);
1309
1310 assert!(lf.delta_enabled);
1311 assert!(!lf.delta_update);
1312
1313 assert_eq!(lf.update_ref_delta, [true, false, true, true]);
1314 assert_eq!(lf.ref_deltas, [1, 0, -1, -1]);
1315
1316 assert_eq!(lf.update_mode_delta, [false, false]);
1317
1318 let q = &h.quant;
1319
1320 assert_eq!(q.base_q_idx, 112);
1321 assert_eq!(q.delta_q_y_dc, 0);
1322 assert_eq!(q.delta_q_uv_dc, 0);
1323 assert_eq!(q.delta_q_uv_ac, 0);
1324
1325 let s = &h.seg;
1326
1327 assert!(!s.enabled);
1328 assert!(!s.update_map);
1329 assert_eq!(s.tree_probs, [0, 0, 0, 0, 0, 0, 0]);
1330 assert_eq!(s.pred_probs, [0, 0, 0]);
1331 assert!(!s.temporal_update);
1332 assert!(!s.update_data);
1333 assert!(!s.abs_or_delta_update);
1334 assert_eq!(s.feature_enabled, [[false; SEG_LVL_MAX]; MAX_SEGMENTS]);
1335 assert_eq!(s.feature_data, [[0; SEG_LVL_MAX]; MAX_SEGMENTS]);
1336
1337 assert_eq!(h.tile_cols_log2, 0);
1338 assert_eq!(h.tile_rows_log2, 0);
1339 assert_eq!(h.header_size_in_bytes, 48);
1340
1341 assert!(!h.lossless);
1342
1343 let h = &frames[1].header;
1344
1345 assert!(matches!(h.profile, Profile::Profile0));
1346 assert!(matches!(h.bit_depth, BitDepth::Depth8));
1347
1348 assert!(h.subsampling_x);
1349 assert!(h.subsampling_y);
1350
1351 assert!(matches!(h.color_space, ColorSpace::Unknown));
1352 assert!(matches!(
1353 h.color_range,
1354 crate::codec::vp9::parser::ColorRange::StudioSwing
1355 ));
1356
1357 assert!(!h.show_existing_frame);
1358 assert_eq!(h.frame_to_show_map_idx, 0);
1359
1360 assert!(matches!(h.frame_type, FrameType::InterFrame));
1361 assert!(h.show_frame);
1362 assert!(!h.error_resilient_mode);
1363
1364 assert_eq!(h.width, 320);
1365 assert_eq!(h.height, 240);
1366
1367 assert!(!h.render_and_frame_size_different);
1368
1369 assert_eq!(h.render_width, 320);
1370 assert_eq!(h.render_height, 240);
1371
1372 assert!(!h.intra_only);
1373 assert_eq!(h.reset_frame_context, 0);
1374
1375 assert_eq!(h.refresh_frame_flags, 1);
1376 assert_eq!(h.ref_frame_idx, [0, 1, 2]);
1377 assert_eq!(h.ref_frame_sign_bias, [0, 0, 0, 1]);
1378
1379 assert!(!h.allow_high_precision_mv);
1380 assert!(matches!(
1381 h.interpolation_filter,
1382 InterpolationFilter::EightTap
1383 ));
1384
1385 assert!(h.refresh_frame_context);
1386 assert!(h.frame_parallel_decoding_mode);
1387 assert_eq!(h.frame_context_idx, 0);
1388
1389 let lf = &h.lf;
1390 assert_eq!(lf.level, 36);
1391 assert_eq!(lf.sharpness, 0);
1392
1393 assert!(lf.delta_enabled);
1394 assert!(!lf.delta_update);
1395
1396 assert_eq!(lf.update_ref_delta, [true, false, true, true]);
1397 assert_eq!(lf.ref_deltas, [1, 0, -1, -1]);
1398
1399 assert_eq!(lf.update_mode_delta, [false, false]);
1400
1401 let q = &h.quant;
1402
1403 assert_eq!(q.base_q_idx, 216);
1404 assert_eq!(q.delta_q_y_dc, 0);
1405 assert_eq!(q.delta_q_uv_dc, 0);
1406 assert_eq!(q.delta_q_uv_ac, 0);
1407
1408 let s = &h.seg;
1409
1410 assert!(!s.enabled);
1411 assert!(!s.update_map);
1412 assert_eq!(s.tree_probs, [0, 0, 0, 0, 0, 0, 0]);
1413 assert_eq!(s.pred_probs, [0, 0, 0]);
1414 assert!(!s.temporal_update);
1415 assert!(!s.update_data);
1416 assert!(!s.abs_or_delta_update);
1417 assert_eq!(s.feature_enabled, [[false; SEG_LVL_MAX]; MAX_SEGMENTS]);
1418 assert_eq!(s.feature_data, [[0; SEG_LVL_MAX]; MAX_SEGMENTS]);
1419
1420 assert_eq!(h.tile_cols_log2, 0);
1421 assert_eq!(h.tile_rows_log2, 0);
1422 assert_eq!(h.header_size_in_bytes, 9);
1423
1424 assert!(!h.lossless);
1425 }
1426 }
1427 }
1428}