cros_codecs/codec/vp9/
parser.rs

1// Copyright 2022 The ChromiumOS Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::bitstream_utils::BitReader;
6use crate::codec::vp9::lookups::AC_QLOOKUP;
7use crate::codec::vp9::lookups::AC_QLOOKUP_10;
8use crate::codec::vp9::lookups::AC_QLOOKUP_12;
9use crate::codec::vp9::lookups::DC_QLOOKUP;
10use crate::codec::vp9::lookups::DC_QLOOKUP_10;
11use crate::codec::vp9::lookups::DC_QLOOKUP_12;
12
13pub const REFS_PER_FRAME: usize = 3;
14
15pub const MAX_REF_LF_DELTAS: usize = 4;
16pub const MAX_MODE_LF_DELTAS: usize = 2;
17
18pub const INTRA_FRAME: usize = 0;
19pub const LAST_FRAME: usize = 1;
20pub const GOLDEN_FRAME: usize = 2;
21pub const ALTREF_FRAME: usize = 3;
22pub const MAX_REF_FRAMES: usize = 4;
23
24pub const MAX_SEGMENTS: usize = 8;
25pub const SEG_TREE_PROBS: usize = MAX_SEGMENTS - 1;
26pub const PREDICTION_PROBS: usize = 3;
27
28/// Valid segment features values.
29#[repr(u8)]
30pub enum SegLvl {
31    AltQ = 0,
32    AltL = 1,
33    RefFrame = 2,
34    LvlSkip = 3,
35}
36pub const SEG_LVL_MAX: usize = 4;
37
38pub const MAX_LOOP_FILTER: u32 = 63;
39
40pub const REF_FRAMES_LOG2: usize = 3;
41pub const REF_FRAMES: usize = 1 << REF_FRAMES_LOG2;
42
43pub const SUPERFRAME_MARKER: u32 = 0x06;
44pub const MAX_FRAMES_IN_SUPERFRAME: usize = 8;
45
46pub const FRAME_MARKER: u32 = 0x02;
47pub const SYNC_CODE: u32 = 0x498342;
48
49pub const MIN_TILE_WIDTH_B64: u32 = 4;
50pub const MAX_TILE_WIDTH_B64: u32 = 64;
51
52/// The number of pictures in the DPB
53pub const NUM_REF_FRAMES: usize = 8;
54
55#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
56pub enum InterpolationFilter {
57    #[default]
58    EightTap = 0,
59    EightTapSmooth = 1,
60    EightTapSharp = 2,
61    Bilinear = 3,
62    Switchable = 4,
63}
64
65impl TryFrom<u32> for InterpolationFilter {
66    type Error = String;
67
68    fn try_from(value: u32) -> Result<Self, Self::Error> {
69        match value {
70            0 => Ok(InterpolationFilter::EightTap),
71            1 => Ok(InterpolationFilter::EightTapSmooth),
72            2 => Ok(InterpolationFilter::EightTapSharp),
73            3 => Ok(InterpolationFilter::Bilinear),
74            4 => Ok(InterpolationFilter::Switchable),
75            _ => Err(format!("Invalid InterpolationFilter {}", value)),
76        }
77    }
78}
79
80#[derive(Copy, Clone, Debug, PartialEq, Eq)]
81pub enum ReferenceFrameType {
82    Intra = 0,
83    Last = 1,
84    Golden = 2,
85    AltRef = 3,
86}
87
88impl TryFrom<u32> for ReferenceFrameType {
89    type Error = String;
90
91    fn try_from(value: u32) -> Result<Self, Self::Error> {
92        match value {
93            0 => Ok(ReferenceFrameType::Intra),
94            1 => Ok(ReferenceFrameType::Last),
95            2 => Ok(ReferenceFrameType::Golden),
96            3 => Ok(ReferenceFrameType::AltRef),
97            _ => Err(format!("Invalid ReferenceFrameType {}", value)),
98        }
99    }
100}
101
102#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
103pub enum FrameType {
104    #[default]
105    KeyFrame = 0,
106    InterFrame = 1,
107}
108
109impl TryFrom<u8> for FrameType {
110    type Error = String;
111
112    fn try_from(value: u8) -> Result<Self, Self::Error> {
113        match value {
114            0 => Ok(FrameType::KeyFrame),
115            1 => Ok(FrameType::InterFrame),
116            _ => Err(format!("Invalid FrameType {}", value)),
117        }
118    }
119}
120
121#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
122pub enum Profile {
123    #[default]
124    Profile0 = 0,
125    Profile1 = 1,
126    Profile2 = 2,
127    Profile3 = 3,
128}
129
130impl TryFrom<u32> for Profile {
131    type Error = String;
132
133    fn try_from(value: u32) -> Result<Self, Self::Error> {
134        match value {
135            0 => Ok(Profile::Profile0),
136            1 => Ok(Profile::Profile1),
137            2 => Ok(Profile::Profile2),
138            3 => Ok(Profile::Profile3),
139            _ => Err(format!("Invalid Profile {}", value)),
140        }
141    }
142}
143
144#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
145pub enum BitDepth {
146    #[default]
147    Depth8 = 8,
148    Depth10 = 10,
149    Depth12 = 12,
150}
151
152impl TryFrom<u32> for BitDepth {
153    type Error = String;
154
155    fn try_from(value: u32) -> Result<Self, Self::Error> {
156        match value {
157            8 => Ok(BitDepth::Depth8),
158            10 => Ok(BitDepth::Depth10),
159            12 => Ok(BitDepth::Depth12),
160            _ => Err(format!("Invalid BitDepth {}", value)),
161        }
162    }
163}
164
165#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
166pub enum ColorSpace {
167    #[default]
168    Unknown = 0,
169    Bt601 = 1,
170    Bt709 = 2,
171    Smpte170 = 3,
172    Smpte240 = 4,
173    Bt2020 = 5,
174    Reserved2 = 6,
175    CsSrgb = 7,
176}
177
178impl TryFrom<u32> for ColorSpace {
179    type Error = String;
180
181    fn try_from(value: u32) -> Result<Self, Self::Error> {
182        match value {
183            0 => Ok(ColorSpace::Unknown),
184            1 => Ok(ColorSpace::Bt601),
185            2 => Ok(ColorSpace::Bt709),
186            3 => Ok(ColorSpace::Smpte170),
187            4 => Ok(ColorSpace::Smpte240),
188            5 => Ok(ColorSpace::Bt2020),
189            6 => Ok(ColorSpace::Reserved2),
190            7 => Ok(ColorSpace::CsSrgb),
191            _ => Err(format!("Invalid ColorSpace {}", value)),
192        }
193    }
194}
195
196#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
197pub enum ColorRange {
198    #[default]
199    StudioSwing = 0,
200    FullSwing = 1,
201}
202
203impl TryFrom<u32> for ColorRange {
204    type Error = String;
205
206    fn try_from(value: u32) -> Result<Self, Self::Error> {
207        match value {
208            0 => Ok(ColorRange::StudioSwing),
209            1 => Ok(ColorRange::FullSwing),
210            _ => Err(format!("Invalid ColorRange {}", value)),
211        }
212    }
213}
214
215#[derive(Clone, Debug, Default, PartialEq, Eq)]
216pub struct LoopFilterParams {
217    /// Indicates the loop filter strength.
218    pub level: u8,
219    /// Indicates the sharpness level. The loop filter level and loop
220    /// filter_sharpness together determine when a block edge is filtered, and
221    /// by how much the filtering can change the sample values.
222    pub sharpness: u8,
223    /// If set, means that the filter level depends on the mode and reference
224    /// frame used to predict a block. If unset, means that the filter level
225    /// does not depend on the mode and reference frame.
226    pub delta_enabled: bool,
227    /// If set, means that the bitstream contains additional syntax elements
228    /// that specify which mode and reference frame deltas are to be updated. If
229    /// unset, means that these syntax elements are not present.
230    pub delta_update: bool,
231    /// If set, means that the bitstream contains additional syntax elements
232    /// that specify which mode and reference frame deltas are to be updated. If
233    /// unset, means that these syntax elements are not present.
234    pub update_ref_delta: [bool; MAX_REF_LF_DELTAS],
235    /// Contains the adjustment needed for the filter level based on the chosen
236    /// reference frame. If this syntax element is not present in the bitstream,
237    /// it maintains its previous value.
238    pub ref_deltas: [i8; MAX_REF_LF_DELTAS],
239    ///  If set, means that the bitstream contains the syntax element
240    ///  loop_filter_mode_deltas. If unset, means that the bitstream does not
241    ///  contain this syntax element.
242    pub update_mode_delta: [bool; MAX_MODE_LF_DELTAS],
243    /// Contains the adjustment needed for the filter level based on the chosen
244    /// mode. If this syntax element is not present in the bitstream, it
245    /// maintains its previous value.
246    pub mode_deltas: [i8; MAX_MODE_LF_DELTAS],
247}
248
249#[derive(Clone, Debug, Default, PartialEq, Eq)]
250pub struct QuantizationParams {
251    /// Indicates the base frame qindex. This is used for Y AC coefficients and
252    /// as the base value for the other quantizers.
253    pub base_q_idx: u8,
254    /// Indicates the Y DC quantizer relative to base_q_idx.
255    pub delta_q_y_dc: i8,
256    /// Indicates the UV DC quantizer relative to base_q_idx.
257    pub delta_q_uv_dc: i8,
258    /// Indicates the UV AC quantizer relative to base_q_idx.
259    pub delta_q_uv_ac: i8,
260}
261
262#[derive(Clone, Debug, Default, PartialEq, Eq)]
263pub struct SegmentationParams {
264    ///  If set, indicates that this frame makes use of the segmentation tool.
265    ///  If unset, indicates that the frame does not use segmentation.
266    pub enabled: bool,
267    /// If set, indicates that the segmentation map should be updated during
268    /// the decoding of this frame. If unset, means that the segmentation map
269    /// from the previous frame is used.
270    pub update_map: bool,
271    /// Specify the probability values to be used when decoding segment_id.
272    pub tree_probs: [u8; SEG_TREE_PROBS],
273    /// Specify the probability values to be used when decoding seg_id_predicted.
274    pub pred_probs: [u8; PREDICTION_PROBS],
275    /// If set, indicates that the updates to the segmentation map are coded
276    /// relative to the existing segmentation map. If unset,
277    /// indicates that the new segmentation map is coded without
278    /// reference to the existing segmentation map.
279    pub temporal_update: bool,
280    /// If set, indicates that new parameters are about to be specified for each
281    /// segment. If unset, indicates that the segmentation parameters should
282    /// keep their existing values.
283    pub update_data: bool,
284    /// If unset, indicates that the segmentation parameters represent
285    /// adjustments relative to the standard values. If set, indicates that the
286    /// segmentation parameters represent the actual values to be used.
287    pub abs_or_delta_update: bool,
288    /// If unset, indicates that the corresponding feature is unused and has
289    /// value equal to 0. if set, indicates that the feature value is coded in
290    /// the bitstream.
291    pub feature_enabled: [[bool; SEG_LVL_MAX]; MAX_SEGMENTS],
292    /// Specifies the magnitude of the feature data for a segment feature.
293    pub feature_data: [[i16; SEG_LVL_MAX]; MAX_SEGMENTS],
294}
295
296impl SegmentationParams {
297    /// Returns whether `feature` is enabled for `segment_id`.
298    fn is_feature_enabled(&self, segment_id: u8, feature: SegLvl) -> bool {
299        self.feature_enabled[segment_id as usize][feature as usize]
300    }
301
302    /// An implementation of seg_feature_active as per "6.4.9 Segmentation feature active syntax"
303    fn is_feature_active(&self, segment_id: u8, feature: SegLvl) -> bool {
304        self.enabled && self.is_feature_enabled(segment_id, feature)
305    }
306
307    /// Returns the data for `feature` on `segment_id`.
308    fn feature_data(&self, segment_id: u8, feature: SegLvl) -> i16 {
309        self.feature_data[segment_id as usize][feature as usize]
310    }
311}
312
313#[derive(Clone, Debug, Default, PartialEq, Eq)]
314pub struct Segmentation {
315    /// Loop filter level
316    pub lvl_lookup: [[u8; MAX_MODE_LF_DELTAS]; MAX_REF_FRAMES],
317
318    /// AC quant scale for luma component
319    pub luma_ac_quant_scale: i16,
320    /// DC quant scale for luma component
321    pub luma_dc_quant_scale: i16,
322    /// AC quant scale for chroma component
323    pub chroma_ac_quant_scale: i16,
324    /// DC quant scale for chroma component
325    pub chroma_dc_quant_scale: i16,
326
327    /// Whether the alternate reference frame segment feature is enabled (SEG_LVL_REF_FRAME)
328    pub reference_frame_enabled: bool,
329    /// The feature data for the reference frame featire
330    pub reference_frame: i16,
331    /// Whether the skip segment feature is enabled (SEG_LVL_SKIP)
332    pub reference_skip_enabled: bool,
333}
334
335impl Segmentation {
336    /// Update the state of the segmentation parameters after seeing a frame
337    pub fn update_segmentation(segmentation: &mut [Segmentation; MAX_SEGMENTS], hdr: &Header) {
338        let lf = &hdr.lf;
339        let seg = &hdr.seg;
340
341        let n_shift = lf.level >> 5;
342
343        for segment_id in 0..MAX_SEGMENTS as u8 {
344            let luma_dc_quant_scale = hdr.get_dc_quant(segment_id, true);
345            let luma_ac_quant_scale = hdr.get_ac_quant(segment_id, true);
346            let chroma_dc_quant_scale = hdr.get_dc_quant(segment_id, false);
347            let chroma_ac_quant_scale = hdr.get_ac_quant(segment_id, false);
348
349            let mut lvl_lookup: [[u8; MAX_MODE_LF_DELTAS]; MAX_REF_FRAMES];
350
351            if lf.level == 0 {
352                lvl_lookup = Default::default()
353            } else {
354                let mut lvl_seg = i32::from(lf.level);
355
356                // 8.8.1 Loop filter frame init process
357                if hdr.seg.is_feature_active(segment_id, SegLvl::AltL) {
358                    if seg.abs_or_delta_update {
359                        lvl_seg = i32::from(seg.feature_data(segment_id, SegLvl::AltL));
360                    } else {
361                        lvl_seg += i32::from(seg.feature_data(segment_id, SegLvl::AltL));
362                    }
363                }
364
365                let lvl_seg = lvl_seg.clamp(0, MAX_LOOP_FILTER as i32) as u8;
366
367                if !lf.delta_enabled {
368                    lvl_lookup = [[lvl_seg; MAX_MODE_LF_DELTAS]; MAX_REF_FRAMES]
369                } else {
370                    let intra_delta = lf.ref_deltas[INTRA_FRAME] as i32;
371                    let mut intra_lvl = lvl_seg as i32 + (intra_delta << n_shift);
372
373                    lvl_lookup = segmentation[segment_id as usize].lvl_lookup;
374                    lvl_lookup[INTRA_FRAME][0] = intra_lvl.clamp(0, MAX_LOOP_FILTER as i32) as u8;
375
376                    // Note, this array has the [0] element unspecified/unused in
377                    // VP9. Confusing, but we do start to index from 1.
378                    #[allow(clippy::needless_range_loop)]
379                    for ref_ in LAST_FRAME..MAX_REF_FRAMES {
380                        for mode in 0..MAX_MODE_LF_DELTAS {
381                            let ref_delta = lf.ref_deltas[ref_] as i32;
382                            let mode_delta = lf.mode_deltas[mode] as i32;
383
384                            intra_lvl =
385                                lvl_seg as i32 + (ref_delta << n_shift) + (mode_delta << n_shift);
386
387                            lvl_lookup[ref_][mode] =
388                                intra_lvl.clamp(0, MAX_LOOP_FILTER as i32) as u8;
389                        }
390                    }
391                }
392            }
393
394            segmentation[usize::from(segment_id)] = Segmentation {
395                lvl_lookup,
396                luma_ac_quant_scale,
397                luma_dc_quant_scale,
398                chroma_ac_quant_scale,
399                chroma_dc_quant_scale,
400                reference_frame_enabled: seg.is_feature_enabled(segment_id, SegLvl::RefFrame),
401                reference_frame: seg.feature_data(segment_id, SegLvl::RefFrame),
402                reference_skip_enabled: seg.is_feature_enabled(segment_id, SegLvl::LvlSkip),
403            }
404        }
405    }
406}
407
408#[derive(Clone, Debug, Default, PartialEq, Eq)]
409struct FrameSize {
410    width: u32,
411    height: u32,
412}
413
414pub struct Frame<'a> {
415    /// The bitstream data for this frame.
416    bitstream: &'a [u8],
417    /// The frame header.
418    pub header: Header,
419    /// The offset into T
420    offset: usize,
421    /// The size of the data in T
422    size: usize,
423}
424
425impl<'a> Frame<'a> {
426    pub fn new(bitstream: &'a [u8], header: Header, offset: usize, size: usize) -> Self {
427        Self { bitstream, header, offset, size }
428    }
429}
430
431impl<'a> AsRef<[u8]> for Frame<'a> {
432    fn as_ref(&self) -> &[u8] {
433        let data = self.bitstream;
434        &data[self.offset..self.offset + self.size]
435    }
436}
437
438/// A VP9 frame header.
439#[derive(Clone, Debug, Default, PartialEq, Eq)]
440pub struct Header {
441    /// A subset of syntax, semantics and algorithms defined in a part.
442    pub profile: Profile,
443    /// The bit depth of the frame.
444    pub bit_depth: BitDepth,
445    /// Specifies the chroma subsampling format.
446    pub subsampling_x: bool,
447    /// Specifies the chroma subsampling format.
448    pub subsampling_y: bool,
449    /// Specifies the color space of the stream.
450    pub color_space: ColorSpace,
451    /// Specifies the black level and range of the luma and chroma signals as
452    /// specified in Rec. ITU-R BT.709-6 and Rec. ITU-R BT.2020-2
453    pub color_range: ColorRange,
454    /// Indicates the frame indexed by frame_to_show_map_idx is to be displayed.
455    /// If unset, indicates that further processing is required.
456    pub show_existing_frame: bool,
457    /// Specifies the frame to be displayed. It is only available if
458    /// show_existing_frame is set.
459    pub frame_to_show_map_idx: u8,
460    /// Indicates whether a frame is a key frame.
461    pub frame_type: FrameType,
462    /// Whether this frame should be displayed.
463    pub show_frame: bool,
464    /// Whether error resilient mode is enabled.
465    pub error_resilient_mode: bool,
466    /// The width of the frame in pixels.
467    pub width: u32,
468    /// The height of the frame in pixels.
469    pub height: u32,
470    /// If unset, means that the render width and height are inferred from the
471    /// frame width and height. If set, means that the render width and height
472    /// are explicitly coded in the bitstream.
473    pub render_and_frame_size_different: bool,
474    /// The render width of the frame in pixels.
475    pub render_width: u32,
476    /// The render height of the frame in pixels.
477    pub render_height: u32,
478    /// If set, indicates that this frame is an intra-only frame. If unset,
479    /// indicates that this frame is a inter frame.
480    pub intra_only: bool,
481    /// Specifies whether the frame context should be reset to default values.
482    pub reset_frame_context: u8,
483    /// Contains a bitmask that specifies which reference frame slots will be
484    /// updated with the current frame after it is decoded.
485    pub refresh_frame_flags: u8,
486    /// Specifies which reference frames are used by inter frames. It is a
487    /// requirement of bitstream conformance that the selected reference frames
488    /// match the current frame in bit depth, profile, chroma subsampling, and
489    /// color space.
490    pub ref_frame_idx: [u8; REFS_PER_FRAME],
491    /// Specifies the intended direction of the motion vector in time for each
492    /// reference frame. A sign bias equal to 0 indicates that the reference
493    /// frame is a backwards reference; a sign bias equal to 1 indicates that
494    /// the reference frame is a forwards reference
495    pub ref_frame_sign_bias: [u8; 4],
496    /// If unset, specifies that motion vectors are specified to quarter pel
497    /// precision. If set, specifies that motion vectors are specified to eighth
498    /// pel precision.
499    pub allow_high_precision_mv: bool,
500    /// The interpolation filter parameters.
501    pub interpolation_filter: InterpolationFilter,
502    /// If set, indicates that the probabilities computed for this frame (after
503    /// adapting to the observed frequencies if adaption is enabled) should be
504    /// stored for reference by future frames. If unset, indicates that the
505    /// probabilities should be discarded at the end of the frame.
506    pub refresh_frame_context: bool,
507    /// Whether parallel decoding mode is enabled.
508    pub frame_parallel_decoding_mode: bool,
509    /// Indicates the frame context to use.
510    pub frame_context_idx: u8,
511    /// The loop filter parameters
512    pub lf: LoopFilterParams,
513    /// The quantization parameters.
514    pub quant: QuantizationParams,
515    /// The segmentation parameters
516    pub seg: SegmentationParams,
517    /// Specifies the base 2 logarithm of the width of each tile (where the
518    /// width is measured in units of 8x8 blocks). It is a requirement of
519    /// bitstream conformance that tile_cols_log2 is less than or equal to 6.
520    pub tile_cols_log2: u8,
521    /// Specifies the base 2 logarithm of the height of each tile (where the
522    /// height is measured in units of 8x8 blocks).
523    pub tile_rows_log2: u8,
524    /// Computed from the syntax elements. If set, indicates that the frame is
525    /// coded using a special 4x4 transform designed for encoding frames that
526    /// are bit-identical with the original frames.
527    pub lossless: bool,
528    /// Indicates the size of the compressed header in bytes.
529    pub header_size_in_bytes: u16,
530    /// Indicates the size of the uncompressed header in bytes.
531    pub uncompressed_header_size_in_bytes: u16,
532}
533
534impl Header {
535    /// An implementation of get_qindex as per "8.6.1 Dequantization functions"
536    fn get_qindex(&self, segment_id: u8) -> u8 {
537        let base_q_idx = self.quant.base_q_idx;
538
539        if self.seg.is_feature_active(segment_id, SegLvl::AltQ) {
540            let mut data = self.seg.feature_data(segment_id, SegLvl::AltQ) as i32;
541
542            if !self.seg.abs_or_delta_update {
543                data += base_q_idx as i32;
544            }
545
546            data.clamp(0, 255) as u8
547        } else {
548            base_q_idx
549        }
550    }
551
552    /// An implementation of get_dc_quant as per "8.6.1 Dequantization functions"
553    fn get_dc_quant(&self, segment_id: u8, luma: bool) -> i16 {
554        let delta_q_dc =
555            if luma { self.quant.delta_q_y_dc } else { self.quant.delta_q_uv_dc } as i32;
556        let qindex = self.get_qindex(segment_id);
557        let q_table_idx = (qindex as i32 + delta_q_dc).clamp(0, 255) as u8;
558
559        let table = match self.bit_depth {
560            BitDepth::Depth8 => &DC_QLOOKUP,
561            BitDepth::Depth10 => &DC_QLOOKUP_10,
562            BitDepth::Depth12 => &DC_QLOOKUP_12,
563        };
564
565        table[q_table_idx as usize]
566    }
567
568    /// An implementation of get_ac_quant as per "8.6.1 Dequantization functions"
569    fn get_ac_quant(&self, segment_id: u8, luma: bool) -> i16 {
570        let delta_q_ac = if luma { 0 } else { self.quant.delta_q_uv_ac } as i32;
571        let qindex = self.get_qindex(segment_id);
572        let q_table_idx = (qindex as i32 + delta_q_ac).clamp(0, 255) as u8;
573
574        let table = match self.bit_depth {
575            BitDepth::Depth8 => &AC_QLOOKUP,
576            BitDepth::Depth10 => &AC_QLOOKUP_10,
577            BitDepth::Depth12 => &AC_QLOOKUP_12,
578        };
579
580        table[q_table_idx as usize]
581    }
582}
583
584/// The VP9 superframe header as per Annex B, B.2.1, B.2.2
585struct SuperframeHeader {
586    /// Indicates the number of frames within this superframe. NOTE - It is
587    /// legal for a superframe to contain just a single frame and have NumFrames
588    /// equal to 1.
589    frames_in_superframe: u32,
590    /// Specifies the size in bytes of frame number i (zero indexed) within this
591    /// superframe.
592    frame_sizes: Vec<usize>,
593}
594
595/// A VP9 bitstream parser.
596#[derive(Clone, Debug, Default, PartialEq, Eq)]
597pub struct Parser {
598    bit_depth: BitDepth,
599    subsampling_x: bool,
600    subsampling_y: bool,
601    color_space: ColorSpace,
602    color_range: ColorRange,
603
604    mi_cols: u32,
605    mi_rows: u32,
606    sb64_cols: u32,
607    sb64_rows: u32,
608
609    lf: LoopFilterParams,
610    seg: SegmentationParams,
611
612    reference_frame_sz: [FrameSize; REF_FRAMES],
613}
614
615impl Parser {
616    fn parse_superframe_hdr(resource: impl AsRef<[u8]>) -> Result<SuperframeHeader, String> {
617        let bitstream = resource.as_ref();
618
619        // Skip to the end of the chunk.
620        let mut reader = BitReader::new(&bitstream[bitstream.len() - 1..], false);
621
622        // Try reading a superframe marker.
623        let marker = reader.read_bits::<u32>(3)?;
624
625        if marker != SUPERFRAME_MARKER {
626            // Not a superframe
627            return Ok(SuperframeHeader {
628                frames_in_superframe: 1,
629                frame_sizes: vec![bitstream.len()],
630            });
631        }
632
633        let bytes_per_framesize = reader.read_bits::<u32>(2)? + 1;
634        let frames_in_superframe = reader.read_bits::<u32>(3)? + 1;
635
636        if frames_in_superframe > MAX_FRAMES_IN_SUPERFRAME as u32 {
637            return Err(format!(
638                "Broken stream: too many frames in superframe, expected a maximum of {:?}, found {:?}",
639                MAX_FRAMES_IN_SUPERFRAME,
640                frames_in_superframe
641            ));
642        }
643
644        let sz_index = 2 + frames_in_superframe * bytes_per_framesize;
645
646        let data = resource.as_ref();
647        let index_offset = data.len() - sz_index as usize;
648        let first_byte = data[index_offset];
649        let last_byte = *data.last().ok_or_else(|| String::from("superframe header is empty"))?;
650
651        if first_byte != last_byte {
652            // Also not a superframe, we must pass both tests as per the specification.
653            return Ok(SuperframeHeader {
654                frames_in_superframe: 1,
655                frame_sizes: vec![bitstream.len()],
656            });
657        }
658
659        let mut frame_sizes = vec![];
660        let mut reader = BitReader::new(&bitstream[index_offset..], false);
661
662        // Skip the superframe header.
663        let _ = reader.read_bits::<u32>(8)?;
664
665        for _ in 0..frames_in_superframe {
666            let mut frame_size = 0;
667
668            for j in 0..bytes_per_framesize {
669                frame_size |= reader.read_bits::<u32>(8)? << (j * 8);
670            }
671
672            frame_sizes.push(frame_size as usize);
673        }
674
675        Ok(SuperframeHeader { frames_in_superframe, frame_sizes })
676    }
677
678    fn read_signed_8(r: &mut BitReader, nbits: u8) -> Result<i8, String> {
679        let value = r.read_bits::<u8>(nbits as usize)?;
680        let negative = r.read_bit()?;
681
682        if negative {
683            Ok(-(value as i8))
684        } else {
685            Ok(value as i8)
686        }
687    }
688
689    fn parse_frame_marker(r: &mut BitReader) -> Result<(), String> {
690        let marker = r.read_bits::<u32>(2)?;
691
692        if marker != FRAME_MARKER {
693            return Err(format!("Broken stream: expected frame marker, found {:?}", marker));
694        }
695
696        Ok(())
697    }
698
699    fn parse_profile(r: &mut BitReader) -> Result<Profile, String> {
700        let low = r.read_bits::<u32>(1)?;
701        let high = r.read_bits::<u32>(1)?;
702
703        let profile = (high << 1) | low;
704
705        if profile == 3 {
706            // Skip the reserved bit
707            let _ = r.read_bit()?;
708        }
709
710        Profile::try_from(profile)
711    }
712
713    fn parse_frame_sync_code(r: &mut BitReader) -> Result<(), String> {
714        let sync_code = r.read_bits::<u32>(24)?;
715
716        if sync_code != SYNC_CODE {
717            return Err(format!(
718                "Broken stream: expected sync code == {:?}, found {:?}",
719                SYNC_CODE, sync_code
720            ));
721        }
722
723        Ok(())
724    }
725
726    fn parse_color_config(&mut self, r: &mut BitReader, hdr: &mut Header) -> Result<(), String> {
727        if matches!(hdr.profile, Profile::Profile2 | Profile::Profile3) {
728            let ten_or_twelve_bit = r.read_bit()?;
729            if ten_or_twelve_bit {
730                hdr.bit_depth = BitDepth::Depth12;
731            } else {
732                hdr.bit_depth = BitDepth::Depth10
733            }
734        } else {
735            hdr.bit_depth = BitDepth::Depth8;
736        }
737
738        let color_space = r.read_bits::<u32>(3)?;
739        hdr.color_space = ColorSpace::try_from(color_space)?;
740
741        if !matches!(hdr.color_space, ColorSpace::CsSrgb) {
742            let color_range = r.read_bits::<u32>(1)?;
743
744            hdr.color_range = ColorRange::try_from(color_range)?;
745
746            if matches!(hdr.profile, Profile::Profile1 | Profile::Profile3) {
747                hdr.subsampling_x = r.read_bit()?;
748                hdr.subsampling_y = r.read_bit()?;
749
750                // Skip the reserved bit
751                let _ = r.read_bit()?;
752            } else {
753                hdr.subsampling_x = true;
754                hdr.subsampling_y = true;
755            }
756        } else {
757            hdr.color_range = ColorRange::FullSwing;
758            if matches!(hdr.profile, Profile::Profile1 | Profile::Profile3) {
759                hdr.subsampling_x = false;
760                hdr.subsampling_y = false;
761
762                // Skip the reserved bit
763                let _ = r.read_bit()?;
764            }
765        }
766
767        self.bit_depth = hdr.bit_depth;
768        self.color_space = hdr.color_space;
769        self.subsampling_x = hdr.subsampling_x;
770        self.subsampling_y = hdr.subsampling_y;
771        self.color_range = hdr.color_range;
772
773        Ok(())
774    }
775
776    fn compute_image_size(&mut self, width: u32, height: u32) {
777        self.mi_cols = (width + 7) >> 3;
778        self.mi_rows = (height + 7) >> 3;
779        self.sb64_cols = (self.mi_cols + 7) >> 3;
780        self.sb64_rows = (self.mi_rows + 7) >> 3;
781    }
782
783    fn parse_frame_size(&mut self, r: &mut BitReader, hdr: &mut Header) -> Result<(), String> {
784        hdr.width = r.read_bits::<u32>(16)? + 1;
785        hdr.height = r.read_bits::<u32>(16)? + 1;
786        self.compute_image_size(hdr.width, hdr.height);
787        Ok(())
788    }
789
790    fn parse_render_size(r: &mut BitReader, hdr: &mut Header) -> Result<(), String> {
791        hdr.render_and_frame_size_different = r.read_bit()?;
792        if hdr.render_and_frame_size_different {
793            hdr.render_width = r.read_bits::<u32>(16)? + 1;
794            hdr.render_height = r.read_bits::<u32>(16)? + 1;
795        } else {
796            hdr.render_width = hdr.width;
797            hdr.render_height = hdr.height;
798        }
799
800        Ok(())
801    }
802
803    fn parse_frame_size_with_refs(
804        &mut self,
805        r: &mut BitReader,
806        hdr: &mut Header,
807    ) -> Result<(), String> {
808        let mut found_ref = false;
809
810        for i in 0..REFS_PER_FRAME {
811            found_ref = r.read_bit()?;
812
813            if found_ref {
814                let idx = hdr.ref_frame_idx[i] as usize;
815                hdr.width = self.reference_frame_sz[idx].width;
816                hdr.height = self.reference_frame_sz[idx].height;
817                break;
818            }
819        }
820
821        if !found_ref {
822            self.parse_frame_size(r, hdr)?;
823        } else {
824            self.compute_image_size(hdr.width, hdr.height)
825        }
826
827        Self::parse_render_size(r, hdr)
828    }
829
830    fn read_interpolation_filter(r: &mut BitReader) -> Result<InterpolationFilter, String> {
831        const LITERAL_TO_TYPE: [InterpolationFilter; 4] = [
832            InterpolationFilter::EightTapSmooth,
833            InterpolationFilter::EightTap,
834            InterpolationFilter::EightTapSharp,
835            InterpolationFilter::Bilinear,
836        ];
837
838        let is_filter_switchable = r.read_bit()?;
839
840        Ok(if is_filter_switchable {
841            InterpolationFilter::Switchable
842        } else {
843            let raw_interpolation_filter = r.read_bits::<u32>(2)?;
844            LITERAL_TO_TYPE[raw_interpolation_filter as usize]
845        })
846    }
847
848    fn setup_past_independence(&mut self, hdr: &mut Header) {
849        self.seg.feature_enabled = Default::default();
850        self.seg.feature_data = Default::default();
851        self.seg.abs_or_delta_update = false;
852
853        self.lf.delta_enabled = true;
854        self.lf.ref_deltas[ReferenceFrameType::Intra as usize] = 1;
855        self.lf.ref_deltas[ReferenceFrameType::Last as usize] = 0;
856        self.lf.ref_deltas[ReferenceFrameType::Golden as usize] = -1;
857        self.lf.ref_deltas[ReferenceFrameType::AltRef as usize] = -1;
858
859        self.lf.mode_deltas = Default::default();
860        hdr.ref_frame_sign_bias = Default::default();
861    }
862
863    fn parse_loop_filter_params(
864        r: &mut BitReader,
865        lf: &mut LoopFilterParams,
866    ) -> Result<(), String> {
867        lf.level = r.read_bits::<u8>(6)?;
868        lf.sharpness = r.read_bits::<u8>(3)?;
869        lf.delta_enabled = r.read_bit()?;
870
871        if lf.delta_enabled {
872            lf.delta_update = r.read_bit()?;
873            if lf.delta_update {
874                for i in 0..MAX_REF_LF_DELTAS {
875                    lf.update_ref_delta[i] = r.read_bit()?;
876                    if lf.update_ref_delta[i] {
877                        lf.ref_deltas[i] = Self::read_signed_8(r, 6)?;
878                    }
879                }
880
881                for i in 0..MAX_MODE_LF_DELTAS {
882                    lf.update_mode_delta[i] = r.read_bit()?;
883                    if lf.update_mode_delta[i] {
884                        lf.mode_deltas[i] = Self::read_signed_8(r, 6)?;
885                    }
886                }
887            }
888        }
889
890        Ok(())
891    }
892
893    fn read_delta_q(r: &mut BitReader, value: &mut i8) -> Result<(), String> {
894        let delta_coded = r.read_bit()?;
895
896        if delta_coded {
897            *value = Self::read_signed_8(r, 4)?;
898        } else {
899            *value = 0;
900        }
901
902        Ok(())
903    }
904
905    fn parse_quantization_params(r: &mut BitReader, hdr: &mut Header) -> Result<(), String> {
906        let quant = &mut hdr.quant;
907
908        quant.base_q_idx = r.read_bits::<u8>(8)?;
909
910        Self::read_delta_q(r, &mut quant.delta_q_y_dc)?;
911        Self::read_delta_q(r, &mut quant.delta_q_uv_dc)?;
912        Self::read_delta_q(r, &mut quant.delta_q_uv_ac)?;
913
914        hdr.lossless = quant.base_q_idx == 0
915            && quant.delta_q_y_dc == 0
916            && quant.delta_q_uv_dc == 0
917            && quant.delta_q_uv_ac == 0;
918
919        Ok(())
920    }
921
922    fn read_prob(r: &mut BitReader) -> Result<u8, String> {
923        let prob_coded = r.read_bit()?;
924
925        let prob = if prob_coded { r.read_bits::<u8>(8)? } else { 255 };
926
927        Ok(prob)
928    }
929
930    fn parse_segmentation_params(
931        r: &mut BitReader,
932        seg: &mut SegmentationParams,
933    ) -> Result<(), String> {
934        const SEGMENTATION_FEATURE_BITS: [u8; SEG_LVL_MAX] = [8, 6, 2, 0];
935        const SEGMENTATION_FEATURE_SIGNED: [bool; SEG_LVL_MAX] = [true, true, false, false];
936
937        seg.update_map = false;
938        seg.update_data = false;
939
940        seg.enabled = r.read_bit()?;
941
942        if !seg.enabled {
943            return Ok(());
944        }
945
946        seg.update_map = r.read_bit()?;
947
948        if seg.update_map {
949            for i in 0..SEG_TREE_PROBS {
950                seg.tree_probs[i] = Self::read_prob(r)?;
951            }
952
953            seg.temporal_update = r.read_bit()?;
954
955            for i in 0..PREDICTION_PROBS {
956                seg.pred_probs[i] = if seg.temporal_update { Self::read_prob(r)? } else { 255 };
957            }
958        }
959
960        seg.update_data = r.read_bit()?;
961
962        if seg.update_data {
963            seg.abs_or_delta_update = r.read_bit()?;
964            for i in 0..MAX_SEGMENTS {
965                for j in 0..SEG_LVL_MAX {
966                    seg.feature_enabled[i][j] = r.read_bit()?;
967                    if seg.feature_enabled[i][j] {
968                        let bits_to_read = SEGMENTATION_FEATURE_BITS[j];
969                        let mut feature_value = r.read_bits_signed::<i16>(bits_to_read as usize)?;
970
971                        if SEGMENTATION_FEATURE_SIGNED[j] {
972                            let feature_sign = r.read_bit()?;
973
974                            if feature_sign {
975                                feature_value = -feature_value;
976                            }
977                        }
978
979                        seg.feature_data[i][j] = feature_value;
980                    }
981                }
982            }
983        }
984
985        Ok(())
986    }
987
988    fn calc_min_log2_tile_cols(sb64_cols: u32) -> u8 {
989        let mut min_log2 = 0;
990
991        while (MAX_TILE_WIDTH_B64 << min_log2) < sb64_cols {
992            min_log2 += 1;
993        }
994
995        min_log2
996    }
997
998    fn calc_max_log2_tile_cols(sb64_cols: u32) -> u8 {
999        let mut max_log2 = 1;
1000
1001        while (sb64_cols >> max_log2) >= MIN_TILE_WIDTH_B64 {
1002            max_log2 += 1;
1003        }
1004
1005        max_log2 - 1
1006    }
1007
1008    fn parse_tile_info(&self, r: &mut BitReader, hdr: &mut Header) -> Result<(), String> {
1009        let max_log2_tile_cols = Self::calc_max_log2_tile_cols(self.sb64_cols);
1010
1011        hdr.tile_cols_log2 = Self::calc_min_log2_tile_cols(self.sb64_cols);
1012
1013        while hdr.tile_cols_log2 < max_log2_tile_cols {
1014            let increment_tile_cols_log2 = r.read_bit()?;
1015
1016            if increment_tile_cols_log2 {
1017                hdr.tile_cols_log2 += 1;
1018            } else {
1019                break;
1020            }
1021        }
1022
1023        hdr.tile_rows_log2 = r.read_bits::<u8>(1)?;
1024
1025        if hdr.tile_rows_log2 > 0 {
1026            let increment_tile_rows_log2 = r.read_bit()?;
1027            hdr.tile_rows_log2 += increment_tile_rows_log2 as u8;
1028        }
1029
1030        Ok(())
1031    }
1032
1033    fn parse_frame_header(
1034        &mut self,
1035        resource: impl AsRef<[u8]>,
1036        offset: usize,
1037    ) -> Result<Header, String> {
1038        let data = &resource.as_ref()[offset..];
1039        let mut r = BitReader::new(data, false);
1040        let mut hdr = Header::default();
1041
1042        Self::parse_frame_marker(&mut r)?;
1043        hdr.profile = Self::parse_profile(&mut r)?;
1044
1045        hdr.show_existing_frame = r.read_bit()?;
1046
1047        if hdr.show_existing_frame {
1048            hdr.frame_to_show_map_idx = r.read_bits::<u8>(3)?;
1049            return Ok(hdr);
1050        }
1051
1052        hdr.frame_type = FrameType::try_from(r.read_bits::<u8>(1)?)?;
1053
1054        hdr.show_frame = r.read_bit()?;
1055        hdr.error_resilient_mode = r.read_bit()?;
1056
1057        let frame_is_intra;
1058
1059        if matches!(hdr.frame_type, FrameType::KeyFrame) {
1060            Self::parse_frame_sync_code(&mut r)?;
1061            self.parse_color_config(&mut r, &mut hdr)?;
1062            self.parse_frame_size(&mut r, &mut hdr)?;
1063            Self::parse_render_size(&mut r, &mut hdr)?;
1064            hdr.refresh_frame_flags = 0xff;
1065            frame_is_intra = true;
1066        } else {
1067            if !hdr.show_frame {
1068                hdr.intra_only = r.read_bit()?;
1069            }
1070
1071            frame_is_intra = hdr.intra_only;
1072
1073            if !hdr.error_resilient_mode {
1074                hdr.reset_frame_context = r.read_bits::<u8>(2)?;
1075            } else {
1076                hdr.reset_frame_context = 0;
1077            }
1078
1079            if hdr.intra_only {
1080                Self::parse_frame_sync_code(&mut r)?;
1081
1082                if !matches!(hdr.profile, Profile::Profile0) {
1083                    self.parse_color_config(&mut r, &mut hdr)?;
1084                } else {
1085                    hdr.color_space = ColorSpace::Bt601;
1086                    hdr.subsampling_x = true;
1087                    hdr.subsampling_y = true;
1088                    hdr.bit_depth = BitDepth::Depth8;
1089
1090                    self.color_space = hdr.color_space;
1091                    self.subsampling_x = hdr.subsampling_x;
1092                    self.subsampling_y = hdr.subsampling_y;
1093                    self.bit_depth = hdr.bit_depth;
1094                }
1095
1096                hdr.refresh_frame_flags = r.read_bits::<u8>(8)?;
1097                self.parse_frame_size(&mut r, &mut hdr)?;
1098                Self::parse_render_size(&mut r, &mut hdr)?;
1099            } else {
1100                // Copy from our cached version
1101                hdr.color_space = self.color_space;
1102                hdr.color_range = self.color_range;
1103                hdr.subsampling_x = self.subsampling_x;
1104                hdr.subsampling_y = self.subsampling_y;
1105                hdr.bit_depth = self.bit_depth;
1106
1107                hdr.refresh_frame_flags = r.read_bits::<u8>(8)?;
1108
1109                for i in 0..REFS_PER_FRAME {
1110                    hdr.ref_frame_idx[i] = r.read_bits::<u8>(3)?;
1111                    hdr.ref_frame_sign_bias[ReferenceFrameType::Last as usize + i] =
1112                        r.read_bits::<u8>(1)?;
1113                }
1114
1115                self.parse_frame_size_with_refs(&mut r, &mut hdr)?;
1116                hdr.allow_high_precision_mv = r.read_bit()?;
1117                hdr.interpolation_filter = Self::read_interpolation_filter(&mut r)?;
1118            }
1119        }
1120
1121        if !hdr.error_resilient_mode {
1122            hdr.refresh_frame_context = r.read_bit()?;
1123            hdr.frame_parallel_decoding_mode = r.read_bit()?;
1124        } else {
1125            hdr.refresh_frame_context = false;
1126            hdr.frame_parallel_decoding_mode = true;
1127        }
1128
1129        hdr.frame_context_idx = r.read_bits::<u8>(2)?;
1130
1131        if frame_is_intra || hdr.error_resilient_mode {
1132            self.setup_past_independence(&mut hdr);
1133        }
1134
1135        Self::parse_loop_filter_params(&mut r, &mut self.lf)?;
1136        Self::parse_quantization_params(&mut r, &mut hdr)?;
1137        Self::parse_segmentation_params(&mut r, &mut self.seg)?;
1138        self.parse_tile_info(&mut r, &mut hdr)?;
1139
1140        hdr.header_size_in_bytes = r.read_bits::<u16>(16)?;
1141
1142        hdr.lf = self.lf.clone();
1143        hdr.seg = self.seg.clone();
1144
1145        for i in 0..REF_FRAMES {
1146            let flag = 1 << i;
1147            if hdr.refresh_frame_flags & flag != 0 {
1148                self.reference_frame_sz[i].width = hdr.width;
1149                self.reference_frame_sz[i].height = hdr.height;
1150            }
1151        }
1152
1153        hdr.uncompressed_header_size_in_bytes = (r.position() as u16 + 7) / 8;
1154
1155        Ok(hdr)
1156    }
1157
1158    /// Parse a single VP9 frame.
1159    pub fn parse_frame<'a>(
1160        &mut self,
1161        bitstream: &'a [u8],
1162        offset: usize,
1163        size: usize,
1164    ) -> Result<Frame<'a>, String> {
1165        let header = self.parse_frame_header(bitstream, offset)?;
1166
1167        Ok(Frame { header, bitstream, offset, size })
1168    }
1169
1170    /// Parses VP9 frames from the data in `resource`. This can result in more than one frame if the
1171    /// data passed in contains a VP9 superframe.
1172    pub fn parse_chunk<'a>(&mut self, resource: &'a [u8]) -> Result<Vec<Frame<'a>>, String> {
1173        let superframe_hdr = Parser::parse_superframe_hdr(resource)?;
1174        let mut offset = 0;
1175
1176        let mut frames = vec![];
1177
1178        for i in 0..superframe_hdr.frames_in_superframe {
1179            let frame_sz = superframe_hdr.frame_sizes[i as usize];
1180            let frame = self.parse_frame(resource, offset, frame_sz)?;
1181            offset += frame_sz;
1182            frames.push(frame);
1183        }
1184
1185        Ok(frames)
1186    }
1187}
1188
1189#[cfg(test)]
1190mod tests {
1191    use crate::bitstream_utils::IvfIterator;
1192    use crate::codec::vp9::parser::BitDepth;
1193    use crate::codec::vp9::parser::ColorSpace;
1194    use crate::codec::vp9::parser::FrameType;
1195    use crate::codec::vp9::parser::InterpolationFilter;
1196    use crate::codec::vp9::parser::Parser;
1197    use crate::codec::vp9::parser::Profile;
1198    use crate::codec::vp9::parser::MAX_SEGMENTS;
1199    use crate::codec::vp9::parser::SEG_LVL_MAX;
1200
1201    #[test]
1202    fn test_parse_superframe() {
1203        // Demuxed, raw vp9 superframe
1204        const VP9_TEST_SUPERFRAME: &[u8] = include_bytes!("test_data/vp9-superframe.bin");
1205
1206        let mut parser = Parser::default();
1207        let frames = parser.parse_chunk(VP9_TEST_SUPERFRAME).expect("Parsing a superframe failed");
1208
1209        assert_eq!(frames.len(), 2);
1210        assert_eq!(frames[0].offset, 0);
1211        assert_eq!(frames[0].size, 1333);
1212        assert_eq!(frames[1].offset, 1333);
1213        assert_eq!(frames[1].size, 214);
1214    }
1215
1216    #[test]
1217    fn test_parse_test25fps() {
1218        // Muxed as IVF
1219        const TEST_STREAM: &[u8] = include_bytes!("test_data/test-25fps.vp9");
1220
1221        let mut parser = Parser::default();
1222        let ivf_iter = IvfIterator::new(TEST_STREAM);
1223
1224        for (frame_n, packet) in ivf_iter.enumerate() {
1225            let frames = parser.parse_chunk(packet.as_ref()).expect("Parsing a superframe failed");
1226
1227            if frame_n == 0 {
1228                assert_eq!(frames.len(), 1);
1229                let h = &frames[0].header;
1230
1231                assert!(matches!(h.profile, Profile::Profile0));
1232                assert!(matches!(h.bit_depth, BitDepth::Depth8));
1233
1234                assert!(h.subsampling_x);
1235                assert!(h.subsampling_y);
1236
1237                assert!(matches!(h.color_space, ColorSpace::Unknown));
1238                assert!(matches!(
1239                    h.color_range,
1240                    crate::codec::vp9::parser::ColorRange::StudioSwing
1241                ));
1242
1243                assert!(!h.show_existing_frame);
1244                assert_eq!(h.frame_to_show_map_idx, 0);
1245
1246                assert!(matches!(h.frame_type, FrameType::KeyFrame));
1247                assert!(h.show_frame);
1248                assert!(!h.error_resilient_mode);
1249
1250                assert_eq!(h.width, 320);
1251                assert_eq!(h.height, 240);
1252
1253                assert!(!h.render_and_frame_size_different);
1254
1255                assert_eq!(h.render_width, 320);
1256                assert_eq!(h.render_height, 240);
1257
1258                assert!(!h.intra_only);
1259                assert_eq!(h.reset_frame_context, 0);
1260
1261                assert_eq!(h.refresh_frame_flags, 0xff);
1262                assert_eq!(h.ref_frame_idx, [0, 0, 0]);
1263                assert_eq!(h.ref_frame_sign_bias, [0, 0, 0, 0]);
1264
1265                assert!(!h.allow_high_precision_mv);
1266                assert!(matches!(h.interpolation_filter, InterpolationFilter::EightTap));
1267
1268                assert!(h.refresh_frame_context);
1269                assert!(h.frame_parallel_decoding_mode);
1270                assert_eq!(h.frame_context_idx, 0);
1271
1272                let lf = &h.lf;
1273                assert_eq!(lf.level, 9);
1274                assert_eq!(lf.sharpness, 0);
1275
1276                assert!(lf.delta_enabled);
1277                assert!(lf.delta_update);
1278
1279                assert_eq!(lf.update_ref_delta, [true, false, true, true]);
1280                assert_eq!(lf.ref_deltas, [1, 0, -1, -1]);
1281
1282                assert_eq!(lf.update_mode_delta, [false, false]);
1283
1284                let q = &h.quant;
1285
1286                assert_eq!(q.base_q_idx, 65);
1287                assert_eq!(q.delta_q_y_dc, 0);
1288                assert_eq!(q.delta_q_uv_dc, 0);
1289                assert_eq!(q.delta_q_uv_ac, 0);
1290
1291                let s = &h.seg;
1292
1293                assert!(!s.enabled);
1294                assert!(!s.update_map);
1295                assert_eq!(s.tree_probs, [0, 0, 0, 0, 0, 0, 0]);
1296                assert_eq!(s.pred_probs, [0, 0, 0]);
1297                assert!(!s.temporal_update);
1298                assert!(!s.update_data);
1299                assert!(!s.abs_or_delta_update);
1300                assert_eq!(s.feature_enabled, [[false; SEG_LVL_MAX]; MAX_SEGMENTS]);
1301                assert_eq!(s.feature_data, [[0; SEG_LVL_MAX]; MAX_SEGMENTS]);
1302
1303                assert_eq!(h.tile_cols_log2, 0);
1304                assert_eq!(h.tile_rows_log2, 0);
1305                assert_eq!(h.header_size_in_bytes, 120);
1306
1307                assert!(!h.lossless);
1308            } else if frame_n == 1 {
1309                assert_eq!(frames.len(), 2);
1310
1311                assert_eq!(frames[0].offset, 0);
1312                assert_eq!(frames[0].size, 2390);
1313                assert_eq!(frames[1].offset, 2390);
1314                assert_eq!(frames[1].size, 108);
1315
1316                let h = &frames[0].header;
1317
1318                assert!(matches!(h.profile, Profile::Profile0));
1319                assert!(matches!(h.bit_depth, BitDepth::Depth8));
1320
1321                assert!(h.subsampling_x);
1322                assert!(h.subsampling_y);
1323
1324                assert!(matches!(h.color_space, ColorSpace::Unknown));
1325                assert!(matches!(
1326                    h.color_range,
1327                    crate::codec::vp9::parser::ColorRange::StudioSwing
1328                ));
1329
1330                assert!(!h.show_existing_frame);
1331                assert_eq!(h.frame_to_show_map_idx, 0);
1332
1333                assert!(matches!(h.frame_type, FrameType::InterFrame));
1334                assert!(!h.show_frame);
1335                assert!(!h.error_resilient_mode);
1336
1337                assert_eq!(h.width, 320);
1338                assert_eq!(h.height, 240);
1339
1340                assert!(!h.render_and_frame_size_different);
1341
1342                assert_eq!(h.render_width, 320);
1343                assert_eq!(h.render_height, 240);
1344
1345                assert!(!h.intra_only);
1346                assert_eq!(h.reset_frame_context, 0);
1347
1348                assert_eq!(h.refresh_frame_flags, 4);
1349                assert_eq!(h.ref_frame_idx, [0, 1, 2]);
1350                assert_eq!(h.ref_frame_sign_bias, [0, 0, 0, 0]);
1351
1352                assert!(h.allow_high_precision_mv);
1353                assert!(matches!(h.interpolation_filter, InterpolationFilter::EightTap));
1354
1355                assert!(h.refresh_frame_context);
1356                assert!(h.frame_parallel_decoding_mode);
1357                assert_eq!(h.frame_context_idx, 1);
1358
1359                let lf = &h.lf;
1360                assert_eq!(lf.level, 15);
1361                assert_eq!(lf.sharpness, 0);
1362
1363                assert!(lf.delta_enabled);
1364                assert!(!lf.delta_update);
1365
1366                assert_eq!(lf.update_ref_delta, [true, false, true, true]);
1367                assert_eq!(lf.ref_deltas, [1, 0, -1, -1]);
1368
1369                assert_eq!(lf.update_mode_delta, [false, false]);
1370
1371                let q = &h.quant;
1372
1373                assert_eq!(q.base_q_idx, 112);
1374                assert_eq!(q.delta_q_y_dc, 0);
1375                assert_eq!(q.delta_q_uv_dc, 0);
1376                assert_eq!(q.delta_q_uv_ac, 0);
1377
1378                let s = &h.seg;
1379
1380                assert!(!s.enabled);
1381                assert!(!s.update_map);
1382                assert_eq!(s.tree_probs, [0, 0, 0, 0, 0, 0, 0]);
1383                assert_eq!(s.pred_probs, [0, 0, 0]);
1384                assert!(!s.temporal_update);
1385                assert!(!s.update_data);
1386                assert!(!s.abs_or_delta_update);
1387                assert_eq!(s.feature_enabled, [[false; SEG_LVL_MAX]; MAX_SEGMENTS]);
1388                assert_eq!(s.feature_data, [[0; SEG_LVL_MAX]; MAX_SEGMENTS]);
1389
1390                assert_eq!(h.tile_cols_log2, 0);
1391                assert_eq!(h.tile_rows_log2, 0);
1392                assert_eq!(h.header_size_in_bytes, 48);
1393
1394                assert!(!h.lossless);
1395
1396                let h = &frames[1].header;
1397
1398                assert!(matches!(h.profile, Profile::Profile0));
1399                assert!(matches!(h.bit_depth, BitDepth::Depth8));
1400
1401                assert!(h.subsampling_x);
1402                assert!(h.subsampling_y);
1403
1404                assert!(matches!(h.color_space, ColorSpace::Unknown));
1405                assert!(matches!(
1406                    h.color_range,
1407                    crate::codec::vp9::parser::ColorRange::StudioSwing
1408                ));
1409
1410                assert!(!h.show_existing_frame);
1411                assert_eq!(h.frame_to_show_map_idx, 0);
1412
1413                assert!(matches!(h.frame_type, FrameType::InterFrame));
1414                assert!(h.show_frame);
1415                assert!(!h.error_resilient_mode);
1416
1417                assert_eq!(h.width, 320);
1418                assert_eq!(h.height, 240);
1419
1420                assert!(!h.render_and_frame_size_different);
1421
1422                assert_eq!(h.render_width, 320);
1423                assert_eq!(h.render_height, 240);
1424
1425                assert!(!h.intra_only);
1426                assert_eq!(h.reset_frame_context, 0);
1427
1428                assert_eq!(h.refresh_frame_flags, 1);
1429                assert_eq!(h.ref_frame_idx, [0, 1, 2]);
1430                assert_eq!(h.ref_frame_sign_bias, [0, 0, 0, 1]);
1431
1432                assert!(!h.allow_high_precision_mv);
1433                assert!(matches!(h.interpolation_filter, InterpolationFilter::EightTap));
1434
1435                assert!(h.refresh_frame_context);
1436                assert!(h.frame_parallel_decoding_mode);
1437                assert_eq!(h.frame_context_idx, 0);
1438
1439                let lf = &h.lf;
1440                assert_eq!(lf.level, 36);
1441                assert_eq!(lf.sharpness, 0);
1442
1443                assert!(lf.delta_enabled);
1444                assert!(!lf.delta_update);
1445
1446                assert_eq!(lf.update_ref_delta, [true, false, true, true]);
1447                assert_eq!(lf.ref_deltas, [1, 0, -1, -1]);
1448
1449                assert_eq!(lf.update_mode_delta, [false, false]);
1450
1451                let q = &h.quant;
1452
1453                assert_eq!(q.base_q_idx, 216);
1454                assert_eq!(q.delta_q_y_dc, 0);
1455                assert_eq!(q.delta_q_uv_dc, 0);
1456                assert_eq!(q.delta_q_uv_ac, 0);
1457
1458                let s = &h.seg;
1459
1460                assert!(!s.enabled);
1461                assert!(!s.update_map);
1462                assert_eq!(s.tree_probs, [0, 0, 0, 0, 0, 0, 0]);
1463                assert_eq!(s.pred_probs, [0, 0, 0]);
1464                assert!(!s.temporal_update);
1465                assert!(!s.update_data);
1466                assert!(!s.abs_or_delta_update);
1467                assert_eq!(s.feature_enabled, [[false; SEG_LVL_MAX]; MAX_SEGMENTS]);
1468                assert_eq!(s.feature_data, [[0; SEG_LVL_MAX]; MAX_SEGMENTS]);
1469
1470                assert_eq!(h.tile_cols_log2, 0);
1471                assert_eq!(h.tile_rows_log2, 0);
1472                assert_eq!(h.header_size_in_bytes, 9);
1473
1474                assert!(!h.lossless);
1475            }
1476        }
1477    }
1478}