vp9_parser/
lib.rs

1#![warn(missing_docs)]
2#![forbid(unsafe_code)]
3#![forbid(unused_results)]
4#![deny(clippy::as_conversions)]
5#![deny(clippy::panic)]
6#![deny(clippy::unwrap_used)]
7
8//! Provides tools to parse VP9 bitstreams and IVF containers.
9use std::{collections::HashMap, convert::TryInto};
10
11use bitreader::BitReader;
12
13pub use error::Vp9ParserError;
14
15mod error;
16pub mod ivf;
17
18type Result<T> = std::result::Result<T, Vp9ParserError>;
19
20/// Number of segments allowed in segmentation map.
21const MAX_SEGMENTS: usize = 8;
22
23/// Minimum width of a tile in units of super blocks.
24const MIN_TILE_WIDTH_B64: u8 = 4;
25
26/// Maximum width of a tile in units of super blocks.
27const MAX_TILE_WIDTH_B64: u8 = 64;
28
29const INTRA_FRAME: usize = 0;
30const LAST_FRAME: usize = 1;
31const GOLDEN_FRAME: usize = 2;
32const ALTREF_FRAME: usize = 3;
33
34const SEG_LVL_ALT_Q: usize = 0;
35const SEG_LVL_ALT_L: usize = 1;
36const SEG_LVL_REF_FRAME: usize = 2;
37const SEG_LVL_SKIP: usize = 3;
38
39/// The VP9 profiles.
40#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
41pub enum Profile {
42    /// Unknown.
43    Unknown,
44    /// Color depth: 8 bit/sample, chroma subsampling: 4:2:0
45    Profile0,
46    /// Color depth: 8 bit, chroma subsampling: 4:2:2, 4:4:0, 4:4:4
47    Profile1,
48    /// Color depth: 10–12 bit, chroma subsampling: 4:2:0
49    Profile2,
50    /// Color depth: 10–12 bit, chroma subsampling: 4:2:2, 4:4:0, 4:4:4
51    Profile3,
52}
53
54impl From<u8> for Profile {
55    fn from(i: u8) -> Self {
56        match i {
57            0 => Profile::Profile0,
58            1 => Profile::Profile1,
59            2 => Profile::Profile2,
60            3 => Profile::Profile3,
61            _ => Profile::Unknown,
62        }
63    }
64}
65
66impl From<Profile> for u8 {
67    fn from(p: Profile) -> Self {
68        match p {
69            Profile::Profile0 => 0,
70            Profile::Profile1 => 1,
71            Profile::Profile2 => 2,
72            Profile::Profile3 => 3,
73            Profile::Unknown => u8::MAX,
74        }
75    }
76}
77
78/// Chroma subsampling.
79#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
80pub enum Subsampling {
81    /// 4:4:4 - No chrome subsampling.
82    Yuv444,
83    /// 4:4:0 - Subsampling along the y axis.
84    Yuv440,
85    /// 4:2:2 - Subsampling along the x axis.
86    Yuv422,
87    /// 4:2:0 - Subsampling along both x and y axis.
88    Yuv420,
89}
90
91/// Chroma subsampling as defined in the Metadata
92#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
93pub enum MetadataSubsampling {
94    /// Unknown.
95    Unknown,
96    /// 4:2:0 - Subsampling along both x and y axis.
97    Yuv420,
98    /// 4:2:0 - Chroma subsampling colocated with (0,0) luma.
99    Yuv420Colocated,
100    /// 4:2:2 - Subsampling along the x axis.
101    Yuv422,
102    /// 4:4:4 - No chrome subsampling.
103    Yuv444,
104}
105
106impl From<u8> for MetadataSubsampling {
107    fn from(d: u8) -> Self {
108        match d {
109            0 => MetadataSubsampling::Yuv420,
110            1 => MetadataSubsampling::Yuv420Colocated,
111            2 => MetadataSubsampling::Yuv422,
112            3 => MetadataSubsampling::Yuv444,
113            _ => MetadataSubsampling::Unknown,
114        }
115    }
116}
117
118/// Color space.
119#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
120pub enum ColorSpace {
121    /// Unknown (in this case the color space must be signaled outside the VP9 bitstream).
122    Unknown,
123    /// Rec. ITU-R BT.601-7
124    Bt601,
125    /// Rec. ITU-R BT.709-6
126    Bt709,
127    /// SMPTE-170
128    Smpte170,
129    /// SMPTE-240
130    Smpte240,
131    /// Rec. ITU-R BT.2020-2
132    Bt2020,
133    /// Reserved
134    Reserved,
135    /// sRGB (IEC 61966-2-1)
136    Rgb,
137}
138
139impl From<u8> for ColorSpace {
140    fn from(i: u8) -> Self {
141        match i {
142            1 => ColorSpace::Bt601,
143            2 => ColorSpace::Bt709,
144            3 => ColorSpace::Smpte170,
145            4 => ColorSpace::Smpte240,
146            5 => ColorSpace::Bt2020,
147            6 => ColorSpace::Reserved,
148            7 => ColorSpace::Rgb,
149            _ => ColorSpace::Unknown,
150        }
151    }
152}
153
154/// Color depth.
155#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
156pub enum ColorDepth {
157    /// Unknown,
158    Unknown,
159    /// 8 bit depth.
160    Depth8,
161    /// 10 bit depth.
162    Depth10,
163    /// 12 bit depth.
164    Depth12,
165}
166
167impl From<u8> for ColorDepth {
168    fn from(d: u8) -> Self {
169        match d {
170            8 => ColorDepth::Depth8,
171            10 => ColorDepth::Depth10,
172            12 => ColorDepth::Depth12,
173            _ => ColorDepth::Unknown,
174        }
175    }
176}
177
178/// Specifies the black level and range of the luma and chroma signals as specified in
179/// Rec. ITU-R BT.709-6 and Rec. ITU-R BT.2020-2.
180#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
181pub enum ColorRange {
182    /// Put restriction on Y, U, V values.
183    StudioSwing,
184    /// No restriction on Y, U, V values.
185    FullSwing,
186}
187
188impl From<bool> for ColorRange {
189    fn from(b: bool) -> Self {
190        match b {
191            false => ColorRange::StudioSwing,
192            true => ColorRange::FullSwing,
193        }
194    }
195}
196
197/// Type of the interpolation filter.
198#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
199pub enum InterpolationFilter {
200    /// Unknown.
201    Unknown,
202    /// EIGHTTAP.
203    Eighttap,
204    /// EIGHTTAP_SMOOTH.
205    EighttapSmooth,
206    /// EIGHTTAP_SHARP.
207    EighttapSharp,
208    /// BILINEAR.
209    Bilinear,
210    /// SWITCHABLE.
211    Switchable,
212}
213
214/// The type of a frame.
215#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
216pub enum FrameType {
217    /// Frame is a key frame.
218    KeyFrame,
219    /// Frame is not a key frame.
220    NonKeyFrame,
221}
222
223impl From<bool> for FrameType {
224    fn from(b: bool) -> Self {
225        match b {
226            false => FrameType::KeyFrame,
227            true => FrameType::NonKeyFrame,
228        }
229    }
230}
231
232/// Defines if the frame context should be reset.
233#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
234pub enum ResetFrameContext {
235    /// Unknown.
236    Unknown,
237    /// Do not reset any frame context.
238    No0,
239    /// Do not reset any frame context.
240    No1,
241    /// Resets just the context specified in the frame header.
242    SingleReset,
243    /// Resets all contexts.
244    FullReset,
245}
246
247impl From<u8> for ResetFrameContext {
248    fn from(i: u8) -> Self {
249        match i {
250            0 => ResetFrameContext::No0,
251            1 => ResetFrameContext::No1,
252            2 => ResetFrameContext::SingleReset,
253            3 => ResetFrameContext::FullReset,
254            _ => ResetFrameContext::Unknown,
255        }
256    }
257}
258
259/// The codec level.
260#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
261pub enum Level {
262    /// Unknown.
263    Unknown,
264    /// Level 1: 0.20 MBit/s
265    Level1,
266    /// Level 1.1: 0.80 MBit/s
267    Level1_1,
268    /// Level 2: 1.8 MBit/s
269    Level2,
270    /// Level 2.1: 3.6 MBit/s
271    Level2_1,
272    /// Level 3: 7.2 MBit/s
273    Level3,
274    /// Level 3.2: 12 MBit/s
275    Level3_1,
276    /// Level 4: 18 MBit/s
277    Level4,
278    /// Level 4.1: 30 MBit/s
279    Level4_1,
280    /// Level 5: 60 MBit/s
281    Level5,
282    /// Level 5.1: 120 MBit/s
283    Level5_1,
284    /// Level 5.2: 180 MBit/s
285    Level5_2,
286    /// Level 6: 180 MBit/s
287    Level6,
288    /// Level 6.1: 240 MBit/s
289    Level6_1,
290    /// Level 6.2: 480 MBit/s
291    Level6_2,
292}
293
294impl From<u8> for Level {
295    fn from(d: u8) -> Self {
296        match d {
297            10 => Level::Level1,
298            11 => Level::Level1_1,
299            20 => Level::Level2,
300            21 => Level::Level2_1,
301            30 => Level::Level3,
302            31 => Level::Level3_1,
303            40 => Level::Level4,
304            41 => Level::Level4_1,
305            50 => Level::Level5,
306            51 => Level::Level5_1,
307            52 => Level::Level5_2,
308            60 => Level::Level6,
309            61 => Level::Level6_1,
310            62 => Level::Level6_2,
311            _ => Level::Unknown,
312        }
313    }
314}
315
316/// VP9 Codec Feature Metadata saved inside the `CodecPrivate` field of containers.
317#[derive(Clone, Copy, Debug)]
318pub struct Metadata {
319    profile: Profile,
320    level: Level,
321    color_depth: ColorDepth,
322    chroma_subsampling: MetadataSubsampling,
323}
324
325impl Metadata {
326    /// Creates the Vp9Metadata from the given `CodecPrivate` data.
327    pub fn new(data: &[u8]) -> Result<Self> {
328        let mut pos = 0;
329
330        let mut features: HashMap<u8, u8> = HashMap::with_capacity(4);
331        while pos < data.len() {
332            let (id, value) = Self::read_feature(&mut pos, data);
333            let _ = features.insert(id, value);
334        }
335
336        let profile = *features.get(&1).ok_or(Vp9ParserError::InvalidMetadata)?;
337        let level = *features.get(&2).ok_or(Vp9ParserError::InvalidMetadata)?;
338        let color_depth = *features.get(&3).ok_or(Vp9ParserError::InvalidMetadata)?;
339        let chroma_subsampling = *features.get(&4).ok_or(Vp9ParserError::InvalidMetadata)?;
340
341        Ok(Self {
342            profile: profile.into(),
343            level: level.into(),
344            color_depth: color_depth.into(),
345            chroma_subsampling: chroma_subsampling.into(),
346        })
347    }
348
349    /// The profile of the video.
350    pub fn profile(&self) -> Profile {
351        self.profile
352    }
353
354    /// The level of the video.
355    pub fn level(&self) -> Level {
356        self.level
357    }
358
359    /// The color depth of the video.
360    pub fn color_depth(&self) -> ColorDepth {
361        self.color_depth
362    }
363
364    /// The chroma subsampling of the video.
365    pub fn chroma_subsampling(&self) -> MetadataSubsampling {
366        self.chroma_subsampling
367    }
368
369    /// Reads the next feature. Returns the id and the value of the feature.
370    #[inline]
371    fn read_feature(pos: &mut usize, data: &[u8]) -> (u8, u8) {
372        let id = data[*pos];
373        let value = data[*pos + 1];
374        *pos += 2;
375        (id, value)
376    }
377}
378
379/// A VP9 frame.
380#[derive(Clone, Debug)]
381pub struct Frame {
382    data: Vec<u8>,
383    profile: Profile,
384    show_existing_frame: bool,
385    frame_to_show_map_idx: Option<u8>,
386    last_frame_type: FrameType,
387    frame_type: FrameType,
388    show_frame: bool,
389    error_resilient_mode: bool,
390    intra_only: bool,
391    reset_frame_context: ResetFrameContext,
392    ref_frame_indices: [u8; 3],
393    ref_frame_sign_bias: [bool; 4],
394    allow_high_precision_mv: bool,
395    refresh_frame_context: bool,
396    refresh_frame_flags: u8,
397    frame_parallel_decoding_mode: bool,
398    frame_context_idx: u8,
399    uncompressed_header_size: usize,
400    compressed_header_size: usize,
401    tile_size: usize,
402    color_depth: ColorDepth,
403    color_space: ColorSpace,
404    color_range: ColorRange,
405    subsampling_x: bool,
406    subsampling_y: bool,
407    width: u16,
408    height: u16,
409    render_width: u16,
410    render_height: u16,
411    mi_cols: u16,
412    mi_rows: u16,
413    tile_rows_log2: u8,
414    tile_cols_log2: u8,
415    interpolation_filter: InterpolationFilter,
416    loop_filter_level: u8,
417    loop_filter_sharpness: u8,
418    loop_filter_delta_enabled: bool,
419    update_ref_delta: bool,
420    loop_filter_ref_deltas: [i8; 4],
421    update_mode_delta: bool,
422    loop_filter_mode_deltas: [i8; 2],
423    base_q_idx: i32,
424    delta_q_y_dc: i32,
425    delta_q_uv_dc: i32,
426    delta_q_uv_ac: i32,
427    lossless: bool,
428    segmentation_enabled: bool,
429    segmentation_update_map: bool,
430    segment_tree_probs: [u8; 7],
431    segment_pred_probs: [u8; 3],
432    segmentation_temporal_update: bool,
433    segmentation_update_data: bool,
434    segmentation_abs_or_delta_update: bool,
435    segment_feature_enabled: [[bool; 4]; 8],
436    segment_feature_data: [[i16; 4]; 8],
437}
438
439impl Frame {
440    /// Creates a frame from the parser state.
441    pub(crate) fn new(
442        parser: &Vp9Parser,
443        uncompressed_header_size: usize,
444        compressed_header_size: usize,
445        tile_size: usize,
446        data: Vec<u8>,
447    ) -> Self {
448        Self {
449            data,
450            profile: parser.profile,
451            show_existing_frame: parser.show_existing_frame,
452            frame_to_show_map_idx: parser.frame_to_show_map_idx,
453            last_frame_type: parser.last_frame_type,
454            frame_type: parser.frame_type,
455            show_frame: parser.show_frame,
456            error_resilient_mode: parser.error_resilient_mode,
457            intra_only: parser.intra_only,
458            reset_frame_context: parser.reset_frame_context,
459            ref_frame_indices: parser.ref_frame_indices,
460            ref_frame_sign_bias: parser.ref_frame_sign_bias,
461            allow_high_precision_mv: parser.allow_high_precision_mv,
462            refresh_frame_context: parser.refresh_frame_context,
463            refresh_frame_flags: parser.refresh_frame_flags,
464            frame_parallel_decoding_mode: parser.frame_parallel_decoding_mode,
465            frame_context_idx: parser.frame_context_idx,
466            uncompressed_header_size,
467            compressed_header_size,
468            tile_size,
469            color_depth: parser.color_depth,
470            color_space: parser.color_space,
471            color_range: parser.color_range,
472            subsampling_x: parser.subsampling_x,
473            subsampling_y: parser.subsampling_y,
474            width: parser.width,
475            height: parser.height,
476            render_width: parser.render_width,
477            render_height: parser.render_height,
478            mi_cols: parser.mi_cols,
479            mi_rows: parser.mi_rows,
480            tile_rows_log2: parser.tile_rows_log2,
481            tile_cols_log2: parser.tile_cols_log2,
482            interpolation_filter: parser.interpolation_filter,
483            loop_filter_level: parser.loop_filter_level,
484            loop_filter_sharpness: parser.loop_filter_sharpness,
485            loop_filter_delta_enabled: parser.loop_filter_delta_enabled,
486            update_ref_delta: parser.update_ref_delta,
487            loop_filter_ref_deltas: parser.loop_filter_ref_deltas,
488            update_mode_delta: parser.update_mode_delta,
489            loop_filter_mode_deltas: parser.loop_filter_mode_deltas,
490            base_q_idx: parser.base_q_idx,
491            delta_q_y_dc: parser.delta_q_y_dc,
492            delta_q_uv_dc: parser.delta_q_uv_dc,
493            delta_q_uv_ac: parser.delta_q_uv_ac,
494            lossless: parser.lossless,
495            segmentation_enabled: parser.segmentation_enabled,
496            segmentation_update_map: parser.segmentation_update_map,
497            segment_tree_probs: parser.segment_tree_probs,
498            segment_pred_probs: parser.segment_pred_probs,
499            segmentation_temporal_update: parser.segmentation_temporal_update,
500            segmentation_update_data: parser.segmentation_update_data,
501            segmentation_abs_or_delta_update: parser.segmentation_abs_or_delta_update,
502            segment_feature_enabled: parser.segment_feature_enabled,
503            segment_feature_data: parser.segment_feature_data,
504        }
505    }
506
507    /// Returns a slice into the data of the compressed header.
508    pub fn compressed_header_data(&self) -> &[u8] {
509        &self.data[self.uncompressed_header_size
510            ..self.uncompressed_header_size + self.compressed_header_size]
511    }
512
513    /// Returns a slice into the data of the compressed header and tile data.
514    pub fn compressed_header_and_tile_data(&self) -> &[u8] {
515        &self.data[self.uncompressed_header_size..self.data.len()]
516    }
517
518    /// Returns a slice into the data of the tile data.
519    pub fn tile_data(&self) -> &[u8] {
520        &self.data[self.uncompressed_header_size + self.compressed_header_size..self.data.len()]
521    }
522
523    /// The profile the frame is using.
524    pub fn profile(&self) -> Profile {
525        self.profile
526    }
527
528    /// Indicates that the frame indexed by `frame_to_show_map_idx` is to be displayed.
529    /// The frame contains no actual frame data.
530    pub fn show_existing_frame(&self) -> bool {
531        self.show_existing_frame
532    }
533
534    /// Specifies the frame to be displayed. It is only available if `show_existing_frame` is true.
535    pub fn frame_to_show_map_idx(&self) -> Option<u8> {
536        self.frame_to_show_map_idx
537    }
538
539    /// The frame type of the previous frame.
540    pub fn last_frame_type(&self) -> FrameType {
541        self.last_frame_type
542    }
543
544    /// The frame type of this frame.
545    pub fn frame_type(&self) -> FrameType {
546        self.frame_type
547    }
548
549    /// Indicates that the frame is to be displayed.
550    pub fn show_frame(&self) -> bool {
551        self.show_frame
552    }
553
554    /// Indicates that error resilient mode is enabled.
555    ///
556    /// Error resilient mode allows the syntax of a frame to be decoded
557    /// independently of previous frames.
558    pub fn error_resilient_mode(&self) -> bool {
559        self.error_resilient_mode
560    }
561
562    /// Indicates that a frame is an `intra-only` frame.
563    ///
564    /// A key frame is different to an `intra-only` frame even though both only use
565    /// intra prediction. The difference is that a key frame fully resets the decoding process.
566    pub fn intra_only(&self) -> bool {
567        self.intra_only
568    }
569
570    /// Specifies whether the frame context should be reset to default values.
571    pub fn reset_frame_context(&self) -> ResetFrameContext {
572        self.reset_frame_context
573    }
574
575    /// The indices of the used reference frames.
576    pub fn ref_frame_indices(&self) -> &[u8; 3] {
577        &self.ref_frame_indices
578    }
579
580    /// Last reference frame index.
581    pub fn last_ref_frame_index(&self) -> u8 {
582        self.ref_frame_indices[0]
583    }
584
585    /// Golden reference frame index.
586    pub fn golden_ref_frame_index(&self) -> u8 {
587        self.ref_frame_indices[1]
588    }
589
590    /// Alternate reference frame index.
591    pub fn alt_ref_frame_index(&self) -> u8 {
592        self.ref_frame_indices[2]
593    }
594
595    /// Specifies the intended direction of the motion vector in time for each reference frame.
596    pub fn ref_frame_sign_bias(&self) -> &[bool; 4] {
597        &self.ref_frame_sign_bias
598    }
599
600    /// Specifies the precision of the motion vectors.
601    ///
602    /// False = quarter precision, True = eighth precision.
603    pub fn allow_high_precision_mv(&self) -> bool {
604        self.allow_high_precision_mv
605    }
606
607    /// Specifies that the probabilities computed for this frame
608    /// should be stored for reference by future frames.
609    pub fn refresh_frame_context(&self) -> bool {
610        self.refresh_frame_context
611    }
612
613    /// Contains a bitmask that specifies which reference frame slots
614    /// will be updated with the current frame after it is decoded.
615    ///
616    /// First bit = first frame (1). Last bit = last frame (8).
617    pub fn refresh_frame_flags(&self) -> u8 {
618        self.refresh_frame_flags
619    }
620
621    /// Specifies if parallel decoding mode is activated.
622    pub fn frame_parallel_decoding_mode(&self) -> bool {
623        self.frame_parallel_decoding_mode
624    }
625
626    /// Specifies which frame context to use.
627    pub fn frame_context_idx(&self) -> u8 {
628        self.frame_context_idx
629    }
630
631    /// The size of the uncompressed header.
632    pub fn uncompressed_header_size(&self) -> usize {
633        self.uncompressed_header_size
634    }
635
636    /// The size of the uncompressed header.
637    pub fn compressed_header_size(&self) -> usize {
638        self.compressed_header_size
639    }
640
641    /// The size of the tile data.
642    pub fn tile_size(&self) -> usize {
643        self.tile_size
644    }
645
646    /// The color depth of the frame.
647    pub fn color_depth(&self) -> ColorDepth {
648        self.color_depth
649    }
650
651    /// The color space of the frame.
652    pub fn color_space(&self) -> ColorSpace {
653        self.color_space
654    }
655
656    /// The color range of the frame.
657    pub fn color_range(&self) -> ColorRange {
658        self.color_range
659    }
660
661    /// The subsampling the frame is using.
662    pub fn subsampling(&self) -> Subsampling {
663        if !self.subsampling_x && !self.subsampling_y {
664            Subsampling::Yuv444
665        } else if !self.subsampling_x && self.subsampling_y {
666            Subsampling::Yuv440
667        } else if self.subsampling_x && !self.subsampling_y {
668            Subsampling::Yuv422
669        } else {
670            Subsampling::Yuv420
671        }
672    }
673
674    /// Indicates if sub sampling is used along the x axis.
675    pub fn subsampling_x(&self) -> bool {
676        self.subsampling_x
677    }
678
679    /// Indicates if sub sampling is used along the y axis.
680    pub fn subsampling_y(&self) -> bool {
681        self.subsampling_y
682    }
683
684    /// The width of the frame.
685    pub fn width(&self) -> u16 {
686        self.width
687    }
688
689    /// The height of the frame.
690    pub fn height(&self) -> u16 {
691        self.height
692    }
693
694    /// A hint for the application for the desired width to render.
695    pub fn render_width(&self) -> u16 {
696        self.render_width
697    }
698
699    /// A hint for the application for the desired height to render.
700    pub fn render_height(&self) -> u16 {
701        self.render_height
702    }
703
704    /// A variable holding the vertical location of the block in units of 8x8 pixels.
705    pub fn mi_cols(&self) -> u16 {
706        self.mi_cols
707    }
708
709    /// A variable holding the horizontal location of the block in units of 8x8 pixels.
710    pub fn mi_rows(&self) -> u16 {
711        self.mi_rows
712    }
713
714    /// The base 2 logarithm of the height of each tile (where the height is measured in units
715    /// of 8x8 blocks)
716    pub fn tile_rows_log2(&self) -> u8 {
717        self.tile_rows_log2
718    }
719
720    /// The base 2 logarithm of the width of each tile (where the width is measured in units
721    /// of 8x8 blocks)
722    pub fn tile_cols_log2(&self) -> u8 {
723        self.tile_cols_log2
724    }
725
726    /// The type of filter used in inter prediction.
727    pub fn interpolation_filter(&self) -> InterpolationFilter {
728        self.interpolation_filter
729    }
730
731    /// The loop filter strength.
732    pub fn loop_filter_level(&self) -> u8 {
733        self.loop_filter_level
734    }
735
736    /// The loop filter sharpness.
737    pub fn loop_filter_sharpness(&self) -> u8 {
738        self.loop_filter_sharpness
739    }
740
741    /// Indicates that the filter level depends on the mode and reference frame
742    /// used to predict a block.
743    pub fn loop_filter_delta_enabled(&self) -> bool {
744        self.loop_filter_delta_enabled
745    }
746
747    /// Indicates that the the bitstream contains the syntax element loop_filter_ref_delta.
748    pub fn update_ref_delta(&self) -> bool {
749        self.update_ref_delta
750    }
751
752    /// Contains the adjustment needed for the filter level based on the chosen reference frame.
753    pub fn loop_filter_ref_deltas(&self) -> &[i8; 4] {
754        &self.loop_filter_ref_deltas
755    }
756
757    /// Indicates that the the bitstream contains the syntax element loop_filter_mode_deltas.
758    pub fn update_mode_delta(&self) -> bool {
759        self.update_mode_delta
760    }
761
762    /// Contains the adjustment needed for the filter level based on the chosen mode.
763    pub fn loop_filter_mode_deltas(&self) -> &[i8; 2] {
764        &self.loop_filter_mode_deltas
765    }
766
767    /// The base frame qindex. This is used for Y AC coefficients and as the base value
768    /// for the other quantizers.
769    pub fn base_q_idx(&self) -> i32 {
770        self.base_q_idx
771    }
772
773    /// The Y DC quantizer relative to base_q_idx.
774    pub fn delta_q_y_dc(&self) -> i32 {
775        self.delta_q_y_dc
776    }
777
778    /// The UV DC quantizer relative to base_q_idx.
779    pub fn delta_q_uv_dc(&self) -> i32 {
780        self.delta_q_uv_dc
781    }
782
783    /// The UV AC quantizer relative to base_q_idx.
784    pub fn delta_q_uv_ac(&self) -> i32 {
785        self.delta_q_uv_ac
786    }
787
788    /// Indicates that the frame is coded using a special 4x4 transform designed
789    /// for encoding frames that are bit-identical with the original frames.
790    pub fn lossless(&self) -> bool {
791        self.lossless
792    }
793
794    /// Specifies that this frame makes use of the segmentation tool.
795    pub fn segmentation_enabled(&self) -> bool {
796        self.segmentation_enabled
797    }
798
799    /// Specifies that the segmentation map should be updated during the decoding of this frame.
800    pub fn segmentation_update_map(&self) -> bool {
801        self.segmentation_update_map
802    }
803
804    /// The probability values to be used when decoding segment_id.
805    pub fn segment_tree_probs(&self) -> &[u8; 7] {
806        &self.segment_tree_probs
807    }
808
809    /// The probability values to be used when decoding seg_id_predicted.
810    pub fn segment_pred_probs(&self) -> &[u8; 3] {
811        &self.segment_pred_probs
812    }
813
814    /// Indicates that the updates to the segmentation map are coded
815    /// relative to the existing segmentation map.
816    pub fn segmentation_temporal_update(&self) -> bool {
817        self.segmentation_temporal_update
818    }
819
820    /// Indicates that new parameters are about to be specified for each segment.
821    pub fn segmentation_update_data(&self) -> bool {
822        self.segmentation_update_data
823    }
824
825    /// Indicates that the segmentation parameters represent the actual values to be used,
826    /// otherwise the segmentation parameters represent adjustments relative to the standard values.
827    pub fn segmentation_abs_or_delta_update(&self) -> bool {
828        self.segmentation_abs_or_delta_update
829    }
830
831    /// Indicates that the corresponding feature is used in a segment.
832    pub fn segment_feature_enabled(&self) -> &[[bool; 4]; 8] {
833        &self.segment_feature_enabled
834    }
835
836    /// Specifies the values of the active features of a segment.
837    pub fn segment_feature_data(&self) -> &[[i16; 4]; 8] {
838        &self.segment_feature_data
839    }
840
841    /// Destroys the frame and returns the underlying data buffer.
842    pub fn into_vec(self) -> Vec<u8> {
843        let Frame { data, .. } = self;
844        data
845    }
846}
847
848/// Parses VP9 bitstreams.
849#[derive(Clone, Debug)]
850pub struct Vp9Parser {
851    ref_frame_sizes: [(u16, u16); 8],
852    profile: Profile,
853    show_existing_frame: bool,
854    frame_to_show_map_idx: Option<u8>,
855    last_frame_type: FrameType,
856    frame_type: FrameType,
857    show_frame: bool,
858    error_resilient_mode: bool,
859    intra_only: bool,
860    reset_frame_context: ResetFrameContext,
861    ref_frame_indices: [u8; 3],
862    ref_frame_sign_bias: [bool; 4],
863    allow_high_precision_mv: bool,
864    refresh_frame_context: bool,
865    refresh_frame_flags: u8,
866    frame_parallel_decoding_mode: bool,
867    frame_context_idx: u8,
868    color_depth: ColorDepth,
869    color_space: ColorSpace,
870    color_range: ColorRange,
871    subsampling_x: bool,
872    subsampling_y: bool,
873    width: u16,
874    height: u16,
875    render_width: u16,
876    render_height: u16,
877    mi_cols: u16,
878    mi_rows: u16,
879    tile_rows_log2: u8,
880    tile_cols_log2: u8,
881    interpolation_filter: InterpolationFilter,
882    loop_filter_level: u8,
883    loop_filter_sharpness: u8,
884    loop_filter_delta_enabled: bool,
885    update_ref_delta: bool,
886    loop_filter_ref_deltas: [i8; 4],
887    update_mode_delta: bool,
888    loop_filter_mode_deltas: [i8; 2],
889    base_q_idx: i32,
890    delta_q_y_dc: i32,
891    delta_q_uv_dc: i32,
892    delta_q_uv_ac: i32,
893    lossless: bool,
894    segmentation_enabled: bool,
895    segmentation_update_map: bool,
896    segment_tree_probs: [u8; 7],
897    segment_pred_probs: [u8; 3],
898    segmentation_temporal_update: bool,
899    segmentation_update_data: bool,
900    segmentation_abs_or_delta_update: bool,
901    segment_feature_enabled: [[bool; 4]; 8],
902    segment_feature_data: [[i16; 4]; 8],
903}
904
905impl Default for Vp9Parser {
906    fn default() -> Self {
907        Self {
908            ref_frame_sizes: [(0u16, 0u16); 8],
909            show_existing_frame: false,
910            frame_to_show_map_idx: None,
911            profile: Profile::Profile0,
912            last_frame_type: FrameType::NonKeyFrame,
913            frame_type: FrameType::NonKeyFrame,
914            show_frame: false,
915            error_resilient_mode: false,
916            intra_only: false,
917            reset_frame_context: ResetFrameContext::No0,
918            refresh_frame_flags: 0,
919            ref_frame_indices: [0u8; 3],
920            ref_frame_sign_bias: [false; 4],
921            allow_high_precision_mv: false,
922            refresh_frame_context: false,
923            frame_parallel_decoding_mode: true,
924            frame_context_idx: 0,
925            color_depth: ColorDepth::Depth8,
926            color_space: ColorSpace::Unknown,
927            color_range: ColorRange::StudioSwing,
928            subsampling_x: true,
929            subsampling_y: true,
930            width: 0,
931            height: 0,
932            render_width: 0,
933            render_height: 0,
934            mi_cols: 0,
935            mi_rows: 0,
936            tile_rows_log2: 0,
937            tile_cols_log2: 0,
938            interpolation_filter: InterpolationFilter::Eighttap,
939            loop_filter_level: 0,
940            loop_filter_sharpness: 0,
941            loop_filter_delta_enabled: false,
942            update_ref_delta: false,
943            loop_filter_ref_deltas: [1, 0, -1, -1],
944            update_mode_delta: false,
945            loop_filter_mode_deltas: [0, 0],
946            base_q_idx: 0,
947            delta_q_y_dc: 0,
948            delta_q_uv_dc: 0,
949            delta_q_uv_ac: 0,
950            lossless: false,
951            segmentation_enabled: false,
952            segmentation_update_map: false,
953            segment_tree_probs: [0u8; 7],
954            segment_pred_probs: [0u8; 3],
955            segmentation_temporal_update: false,
956            segmentation_update_data: false,
957            segmentation_abs_or_delta_update: false,
958            segment_feature_enabled: [[false; 4]; 8],
959            segment_feature_data: [[0i16; 4]; 8],
960        }
961    }
962}
963
964impl Vp9Parser {
965    /// Creates a new parser.
966    pub fn new() -> Self {
967        Default::default()
968    }
969
970    /// Resets the state of the parser. Used when switching the bitstream or seeking.
971    pub fn reset(&mut self) {
972        *self = Vp9Parser::default();
973    }
974
975    /// Parses a VP9 bitstream packet and returns the encoded frames.
976    ///
977    /// Packets needs to be supplied in the order they are appearing in the bitstream. The caller
978    /// needs to reset the parser if the bitstream is changed or a seek happened. Not resetting the
979    /// parser in such cases results in garbage data or errors.
980    pub fn parse_packet(&mut self, mut packet: Vec<u8>) -> Result<Vec<Frame>> {
981        if packet.is_empty() {
982            return Ok(vec![]);
983        }
984
985        // Test for a super frame.
986        let last_byte_index = packet.len() - 1;
987        let last_byte = packet[last_byte_index];
988        if last_byte & 0b1110_0000 == 0b1100_0000 {
989            let bytes_per_framesize_minus_1 = (last_byte & 0b11000) >> 3;
990            let frames_in_superframe_minus_1 = last_byte & 0b111;
991            let bytes_size: usize = (bytes_per_framesize_minus_1 + 1).into();
992            let frame_count: usize = (frames_in_superframe_minus_1 + 1).into();
993            let index_size = 2 + frame_count * bytes_size;
994            let first_byte_index = packet.len() - index_size;
995            let first_byte = packet[first_byte_index];
996
997            // Found a super frame.
998            if first_byte == last_byte {
999                let mut frames = Vec::with_capacity(frame_count);
1000
1001                let index_start = first_byte_index + 1;
1002                let entry_size = frame_count * bytes_size;
1003
1004                let mut entry_data = Vec::with_capacity(entry_size);
1005                entry_data.extend_from_slice(&packet[index_start..index_start + entry_size]);
1006
1007                match frame_count {
1008                    1 => {
1009                        // Odd, but valid bitstream configuration.
1010                        let frame_size = self.read_frame_size(&mut entry_data, bytes_size, 0)?;
1011                        packet.truncate(frame_size);
1012                        let frame = self.parse_frame(packet)?;
1013
1014                        frames.push(frame);
1015                    }
1016                    2 => {
1017                        // Most common case. The first frame produces a frame that is not displayed but
1018                        // stored as a reference frame. The second frame is mostly empty and references
1019                        // the previously stored frame.
1020                        let frame_size = self.read_frame_size(&mut entry_data, bytes_size, 0)?;
1021                        let mut left_over = packet.split_off(frame_size);
1022                        let first_frame = self.parse_frame(packet)?;
1023
1024                        let frame_size = self.read_frame_size(&mut entry_data, bytes_size, 1)?;
1025                        left_over.truncate(frame_size);
1026                        let second_frame = self.parse_frame(left_over)?;
1027
1028                        frames.push(first_frame);
1029                        frames.push(second_frame);
1030                    }
1031                    _ => {
1032                        // Odd, but also a valid bitstream configuration.
1033                        for frame_index in 0..frame_count {
1034                            let frame_size =
1035                                self.read_frame_size(&mut entry_data, bytes_size, frame_index)?;
1036
1037                            let left_over = packet.split_off(frame_size);
1038                            let frame = self.parse_frame(packet)?;
1039                            frames.push(frame);
1040
1041                            packet = left_over;
1042                        }
1043                    }
1044                }
1045
1046                return Ok(frames);
1047            }
1048        }
1049
1050        // Normal frame.
1051        let frame = self.parse_frame(packet)?;
1052        Ok(vec![frame])
1053    }
1054
1055    fn read_frame_size(
1056        &self,
1057        entry_data: &mut [u8],
1058        bytes_size: usize,
1059        index: usize,
1060    ) -> Result<usize> {
1061        // sic! Even though the values inside the uncompressed header are saved in BE,
1062        // these values are saved in LE.
1063        let value: usize = match bytes_size {
1064            1 => u8::from_le_bytes(entry_data[index..index + 1].try_into()?).into(),
1065            2 => u16::from_le_bytes(entry_data[index * 2..(index * 2) + 2].try_into()?).into(),
1066            3 => {
1067                let bytes = &entry_data[index * 3..(index * 3) + 3];
1068                u32::from_le_bytes([bytes[0], bytes[1], bytes[2], 0x0]).try_into()?
1069            }
1070            4 => {
1071                u32::from_le_bytes(entry_data[index * 4..(index * 4) + 4].try_into()?).try_into()?
1072            }
1073            _ => {
1074                return Err(Vp9ParserError::InvalidFrameSizeByteSize(bytes_size));
1075            }
1076        };
1077        Ok(value)
1078    }
1079
1080    fn parse_frame(&mut self, data: Vec<u8>) -> Result<Frame> {
1081        let mut br = BitReader::new(&data);
1082
1083        let frame_marker = br.read_u8(2)?;
1084        if frame_marker != 2 {
1085            return Err(Vp9ParserError::InvalidFrameMarker);
1086        }
1087
1088        let profile_low_bit = br.read_u8(1)?;
1089        let profile_high_bit = br.read_u8(1)?;
1090        self.profile = ((profile_high_bit << 1) + profile_low_bit).into();
1091        if self.profile == Profile::Profile3 {
1092            let _reserved_zero = br.read_u8(1)?;
1093        }
1094
1095        self.show_existing_frame = br.read_bool()?;
1096
1097        if self.show_existing_frame {
1098            self.frame_to_show_map_idx = Some(br.read_u8(3)?);
1099            self.refresh_frame_flags = 0;
1100            self.loop_filter_level = 0;
1101
1102            let frame = Frame::new(self, 0, 0, 0, vec![]);
1103            return Ok(frame);
1104        } else {
1105            self.frame_to_show_map_idx = None;
1106        }
1107
1108        self.last_frame_type = self.frame_type;
1109        self.frame_type = br.read_bool()?.into();
1110
1111        self.show_frame = br.read_bool()?;
1112        self.error_resilient_mode = br.read_bool()?;
1113
1114        if self.frame_type == FrameType::KeyFrame {
1115            self.frame_sync_code(&mut br)?;
1116            self.color_config(&mut br)?;
1117            self.frame_size(&mut br)?;
1118            self.render_size(&mut br)?;
1119            self.refresh_frame_flags = 0xFF;
1120        } else {
1121            if !self.show_frame {
1122                self.intra_only = br.read_bool()?
1123            } else {
1124                self.intra_only = false;
1125            };
1126
1127            if !self.error_resilient_mode {
1128                self.reset_frame_context = br.read_u8(2)?.into()
1129            } else {
1130                self.reset_frame_context = ResetFrameContext::No0;
1131            };
1132
1133            if self.intra_only {
1134                self.frame_sync_code(&mut br)?;
1135                if self.profile > Profile::Profile0 {
1136                    self.color_config(&mut br)?;
1137                } else {
1138                    self.color_depth = ColorDepth::Depth8;
1139                    self.color_space = ColorSpace::Bt601;
1140                    self.subsampling_x = true;
1141                    self.subsampling_y = true;
1142                }
1143                self.refresh_frame_flags = br.read_u8(8)?;
1144                self.frame_size(&mut br)?;
1145                self.render_size(&mut br)?;
1146            } else {
1147                self.refresh_frame_flags = br.read_u8(8)?;
1148                for i in 0..3 {
1149                    self.ref_frame_indices[i] = br.read_u8(3)?;
1150                    self.ref_frame_sign_bias[LAST_FRAME + i] = br.read_bool()?;
1151                }
1152                self.frame_size_with_refs(&mut br)?;
1153                self.allow_high_precision_mv = br.read_bool()?;
1154                self.read_interpolation_filter(&mut br)?;
1155            }
1156        }
1157
1158        if !self.error_resilient_mode {
1159            self.refresh_frame_context = br.read_bool()?;
1160            self.frame_parallel_decoding_mode = br.read_bool()?;
1161        } else {
1162            self.refresh_frame_context = false;
1163            self.frame_parallel_decoding_mode = false;
1164        };
1165
1166        self.frame_context_idx = br.read_u8(2)?;
1167
1168        if self.intra_only || self.error_resilient_mode {
1169            self.frame_context_idx = 0
1170        }
1171
1172        if self.frame_type == FrameType::KeyFrame || self.error_resilient_mode || self.intra_only {
1173            // Reset the loop filter deltas.
1174            self.loop_filter_ref_deltas[INTRA_FRAME] = 1;
1175            self.loop_filter_ref_deltas[LAST_FRAME] = 0;
1176            self.loop_filter_ref_deltas[GOLDEN_FRAME] = -1;
1177            self.loop_filter_ref_deltas[ALTREF_FRAME] = -1;
1178            self.loop_filter_mode_deltas[0] = 0;
1179            self.loop_filter_mode_deltas[1] = 0;
1180        }
1181        self.loop_filter_params(&mut br)?;
1182
1183        self.quantization_params(&mut br)?;
1184        self.segmentation_params(&mut br)?;
1185        self.tile_info(&mut br)?;
1186
1187        let compressed_header_size: usize = (br.read_u16(16)?).into();
1188        self.trailing_bits(&mut br)?;
1189        let uncompressed_header_size: usize = (br.position() / 8).try_into()?;
1190
1191        let size = data.len();
1192        let tile_size = size - (uncompressed_header_size + compressed_header_size);
1193
1194        let frame = Frame::new(
1195            self,
1196            uncompressed_header_size,
1197            compressed_header_size,
1198            tile_size,
1199            data,
1200        );
1201
1202        self.refresh_ref_frames();
1203
1204        Ok(frame)
1205    }
1206
1207    // Implements spec "8.10 Reference frame update process".
1208    fn refresh_ref_frames(&mut self) {
1209        let flags = self.refresh_frame_flags;
1210        let new_width = self.width;
1211        let new_height = self.height;
1212        self.ref_frame_sizes
1213            .iter_mut()
1214            .enumerate()
1215            .for_each(|(i, (width, height))| {
1216                if (flags >> i) & 1 == 1 {
1217                    *width = new_width;
1218                    *height = new_height;
1219                }
1220            });
1221    }
1222
1223    fn frame_sync_code(&self, br: &mut BitReader) -> Result<()> {
1224        let frame_sync_byte_0 = br.read_u8(8)?;
1225        let frame_sync_byte_1 = br.read_u8(8)?;
1226        let frame_sync_byte_2 = br.read_u8(8)?;
1227
1228        if frame_sync_byte_0 != 0x49 && frame_sync_byte_1 != 0x83 && frame_sync_byte_2 != 0x42 {
1229            return Err(Vp9ParserError::InvalidSyncByte);
1230        }
1231
1232        Ok(())
1233    }
1234
1235    fn color_config(&mut self, br: &mut BitReader) -> Result<()> {
1236        if self.profile >= Profile::Profile2 {
1237            let ten_or_twelve_bit = br.read_bool()?;
1238            if ten_or_twelve_bit {
1239                self.color_depth = ColorDepth::Depth12;
1240            } else {
1241                self.color_depth = ColorDepth::Depth10;
1242            }
1243        } else {
1244            self.color_depth = ColorDepth::Depth8;
1245        };
1246
1247        self.color_space = br.read_u8(3)?.into();
1248
1249        if self.color_space == ColorSpace::Rgb {
1250            self.color_range = ColorRange::FullSwing;
1251            if self.profile == Profile::Profile1 || self.profile == Profile::Profile3 {
1252                self.subsampling_x = false;
1253                self.subsampling_y = false;
1254                let _reserved_zero = br.read_u8(1)?;
1255            }
1256        } else {
1257            self.color_range = br.read_bool()?.into();
1258            if self.profile == Profile::Profile1 || self.profile == Profile::Profile3 {
1259                self.subsampling_x = br.read_bool()?;
1260                self.subsampling_y = br.read_bool()?;
1261                let _reserved_zero = br.read_u8(1)?;
1262            } else {
1263                self.subsampling_x = true;
1264                self.subsampling_y = true;
1265            }
1266        }
1267
1268        Ok(())
1269    }
1270
1271    fn frame_size(&mut self, br: &mut BitReader) -> Result<()> {
1272        let frame_width_minus_1 = br.read_u16(16)?;
1273        let frame_height_minus_1 = br.read_u16(16)?;
1274        self.width = frame_width_minus_1 + 1;
1275        self.height = frame_height_minus_1 + 1;
1276
1277        self.compute_image_size();
1278
1279        Ok(())
1280    }
1281
1282    fn render_size(&mut self, br: &mut BitReader) -> Result<()> {
1283        let render_and_frame_size_different = br.read_bool()?;
1284        if render_and_frame_size_different {
1285            let render_width_minus_1 = br.read_u16(16)?;
1286            let render_height_minus_1 = br.read_u16(16)?;
1287            self.render_width = render_width_minus_1 + 1;
1288            self.render_height = render_height_minus_1 + 1;
1289        } else {
1290            self.render_width = self.width;
1291            self.render_height = self.height;
1292        }
1293
1294        Ok(())
1295    }
1296
1297    fn frame_size_with_refs(&mut self, br: &mut BitReader) -> Result<()> {
1298        let mut found_ref = false;
1299        for i in 0..3 {
1300            found_ref = br.read_bool()?;
1301            if found_ref {
1302                let sizes = *self
1303                    .ref_frame_sizes
1304                    .get(usize::from(self.ref_frame_indices[i]))
1305                    .ok_or(Vp9ParserError::InvalidRefFrameIndex)?;
1306
1307                self.width = sizes.0;
1308                self.height = sizes.1;
1309                break;
1310            }
1311        }
1312
1313        if !found_ref {
1314            self.frame_size(br)?;
1315        } else {
1316            self.compute_image_size();
1317        }
1318
1319        self.render_size(br)?;
1320
1321        Ok(())
1322    }
1323
1324    fn compute_image_size(&mut self) {
1325        self.mi_cols = (self.width + 7) >> 3;
1326        self.mi_rows = (self.height + 7) >> 3;
1327    }
1328
1329    fn read_interpolation_filter(&mut self, br: &mut BitReader) -> Result<()> {
1330        let is_filter_switchable = br.read_bool()?;
1331        if is_filter_switchable {
1332            self.interpolation_filter = InterpolationFilter::Switchable;
1333        } else {
1334            let raw_interpolation_filter = br.read_u8(2)?;
1335            self.interpolation_filter = match raw_interpolation_filter {
1336                0 => InterpolationFilter::EighttapSmooth,
1337                1 => InterpolationFilter::Eighttap,
1338                2 => InterpolationFilter::EighttapSharp,
1339                3 => InterpolationFilter::Bilinear,
1340                _ => InterpolationFilter::Unknown,
1341            };
1342        }
1343
1344        Ok(())
1345    }
1346
1347    fn loop_filter_params(&mut self, br: &mut BitReader) -> Result<()> {
1348        self.loop_filter_level = br.read_u8(6)?;
1349        self.loop_filter_sharpness = br.read_u8(3)?;
1350        self.loop_filter_delta_enabled = br.read_bool()?;
1351
1352        if self.loop_filter_delta_enabled {
1353            let loop_filter_delta_update = br.read_bool()?;
1354            if loop_filter_delta_update {
1355                for delta in self.loop_filter_ref_deltas.iter_mut() {
1356                    let update_ref_delta = br.read_bool()?;
1357                    if update_ref_delta {
1358                        *delta = br.read_inverse_i8(6)?;
1359                    }
1360                }
1361
1362                for mode in self.loop_filter_mode_deltas.iter_mut() {
1363                    let update_mode_delta = br.read_bool()?;
1364                    if update_mode_delta {
1365                        *mode = br.read_inverse_i8(6)?;
1366                    }
1367                }
1368            }
1369        }
1370
1371        Ok(())
1372    }
1373
1374    fn quantization_params(&mut self, br: &mut BitReader) -> Result<()> {
1375        self.base_q_idx = (br.read_u8(8)?).into();
1376        self.delta_q_y_dc = self.read_delta_q(br)?;
1377        self.delta_q_uv_dc = self.read_delta_q(br)?;
1378        self.delta_q_uv_ac = self.read_delta_q(br)?;
1379        self.lossless = self.base_q_idx == 0
1380            && self.delta_q_y_dc == 0
1381            && self.delta_q_uv_dc == 0
1382            && self.delta_q_uv_ac == 0;
1383
1384        Ok(())
1385    }
1386
1387    fn read_delta_q(&self, br: &mut BitReader) -> Result<i32> {
1388        let delta_coded = br.read_bool()?;
1389        if delta_coded {
1390            let delta_q = (br.read_inverse_i8(4)?).into();
1391            Ok(delta_q)
1392        } else {
1393            Ok(0)
1394        }
1395    }
1396
1397    fn segmentation_params(&mut self, br: &mut BitReader) -> Result<()> {
1398        self.segmentation_enabled = br.read_bool()?;
1399        if self.segmentation_enabled {
1400            self.segmentation_update_map = br.read_bool()?;
1401            if self.segmentation_update_map {
1402                for prob in self.segment_tree_probs.iter_mut() {
1403                    *prob = Self::read_prob(br)?;
1404                }
1405
1406                self.segmentation_temporal_update = br.read_bool()?;
1407                for prob in self.segment_pred_probs.iter_mut() {
1408                    *prob = if self.segmentation_temporal_update {
1409                        Self::read_prob(br)?
1410                    } else {
1411                        255
1412                    };
1413                }
1414            }
1415
1416            self.segmentation_update_data = br.read_bool()?;
1417            if self.segmentation_update_data {
1418                self.segmentation_abs_or_delta_update = br.read_bool()?;
1419                for i in 0..MAX_SEGMENTS {
1420                    self.segment_feature_enabled[i][SEG_LVL_ALT_Q] = br.read_bool()?;
1421                    if self.segment_feature_enabled[i][SEG_LVL_ALT_Q] {
1422                        self.segment_feature_data[i][SEG_LVL_ALT_Q] = br.read_inverse_i16(8)?;
1423                    };
1424                    self.segment_feature_enabled[i][SEG_LVL_ALT_L] = br.read_bool()?;
1425                    if self.segment_feature_enabled[i][SEG_LVL_ALT_L] {
1426                        self.segment_feature_data[i][SEG_LVL_ALT_L] = br.read_inverse_i16(6)?;
1427                    };
1428                    self.segment_feature_enabled[i][SEG_LVL_REF_FRAME] = br.read_bool()?;
1429                    if self.segment_feature_enabled[i][SEG_LVL_REF_FRAME] {
1430                        self.segment_feature_data[i][SEG_LVL_REF_FRAME] = br.read_inverse_i16(2)?;
1431                    };
1432                    self.segment_feature_enabled[i][SEG_LVL_SKIP] = br.read_bool()?;
1433                    self.segment_feature_data[i][SEG_LVL_SKIP] = 0;
1434                }
1435            }
1436        }
1437
1438        Ok(())
1439    }
1440
1441    fn read_prob(br: &mut BitReader) -> Result<u8> {
1442        let prob_coded = br.read_bool()?;
1443        if prob_coded {
1444            let prob = br.read_u8(8)?;
1445            Ok(prob)
1446        } else {
1447            Ok(255)
1448        }
1449    }
1450
1451    fn tile_info(&mut self, br: &mut BitReader) -> Result<()> {
1452        let min_log2_tile_cols = self.calc_min_log2_tile_cols()?;
1453        let max_log2_tile_cols = self.calc_max_log2_tile_cols()?;
1454        self.tile_cols_log2 = min_log2_tile_cols;
1455        while self.tile_cols_log2 < max_log2_tile_cols {
1456            let increment_tile_cols_log2 = br.read_bool()?;
1457            if increment_tile_cols_log2 {
1458                self.tile_cols_log2 += 1;
1459            } else {
1460                break;
1461            }
1462        }
1463        self.tile_rows_log2 = br.read_u8(1)?;
1464        if self.tile_rows_log2 == 1 {
1465            let increment_tile_rows_log2 = br.read_u8(1)?;
1466            self.tile_rows_log2 += increment_tile_rows_log2;
1467        }
1468
1469        Ok(())
1470    }
1471
1472    fn calc_min_log2_tile_cols(&self) -> Result<u8> {
1473        let mut min_log2 = 0;
1474        let sb64_cols: u8 = ((self.mi_cols + 7) >> 3).try_into()?;
1475        while (MAX_TILE_WIDTH_B64 << min_log2) < sb64_cols {
1476            min_log2 += 1;
1477        }
1478        Ok(min_log2)
1479    }
1480
1481    fn calc_max_log2_tile_cols(&self) -> Result<u8> {
1482        let mut max_log2 = 1;
1483        let sb64_cols: u8 = ((self.mi_cols + 7) >> 3).try_into()?;
1484        while (sb64_cols >> max_log2) >= MIN_TILE_WIDTH_B64 {
1485            max_log2 += 1;
1486        }
1487        Ok(max_log2 - 1)
1488    }
1489
1490    // Aligns the reader to the next byte offset.
1491    fn trailing_bits(&self, br: &mut BitReader) -> Result<()> {
1492        while br.is_aligned(1) {
1493            let zero_bit = br.read_bool()?;
1494            if zero_bit {
1495                return Err(Vp9ParserError::InvalidPadding);
1496            }
1497        }
1498
1499        Ok(())
1500    }
1501}
1502
1503// The sign bit is at the start and not the end (even though it's BE).
1504trait SignedRead {
1505    fn read_inverse_i8(&mut self, bits: u8) -> Result<i8>;
1506    fn read_inverse_i16(&mut self, bits: u8) -> Result<i16>;
1507}
1508
1509impl<'a> SignedRead for BitReader<'a> {
1510    fn read_inverse_i8(&mut self, bits: u8) -> Result<i8> {
1511        debug_assert!(bits < 8);
1512
1513        let value: i8 = self.read_u8(bits)?.try_into()?;
1514        if self.read_bool()? {
1515            Ok(-(value))
1516        } else {
1517            Ok(value)
1518        }
1519    }
1520
1521    fn read_inverse_i16(&mut self, bits: u8) -> Result<i16> {
1522        debug_assert!(bits < 16);
1523
1524        let value: i16 = self.read_u16(bits)?.try_into()?;
1525        if self.read_bool()? {
1526            Ok(-(value))
1527        } else {
1528            Ok(value)
1529        }
1530    }
1531}
1532
1533#[cfg(test)]
1534mod tests {
1535    use super::*;
1536
1537    #[test]
1538    fn parse_metadata() -> Result<()> {
1539        let data: Vec<u8> = vec![0x04, 0x02, 0x03, 0x08, 0x02, 0x28, 0x01, 0x03];
1540
1541        let metadata = Metadata::new(&data)?;
1542
1543        assert_eq!(metadata.profile(), Profile::Profile3);
1544        assert_eq!(metadata.level(), Level::Level4);
1545        assert_eq!(metadata.color_depth(), ColorDepth::Depth8);
1546        assert_eq!(metadata.chroma_subsampling(), MetadataSubsampling::Yuv422);
1547
1548        Ok(())
1549    }
1550}