cros_codecs/codec/av1/
parser.rs

1// Copyright 2023 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 std::borrow::Cow;
6use std::rc::Rc;
7
8use crate::codec::av1::helpers;
9use crate::codec::av1::reader::Reader;
10
11pub const TOTAL_REFS_PER_FRAME: usize = 8;
12pub const NUM_REF_FRAMES: usize = 8;
13pub const REFS_PER_FRAME: usize = 7;
14pub const MAX_SEGMENTS: usize = 8;
15pub const SEG_LVL_ALT_Q: usize = 0;
16pub const SEG_LVL_ALT_LF_Y_V: usize = 1;
17pub const SEG_LVL_REF_FRAME: usize = 5;
18pub const SEG_LVL_SKIP: usize = 6;
19pub const SEG_LVL_GLOBAL_MV: usize = 7;
20pub const SEG_LVL_MAX: usize = 8;
21pub const MAX_TILE_COLS: usize = 64;
22pub const MAX_TILE_ROWS: usize = 64;
23pub const CDEF_MAX: usize = 1 << 3;
24pub const MAX_NUM_PLANES: usize = 3;
25pub const MAX_NUM_Y_POINTS: usize = 16;
26pub const MAX_NUM_CB_POINTS: usize = 16;
27pub const MAX_NUM_CR_POINTS: usize = 16;
28pub const MAX_NUM_POS_LUMA: usize = 25;
29pub const MAX_NUM_SPATIAL_LAYERS: usize = 4;
30pub const MAX_NUM_TEMPORAL_LAYERS: usize = 8;
31pub const MAX_NUM_OPERATING_POINTS: usize = MAX_NUM_SPATIAL_LAYERS * MAX_NUM_TEMPORAL_LAYERS;
32pub const SELECT_SCREEN_CONTENT_TOOLS: usize = 2;
33pub const SELECT_INTEGER_MV: usize = 2;
34pub const PRIMARY_REF_NONE: u32 = 7;
35pub const SUPERRES_DENOM_BITS: usize = 3;
36pub const SUPERRES_DENOM_MIN: usize = 9;
37pub const SUPERRES_NUM: usize = 8;
38pub const MAX_TILE_WIDTH: u32 = 4096;
39pub const MAX_TILE_HEIGHT: u32 = 2304;
40pub const MAX_TILE_AREA: u32 = MAX_TILE_WIDTH * MAX_TILE_HEIGHT;
41pub const RESTORATION_TILESIZE_MAX: u16 = 256;
42pub const WARPEDMODEL_PREC_BITS: u32 = 16;
43pub const WARP_PARAM_REDUCE_BITS: u32 = 6;
44pub const GM_ABS_ALPHA_BITS: u32 = 12;
45pub const GM_ALPHA_PREC_BITS: u32 = 15;
46pub const GM_ABS_TRANS_ONLY_BITS: u32 = 9;
47pub const GM_TRANS_ONLY_PREC_BITS: u32 = 3;
48pub const GM_ABS_TRANS_BITS: u32 = 12;
49pub const GM_TRANS_PREC_BITS: u32 = 6;
50
51// Same as Segmentation_Feature_Bits in the specification. See 5.9.14
52pub const FEATURE_BITS: [u8; SEG_LVL_MAX] = [8, 6, 6, 6, 6, 3, 0, 0];
53// Same as Segmentation_Feature_Signed in the specification. See 5.9.14
54pub const FEATURE_SIGNED: [bool; SEG_LVL_MAX] = [true, true, true, true, true, false, false, false];
55// Same as Segmentation_Feature_Max in the specification. See 5.9.14
56pub const FEATURE_MAX: [i32; SEG_LVL_MAX] = [255, 63, 63, 63, 63, 7, 0, 0];
57
58/// Tells what should be done with the OBU after [`Parser::read_obu`] is called.
59pub enum ObuAction<'a> {
60    /// We should process the OBU normally.
61    Process(Obu<'a>),
62    /// We should drop this OBU and advance to the next one. The u32 is how much
63    /// we should advance.
64    Drop(u32),
65}
66
67#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
68pub enum ObuType {
69    #[default]
70    Reserved = 0,
71    SequenceHeader = 1,
72    TemporalDelimiter = 2,
73    FrameHeader = 3,
74    TileGroup = 4,
75    Metadata = 5,
76    Frame = 6,
77    RedundantFrameHeader = 7,
78    TileList = 8,
79    Reserved2 = 9,
80    Reserved3 = 10,
81    Reserved4 = 11,
82    Reserved5 = 12,
83    Reserved6 = 13,
84    Reserved7 = 14,
85    Padding = 15,
86}
87
88impl TryFrom<u32> for ObuType {
89    type Error = String;
90
91    fn try_from(value: u32) -> Result<Self, Self::Error> {
92        match value {
93            0 => Ok(ObuType::Reserved),
94            1 => Ok(ObuType::SequenceHeader),
95            2 => Ok(ObuType::TemporalDelimiter),
96            3 => Ok(ObuType::FrameHeader),
97            4 => Ok(ObuType::TileGroup),
98            5 => Ok(ObuType::Metadata),
99            6 => Ok(ObuType::Frame),
100            7 => Ok(ObuType::RedundantFrameHeader),
101            8 => Ok(ObuType::TileList),
102            9 => Ok(ObuType::Reserved2),
103            10 => Ok(ObuType::Reserved3),
104            11 => Ok(ObuType::Reserved4),
105            12 => Ok(ObuType::Reserved5),
106            13 => Ok(ObuType::Reserved6),
107            14 => Ok(ObuType::Reserved7),
108            15 => Ok(ObuType::Padding),
109            _ => Err(format!("Invalid ObuType {}", value)),
110        }
111    }
112}
113
114#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
115pub enum Profile {
116    #[default]
117    Profile0 = 0,
118    Profile1 = 1,
119    Profile2 = 2,
120}
121
122impl TryFrom<u32> for Profile {
123    type Error = String;
124
125    fn try_from(value: u32) -> Result<Self, Self::Error> {
126        match value {
127            0 => Ok(Profile::Profile0),
128            1 => Ok(Profile::Profile1),
129            2 => Ok(Profile::Profile2),
130            _ => Err(format!("Invalid Profile {}", value)),
131        }
132    }
133}
134
135#[derive(Clone, Debug, Default, PartialEq, Eq)]
136pub struct ObuHeader {
137    pub obu_type: ObuType,
138    pub extension_flag: bool,
139    pub has_size_field: bool,
140    pub temporal_id: u32,
141    pub spatial_id: u32,
142}
143
144impl ObuHeader {
145    /// Length in bytes
146    #[allow(clippy::len_without_is_empty)]
147    pub fn len(&self) -> usize {
148        if self.extension_flag {
149            2
150        } else {
151            1
152        }
153    }
154}
155
156/// Contains the OBU header and a reference to its data. The OBU itself hasn't been parsed yet.
157#[derive(Clone, Debug, Default, PartialEq, Eq)]
158pub struct Obu<'a> {
159    /// The OBU header.
160    pub header: ObuHeader,
161    /// Amount of bytes from the input consumed to parse this OBU.
162    pub bytes_used: usize,
163    /// The slice backing the OBU.
164    data: Cow<'a, [u8]>,
165}
166
167impl<'a> AsRef<[u8]> for Obu<'a> {
168    fn as_ref(&self) -> &[u8] {
169        self.data.as_ref()
170    }
171}
172
173/// A fully parsed OBU, with additional data when relevant.
174pub enum ParsedObu<'a> {
175    Reserved,
176    SequenceHeader(Rc<SequenceHeaderObu>),
177    TemporalDelimiter,
178    FrameHeader(FrameHeaderObu),
179    TileGroup(TileGroupObu<'a>),
180    Metadata,
181    Frame(FrameObu<'a>),
182    RedundantFrameHeader,
183    TileList,
184    Reserved2,
185    Reserved3,
186    Reserved4,
187    Reserved5,
188    Reserved6,
189    Reserved7,
190    Padding,
191}
192
193impl<'a> ParsedObu<'a> {
194    pub fn obu_type(&self) -> ObuType {
195        match self {
196            ParsedObu::Reserved => ObuType::Reserved,
197            ParsedObu::SequenceHeader(_) => ObuType::SequenceHeader,
198            ParsedObu::TemporalDelimiter => ObuType::TemporalDelimiter,
199            ParsedObu::FrameHeader(_) => ObuType::FrameHeader,
200            ParsedObu::TileGroup(_) => ObuType::TileGroup,
201            ParsedObu::Metadata => ObuType::Metadata,
202            ParsedObu::Frame(_) => ObuType::Frame,
203            ParsedObu::RedundantFrameHeader => ObuType::RedundantFrameHeader,
204            ParsedObu::TileList => ObuType::TileList,
205            ParsedObu::Reserved2 => ObuType::Reserved2,
206            ParsedObu::Reserved3 => ObuType::Reserved3,
207            ParsedObu::Reserved4 => ObuType::Reserved4,
208            ParsedObu::Reserved5 => ObuType::Reserved5,
209            ParsedObu::Reserved6 => ObuType::Reserved6,
210            ParsedObu::Reserved7 => ObuType::Reserved7,
211            ParsedObu::Padding => ObuType::Padding,
212        }
213    }
214}
215
216#[derive(Clone, Debug, Default, PartialEq, Eq)]
217pub struct Tile {
218    /// Same as TileOffset in the specification.
219    pub tile_offset: u32,
220    /// Same as TileSize in the specification.
221    pub tile_size: u32,
222    /// Same as TileRow in the specification.
223    pub tile_row: u32,
224    /// Same as TileCol in the specification.
225    pub tile_col: u32,
226    // Same as MiRowStart in the specification.
227    pub mi_row_start: u32,
228    // Same as MiRowEnd in the specification.
229    pub mi_row_end: u32,
230    // Same as MiColStart in the specification.
231    pub mi_col_start: u32,
232    // Same as MiColEnd in the specification.
233    pub mi_col_end: u32,
234}
235
236#[derive(Clone, Debug, Default, PartialEq, Eq)]
237pub struct TileGroupObu<'a> {
238    /// The OBU backing this tile group.
239    pub obu: Obu<'a>,
240    /// Specifies whether tg_start and tg_end are present. If tg_start and
241    /// tg_end are not present, this tile group covers the entire frame.
242    pub tile_start_and_end_present_flag: bool,
243    /// Specifies the zero-based index of the first tile in the current tile
244    /// group.
245    pub tg_start: u32,
246    /// Specifies the zero-based index of the last tile in the current tile
247    /// group.
248    pub tg_end: u32,
249    /// Contains the tiles in this tile group. Use `tile_offset`to index into
250    /// the OBU data.
251    ///
252    /// The tiles in the Vec span from tg_start to tg_end.
253    pub tiles: Vec<Tile>,
254}
255
256#[derive(Clone, Debug, Default, PartialEq, Eq)]
257pub struct OperatingPoint {
258    /// Specifies the level that the coded video sequence conforms to when
259    /// operating point i is selected.
260    pub seq_level_idx: u8,
261    /// Specifies the tier that the coded video sequence conforms to when
262    /// operating point i is selected.
263    pub seq_tier: u8,
264    /// Specifies the value of operating_point_idc for the selected operating
265    /// point.
266    pub idc: u16,
267    /// If set, indicates that there is a decoder model associated with
268    /// operating point i. If not set, indicates that there is not a decoder
269    /// model associated with operating point i.
270    pub decoder_model_present_for_this_op: bool,
271    /// Specifies the time interval between the arrival of the first bit in the
272    /// smoothing buffer and the subsequent removal of the data that belongs to
273    /// the first coded frame for operating point op, measured in units of
274    /// 1/90000 seconds. The length of decoder_buffer_delay is specified by
275    /// buffer_delay_length_minus_1 + 1, in bits.
276    pub decoder_buffer_delay: u32,
277    /// Specifies, in combination with decoder_buffer_delay\[ op \] syntax
278    /// element, the first bit arrival time of frames to be decoded to the
279    /// smoothing buffer. encoder_buffer_delay is measured in units of 1/90000
280    /// seconds.
281    pub encoder_buffer_delay: u32,
282    /// If set, indicates that the smoothing buffer operates in low-delay mode
283    /// for operating point op. In low-delay mode late decode times and buffer
284    /// underflow are both permitted. If not set, indicates that the smoothing
285    /// buffer operates in strict mode, where buffer underflow is not allowed.
286    pub low_delay_mode_flag: bool,
287    /// If set, indicates that initial_display_delay_minus_1 is specified for
288    /// operating point i. If not set, indicates that
289    /// initial_display_delay_minus_1 is not specified for operating point i.
290    pub initial_display_delay_present_for_this_op: bool,
291    /// Plus 1 specifies, for operating point i, the number of decoded frames
292    /// that should be present in the buffer pool before the first presentable
293    /// frame is displayed. This will ensure that all presentable frames in the
294    /// sequence can be decoded at or before the time that they are scheduled
295    /// for display. If not signaled then initial_display_delay_minus_1\[ i \] =
296    /// BUFFER_POOL_MAX_SIZE - 1.
297    pub initial_display_delay_minus_1: u32,
298}
299
300#[derive(Clone, Debug, Default, PartialEq, Eq)]
301pub struct TimingInfo {
302    /// The number of time units of a clock operating at the frequency
303    /// time_scale Hz that corresponds to one increment of a clock tick counter.
304    /// A display clock tick, in seconds, is equal to num_units_in_display_tick
305    /// divided by time_scale:
306    pub num_units_in_display_tick: u32,
307    /// The number of time units that pass in one second.
308    pub time_scale: u32,
309    /// If set, indicates that pictures should be displayed according to their
310    /// output order with the number of ticks between two consecutive pictures
311    /// (without dropping frames) specified by num_ticks_per_picture_minus_1 +
312    /// 1. If not set, indicates that the interval between two consecutive
313    /// pictures is not specified.
314    pub equal_picture_interval: bool,
315    /// Plus 1 specifies the number of clock ticks corresponding to output time
316    /// between two consecutive pictures in the output order.
317    pub num_ticks_per_picture_minus_1: u32,
318}
319
320#[derive(Clone, Debug, Default, PartialEq, Eq)]
321pub struct DecoderModelInfo {
322    /// Plus 1 specifies the length of the decoder_buffer_delay and the
323    /// encoder_buffer_delay syntax elements, in bits.
324    pub buffer_delay_length_minus_1: u8,
325    /// The number of time units of a decoding clock operating at the frequency
326    /// time_scale Hz that corresponds to one increment of a clock tick counter:
327    pub num_units_in_decoding_tick: u32,
328    /// Plus 1 specifies the length of the buffer_removal_time syntax element,
329    /// in bits.
330    pub buffer_removal_time_length_minus_1: u8,
331    /// Plus 1 specifies the length of the frame_presentation_time syntax
332    /// element, in bits.
333    pub frame_presentation_time_length_minus_1: u32,
334}
335
336/// Defined by the “Color primaries” section of ISO/IEC 23091-4/ITU-T H.273
337/// See 6.4.2
338#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
339pub enum ColorPrimaries {
340    Bt709 = 1,
341    #[default]
342    Unspecified = 2,
343    Bt470M = 4,
344    Bt470bg = 5,
345    Bt601 = 6,
346    Smpte240 = 7,
347    GenericFilm = 8,
348    Bt2020 = 9,
349    Xyz = 10,
350    Smpte431 = 11,
351    Smpte432 = 12,
352    Ebu3213 = 22,
353}
354
355impl TryFrom<u32> for ColorPrimaries {
356    type Error = String;
357
358    fn try_from(value: u32) -> Result<Self, Self::Error> {
359        match value {
360            1 => Ok(ColorPrimaries::Bt709),
361            2 => Ok(ColorPrimaries::Unspecified),
362            4 => Ok(ColorPrimaries::Bt470M),
363            5 => Ok(ColorPrimaries::Bt470bg),
364            6 => Ok(ColorPrimaries::Bt601),
365            7 => Ok(ColorPrimaries::Smpte240),
366            8 => Ok(ColorPrimaries::GenericFilm),
367            9 => Ok(ColorPrimaries::Bt2020),
368            10 => Ok(ColorPrimaries::Xyz),
369            11 => Ok(ColorPrimaries::Smpte431),
370            12 => Ok(ColorPrimaries::Smpte432),
371            22 => Ok(ColorPrimaries::Ebu3213),
372            _ => Err(format!("Invalid ColorPrimaries {}", value)),
373        }
374    }
375}
376
377#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
378pub enum TransferCharacteristics {
379    Reserved0 = 0,
380    Bt709 = 1,
381    #[default]
382    Unspecified = 2,
383    Reserved3 = 3,
384    Bt470m = 4,
385    Bt470bg = 5,
386    Bt601 = 6,
387    Smpte240 = 7,
388    Linear = 8,
389    Log100 = 9,
390    Log100Sqrt10 = 10,
391    Iec61966 = 11,
392    Bt1361 = 12,
393    Srgb = 13,
394    Bt202010Bit = 14,
395    Bt202012Bit = 15,
396    Smpte2084 = 16,
397    Smpte428 = 17,
398    Hlg = 18,
399}
400
401impl TryFrom<u32> for TransferCharacteristics {
402    type Error = String;
403
404    fn try_from(value: u32) -> Result<Self, Self::Error> {
405        match value {
406            0 => Ok(TransferCharacteristics::Reserved0),
407            1 => Ok(TransferCharacteristics::Bt709),
408            2 => Ok(TransferCharacteristics::Unspecified),
409            3 => Ok(TransferCharacteristics::Reserved3),
410            4 => Ok(TransferCharacteristics::Bt470m),
411            5 => Ok(TransferCharacteristics::Bt470bg),
412            6 => Ok(TransferCharacteristics::Bt601),
413            7 => Ok(TransferCharacteristics::Smpte240),
414            8 => Ok(TransferCharacteristics::Linear),
415            9 => Ok(TransferCharacteristics::Log100),
416            10 => Ok(TransferCharacteristics::Log100Sqrt10),
417            11 => Ok(TransferCharacteristics::Iec61966),
418            12 => Ok(TransferCharacteristics::Bt1361),
419            13 => Ok(TransferCharacteristics::Srgb),
420            14 => Ok(TransferCharacteristics::Bt202010Bit),
421            15 => Ok(TransferCharacteristics::Bt202012Bit),
422            16 => Ok(TransferCharacteristics::Smpte2084),
423            17 => Ok(TransferCharacteristics::Smpte428),
424            18 => Ok(TransferCharacteristics::Hlg),
425            _ => Err(format!("Invalid TransferCharacteristics {}", value)),
426        }
427    }
428}
429
430#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
431pub enum BitDepth {
432    #[default]
433    Depth8 = 0,
434    Depth10 = 1,
435    Depth12 = 2,
436}
437
438impl TryFrom<u32> for BitDepth {
439    type Error = String;
440
441    fn try_from(value: u32) -> Result<Self, Self::Error> {
442        match value {
443            0 => Ok(BitDepth::Depth8),
444            1 => Ok(BitDepth::Depth10),
445            2 => Ok(BitDepth::Depth12),
446            _ => Err(format!("Invalid BitDepth {}", value)),
447        }
448    }
449}
450
451#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
452pub enum MatrixCoefficients {
453    Identity = 0,
454    Bt709 = 1,
455    #[default]
456    Unspecified = 2,
457    Reserved3 = 3,
458    Fcc = 4,
459    Bt470bg = 5,
460    Bt601 = 6,
461    Smpte240 = 7,
462    Ycgco = 8,
463    Bt2020Ncl = 9,
464    Bt2020Cl = 10,
465    Smpte2085 = 11,
466    ChromaDerivedNcl = 12,
467    ChromaDerivedCl = 13,
468    Ictcp = 14,
469}
470
471impl TryFrom<u32> for MatrixCoefficients {
472    type Error = String;
473
474    fn try_from(value: u32) -> Result<Self, Self::Error> {
475        match value {
476            0 => Ok(MatrixCoefficients::Identity),
477            1 => Ok(MatrixCoefficients::Bt709),
478            2 => Ok(MatrixCoefficients::Unspecified),
479            3 => Ok(MatrixCoefficients::Reserved3),
480            4 => Ok(MatrixCoefficients::Fcc),
481            5 => Ok(MatrixCoefficients::Bt470bg),
482            6 => Ok(MatrixCoefficients::Bt601),
483            7 => Ok(MatrixCoefficients::Smpte240),
484            8 => Ok(MatrixCoefficients::Ycgco),
485            9 => Ok(MatrixCoefficients::Bt2020Ncl),
486            10 => Ok(MatrixCoefficients::Bt2020Cl),
487            11 => Ok(MatrixCoefficients::Smpte2085),
488            12 => Ok(MatrixCoefficients::ChromaDerivedNcl),
489            13 => Ok(MatrixCoefficients::ChromaDerivedCl),
490            14 => Ok(MatrixCoefficients::Ictcp),
491            _ => Err(format!("Invalid MatrixCoefficients {}", value)),
492        }
493    }
494}
495
496#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
497pub enum ChromaSamplePosition {
498    #[default]
499    Unknown = 0,
500    Vertical = 1,
501    Colocated = 2,
502    Reserved = 3,
503}
504
505impl TryFrom<u32> for ChromaSamplePosition {
506    type Error = String;
507
508    fn try_from(value: u32) -> Result<Self, Self::Error> {
509        match value {
510            0 => Ok(ChromaSamplePosition::Unknown),
511            1 => Ok(ChromaSamplePosition::Vertical),
512            2 => Ok(ChromaSamplePosition::Colocated),
513            3 => Ok(ChromaSamplePosition::Reserved),
514            _ => Err(format!("Invalid ChromaSamplePosition {}", value)),
515        }
516    }
517}
518
519#[derive(Clone, Debug, Default, PartialEq, Eq)]
520pub struct ColorConfig {
521    /// Syntax elements which, together with seq_profile, determine the bit
522    /// depth.
523    pub high_bitdepth: bool,
524    /// Syntax elements which, together with seq_profile, determine the bit
525    /// depth.
526    pub twelve_bit: bool,
527    /// If set, indicates that the video does not contain U and V color planes.
528    /// If not set, indicates that the video contains Y, U, and V color planes.
529    pub mono_chrome: bool,
530    /// If set, specifies that color_primaries, transfer_characteristics, and
531    /// matrix_coefficients are present. If not set, specifies that
532    /// color_primaries, transfer_characteristics and matrix_coefficients are
533    /// not present.
534    pub color_description_present_flag: bool,
535    /// Defined by the “Color primaries” section of ISO/IEC 23091-4/ITU-T H.273.
536    pub color_primaries: ColorPrimaries,
537    /// Defined by the “Transfer characteristics” section of ISO/IEC
538    /// 23091-4/ITU-T H.273.
539    pub transfer_characteristics: TransferCharacteristics,
540    /// Defined by the “Matrix coefficients” section of ISO/IEC 23091-4/ITU-T
541    /// H.273.
542    pub matrix_coefficients: MatrixCoefficients,
543    /// Binary value that is associated with the VideoFullRangeFlag variable
544    /// specified in ISO/IEC 23091-4/ITU- T H.273. color range equal to 0 shall
545    /// be referred to as the studio swing representation and color range equal
546    /// to 1 shall be referred to as the full swing representation for all
547    /// intents relating to this specification.
548    pub color_range: bool,
549    /// Specify the chroma subsampling format
550    pub subsampling_x: bool,
551    /// Specify the chroma subsampling format
552    pub subsampling_y: bool,
553    /// Specifies the sample position for subsampled streams
554    pub chroma_sample_position: ChromaSamplePosition,
555    /// If set, indicates that the U and V planes may have separate delta
556    /// quantizer values. If not set, indicates that the U and V planes will
557    /// share the same delta quantizer value.
558    pub separate_uv_delta_q: bool,
559}
560
561#[derive(Clone, Debug, Default, PartialEq, Eq)]
562pub struct SequenceHeaderObu {
563    /// The OBU header from the OBU that generated this sequence.
564    pub obu_header: ObuHeader,
565    /// Specifies the features that can be used in the coded video sequence.
566    pub seq_profile: Profile,
567    /// If set, specifies that the coded video sequence contains only one coded
568    /// frame. If not set, specifies that the coded video sequence contains one
569    /// or more coded frames.
570    pub still_picture: bool,
571    /// Specifies that the syntax elements not needed by a still picture are
572    /// omitted.
573    pub reduced_still_picture_header: bool,
574    /// Specifies the number of bits minus 1 used for transmitting the frame
575    /// width syntax elements.
576    pub frame_width_bits_minus_1: u8,
577    /// Specifies the number of bits minus 1 used for transmitting the frame
578    /// height syntax elements.
579    pub frame_height_bits_minus_1: u8,
580    /// Specifies the maximum frame width minus 1 for the frames represented by
581    /// this sequence header.
582    pub max_frame_width_minus_1: u16,
583    /// Specifies the maximum frame height minus 1 for the frames represented by
584    /// this sequence header.
585    pub max_frame_height_minus_1: u16,
586    /// Specifies whether frame id numbers are present in the coded video
587    /// sequence.
588    pub frame_id_numbers_present_flag: bool,
589    /// Specifies the number of bits minus 2 used to encode delta_frame_id
590    /// syntax elements.
591    pub delta_frame_id_length_minus_2: u32,
592    /// Used to calculate the number of bits used to encode the frame_id syntax
593    /// element.
594    pub additional_frame_id_length_minus_1: u32,
595    /// When set, indicates that superblocks contain 128x128 luma samples. When
596    /// not set, it indicates that superblocks contain 64x64 luma samples. (The
597    /// number of contained chroma samples depends on subsampling_x and
598    /// subsampling_y.)
599    pub use_128x128_superblock: bool,
600    /// When set, specifies that the use_filter_intra syntax element may be
601    /// present. When not set, specifies that the use_filter_intra syntax
602    /// element will not be present.
603    pub enable_filter_intra: bool,
604    /// Specifies whether the intra edge filtering process should be enabled.
605    pub enable_intra_edge_filter: bool,
606    /// When set, specifies that the mode info for inter blocks may contain the
607    /// syntax element interintra. If not set, specifies that the syntax element
608    /// interintra will not be present.
609    pub enable_interintra_compound: bool,
610    /// When set, specifies that the mode info for inter blocks may contain the
611    /// syntax element compound_type. When not set, specifies that the syntax
612    /// element compound_type will not be present.
613    pub enable_masked_compound: bool,
614    /// When set, indicates that the allow_warped_motion syntax element may be
615    /// present. When not set, indicates that the allow_warped_motion syntax
616    /// element will not be present.
617    pub enable_warped_motion: bool,
618    /// When set, indicates that tools based on the values of order hints may be
619    /// used. When not set, indicates that tools based on order hints are
620    /// disabled.
621    pub enable_order_hint: bool,
622    /// When set, indicates that the inter prediction filter type may be
623    /// specified independently in the horizontal and vertical directions. If
624    /// the flag is not set, only one filter type may be specified, which is
625    /// then used in both directions.
626    pub enable_dual_filter: bool,
627    /// If set, indicates that the distance weights process may be used for
628    /// inter prediction.
629    pub enable_jnt_comp: bool,
630    /// If set, indicates that the use_ref_frame_mvs syntax element may be
631    /// present. If not set, indicates that the use_ref_frame_mvs syntax element
632    /// will not be present.
633    pub enable_ref_frame_mvs: bool,
634    /// If not set, indicates that the seq_force_screen_content_tools syntax
635    /// element will be present. If set, indicates that
636    /// seq_force_screen_content_tools should be set equal to
637    /// SELECT_SCREEN_CONTENT_TOOLS.
638    pub seq_choose_screen_content_tools: bool,
639    /// Equal to SELECT_SCREEN_CONTENT_TOOLS indicates that the
640    /// allow_screen_content_tools syntax element will be present in the frame
641    /// header. Otherwise, seq_force_screen_content_tools contains the value for
642    /// allow_screen_content_tools.
643    pub seq_force_screen_content_tools: u32,
644    /// If not set, indicates that the seq_force_integer_mv syntax element will
645    /// be present. If set, indicates that seq_force_integer_mv should be set
646    /// equal to SELECT_INTEGER_MV.
647    pub seq_choose_integer_mv: bool,
648    /// Equal to SELECT_INTEGER_MV indicates that the force_integer_mv syntax
649    /// element will be present in the frame header (providing
650    /// allow_screen_content_tools is equal to 1). Otherwise,
651    /// seq_force_integer_mv contains the value for force_integer_mv.
652    pub seq_force_integer_mv: u32,
653    /// Used to compute OrderHintBits.
654    pub order_hint_bits_minus_1: i32,
655    /// Specifies the number of bits used for the order_hint syntax element.
656    pub order_hint_bits: i32,
657    /// If set, specifies that the use_superres syntax element will be present
658    /// in the uncompressed header. If not set, specifies that the use_superres
659    /// syntax element will not be present (instead use_superres will be set to
660    /// 0 in the uncompressed header without being read).
661    pub enable_superres: bool,
662    /// If set, specifies that cdef filtering may be enabled. If not set,
663    /// specifies that cdef filtering is disabled.
664    pub enable_cdef: bool,
665    /// If set, specifies that loop restoration filtering may be enabled. If
666    /// not set, specifies that loop restoration filtering is disabled.
667    pub enable_restoration: bool,
668    /// Specifies whether film grain parameters are present in the coded video
669    /// sequence.
670    pub film_grain_params_present: bool,
671    /// Indicates the number of operating points minus 1 present in the coded
672    /// video sequence. An operating point specifies which spatial and temporal
673    /// layers should be decoded.
674    pub operating_points_cnt_minus_1: u32,
675    /// The set of operating points.
676    pub operating_points: [OperatingPoint; MAX_NUM_OPERATING_POINTS],
677    /// Specifies whether decoder model information is present in the coded
678    /// video sequence.
679    pub decoder_model_info_present_flag: bool,
680    /// The decoder model info.
681    pub decoder_model_info: DecoderModelInfo,
682    /// Specifies whether initial display delay information is present in the
683    /// coded video sequence.
684    pub initial_display_delay_present_flag: bool,
685    /// Specifies whether timing info is present in the coded video sequence.
686    pub timing_info_present_flag: bool,
687    /// The timing info.
688    pub timing_info: TimingInfo,
689    /// The color config.
690    pub color_config: ColorConfig,
691
692    /* CamelCase variables in the specification */
693    pub bit_depth: BitDepth,
694    pub num_planes: u32,
695}
696
697#[derive(Clone, Debug, Default, PartialEq, Eq)]
698pub struct StreamInfo {
699    pub seq_header: Rc<SequenceHeaderObu>,
700    pub render_width: u32,
701    pub render_height: u32,
702}
703
704/// A TemporalDelimiterOBU
705#[derive(Clone, Debug, Default, PartialEq, Eq)]
706pub struct TemporalDelimiterObu {
707    pub obu_header: ObuHeader,
708}
709
710#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
711pub enum InterpolationFilter {
712    #[default]
713    EightTap = 0,
714    EightTapSmooth = 1,
715    EightTapSharp = 2,
716    Bilinear = 3,
717    Switchable = 4,
718}
719
720impl TryFrom<u32> for InterpolationFilter {
721    type Error = String;
722
723    fn try_from(value: u32) -> Result<Self, Self::Error> {
724        match value {
725            0 => Ok(InterpolationFilter::EightTap),
726            1 => Ok(InterpolationFilter::EightTapSmooth),
727            2 => Ok(InterpolationFilter::EightTapSharp),
728            3 => Ok(InterpolationFilter::Bilinear),
729            4 => Ok(InterpolationFilter::Switchable),
730            _ => Err(format!("Invalid InterpolationFilter {}", value)),
731        }
732    }
733}
734
735#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
736pub enum TxModes {
737    #[default]
738    Only4x4 = 0,
739    Largest = 1,
740    Select = 2,
741}
742
743impl TryFrom<u32> for TxModes {
744    type Error = String;
745
746    fn try_from(value: u32) -> Result<Self, Self::Error> {
747        match value {
748            0 => Ok(TxModes::Only4x4),
749            1 => Ok(TxModes::Largest),
750            2 => Ok(TxModes::Select),
751            _ => Err(format!("Invalid TxModes {}", value)),
752        }
753    }
754}
755
756#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
757pub enum FrameRestorationType {
758    #[default]
759    None = 0,
760    Wiener = 1,
761    Sgrproj = 2,
762    Switchable = 3,
763}
764
765impl TryFrom<u32> for FrameRestorationType {
766    type Error = String;
767
768    fn try_from(value: u32) -> Result<Self, Self::Error> {
769        match value {
770            0 => Ok(FrameRestorationType::None),
771            1 => Ok(FrameRestorationType::Wiener),
772            2 => Ok(FrameRestorationType::Sgrproj),
773            3 => Ok(FrameRestorationType::Switchable),
774            _ => Err(format!("Invalid FrameRestorationType {}", value)),
775        }
776    }
777}
778
779#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
780pub enum ReferenceFrameType {
781    #[default]
782    Intra = 0,
783    Last = 1,
784    Last2 = 2,
785    Last3 = 3,
786    Golden = 4,
787    BwdRef = 5,
788    AltRef2 = 6,
789    AltRef = 7,
790}
791
792impl TryFrom<u32> for ReferenceFrameType {
793    type Error = String;
794
795    fn try_from(value: u32) -> Result<Self, Self::Error> {
796        match value {
797            0 => Ok(ReferenceFrameType::Intra),
798            1 => Ok(ReferenceFrameType::Last),
799            2 => Ok(ReferenceFrameType::Last2),
800            3 => Ok(ReferenceFrameType::Last3),
801            4 => Ok(ReferenceFrameType::Golden),
802            5 => Ok(ReferenceFrameType::BwdRef),
803            6 => Ok(ReferenceFrameType::AltRef2),
804            7 => Ok(ReferenceFrameType::AltRef),
805            _ => Err(format!("Invalid ReferenceFrameType {}", value)),
806        }
807    }
808}
809
810#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
811pub enum WarpModelType {
812    #[default]
813    Identity = 0,
814    Translation = 1,
815    RotZoom = 2,
816    Affine = 3,
817}
818
819impl TryFrom<u32> for WarpModelType {
820    type Error = String;
821
822    fn try_from(value: u32) -> Result<Self, Self::Error> {
823        match value {
824            0 => Ok(WarpModelType::Identity),
825            1 => Ok(WarpModelType::Translation),
826            2 => Ok(WarpModelType::RotZoom),
827            3 => Ok(WarpModelType::Affine),
828            _ => Err(format!("Invalid WarpModelType {}", value)),
829        }
830    }
831}
832
833#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
834pub enum FrameType {
835    #[default]
836    KeyFrame = 0,
837    InterFrame = 1,
838    IntraOnlyFrame = 2,
839    SwitchFrame = 3,
840}
841
842impl TryFrom<u32> for FrameType {
843    type Error = String;
844
845    fn try_from(value: u32) -> Result<Self, Self::Error> {
846        match value {
847            0 => Ok(FrameType::KeyFrame),
848            1 => Ok(FrameType::InterFrame),
849            2 => Ok(FrameType::IntraOnlyFrame),
850            3 => Ok(FrameType::SwitchFrame),
851            _ => Err(format!("Invalid FrameType {}", value)),
852        }
853    }
854}
855
856#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
857pub enum TxMode {
858    #[default]
859    Only4x4 = 0,
860    Largest = 1,
861    Select = 2,
862}
863
864impl TryFrom<u32> for TxMode {
865    type Error = String;
866
867    fn try_from(value: u32) -> Result<Self, Self::Error> {
868        match value {
869            0 => Ok(TxMode::Only4x4),
870            1 => Ok(TxMode::Largest),
871            2 => Ok(TxMode::Select),
872            _ => Err(format!("Invalid TxMode {}", value)),
873        }
874    }
875}
876
877#[derive(Clone, Debug, Default, PartialEq, Eq)]
878pub struct FrameObu<'a> {
879    pub header: FrameHeaderObu,
880    pub tile_group: TileGroupObu<'a>,
881}
882
883/// A FrameHeaderOBU
884#[derive(Clone, Debug, Default, PartialEq, Eq)]
885pub struct FrameHeaderObu {
886    /// The original OBU header. This may be from a FrameOBU or a FrameHeaderOBU
887    /// directly.
888    pub obu_header: ObuHeader,
889    /// If set, indicates the frame indexed by frame_to_show_map_idx is to be
890    /// output; If not set, indicates that further processing is required.
891    pub show_existing_frame: bool,
892    /// Specifies the frame to be output. It is only available if
893    /// show_existing_frame is set.
894    pub frame_to_show_map_idx: u8,
895    /// Specifies the length of the frame_presentation_time syntax element, in
896    /// bits.
897    pub frame_presentation_time: u32,
898    /// Provides the frame id number for the frame to output.
899    pub display_frame_id: u32,
900    /// Specifies the type of the frame
901    pub frame_type: FrameType,
902    /// If set, specifies that this frame should be immediately output once
903    /// decoded. If not set specifies that this frame should not be
904    /// immediately output. (It may be output later if a later uncompressed
905    /// header uses show_existing_frame is set).
906    pub show_frame: bool,
907    /// When set, specifies that the frame may be output using the
908    /// show_existing_frame mechanism. When not set, specifies that this frame
909    /// will not be output using the show_existing_frame mechanism.
910    pub showable_frame: bool,
911    /// If set, indicates that error resilient mode is enabled;
912    /// error_resilient_mode equal to 0 indicates that error resilient mode is
913    /// disabled.
914    pub error_resilient_mode: bool,
915    /// Specifies whether the CDF update in the symbol decoding process should
916    /// be disabled.
917    pub disable_cdf_update: bool,
918    /// When set, indicates that intra blocks may use palette encoding; When not
919    /// set, indicates that palette encoding is never used.
920    pub allow_screen_content_tools: u32,
921    /// If set, specifies that motion vectors will always be integers. If not
922    /// set, specifies that motion vectors can contain fractional bits.
923    pub force_integer_mv: u32,
924    /// Specifies the frame id number for the current frame. Frame id numbers
925    /// are additional information that do not affect the decoding process, but
926    /// provide decoders with a way of detecting missing reference frames so
927    /// that appropriate action can be taken.
928    pub current_frame_id: u32,
929    /// If not set, specifies that the frame size is equal to the size in the
930    /// sequence header. If set, specifies that the frame size will either be
931    /// specified as the size of one of the reference frames, or computed from
932    /// the frame_width_minus_1 and frame_height_minus_1 syntax elements.
933    pub frame_size_override_flag: bool,
934    /// Specifies OrderHintBits least significant bits of the expected output
935    /// order for this frame.
936    pub order_hint: u32,
937    /// Specifies which reference frame contains the CDF values and other state
938    /// that should be loaded at the start of the frame.
939    pub primary_ref_frame: u32,
940    /// If set, specifies that buffer_removal_time is present.  If not set,
941    /// specifies that buffer_removal_time is not present.
942    pub buffer_removal_time_present_flag: bool,
943    /// Specifies the frame removal time in units of DecCT clock ticks counted
944    /// from the removal time of the last random access point for operating
945    /// point opNum. buffer_removal_time is signaled as a fixed length unsigned
946    /// integer with a length in bits given by
947    /// buffer_removal_time_length_minus_1 + 1.
948    pub buffer_removal_time: Vec<u32>,
949    /// Contains a bitmask that specifies which reference frame slots will be
950    /// updated with the current frame after it is decoded.
951    pub refresh_frame_flags: u32,
952    /// Specifies the expected output order hint for each reference frame.
953    pub ref_order_hint: [u32; NUM_REF_FRAMES],
954    /// If set, indicates that intra block copy may be used in this frame. If
955    /// not set indicates that intra block copy is not allowed in this frame.
956    pub allow_intrabc: bool,
957    /// If set, indicates that only two reference frames are explicitly
958    /// signaled. If not set, indicates that all reference frames are explicitly
959    /// signaled.
960    pub frame_refs_short_signaling: bool,
961    /// Specifies the reference frame to use for LAST_FRAME.
962    pub last_frame_idx: u8,
963    /// Specifies the reference frame to use for GOLDEN_FRAME.
964    pub gold_frame_idx: u8,
965    /// Specifies which reference frames are used by inter frames
966    pub ref_frame_idx: [u8; REFS_PER_FRAME],
967    /// If not set, specifies that motion vectors are specified to quarter pel
968    /// precision; If set, specifies that motion vectors are specified to eighth
969    /// pel precision.
970    pub allow_high_precision_mv: bool,
971    /// If not set, specifies that only the SIMPLE motion mode will be used.
972    pub is_motion_mode_switchable: bool,
973    /// If set, specifies that motion vector information from a previous frame
974    /// can be used when decoding the current frame. If not set, specifies that
975    /// this information will not be used.
976    pub use_ref_frame_mvs: bool,
977    /// If set, indicates that the end of frame CDF update is disabled; If not
978    /// set, indicates that the end of frame CDF update is enabled.
979    pub disable_frame_end_update_cdf: bool,
980    /// If set, indicates that the syntax element motion_mode may be present.
981    /// If not set, indicates that the syntax element motion_mode will not be
982    /// present
983    pub allow_warped_motion: bool,
984    /// If set, specifies that the frame is restricted to a reduced subset of
985    /// the full set of transform types.
986    pub reduced_tx_set: bool,
987    /// If not set, means that the render width and height are inferred from the
988    /// frame width and height. If set, means that the render width and height
989    /// are explicitly coded.
990    pub render_and_frame_size_different: bool,
991    /// If not set, indicates that no upscaling is needed. If set, indicates
992    /// that upscaling is needed.
993    pub use_superres: bool,
994    /// If set indicates that the filter selection is signaled at the block
995    /// level; If not set, indicates that the filter selection is signaled at
996    /// the frame level.
997    pub is_filter_switchable: bool,
998    /// The interpolation filter parameters.
999    pub interpolation_filter: InterpolationFilter,
1000    /// The loop filter parameters.
1001    pub loop_filter_params: LoopFilterParams,
1002    /// The quantization parameters.
1003    pub quantization_params: QuantizationParams,
1004    /// The segmentation parameters.
1005    pub segmentation_params: SegmentationParams,
1006    /// The tile info.
1007    pub tile_info: TileInfo,
1008    /// The CDEF parameters.
1009    pub cdef_params: CdefParams,
1010    /// The loop restoration parameters.
1011    pub loop_restoration_params: LoopRestorationParams,
1012    /// Used to compute TxMode.
1013    pub tx_mode_select: u32,
1014    /// If set specifies that the syntax element skip_mode will be present.  If
1015    /// not set, specifies that skip_mode will not be used for this frame.
1016    pub skip_mode_present: bool,
1017    /// If set, specifies that the mode info for inter blocks contains the
1018    /// syntax element comp_mode that indicates whether to use single or
1019    /// compound reference prediction. If not set, specifies that all inter
1020    /// blocks will use single prediction.
1021    pub reference_select: bool,
1022    /// The global motion parameters.
1023    pub global_motion_params: GlobalMotionParams,
1024    /// The film grain parameters.
1025    pub film_grain_params: FilmGrainParams,
1026
1027    /* CamelCase variables */
1028    pub superres_denom: u32,
1029    pub frame_is_intra: bool,
1030    pub order_hints: [u32; NUM_REF_FRAMES],
1031    pub ref_frame_sign_bias: [bool; NUM_REF_FRAMES],
1032    pub coded_lossless: bool,
1033    pub all_lossless: bool,
1034    pub lossless_array: [bool; MAX_SEGMENTS],
1035    pub seg_qm_level: [[u32; MAX_SEGMENTS]; 3],
1036    pub upscaled_width: u32,
1037    pub frame_width: u32,
1038    pub frame_height: u32,
1039    pub render_width: u32,
1040    pub render_height: u32,
1041    pub tx_mode: TxMode,
1042    pub skip_mode_frame: [u32; 2],
1043    pub mi_cols: u32,
1044    pub mi_rows: u32,
1045    pub header_bytes: usize,
1046}
1047
1048#[derive(Clone, Debug, Default, PartialEq, Eq)]
1049pub struct LoopFilterParams {
1050    /// An array containing loop filter strength values. Different loop filter
1051    /// strength values from the array are used depending on the image plane
1052    /// being filtered, and the edge direction (vertical or horizontal) being
1053    /// filtered.
1054    pub loop_filter_level: [u8; 4],
1055    /// Indicates the sharpness level. The loop_filter_level and
1056    /// loop_filter_sharpness together determine when a block edge is filtered,
1057    /// and by how much the filtering can change the sample values.
1058    pub loop_filter_sharpness: u8,
1059    /// If set, means that the filter level depends on the mode and reference
1060    /// frame used to predict a block. If not set, means that the filter level
1061    /// does not depend on the mode and reference frame.
1062    pub loop_filter_delta_enabled: bool,
1063    /// If set, means that additional syntax elements are present that specify
1064    /// which mode and reference frame deltas are to be updated.
1065    /// loop_filter_delta_update equal to 0 means that these syntax elements are
1066    /// not present.
1067    pub loop_filter_delta_update: bool,
1068    /// Contains the adjustment needed for the filter level based on the chosen
1069    /// reference frame. If this syntax element is not present, it maintains
1070    /// its previous value.
1071    pub loop_filter_ref_deltas: [i8; TOTAL_REFS_PER_FRAME],
1072    /// Contains the adjustment needed for the filter level based on the chosen
1073    /// mode. If this syntax element is not present in the, it maintains its
1074    /// previous value.
1075    pub loop_filter_mode_deltas: [i8; 2],
1076    /// Specifies whether loop filter delta values are present.
1077    pub delta_lf_present: bool,
1078    /// Specifies the left shift which should be applied to decoded loop filter
1079    /// delta values.
1080    pub delta_lf_res: u8,
1081    /// If set, specifies that separate loop filter deltas are sent for
1082    /// horizontal luma edges, vertical luma edges, the U edges, and the V
1083    /// edges. If not set, specifies that the same loop filter delta is used for
1084    /// all edges.
1085    pub delta_lf_multi: bool,
1086}
1087
1088#[derive(Clone, Debug, Default, PartialEq, Eq)]
1089pub struct QuantizationParams {
1090    /// Indicates the base frame qindex. This is used for Y AC coefficients and
1091    /// as the base value for the other quantizers.
1092    pub base_q_idx: u32,
1093    /// Indicates the base frame qindex. This is used for Y AC coefficients and
1094    /// as the base value for the other quantizers.
1095    pub diff_uv_delta: bool,
1096    /// Specifies that the quantizer matrix will be used to compute quantizers.
1097    pub using_qmatrix: bool,
1098    /// Specifies the level in the quantizer matrix that should be used for luma
1099    /// plane decoding.
1100    pub qm_y: u32,
1101    /// Specifies the level in the quantizer matrix that should be used for
1102    /// chroma U plane decoding.
1103    pub qm_u: u32,
1104    /// Specifies the level in the quantizer matrix that should be used for
1105    /// chroma V plane decoding.
1106    pub qm_v: u32,
1107    /// Specifies whether quantizer index delta values are present.
1108    pub delta_q_present: bool,
1109    /// Specifies the left shift which should be applied to decoded quantizer
1110    /// index delta values.
1111    pub delta_q_res: u32,
1112    /// Same as DeltaQYDc
1113    pub delta_q_y_dc: i32,
1114    /// Same as DeltaQUDc
1115    pub delta_q_u_dc: i32,
1116    /// Same as DeltaQUAc
1117    pub delta_q_u_ac: i32,
1118    /// Same as DeltaQVDc
1119    pub delta_q_v_dc: i32,
1120    /// Same as DeltaQVAc
1121    pub delta_q_v_ac: i32,
1122}
1123
1124#[derive(Clone, Debug, Default, PartialEq, Eq)]
1125pub struct SegmentationParams {
1126    /// If set, indicates that this frame makes use of the segmentation tool; If
1127    /// not set, indicates that the frame does not use segmentation.
1128    pub segmentation_enabled: bool,
1129    /// If set, indicates that the segmentation map are updated during the
1130    /// decoding of this frame. If not set, means that the segmentation map from
1131    /// the previous frame is used.
1132    pub segmentation_update_map: bool,
1133    /// If set, indicates that the updates to the segmentation map are coded
1134    /// relative to the existing segmentation map. If not set, indicates that
1135    /// the new segmentation map is coded without reference to the existing
1136    /// segmentation map.
1137    pub segmentation_temporal_update: bool,
1138    /// If set, indicates that new parameters are about to be specified for each
1139    /// segment. If not set, indicates that the segmentation parameters should
1140    /// keep their existing values.
1141    pub segmentation_update_data: bool,
1142    /// If not set, indicates that the corresponding feature is unused and has
1143    /// value equal to 0. If set, indicates that the feature value is coded.
1144    pub feature_enabled: [[bool; SEG_LVL_MAX]; MAX_SEGMENTS],
1145    /// Specifies the feature data for a segment feature.
1146    pub feature_data: [[i16; SEG_LVL_MAX]; MAX_SEGMENTS],
1147    /// Same as SegIdPreSkip
1148    pub seg_id_pre_skip: bool,
1149    /// Same as LastActiveSegId
1150    pub last_active_seg_id: u8,
1151}
1152
1153#[derive(Clone, Debug, PartialEq, Eq)]
1154pub struct TileInfo {
1155    /// If set, means that the tiles are uniformly spaced across the frame. (In
1156    /// other words, all tiles are the same size except for the ones at the
1157    /// right and bottom edge which can be smaller.) If not set, means that the
1158    /// tile sizes are coded.
1159    pub uniform_tile_spacing_flag: bool,
1160    /// Used to compute TileColsLog2.
1161    pub increment_tile_rows_log2: u32,
1162    /// Specifies the width of a tile minus 1 in units of superblocks.
1163    pub width_in_sbs_minus_1: [u32; MAX_TILE_COLS],
1164    /// Specifies the height of a tile minus 1 in units of superblocks.
1165    pub height_in_sbs_minus_1: [u32; MAX_TILE_ROWS],
1166    /// Specifies which tile to use for the CDF update
1167    pub context_update_tile_id: u32,
1168    /// An array specifying the start column (in units of 4x4 luma samples) for
1169    /// each tile across the image.
1170    pub mi_col_starts: [u32; MAX_TILE_COLS + 1],
1171    /// An array specifying the start row (in units of 4x4 luma samples) for
1172    /// each tile down the image.
1173    pub mi_row_starts: [u32; MAX_TILE_ROWS + 1],
1174    /// Specifies the base 2 logarithm of the desired number of tiles down the
1175    /// frame.
1176    pub tile_cols_log2: u32,
1177    /// Specifies the number of tiles across the frame.
1178    pub tile_cols: u32,
1179    /// Specifies the base 2 logarithm of the desired number of tiles down the
1180    /// frame.
1181    pub tile_rows_log2: u32,
1182    /// Secifies the number of tiles down the frame
1183    pub tile_rows: u32,
1184    /// Specifies the number of bytes needed to code each tile size.
1185    pub tile_size_bytes: u32,
1186}
1187
1188impl Default for TileInfo {
1189    fn default() -> Self {
1190        Self {
1191            uniform_tile_spacing_flag: Default::default(),
1192            increment_tile_rows_log2: Default::default(),
1193            width_in_sbs_minus_1: [0; MAX_TILE_COLS],
1194            height_in_sbs_minus_1: [0; MAX_TILE_ROWS],
1195            context_update_tile_id: Default::default(),
1196            mi_col_starts: [0; MAX_TILE_COLS + 1],
1197            mi_row_starts: [0; MAX_TILE_ROWS + 1],
1198            tile_cols_log2: Default::default(),
1199            tile_cols: Default::default(),
1200            tile_rows_log2: Default::default(),
1201            tile_rows: Default::default(),
1202            tile_size_bytes: Default::default(),
1203        }
1204    }
1205}
1206
1207#[derive(Clone, Debug, Default, PartialEq, Eq)]
1208pub struct CdefParams {
1209    /// Controls the amount of damping in the deringing filter.
1210    pub cdef_damping: u32,
1211    /// Specifies the number of bits needed to specify which CDEF filter to
1212    /// apply.
1213    pub cdef_bits: u32,
1214    /// Specify the strength of the primary filter.
1215    pub cdef_y_pri_strength: [u32; CDEF_MAX],
1216    /// Specify the strength of the secondary filter.
1217    pub cdef_y_sec_strength: [u32; CDEF_MAX],
1218    /// Specify the strength of the primary filter.
1219    pub cdef_uv_pri_strength: [u32; CDEF_MAX],
1220    /// Specify the strength of the secondary filter.
1221    pub cdef_uv_sec_strength: [u32; CDEF_MAX],
1222}
1223
1224#[derive(Clone, Debug, Default, PartialEq, Eq)]
1225pub struct LoopRestorationParams {
1226    /// Specifies if the luma restoration size should be halved.
1227    pub lr_unit_shift: u8,
1228    /// Only present for 4:2:0 formats and specifies if the chroma size should
1229    /// be half the luma size.
1230    pub lr_uv_shift: u8,
1231    /// Same as FrameRestorationType in the specification.
1232    pub frame_restoration_type: [FrameRestorationType; MAX_NUM_PLANES],
1233    /// Same as LoopRestorationSize in the specification.
1234    pub loop_restoration_size: [u16; MAX_NUM_PLANES],
1235    /// Same as UsesLr in the specification.
1236    pub uses_lr: bool,
1237    /// Same as UsesChromaLr in the specification.
1238    pub uses_chroma_lr: bool,
1239}
1240
1241#[derive(Clone, Debug, Default, PartialEq, Eq)]
1242pub struct GlobalMotionParams {
1243    /// Specifies whether global motion parameters are present for a particular
1244    /// reference frame.
1245    pub is_global: [bool; NUM_REF_FRAMES],
1246    /// Specifies whether a particular reference frame uses rotation and zoom
1247    /// global motion.
1248    pub is_rot_zoom: [bool; NUM_REF_FRAMES],
1249    /// Specifies whether a particular reference frame uses translation global
1250    /// motion.
1251    pub is_translation: [bool; NUM_REF_FRAMES],
1252    /// gm_params\[ ref \]\[ j \] is set equal to SavedGmParams\[
1253    /// frame_to_show_map_idx \]\[ ref \]\[ j \] for ref = LAST_FRAME..ALTREF_FRAME,
1254    /// for j = 0..5.
1255    pub gm_params: [[i32; 6]; NUM_REF_FRAMES],
1256    /// Whether the parameters are valid (see warpValid and section 7.11.3.6)
1257    pub warp_valid: [bool; NUM_REF_FRAMES],
1258    /// Same as GmType.
1259    pub gm_type: [WarpModelType; NUM_REF_FRAMES],
1260}
1261
1262#[derive(Clone, Debug, Default, PartialEq, Eq)]
1263pub struct FilmGrainParams {
1264    /// If set, specifies that film grain should be added to this frame. If not
1265    /// set, specifies that film grain should not be added.
1266    pub apply_grain: bool,
1267    /// Specifies the starting value for the pseudo-random numbers used during
1268    /// film grain synthesis.
1269    pub grain_seed: u16,
1270    /// If set means that a new set of parameters should be sent.  If not set,
1271    /// means that the previous set of parameters should be used.
1272    pub update_grain: bool,
1273    /// Indicates which reference frame contains the film grain parameters to be
1274    /// used for this frame.
1275    pub film_grain_params_ref_idx: u8,
1276    /// Specifies the number of points for the piece-wise linear scaling
1277    /// function of the luma component.
1278    pub num_y_points: u8,
1279    /// Represents the x (luma value) coordinate for the i-th point of the
1280    /// piecewise linear scaling function for luma component. The values are
1281    /// signaled on the scale of 0..255. (In case of 10 bit video, these values
1282    /// correspond to luma values divided by 4. In case of 12 bit video, these
1283    /// values correspond to luma values divided by 16.)
1284    pub point_y_value: [u8; MAX_NUM_Y_POINTS],
1285    /// Pepresents the scaling (output) value for the i-th point of the
1286    /// piecewise linear scaling function for luma component.
1287    pub point_y_scaling: [u8; MAX_NUM_Y_POINTS],
1288    /// Specifies that the chroma scaling is inferred from the luma scaling.
1289    pub chroma_scaling_from_luma: bool,
1290    /// Specifies the number of points for the piece-wise linear scaling
1291    /// function of the cb component.
1292    pub num_cb_points: u8,
1293    /// Represents the x coordinate for the i-th point of the piece-wise linear
1294    /// scaling function for cb component. The values are signaled on the scale
1295    /// of 0..255.
1296    pub point_cb_value: [u8; MAX_NUM_CB_POINTS],
1297    /// Represents the scaling (output) value for the i-th point of the
1298    /// piecewise linear scaling function for cb component.
1299    pub point_cb_scaling: [u8; MAX_NUM_CB_POINTS],
1300    /// Specifies represents the number of points for the piece-wise linear
1301    /// scaling function of the cr component.
1302    pub num_cr_points: u8,
1303    /// Represents the x coordinate for the i-th point of the piece-wise linear
1304    /// scaling function for cr component. The values are signaled on the scale
1305    /// of 0..255.
1306    pub point_cr_value: [u8; MAX_NUM_CR_POINTS],
1307    /// Represents the scaling (output) value for the i-th point of the
1308    /// piecewise linear scaling function for cr component.
1309    pub point_cr_scaling: [u8; MAX_NUM_CR_POINTS],
1310    /// Represents the shift – 8 applied to the values of the chroma component.
1311    /// The grain_scaling_minus_8 can take values of 0..3 and determines the
1312    /// range and quantization step of the standard deviation of film grain.
1313    pub grain_scaling_minus_8: u8,
1314    /// Specifies the number of auto-regressive coefficients for luma and chroma.
1315    pub ar_coeff_lag: u32,
1316    /// Specifies auto-regressive coefficients used for the Y plane.
1317    pub ar_coeffs_y_plus_128: [u8; MAX_NUM_POS_LUMA],
1318    /// Specifies auto-regressive coefficients used for the U plane.
1319    pub ar_coeffs_cb_plus_128: [u8; MAX_NUM_POS_LUMA],
1320    /// Specifies auto-regressive coefficients used for the V plane.
1321    pub ar_coeffs_cr_plus_128: [u8; MAX_NUM_POS_LUMA],
1322    /// Specifies the range of the auto-regressive coefficients. Values of 0, 1,
1323    /// 2, and 3 correspond to the ranges for auto-regressive coefficients of
1324    /// [-2, 2), [-1, 1), [-0.5, 0.5) and [-0.25, 0.25) respectively.
1325    pub ar_coeff_shift_minus_6: u8,
1326    /// Specifies how much the Gaussian random numbers should be scaled down
1327    /// during the grain synthesis process.
1328    pub grain_scale_shift: u8,
1329    /// Represents a multiplier for the cb component used in derivation of the
1330    /// input index to the cb component scaling function.
1331    pub cb_mult: u8,
1332    /// Represents a multiplier for the average luma component used in
1333    /// derivation of the input index to the cb component scaling function.
1334    pub cb_luma_mult: u8,
1335    /// Represents an offset used in derivation of the input index to the cb
1336    /// component scaling function.
1337    pub cb_offset: u16,
1338    /// Represents a multiplier for the cr component used in derivation of the
1339    /// input index to the cr component scaling function.
1340    pub cr_mult: u8,
1341    /// Represents a multiplier for the average luma component used in
1342    /// derivation of the input index to the cr component scaling function.
1343    pub cr_luma_mult: u8,
1344    /// Represents an offset used in derivation of the input index to the cr
1345    /// component scaling function.
1346    pub cr_offset: u16,
1347    /// If set, indicates that the overlap between film grain blocks shall be
1348    /// applied. If not set, indicates that the overlap between film grain
1349    /// blocks shall not be applied.
1350    pub overlap_flag: bool,
1351    /// If set, indicates that clipping to the restricted (studio) range shall
1352    /// be applied to the sample values after adding the film grain (see the
1353    /// semantics for color_range for an explanation of studio swing).  If not
1354    /// set, indicates that clipping to the full range shall be applied to the
1355    /// sample values after adding the film grain.
1356    pub clip_to_restricted_range: bool,
1357}
1358
1359/// Keeps track of the state of the reference frames in the parser. All
1360/// variables are CamelCase.
1361#[derive(Clone, Debug, Default, PartialEq, Eq)]
1362struct ReferenceFrameInfo {
1363    /// An array which is indexed by a reference picture slot number. A value of
1364    /// true in the array signifies that the corresponding reference picture
1365    /// slot is valid for use as a reference picture, while a value of false
1366    /// signifies that the corresponding reference picture slot is not valid for
1367    /// use as a reference picture.
1368    ref_valid: bool,
1369    /// Specifies the frame id for each reference frame.
1370    ref_frame_id: u32,
1371    /// See 7.20 Reference Frame Update Process.
1372    ref_upscaled_width: u32,
1373    /// See 7.20 Reference Frame Update Process.
1374    ref_frame_width: u32,
1375    /// See 7.20 Reference Frame Update Process.
1376    ref_frame_height: u32,
1377    /// See 7.20 Reference Frame Update Process.
1378    ref_render_width: u32,
1379    /// See 7.20 Reference Frame Update Process.
1380    ref_render_height: u32,
1381    /// See 7.20 Reference Frame Update Process.
1382    ref_mi_cols: u32,
1383    /// See 7.20 Reference Frame Update Process.
1384    ref_mi_rows: u32,
1385    /// See 7.20 Reference Frame Update Process.
1386    ref_frame_type: FrameType,
1387    /// See 7.20 Reference Frame Update Process.
1388    ref_subsampling_x: bool,
1389    /// See 7.20 Reference Frame Update Process.
1390    ref_subsampling_y: bool,
1391    /// See 7.20 Reference Frame Update Process.
1392    ref_bit_depth: BitDepth,
1393    /// See 7.20 Reference Frame Update Process.
1394    ref_order_hint: u32,
1395    /// The saved segmentation parameters.
1396    segmentation_params: SegmentationParams,
1397    /// The saved global motion parameters.
1398    global_motion_params: GlobalMotionParams,
1399    /// The saved loop filter parameters.
1400    loop_filter_params: LoopFilterParams,
1401    /// The saved film grain parameters.
1402    film_grain_params: FilmGrainParams,
1403    /// The saved tile info parameters.
1404    tile_info: TileInfo,
1405    display_frame_id: u32,
1406    showable_frame: bool,
1407}
1408
1409#[derive(Clone, Debug, Default)]
1410pub struct AnnexBState {
1411    pub temporal_unit_size: u32,
1412    pub frame_unit_size: u32,
1413    pub temporal_unit_consumed: u32,
1414    pub frame_unit_consumed: u32,
1415}
1416
1417#[derive(Clone, Debug)]
1418enum StreamFormat {
1419    LowOverhead,
1420    AnnexB(AnnexBState),
1421}
1422
1423#[derive(Debug)]
1424pub struct Parser {
1425    stream_format: StreamFormat,
1426    operating_point: u32,
1427    /// Same as SeenFrameHeader in the specification
1428    seen_frame_header: bool,
1429    operating_point_idc: u16,
1430    should_probe_for_annexb: bool,
1431    is_first_frame: bool,
1432    ref_info: [ReferenceFrameInfo; NUM_REF_FRAMES],
1433
1434    /* CamelCase variables */
1435    mi_cols: u32,
1436    mi_rows: u32,
1437    prev_frame_id: u32,
1438    current_frame_id: u32,
1439    mi_col_starts: [u32; MAX_TILE_COLS + 1],
1440    mi_row_starts: [u32; MAX_TILE_ROWS + 1],
1441    tile_cols_log2: u32,
1442    tile_cols: u32,
1443    tile_rows_log2: u32,
1444    tile_rows: u32,
1445    tile_size_bytes: u32,
1446
1447    /// We keep this to implement frame_header_copy() in the specification, and to fill in
1448    /// StreamInfo render_width and render_height.
1449    pub last_frame_header: Option<FrameHeaderObu>,
1450    /// The last SequenceHeaderObu parsed.
1451    pub sequence_header: Option<Rc<SequenceHeaderObu>>,
1452}
1453
1454impl Parser {
1455    /// Probes the input data for the Annex B format. Anything other than
1456    /// Ok(true) refers to data in "low-overhead" format instead, as we are trying to parse
1457    fn annexb_probe(data: &[u8]) -> Result<bool, String> {
1458        let mut r = Reader::new(data);
1459        let mut seen_sequence = false;
1460        let mut seen_frame = false;
1461
1462        // Try reading the first TU and frame unit size
1463        let temporal_unit_size = r.read_leb128()?;
1464        if temporal_unit_size == 0 {
1465            return Ok(false);
1466        }
1467
1468        let frame_unit_size = r.read_leb128()?;
1469        if frame_unit_size == 0 || frame_unit_size > temporal_unit_size {
1470            return Ok(false);
1471        }
1472
1473        let obu_length = r.read_leb128()?;
1474        if obu_length == 0 || obu_length > frame_unit_size {
1475            return Ok(false);
1476        }
1477
1478        // The first OBU in the first frame_unit of each temporal_unit must
1479        // be a temporal delimiter OBU (and this is the only place temporal
1480        // delimiter OBUs can appear)
1481        let header = Self::parse_obu_header(&mut r.clone())?;
1482        if !matches!(header.obu_type, ObuType::TemporalDelimiter) {
1483            return Ok(false);
1484        }
1485
1486        // Try identifying a sequence and a frame.
1487        r.0.skip_bits(obu_length as usize * 8)?;
1488        let mut num_bytes_read = 0;
1489
1490        loop {
1491            let obu_length = r.read_leb128()?;
1492            let mut obu_reader = r.clone();
1493
1494            r.0.skip_bits(obu_length as usize * 8)?;
1495            num_bytes_read += obu_length;
1496
1497            if !seen_sequence {
1498                let header = Self::parse_obu_header(&mut obu_reader)?;
1499                seen_sequence = matches!(header.obu_type, ObuType::SequenceHeader);
1500            }
1501
1502            if !seen_frame {
1503                let header = Self::parse_obu_header(&mut obu_reader)?;
1504                seen_frame = matches!(header.obu_type, ObuType::Frame | ObuType::FrameHeader);
1505            }
1506
1507            if seen_sequence && seen_frame {
1508                // OK, enough evidence of Annex B format.
1509                return Ok(true);
1510            }
1511
1512            if num_bytes_read >= frame_unit_size {
1513                // We read what we've identified as the first frame and yet no
1514                // sequence and no actual frames were found.
1515                return Ok(false);
1516            }
1517        }
1518    }
1519
1520    fn compute_image_size(&mut self, fh: &mut FrameHeaderObu) {
1521        fh.mi_cols = 2 * ((fh.frame_width + 7) >> 3);
1522        fh.mi_rows = 2 * ((fh.frame_height + 7) >> 3);
1523        self.mi_cols = fh.mi_cols;
1524        self.mi_rows = fh.mi_rows;
1525    }
1526
1527    // 5.9.8
1528    fn parse_superres_params(
1529        fh: &mut FrameHeaderObu,
1530        r: &mut Reader,
1531        seq: &SequenceHeaderObu,
1532    ) -> Result<(), String> {
1533        if seq.enable_superres {
1534            fh.use_superres = r.0.read_bit()?;
1535        } else {
1536            fh.use_superres = false;
1537        }
1538
1539        if fh.use_superres {
1540            fh.superres_denom =
1541                r.0.read_bits::<u32>(SUPERRES_DENOM_BITS)? + SUPERRES_DENOM_MIN as u32;
1542        } else {
1543            fh.superres_denom = SUPERRES_NUM as u32;
1544        }
1545
1546        fh.upscaled_width = fh.frame_width;
1547        fh.frame_width =
1548            (fh.upscaled_width * SUPERRES_NUM as u32 + (fh.superres_denom / 2)) / fh.superres_denom;
1549
1550        Ok(())
1551    }
1552
1553    // 7.8 verbatim.
1554    fn set_frame_refs(
1555        &self,
1556        fh: &mut FrameHeaderObu,
1557        ref_order_hint: &[u32; NUM_REF_FRAMES],
1558    ) -> Result<(), String> {
1559        let seq = self.sequence()?;
1560        let mut ref_frame_idx = [-1i32; REFS_PER_FRAME];
1561
1562        ref_frame_idx[0] = fh.last_frame_idx.into();
1563        ref_frame_idx[ReferenceFrameType::Golden as usize - ReferenceFrameType::Last as usize] =
1564            fh.gold_frame_idx.into();
1565
1566        let mut used_frame = [false; NUM_REF_FRAMES];
1567        used_frame[fh.last_frame_idx as usize] = true;
1568        used_frame[fh.gold_frame_idx as usize] = true;
1569
1570        let cur_frame_hint = 1 << (seq.order_hint_bits - 1);
1571        let mut shifted_order_hints = [0; NUM_REF_FRAMES];
1572        for i in 0..NUM_REF_FRAMES {
1573            shifted_order_hints[i] = cur_frame_hint
1574                + helpers::get_relative_dist(
1575                    seq.enable_order_hint,
1576                    seq.order_hint_bits,
1577                    ref_order_hint[i].try_into().unwrap(),
1578                    fh.order_hint.try_into().unwrap(),
1579                );
1580        }
1581
1582        let mut latest_order_hint = shifted_order_hints[fh.last_frame_idx as usize];
1583        if latest_order_hint >= cur_frame_hint {
1584            return Err("It is a requirement of bitstream conformance that last_order_hint < cur_frame_hint".into());
1585        }
1586
1587        let mut earliest_order_hint = shifted_order_hints[fh.gold_frame_idx as usize];
1588        if earliest_order_hint >= cur_frame_hint {
1589            return Err("It is a requirement of bitstream conformance that gold_order_hint < cur_frame_hint".into());
1590        }
1591
1592        let ref_ = helpers::find_latest_backward(
1593            &shifted_order_hints,
1594            &used_frame,
1595            cur_frame_hint,
1596            &mut latest_order_hint,
1597        );
1598
1599        if ref_ >= 0 {
1600            ref_frame_idx
1601                [ReferenceFrameType::AltRef as usize - ReferenceFrameType::Last as usize] = ref_;
1602            used_frame[ref_ as usize] = true;
1603        }
1604
1605        let ref_ = helpers::find_earliest_backward(
1606            &shifted_order_hints,
1607            &used_frame,
1608            cur_frame_hint,
1609            &mut earliest_order_hint,
1610        );
1611
1612        if ref_ >= 0 {
1613            ref_frame_idx
1614                [ReferenceFrameType::BwdRef as usize - ReferenceFrameType::Last as usize] = ref_;
1615            used_frame[ref_ as usize] = true;
1616        }
1617
1618        let ref_ = helpers::find_earliest_backward(
1619            &shifted_order_hints,
1620            &used_frame,
1621            cur_frame_hint,
1622            &mut earliest_order_hint,
1623        );
1624
1625        if ref_ >= 0 {
1626            ref_frame_idx
1627                [ReferenceFrameType::AltRef2 as usize - ReferenceFrameType::Last as usize] = ref_;
1628            used_frame[ref_ as usize] = true;
1629        }
1630
1631        const REF_FRAME_LIST: [usize; 5] = [
1632            ReferenceFrameType::Last2 as usize - ReferenceFrameType::Last as usize,
1633            ReferenceFrameType::Last3 as usize - ReferenceFrameType::Last as usize,
1634            ReferenceFrameType::BwdRef as usize - ReferenceFrameType::Last as usize,
1635            ReferenceFrameType::AltRef2 as usize - ReferenceFrameType::Last as usize,
1636            ReferenceFrameType::AltRef as usize - ReferenceFrameType::Last as usize,
1637        ];
1638
1639        #[allow(clippy::needless_range_loop)]
1640        for i in 0..REFS_PER_FRAME - 2 {
1641            let ref_frame = REF_FRAME_LIST[i];
1642
1643            if ref_frame_idx[ref_frame] < 0 {
1644                let ref_ = helpers::find_latest_forward(
1645                    &shifted_order_hints,
1646                    &used_frame,
1647                    cur_frame_hint,
1648                    &mut latest_order_hint,
1649                );
1650
1651                if ref_ >= 0 {
1652                    ref_frame_idx[ref_frame] = ref_;
1653                    used_frame[ref_ as usize] = true;
1654                }
1655            }
1656        }
1657
1658        let mut ref_ = 0;
1659        earliest_order_hint = shifted_order_hints[0];
1660        #[allow(clippy::needless_range_loop)]
1661        for i in 1..NUM_REF_FRAMES {
1662            let hint = shifted_order_hints[i];
1663            if hint < earliest_order_hint {
1664                ref_ = i as u8;
1665                earliest_order_hint = hint;
1666            }
1667        }
1668
1669        fh.ref_frame_idx
1670            .iter_mut()
1671            .zip(ref_frame_idx.iter().copied())
1672            .for_each(|(dest, src)| *dest = if src < 0 { ref_ } else { src as u8 });
1673
1674        Ok(())
1675    }
1676
1677    // 5.9.5.
1678    fn parse_frame_size(&mut self, fh: &mut FrameHeaderObu, r: &mut Reader) -> Result<(), String> {
1679        let seq = self.sequence()?;
1680        if fh.frame_size_override_flag {
1681            let n = seq.frame_width_bits_minus_1 + 1;
1682            fh.frame_width = r.0.read_bits::<u32>(n as usize)? + 1;
1683
1684            let n = seq.frame_height_bits_minus_1 + 1;
1685            fh.frame_height = r.0.read_bits::<u32>(n as usize)? + 1;
1686        } else {
1687            fh.frame_width = seq.max_frame_width_minus_1 as u32 + 1;
1688            fh.frame_height = seq.max_frame_height_minus_1 as u32 + 1;
1689        }
1690
1691        Self::parse_superres_params(fh, r, seq)?;
1692        self.compute_image_size(fh);
1693
1694        Ok(())
1695    }
1696
1697    fn parse_render_size(fh: &mut FrameHeaderObu, r: &mut Reader) -> Result<(), String> {
1698        fh.render_and_frame_size_different = r.0.read_bit()?;
1699        if fh.render_and_frame_size_different {
1700            fh.render_width = r.0.read_bits::<u32>(16)? + 1;
1701            fh.render_height = r.0.read_bits::<u32>(16)? + 1;
1702        } else {
1703            fh.render_width = fh.upscaled_width;
1704            fh.render_height = fh.frame_height;
1705        }
1706        Ok(())
1707    }
1708
1709    fn frame_size_with_refs(
1710        &mut self,
1711        fh: &mut FrameHeaderObu,
1712        r: &mut Reader,
1713    ) -> Result<(), String> {
1714        let mut found_ref = false;
1715        let seq = self.sequence()?;
1716
1717        for i in 0..REFS_PER_FRAME {
1718            found_ref = r.0.read_bit()?;
1719
1720            if found_ref {
1721                let rf = &self.ref_info[fh.ref_frame_idx[i] as usize];
1722                fh.upscaled_width = rf.ref_upscaled_width;
1723                fh.frame_width = fh.upscaled_width;
1724                fh.frame_height = rf.ref_frame_height;
1725                fh.render_width = rf.ref_render_width;
1726                fh.render_height = rf.ref_render_height;
1727                break;
1728            }
1729        }
1730
1731        if !found_ref {
1732            self.parse_frame_size(fh, r)?;
1733            Self::parse_render_size(fh, r)?;
1734        } else {
1735            Self::parse_superres_params(fh, r, seq)?;
1736            self.compute_image_size(fh);
1737        }
1738
1739        Ok(())
1740    }
1741
1742    /// Skip the padding bits, ensuring that they actually make sense.
1743    fn skip_and_check_trailing_bits(r: &mut Reader, obu: &Obu) -> Result<(), String> {
1744        // We can't have that in parse_obu as per the spec, because the reader
1745        // is not initialized on our design at that point, so move the check to
1746        // inside this function.
1747        if obu.data.len() == 0
1748            || matches!(
1749                obu.header.obu_type,
1750                ObuType::TileList | ObuType::TileGroup | ObuType::Frame
1751            )
1752        {
1753            return Ok(());
1754        }
1755        let num_trailing = obu.as_ref().len() as u64 * 8 - r.0.position();
1756        r.read_trailing_bits(num_trailing)?;
1757        Ok(())
1758    }
1759
1760    fn parse_obu_header(r: &mut Reader) -> Result<ObuHeader, String> {
1761        let _obu_forbidden_bit = r.0.read_bit()?;
1762
1763        let mut header = ObuHeader {
1764            obu_type: ObuType::try_from(r.0.read_bits::<u32>(4)?)?,
1765            extension_flag: r.0.read_bit()?,
1766            has_size_field: r.0.read_bit()?,
1767            temporal_id: Default::default(),
1768            spatial_id: Default::default(),
1769        };
1770
1771        let obu_reserved_1bit = r.0.read_bit()?;
1772        assert!(!obu_reserved_1bit); // Must be set to zero as per spec.
1773
1774        if header.extension_flag {
1775            header.temporal_id = r.0.read_bits::<u32>(3)?;
1776            header.spatial_id = r.0.read_bits::<u32>(2)?;
1777            let _ = r.0.read_bits::<u32>(3)?;
1778        }
1779
1780        Ok(header)
1781    }
1782
1783    /// Parses one OBU from `data`, which can be in Annex B or low-overhead
1784    /// format.
1785    ///
1786    /// `None` may eventually be returned if the OBU is to be dropped.
1787    pub fn read_obu<'a>(&mut self, data: &'a [u8]) -> Result<ObuAction<'a>, String> {
1788        if data.is_empty() {
1789            return Err("Empty data".into());
1790        }
1791
1792        let mut reader = Reader::new(data);
1793
1794        if self.should_probe_for_annexb {
1795            // Try probing for Annex B data.
1796            self.stream_format = if matches!(Self::annexb_probe(data), Ok(true)) {
1797                log::debug!("Parsing an Annex B stream");
1798                StreamFormat::AnnexB(AnnexBState::default())
1799            } else {
1800                log::debug!("Parsing a low-overhead stream");
1801                StreamFormat::LowOverhead
1802            };
1803
1804            self.should_probe_for_annexb = false;
1805        }
1806
1807        let obu_length: usize = if let StreamFormat::AnnexB(annexb_state) = &mut self.stream_format
1808        {
1809            // Read the length to skip to the start of the open_bitstream_unit()
1810            // syntax element.
1811            let obu_length = reader.current_annexb_obu_length(annexb_state)?;
1812            match obu_length {
1813                Some(length) => length,
1814                None => return Ok(ObuAction::Drop(reader.consumed(0))),
1815            }
1816        } else {
1817            0
1818        };
1819
1820        let start_pos = reader.consumed(0);
1821
1822        // Both "low-overhead" and Annex B are now at the same point, i.e.: a
1823        // open_bitstream_unit() follows.
1824        let header = Self::parse_obu_header(&mut reader)?;
1825        if matches!(self.stream_format, StreamFormat::LowOverhead) {
1826            assert!(header.has_size_field);
1827        }
1828
1829        let obu_size: usize = if header.has_size_field {
1830            reader.read_leb128()? as usize
1831        } else {
1832            /* trap any bugs when computing the final length */
1833            obu_length
1834                .checked_sub(1)
1835                .ok_or::<String>("obu_length must be greater than 0".into())?
1836                .checked_sub(usize::from(header.extension_flag))
1837                .ok_or::<String>("obu_length too short".into())?
1838        };
1839
1840        let consumed = reader.consumed(start_pos);
1841
1842        if let StreamFormat::AnnexB(annexb_state) = &mut self.stream_format {
1843            annexb_state.temporal_unit_consumed += consumed;
1844            annexb_state.frame_unit_consumed += consumed;
1845
1846            annexb_state.temporal_unit_consumed += u32::try_from(obu_size).unwrap();
1847            annexb_state.frame_unit_consumed += u32::try_from(obu_size).unwrap();
1848        }
1849
1850        assert!(reader.0.position() % 8 == 0);
1851        let start_offset: usize = (reader.0.position() / 8).try_into().unwrap();
1852
1853        log::debug!(
1854            "Identified OBU type {:?}, data size: {}, obu_size: {}",
1855            header.obu_type,
1856            start_offset + obu_size,
1857            obu_size
1858        );
1859
1860        if header.obu_type != ObuType::SequenceHeader
1861            && header.obu_type != ObuType::TemporalDelimiter
1862            && self.operating_point_idc != 0
1863            && header.extension_flag
1864        {
1865            let in_temporal_layer = ((self.operating_point_idc >> header.temporal_id) & 1) != 0;
1866            let in_spatial_layer = ((self.operating_point_idc >> (header.spatial_id + 8)) & 1) != 0;
1867            if !in_temporal_layer || !in_spatial_layer {
1868                log::debug!("Dropping obu as per drop_obu() in the specification",);
1869                return Ok(ObuAction::Drop(reader.consumed(0)));
1870            }
1871        }
1872
1873        Ok(ObuAction::Process(Obu {
1874            header,
1875            data: Cow::from(&data[start_offset..start_offset + obu_size]),
1876            bytes_used: start_offset + obu_size,
1877        }))
1878    }
1879
1880    fn parse_color_config(s: &mut SequenceHeaderObu, r: &mut Reader) -> Result<(), String> {
1881        let cc = &mut s.color_config;
1882
1883        cc.high_bitdepth = r.0.read_bit()?;
1884        if s.seq_profile as u32 == 2 && cc.high_bitdepth {
1885            cc.twelve_bit = r.0.read_bit()?;
1886            if cc.twelve_bit {
1887                s.bit_depth = BitDepth::Depth12;
1888            } else {
1889                s.bit_depth = BitDepth::Depth10;
1890            }
1891        } else if s.seq_profile as u32 <= 2 {
1892            s.bit_depth = if cc.high_bitdepth { BitDepth::Depth10 } else { BitDepth::Depth8 };
1893        }
1894
1895        if s.seq_profile as u32 == 1 {
1896            cc.mono_chrome = false;
1897        } else {
1898            cc.mono_chrome = r.0.read_bit()?;
1899        }
1900
1901        if cc.mono_chrome {
1902            s.num_planes = 1;
1903        } else {
1904            s.num_planes = 3;
1905        }
1906
1907        cc.color_description_present_flag = r.0.read_bit()?;
1908        if cc.color_description_present_flag {
1909            cc.color_primaries = ColorPrimaries::try_from(r.0.read_bits::<u32>(8)?)?;
1910            cc.transfer_characteristics =
1911                TransferCharacteristics::try_from(r.0.read_bits::<u32>(8)?)?;
1912            cc.matrix_coefficients = MatrixCoefficients::try_from(r.0.read_bits::<u32>(8)?)?;
1913        } else {
1914            cc.color_primaries = ColorPrimaries::Unspecified;
1915            cc.transfer_characteristics = TransferCharacteristics::Unspecified;
1916            cc.matrix_coefficients = MatrixCoefficients::Unspecified;
1917        }
1918
1919        if cc.mono_chrome {
1920            cc.color_range = r.0.read_bit()?;
1921            cc.subsampling_x = true;
1922            cc.subsampling_y = true;
1923            cc.chroma_sample_position = ChromaSamplePosition::Unknown;
1924            cc.separate_uv_delta_q = false;
1925            return Ok(());
1926        } else if matches!(cc.color_primaries, ColorPrimaries::Bt709)
1927            && matches!(cc.transfer_characteristics, TransferCharacteristics::Srgb)
1928            && matches!(cc.matrix_coefficients, MatrixCoefficients::Identity)
1929        {
1930            cc.color_range = true;
1931            cc.subsampling_x = false;
1932            cc.subsampling_y = false;
1933        } else {
1934            cc.color_range = r.0.read_bit()?;
1935            if s.seq_profile as u32 == 0 {
1936                cc.subsampling_x = true;
1937                cc.subsampling_y = true;
1938            } else if s.seq_profile as u32 == 1 {
1939                cc.subsampling_x = false;
1940                cc.subsampling_y = false;
1941            } else if matches!(s.bit_depth, BitDepth::Depth12) {
1942                cc.subsampling_x = r.0.read_bit()?;
1943                if cc.subsampling_x {
1944                    cc.subsampling_y = r.0.read_bit()?;
1945                } else {
1946                    cc.subsampling_y = false;
1947                }
1948            } else {
1949                cc.subsampling_x = true;
1950                cc.subsampling_y = false;
1951            }
1952
1953            if cc.subsampling_x && cc.subsampling_y {
1954                cc.chroma_sample_position =
1955                    ChromaSamplePosition::try_from(r.0.read_bits::<u32>(2)?)?;
1956            }
1957        }
1958
1959        cc.separate_uv_delta_q = r.0.read_bit()?;
1960
1961        Ok(())
1962    }
1963
1964    fn parse_operating_parameters_info(
1965        opi: &mut OperatingPoint,
1966        r: &mut Reader,
1967        buffer_delay_length_minus_1: u8,
1968    ) -> Result<(), String> {
1969        let n = buffer_delay_length_minus_1 + 1;
1970        opi.decoder_buffer_delay = r.0.read_bits::<u32>(n as usize)?;
1971        opi.encoder_buffer_delay = r.0.read_bits::<u32>(n as usize)?;
1972        opi.low_delay_mode_flag = r.0.read_bit()?;
1973        Ok(())
1974    }
1975
1976    fn parse_decoder_model_info(dmi: &mut DecoderModelInfo, r: &mut Reader) -> Result<(), String> {
1977        dmi.buffer_delay_length_minus_1 = r.0.read_bits::<u32>(5)? as u8;
1978        dmi.num_units_in_decoding_tick = r.0.read_bits::<u32>(32)?;
1979        dmi.buffer_removal_time_length_minus_1 = r.0.read_bits::<u32>(5)? as u8;
1980        dmi.frame_presentation_time_length_minus_1 = r.0.read_bits::<u32>(5)?;
1981        Ok(())
1982    }
1983
1984    fn parse_timing_info(ti: &mut TimingInfo, r: &mut Reader) -> Result<(), String> {
1985        ti.num_units_in_display_tick = r.0.read_bits::<u32>(32)?;
1986        ti.time_scale = r.0.read_bits::<u32>(32)?;
1987        ti.equal_picture_interval = r.0.read_bit()?;
1988        if ti.equal_picture_interval {
1989            ti.num_ticks_per_picture_minus_1 = r.read_uvlc()?;
1990        }
1991        Ok(())
1992    }
1993
1994    /// Selects an operating point. Only call this after the Sequence OBU for
1995    /// which the operating point should apply has been parsed.
1996    pub fn choose_operating_point(&mut self, operating_point: u32) -> Result<(), String> {
1997        if operating_point > self.sequence()?.operating_points_cnt_minus_1 {
1998            return Err(format!(
1999                "Invalid operating point {} (max {})",
2000                operating_point,
2001                self.sequence()?.operating_points_cnt_minus_1
2002            ));
2003        }
2004        self.operating_point = operating_point;
2005        self.operating_point_idc = self.sequence()?.operating_points[operating_point as usize].idc;
2006        Ok(())
2007    }
2008
2009    fn parse_temporal_delimiter_obu(&mut self) -> Result<(), String> {
2010        self.seen_frame_header = false;
2011        Ok(())
2012    }
2013
2014    fn parse_sequence_header_obu(&mut self, obu: &Obu) -> Result<Rc<SequenceHeaderObu>, String> {
2015        let mut s = SequenceHeaderObu { obu_header: obu.header.clone(), ..Default::default() };
2016
2017        let mut r = Reader::new(obu.as_ref());
2018        let profile = r.0.read_bits::<u32>(3)?;
2019
2020        s.seq_profile = Profile::try_from(profile)?;
2021        s.still_picture = r.0.read_bit()?;
2022        s.reduced_still_picture_header = r.0.read_bit()?;
2023
2024        if s.reduced_still_picture_header {
2025            /* Default::default() already ensures a lot of this, but lets go verbatim */
2026            s.timing_info_present_flag = false;
2027            s.decoder_model_info_present_flag = false;
2028            s.initial_display_delay_present_flag = false;
2029            s.operating_points_cnt_minus_1 = 0;
2030            s.operating_points[0].idc = 0;
2031            s.operating_points[0].seq_level_idx = r.0.read_bits::<u32>(5)? as u8;
2032            s.operating_points[0].seq_tier = 0;
2033            s.operating_points[0].decoder_model_present_for_this_op = false;
2034            s.operating_points[0].initial_display_delay_present_for_this_op = false;
2035        } else {
2036            s.timing_info_present_flag = r.0.read_bit()?;
2037            if s.timing_info_present_flag {
2038                Self::parse_timing_info(&mut s.timing_info, &mut r)?;
2039                s.decoder_model_info_present_flag = r.0.read_bit()?;
2040                if s.decoder_model_info_present_flag {
2041                    Self::parse_decoder_model_info(&mut s.decoder_model_info, &mut r)?;
2042                }
2043            } else {
2044                s.decoder_model_info_present_flag = false;
2045            }
2046
2047            s.initial_display_delay_present_flag = r.0.read_bit()?;
2048            s.operating_points_cnt_minus_1 = r.0.read_bits::<u32>(5)?;
2049            if s.operating_points_cnt_minus_1 > MAX_NUM_OPERATING_POINTS as u32 {
2050                return Err(format!(
2051                    "Invalid operating_points_cnt_minus_1 {}",
2052                    s.operating_points_cnt_minus_1
2053                ));
2054            }
2055
2056            for i in 0..=s.operating_points_cnt_minus_1 as usize {
2057                s.operating_points[i].idc = r.0.read_bits::<u32>(12)? as u16;
2058                s.operating_points[i].seq_level_idx = r.0.read_bits::<u32>(5)? as u8;
2059                if s.operating_points[i].seq_level_idx > 7 {
2060                    s.operating_points[i].seq_tier = r.0.read_bit()? as u8;
2061                } else {
2062                    s.operating_points[i].seq_tier = 0;
2063                }
2064                if s.decoder_model_info_present_flag {
2065                    s.operating_points[i].decoder_model_present_for_this_op = r.0.read_bit()?;
2066                    if s.operating_points[i].decoder_model_present_for_this_op {
2067                        let buffer_delay_length_minus_1 =
2068                            s.decoder_model_info.buffer_delay_length_minus_1;
2069                        Self::parse_operating_parameters_info(
2070                            &mut s.operating_points[i],
2071                            &mut r,
2072                            buffer_delay_length_minus_1,
2073                        )?;
2074                    }
2075                } else {
2076                    s.operating_points[i].decoder_model_present_for_this_op = false;
2077                }
2078
2079                if s.initial_display_delay_present_flag {
2080                    s.operating_points[i].initial_display_delay_present_for_this_op =
2081                        r.0.read_bit()?;
2082                    if s.operating_points[i].initial_display_delay_present_for_this_op {
2083                        s.operating_points[i].initial_display_delay_minus_1 =
2084                            r.0.read_bits::<u32>(4)?;
2085                    }
2086                }
2087            }
2088        }
2089
2090        s.frame_width_bits_minus_1 = r.0.read_bits::<u32>(4)? as u8;
2091        s.frame_height_bits_minus_1 = r.0.read_bits::<u32>(4)? as u8;
2092        // frame_width_bits_minus_1 has been read from 4 bits, meaning we can read 16 bits at most.
2093        s.max_frame_width_minus_1 =
2094            r.0.read_bits::<u32>(s.frame_width_bits_minus_1 as usize + 1)? as u16;
2095        // frame_height_bits_minus_1 has been read from 4 bits, meaning we can read 16 bits at most.
2096        s.max_frame_height_minus_1 =
2097            r.0.read_bits::<u32>(s.frame_height_bits_minus_1 as usize + 1)? as u16;
2098        if s.reduced_still_picture_header {
2099            s.frame_id_numbers_present_flag = false;
2100        } else {
2101            s.frame_id_numbers_present_flag = r.0.read_bit()?;
2102        }
2103        if s.frame_id_numbers_present_flag {
2104            s.delta_frame_id_length_minus_2 = r.0.read_bits::<u32>(4)?;
2105            s.additional_frame_id_length_minus_1 = r.0.read_bits::<u32>(3)?;
2106            let frame_id_length =
2107                s.additional_frame_id_length_minus_1 + s.delta_frame_id_length_minus_2 + 3;
2108            if frame_id_length > 16 {
2109                return Err(format!("Invalid frame_id_length {}", frame_id_length));
2110            }
2111        }
2112
2113        s.use_128x128_superblock = r.0.read_bit()?;
2114        s.enable_filter_intra = r.0.read_bit()?;
2115        s.enable_intra_edge_filter = r.0.read_bit()?;
2116        if s.reduced_still_picture_header {
2117            s.enable_interintra_compound = false;
2118            s.enable_masked_compound = false;
2119            s.enable_warped_motion = false;
2120            s.enable_dual_filter = false;
2121            s.enable_order_hint = false;
2122            s.enable_jnt_comp = false;
2123            s.enable_ref_frame_mvs = false;
2124            s.seq_force_screen_content_tools = SELECT_SCREEN_CONTENT_TOOLS as _;
2125            s.seq_force_integer_mv = SELECT_INTEGER_MV as _;
2126            s.order_hint_bits = 0;
2127            s.order_hint_bits_minus_1 = -1;
2128        } else {
2129            s.enable_interintra_compound = r.0.read_bit()?;
2130            s.enable_masked_compound = r.0.read_bit()?;
2131            s.enable_warped_motion = r.0.read_bit()?;
2132            s.enable_dual_filter = r.0.read_bit()?;
2133            s.enable_order_hint = r.0.read_bit()?;
2134            if s.enable_order_hint {
2135                s.enable_jnt_comp = r.0.read_bit()?;
2136                s.enable_ref_frame_mvs = r.0.read_bit()?;
2137            } else {
2138                s.enable_jnt_comp = false;
2139                s.enable_ref_frame_mvs = false;
2140            }
2141            s.seq_choose_screen_content_tools = r.0.read_bit()?;
2142            if s.seq_choose_screen_content_tools {
2143                s.seq_force_screen_content_tools = SELECT_SCREEN_CONTENT_TOOLS as _;
2144            } else {
2145                s.seq_force_screen_content_tools = r.0.read_bit()? as _;
2146            }
2147            if s.seq_force_screen_content_tools > 0 {
2148                s.seq_choose_integer_mv = r.0.read_bit()?;
2149                if s.seq_choose_integer_mv {
2150                    s.seq_force_integer_mv = SELECT_INTEGER_MV as _;
2151                } else {
2152                    s.seq_force_integer_mv = r.0.read_bit()? as _;
2153                }
2154            } else {
2155                s.seq_force_integer_mv = SELECT_INTEGER_MV as _;
2156            }
2157
2158            if s.enable_order_hint {
2159                s.order_hint_bits_minus_1 = r.0.read_bits::<u32>(3)?.try_into().unwrap();
2160                s.order_hint_bits = s.order_hint_bits_minus_1 + 1;
2161            } else {
2162                s.order_hint_bits_minus_1 = -1;
2163                s.order_hint_bits = 0;
2164            }
2165        }
2166
2167        s.enable_superres = r.0.read_bit()?;
2168        s.enable_cdef = r.0.read_bit()?;
2169        s.enable_restoration = r.0.read_bit()?;
2170
2171        Self::parse_color_config(&mut s, &mut r)?;
2172
2173        s.film_grain_params_present = r.0.read_bit()?;
2174
2175        Self::skip_and_check_trailing_bits(&mut r, obu)?;
2176        let rc = Rc::new(s);
2177        self.sequence_header = Some(rc.clone());
2178
2179        /* Client is supposed to set the operating point through external means,
2180         * here we just set 0 as default. */
2181        self.choose_operating_point(0)?;
2182
2183        Ok(rc)
2184    }
2185
2186    /// Implements 7.21. Note that 7.20 will use the information from the
2187    /// header, so we must save them now, as they will not be parsed from the
2188    /// bitstream. We also save some internal parser state which will be useful
2189    /// later.
2190    fn load_reference_frame(&self, fh: &mut FrameHeaderObu) -> Result<(), String> {
2191        let rf = &self.ref_info[fh.frame_to_show_map_idx as usize];
2192
2193        // Section 6.8.1: It is a requirement of bitstream conformance that a
2194        // sequence header OBU has been received before a frame header OBU.
2195        let seq = self.sequence()?;
2196
2197        /* at least save the sizes and for both kf and non-kf */
2198        fh.frame_type = rf.ref_frame_type;
2199        fh.upscaled_width = rf.ref_upscaled_width;
2200        fh.frame_width = rf.ref_frame_width;
2201        fh.frame_height = rf.ref_frame_height;
2202        fh.render_width = rf.ref_render_width;
2203        fh.render_height = rf.ref_render_height;
2204
2205        /* Save into the frame header */
2206        if fh.frame_type == FrameType::KeyFrame {
2207            fh.current_frame_id = rf.ref_frame_id;
2208            /* We don't keep track of sequence information at the frame level */
2209            fh.mi_cols = rf.ref_mi_cols;
2210            fh.mi_rows = rf.ref_mi_rows;
2211            /* The accelerator is keeping track of CDF values, so that is skipped too */
2212            fh.global_motion_params = rf.global_motion_params.clone();
2213
2214            if seq.film_grain_params_present {
2215                fh.film_grain_params = rf.film_grain_params.clone();
2216            }
2217            fh.loop_filter_params = rf.loop_filter_params.clone();
2218            fh.segmentation_params = rf.segmentation_params.clone();
2219        }
2220
2221        Ok(())
2222    }
2223
2224    fn setup_past_independence(fh: &mut FrameHeaderObu) {
2225        fh.segmentation_params.feature_enabled = Default::default();
2226        fh.segmentation_params.feature_data = Default::default();
2227
2228        for i in ReferenceFrameType::Last as usize..ReferenceFrameType::AltRef as usize {
2229            fh.global_motion_params.gm_type[i] = WarpModelType::Identity;
2230        }
2231
2232        fh.loop_filter_params.loop_filter_delta_enabled = true;
2233        fh.loop_filter_params.loop_filter_ref_deltas = [1, 0, 0, 0, -1, 0, -1, -1];
2234        fh.loop_filter_params.loop_filter_mode_deltas = Default::default();
2235    }
2236
2237    fn parse_tile_info(&mut self, r: &mut Reader, ti: &mut TileInfo) -> Result<(), String> {
2238        let seq = self.sequence()?;
2239
2240        let sb_cols = if seq.use_128x128_superblock {
2241            (self.mi_cols + 31) >> 5
2242        } else {
2243            (self.mi_cols + 15) >> 4
2244        };
2245
2246        let sb_rows = if seq.use_128x128_superblock {
2247            (self.mi_rows + 31) >> 5
2248        } else {
2249            (self.mi_rows + 15) >> 4
2250        };
2251
2252        let sb_shift = if seq.use_128x128_superblock { 5 } else { 4 };
2253        let sb_size = sb_shift + 2;
2254
2255        let max_tile_width_sb = MAX_TILE_WIDTH >> sb_size;
2256        let mut max_tile_area_sb = MAX_TILE_AREA >> (2 * sb_size);
2257
2258        let min_log2_tile_cols = helpers::tile_log2(max_tile_width_sb, sb_cols);
2259
2260        let max_log2_tile_cols =
2261            helpers::tile_log2(1, std::cmp::min(sb_cols, MAX_TILE_COLS as u32));
2262
2263        let max_log2_tile_rows =
2264            helpers::tile_log2(1, std::cmp::min(sb_rows, MAX_TILE_ROWS as u32));
2265
2266        let min_log2_tiles = std::cmp::max(
2267            min_log2_tile_cols,
2268            helpers::tile_log2(max_tile_area_sb, sb_rows * sb_cols),
2269        );
2270
2271        ti.uniform_tile_spacing_flag = r.0.read_bit()?;
2272
2273        if ti.uniform_tile_spacing_flag {
2274            self.tile_cols_log2 = min_log2_tile_cols;
2275            while self.tile_cols_log2 < max_log2_tile_cols {
2276                let increment_tile_cols_log_2 = r.0.read_bit()?;
2277                if increment_tile_cols_log_2 {
2278                    self.tile_cols_log2 += 1;
2279                } else {
2280                    break;
2281                }
2282            }
2283
2284            let tile_width_sb = (sb_cols + (1 << self.tile_cols_log2) - 1) >> self.tile_cols_log2;
2285
2286            let mut i = 0;
2287            let mut start_sb = 0;
2288
2289            while start_sb < sb_cols {
2290                self.mi_col_starts[i] = start_sb << sb_shift;
2291                i += 1;
2292                start_sb += tile_width_sb;
2293            }
2294
2295            self.mi_col_starts[i] = self.mi_cols;
2296            self.tile_cols = i as _;
2297
2298            if self.tile_cols > MAX_TILE_COLS as u32 {
2299                return Err(format!("Invalid tile_cols {}", self.tile_cols));
2300            }
2301
2302            /* compute this anyways */
2303            while i >= 1 {
2304                ti.width_in_sbs_minus_1[i - 1] =
2305                    ((self.mi_col_starts[i] - self.mi_col_starts[i - 1] + ((1 << sb_shift) - 1))
2306                        >> sb_shift)
2307                        - 1;
2308                i -= 1;
2309            }
2310
2311            let min_log2_tile_rows =
2312                std::cmp::max(min_log2_tiles.saturating_sub(self.tile_cols_log2), 0);
2313            self.tile_rows_log2 = min_log2_tile_rows;
2314
2315            while self.tile_rows_log2 < max_log2_tile_rows {
2316                let increment_tile_rows_log_2 = r.0.read_bit()?;
2317
2318                if increment_tile_rows_log_2 {
2319                    self.tile_rows_log2 += 1;
2320                } else {
2321                    break;
2322                }
2323            }
2324
2325            let tile_height_sb = (sb_rows + (1 << self.tile_rows_log2) - 1) >> self.tile_rows_log2;
2326
2327            let mut i = 0;
2328            let mut start_sb = 0;
2329
2330            while start_sb < sb_rows {
2331                self.mi_row_starts[i] = start_sb << sb_shift;
2332                i += 1;
2333                start_sb += tile_height_sb;
2334            }
2335
2336            self.mi_row_starts[i] = self.mi_rows;
2337            self.tile_rows = i as _;
2338
2339            if self.tile_rows > MAX_TILE_ROWS as u32 {
2340                return Err(format!("Invalid tile_rows {}", self.tile_cols));
2341            }
2342
2343            /* compute this anyways */
2344            while i >= 1 {
2345                ti.height_in_sbs_minus_1[i - 1] =
2346                    ((self.mi_row_starts[i] - self.mi_row_starts[i - 1] + ((1 << sb_shift) - 1))
2347                        >> sb_shift)
2348                        - 1;
2349                i -= 1;
2350            }
2351        } else {
2352            let mut widest_tile_sb = 0;
2353            let mut start_sb = 0;
2354            let mut i = 0;
2355
2356            while start_sb < sb_cols {
2357                self.mi_col_starts[i] = start_sb << sb_shift;
2358
2359                let max_width = std::cmp::min(sb_cols - start_sb, max_tile_width_sb);
2360                ti.width_in_sbs_minus_1[i] = r.read_ns(max_width.try_into().unwrap())?;
2361
2362                let size_sb = ti.width_in_sbs_minus_1[i] + 1;
2363                widest_tile_sb = std::cmp::max(size_sb, widest_tile_sb);
2364
2365                start_sb += size_sb;
2366                i += 1;
2367            }
2368
2369            self.mi_col_starts[i] = self.mi_cols;
2370            self.tile_cols = i as _;
2371            self.tile_cols_log2 = helpers::tile_log2(1, self.tile_cols);
2372
2373            if min_log2_tiles > 0 {
2374                max_tile_area_sb = (sb_rows * sb_cols) >> (min_log2_tiles + 1);
2375            } else {
2376                max_tile_area_sb = sb_rows * sb_cols;
2377            }
2378
2379            let max_tile_height_sb = std::cmp::max(max_tile_area_sb / widest_tile_sb, 1);
2380            let mut start_sb = 0;
2381            let mut i = 0;
2382            while start_sb < sb_rows {
2383                self.mi_row_starts[i] = start_sb << sb_shift;
2384                let max_height = std::cmp::min(sb_rows - start_sb, max_tile_height_sb);
2385                ti.height_in_sbs_minus_1[i] = r.read_ns(max_height.try_into().unwrap())?;
2386
2387                let size_sb = ti.height_in_sbs_minus_1[i] + 1;
2388                start_sb += size_sb;
2389                i += 1;
2390            }
2391
2392            self.mi_row_starts[i] = self.mi_rows;
2393            self.tile_rows = i as _;
2394            self.tile_rows_log2 = helpers::tile_log2(1, self.tile_rows);
2395        }
2396
2397        if self.tile_cols_log2 > 0 || self.tile_rows_log2 > 0 {
2398            let num_bits: usize = (self.tile_rows_log2 + self.tile_cols_log2).try_into().unwrap();
2399            ti.context_update_tile_id = r.0.read_bits::<u32>(num_bits)?;
2400
2401            if ti.context_update_tile_id >= self.tile_rows * self.tile_cols {
2402                return Err(format!(
2403                    "Invalid context_update_tile_id {}",
2404                    ti.context_update_tile_id
2405                ));
2406            }
2407            self.tile_size_bytes = r.0.read_bits::<u32>(2)? + 1;
2408        } else {
2409            ti.context_update_tile_id = 0;
2410        }
2411
2412        ti.mi_col_starts = self.mi_col_starts;
2413        ti.mi_row_starts = self.mi_row_starts;
2414        ti.tile_cols_log2 = self.tile_cols_log2;
2415        ti.tile_cols = self.tile_cols;
2416        ti.tile_rows_log2 = self.tile_rows_log2;
2417        ti.tile_rows = self.tile_rows;
2418        ti.tile_size_bytes = self.tile_size_bytes;
2419
2420        Ok(())
2421    }
2422
2423    fn parse_quantization_params(
2424        r: &mut Reader,
2425        q: &mut QuantizationParams,
2426        num_planes: u32,
2427        separate_uv_delta_q: bool,
2428    ) -> Result<(), String> {
2429        q.base_q_idx = r.0.read_bits::<u32>(8)?;
2430        q.delta_q_y_dc = r.read_delta_q()?;
2431        if num_planes > 1 {
2432            if separate_uv_delta_q {
2433                q.diff_uv_delta = r.0.read_bit()?;
2434            } else {
2435                q.diff_uv_delta = false;
2436            }
2437
2438            q.delta_q_u_dc = r.read_delta_q()?;
2439            q.delta_q_u_ac = r.read_delta_q()?;
2440            if q.diff_uv_delta {
2441                q.delta_q_v_dc = r.read_delta_q()?;
2442                q.delta_q_v_ac = r.read_delta_q()?;
2443            } else {
2444                q.delta_q_v_dc = q.delta_q_u_dc;
2445                q.delta_q_v_ac = q.delta_q_u_ac;
2446            }
2447        } else {
2448            q.delta_q_u_dc = 0;
2449            q.delta_q_u_ac = 0;
2450            q.delta_q_v_dc = 0;
2451            q.delta_q_v_ac = 0;
2452        }
2453
2454        q.using_qmatrix = r.0.read_bit()?;
2455        if q.using_qmatrix {
2456            q.qm_y = r.0.read_bits::<u32>(4)?;
2457            q.qm_u = r.0.read_bits::<u32>(4)?;
2458            if !separate_uv_delta_q {
2459                q.qm_v = q.qm_u;
2460            } else {
2461                q.qm_v = r.0.read_bits::<u32>(4)?;
2462            }
2463        }
2464        Ok(())
2465    }
2466
2467    fn parse_delta_q_params(r: &mut Reader, q: &mut QuantizationParams) -> Result<(), String> {
2468        q.delta_q_res = 0;
2469        q.delta_q_present = false;
2470        if q.base_q_idx > 0 {
2471            q.delta_q_present = r.0.read_bit()?;
2472        }
2473        if q.delta_q_present {
2474            q.delta_q_res = r.0.read_bits::<u32>(2)?;
2475        }
2476
2477        Ok(())
2478    }
2479
2480    fn parse_delta_lf_params(
2481        r: &mut Reader,
2482        lf: &mut LoopFilterParams,
2483        delta_q_present: bool,
2484        allow_intrabc: bool,
2485    ) -> Result<(), String> {
2486        lf.delta_lf_present = false;
2487        lf.delta_lf_res = 0;
2488        lf.delta_lf_multi = false;
2489        if delta_q_present {
2490            if !allow_intrabc {
2491                lf.delta_lf_present = r.0.read_bit()?;
2492            }
2493            if lf.delta_lf_present {
2494                lf.delta_lf_res = r.0.read_bits::<u32>(2)? as u8;
2495                lf.delta_lf_multi = r.0.read_bit()?;
2496            }
2497        }
2498        Ok(())
2499    }
2500
2501    fn parse_segmentation_params(
2502        &self,
2503        r: &mut Reader,
2504        fh: &mut FrameHeaderObu,
2505    ) -> Result<(), String> {
2506        let s = &mut fh.segmentation_params;
2507        s.segmentation_enabled = r.0.read_bit()?;
2508        if s.segmentation_enabled {
2509            if fh.primary_ref_frame == PRIMARY_REF_NONE {
2510                s.segmentation_update_map = true;
2511                s.segmentation_temporal_update = false;
2512                s.segmentation_update_data = true;
2513            } else {
2514                s.segmentation_update_map = r.0.read_bit()?;
2515                if s.segmentation_update_map {
2516                    s.segmentation_temporal_update = r.0.read_bit()?;
2517                }
2518                s.segmentation_update_data = r.0.read_bit()?;
2519            }
2520            if s.segmentation_update_data {
2521                for i in 0..MAX_SEGMENTS {
2522                    for j in 0..SEG_LVL_MAX {
2523                        let feature_enabled = r.0.read_bit()?;
2524                        s.feature_enabled[i][j] = feature_enabled;
2525                        if feature_enabled {
2526                            let bits_to_read = FEATURE_BITS[j];
2527                            let limit = FEATURE_MAX[j];
2528                            let signed = FEATURE_SIGNED[j];
2529
2530                            if signed {
2531                                let feature_value = r.read_su(1 + bits_to_read as usize)?;
2532                                let clipped_value = helpers::clip3(-limit, limit, feature_value);
2533                                s.feature_data[i][j] = clipped_value as _;
2534                            } else {
2535                                let feature_value = r.0.read_bits::<u32>(bits_to_read as usize)?;
2536                                let clipped_value = helpers::clip3(
2537                                    0,
2538                                    limit,
2539                                    feature_value
2540                                        .try_into()
2541                                        .map_err(|_| "Invalid feature_value")?,
2542                                );
2543                                s.feature_data[i][j] = clipped_value as _;
2544                            }
2545                        }
2546                    }
2547                }
2548            } else {
2549                /* copy from prev_frame */
2550                let prev_frame =
2551                    &self.ref_info[fh.ref_frame_idx[fh.primary_ref_frame as usize] as usize];
2552
2553                if !prev_frame.ref_valid {
2554                    return Err("Reference is invalid".into());
2555                }
2556
2557                s.feature_enabled = prev_frame.segmentation_params.feature_enabled;
2558                s.feature_data = prev_frame.segmentation_params.feature_data;
2559            }
2560        } else {
2561            for i in 0..MAX_SEGMENTS {
2562                for j in 0..SEG_LVL_MAX {
2563                    s.feature_enabled[i][j] = false;
2564                    s.feature_data[i][j] = 0;
2565                }
2566            }
2567        }
2568
2569        s.seg_id_pre_skip = false;
2570        s.last_active_seg_id = 0;
2571        for i in 0..MAX_SEGMENTS {
2572            for j in 0..SEG_LVL_MAX {
2573                if s.feature_enabled[i][j] {
2574                    s.last_active_seg_id = i as u8;
2575                    if j >= SEG_LVL_REF_FRAME {
2576                        s.seg_id_pre_skip = true;
2577                    }
2578                }
2579            }
2580        }
2581
2582        Ok(())
2583    }
2584
2585    fn parse_loop_filter_parameters(
2586        r: &mut Reader,
2587        fh: &mut FrameHeaderObu,
2588        num_planes: u32,
2589    ) -> Result<(), String> {
2590        let lf = &mut fh.loop_filter_params;
2591        if fh.coded_lossless || fh.allow_intrabc {
2592            lf.loop_filter_level[0] = 0;
2593            lf.loop_filter_level[1] = 0;
2594            lf.loop_filter_ref_deltas = [1, 0, 0, 0, -1, 0, -1, -1];
2595
2596            lf.loop_filter_mode_deltas = Default::default();
2597
2598            return Ok(());
2599        }
2600
2601        lf.loop_filter_level[0] = r.0.read_bits::<u32>(6)? as u8;
2602        lf.loop_filter_level[1] = r.0.read_bits::<u32>(6)? as u8;
2603        if num_planes > 1 && (lf.loop_filter_level[0] > 0 || lf.loop_filter_level[1] > 0) {
2604            lf.loop_filter_level[2] = r.0.read_bits::<u32>(6)? as u8;
2605            lf.loop_filter_level[3] = r.0.read_bits::<u32>(6)? as u8;
2606        }
2607
2608        lf.loop_filter_sharpness = r.0.read_bits::<u32>(3)? as u8;
2609        lf.loop_filter_delta_enabled = r.0.read_bit()?;
2610        if lf.loop_filter_delta_enabled {
2611            lf.loop_filter_delta_update = r.0.read_bit()?;
2612            if lf.loop_filter_delta_update {
2613                for i in 0..TOTAL_REFS_PER_FRAME {
2614                    let update_ref_delta = r.0.read_bit()?;
2615                    if update_ref_delta {
2616                        lf.loop_filter_ref_deltas[i] = r.read_su(7)? as i8;
2617                    }
2618                }
2619
2620                for i in 0..2 {
2621                    let update_mode_delta = r.0.read_bit()?;
2622                    if update_mode_delta {
2623                        lf.loop_filter_mode_deltas[i] = r.read_su(7)? as i8;
2624                    }
2625                }
2626            }
2627        }
2628
2629        Ok(())
2630    }
2631
2632    fn parse_cdef_params(
2633        r: &mut Reader,
2634        fh: &mut FrameHeaderObu,
2635        enable_cdef: bool,
2636        num_planes: u32,
2637    ) -> Result<(), String> {
2638        let cdef = &mut fh.cdef_params;
2639
2640        if fh.coded_lossless || fh.allow_intrabc || !enable_cdef {
2641            cdef.cdef_bits = 0;
2642            cdef.cdef_y_pri_strength[0] = 0;
2643            cdef.cdef_y_sec_strength[0] = 0;
2644            cdef.cdef_uv_pri_strength[0] = 0;
2645            cdef.cdef_uv_sec_strength[0] = 0;
2646            cdef.cdef_damping = 3;
2647            return Ok(());
2648        }
2649
2650        cdef.cdef_damping = r.0.read_bits::<u32>(2)? + 3;
2651        cdef.cdef_bits = r.0.read_bits::<u32>(2)?;
2652        for i in 0..(1 << cdef.cdef_bits) as usize {
2653            cdef.cdef_y_pri_strength[i] = r.0.read_bits::<u32>(4)?;
2654            cdef.cdef_y_sec_strength[i] = r.0.read_bits::<u32>(2)?;
2655            if cdef.cdef_y_sec_strength[i] == 3 {
2656                cdef.cdef_y_sec_strength[i] += 1;
2657            }
2658            if num_planes > 1 {
2659                cdef.cdef_uv_pri_strength[i] = r.0.read_bits::<u32>(4)?;
2660                cdef.cdef_uv_sec_strength[i] = r.0.read_bits::<u32>(2)?;
2661                if cdef.cdef_uv_sec_strength[i] == 3 {
2662                    cdef.cdef_uv_sec_strength[i] += 1;
2663                }
2664            }
2665        }
2666
2667        Ok(())
2668    }
2669
2670    fn parse_loop_restoration_params(
2671        r: &mut Reader,
2672        fh: &mut FrameHeaderObu,
2673        enable_restoration: bool,
2674        num_planes: u32,
2675        use_128x128_superblock: bool,
2676        subsampling_x: bool,
2677        subsampling_y: bool,
2678    ) -> Result<(), String> {
2679        let lr = &mut fh.loop_restoration_params;
2680
2681        if fh.all_lossless || fh.allow_intrabc || !enable_restoration {
2682            lr.frame_restoration_type[0] = FrameRestorationType::None;
2683            lr.frame_restoration_type[1] = FrameRestorationType::None;
2684            lr.frame_restoration_type[2] = FrameRestorationType::None;
2685            lr.uses_lr = false;
2686            return Ok(());
2687        }
2688
2689        lr.uses_lr = false;
2690        lr.uses_chroma_lr = false;
2691
2692        const REMAP_LR_TYPE: [FrameRestorationType; 4] = [
2693            FrameRestorationType::None,
2694            FrameRestorationType::Switchable,
2695            FrameRestorationType::Wiener,
2696            FrameRestorationType::Sgrproj,
2697        ];
2698
2699        for i in 0..num_planes as usize {
2700            let lr_type = r.0.read_bits::<u32>(2)?;
2701            lr.frame_restoration_type[i] = REMAP_LR_TYPE[lr_type as usize];
2702            if lr.frame_restoration_type[i] != FrameRestorationType::None {
2703                lr.uses_lr = true;
2704                if i > 0 {
2705                    lr.uses_chroma_lr = true;
2706                }
2707            }
2708        }
2709
2710        if lr.uses_lr {
2711            if use_128x128_superblock {
2712                lr.lr_unit_shift = r.0.read_bits::<u32>(1)? as u8 + 1;
2713            } else {
2714                lr.lr_unit_shift = r.0.read_bits::<u32>(1)? as u8;
2715                if lr.lr_unit_shift > 0 {
2716                    lr.lr_unit_shift += r.0.read_bits::<u32>(1)? as u8;
2717                }
2718            }
2719
2720            lr.loop_restoration_size[0] = RESTORATION_TILESIZE_MAX >> (2 - lr.lr_unit_shift);
2721            if subsampling_x && subsampling_y && lr.uses_chroma_lr {
2722                lr.lr_uv_shift = r.0.read_bits::<u32>(1)? as u8;
2723            } else {
2724                lr.lr_uv_shift = 0;
2725            }
2726
2727            lr.loop_restoration_size[1] = lr.loop_restoration_size[0] >> lr.lr_uv_shift;
2728            lr.loop_restoration_size[2] = lr.loop_restoration_size[0] >> lr.lr_uv_shift;
2729        }
2730
2731        Ok(())
2732    }
2733
2734    fn read_tx_mode(r: &mut Reader, fh: &mut FrameHeaderObu) -> Result<(), String> {
2735        if fh.coded_lossless {
2736            fh.tx_mode = TxMode::Only4x4;
2737        } else {
2738            let tx_mode_select = r.0.read_bit()?;
2739
2740            if tx_mode_select {
2741                fh.tx_mode = TxMode::Select;
2742            } else {
2743                fh.tx_mode = TxMode::Largest;
2744            }
2745        }
2746
2747        Ok(())
2748    }
2749
2750    fn parse_skip_mode_params(
2751        &self,
2752        r: &mut Reader,
2753        fh: &mut FrameHeaderObu,
2754        enable_order_hint: bool,
2755        order_hint_bits: i32,
2756    ) -> Result<(), String> {
2757        let skip_mode_allowed;
2758
2759        if fh.frame_is_intra || !fh.reference_select || !enable_order_hint {
2760            skip_mode_allowed = false;
2761        } else {
2762            let mut forward_idx = -1;
2763            let mut backward_idx = -1;
2764            let mut forward_hint = 0;
2765            let mut backward_hint = 0;
2766            for i in 0..REFS_PER_FRAME {
2767                let ref_hint = self.ref_info[fh.ref_frame_idx[i] as usize].ref_order_hint;
2768                if helpers::get_relative_dist(
2769                    enable_order_hint,
2770                    order_hint_bits,
2771                    ref_hint.try_into().unwrap(),
2772                    fh.order_hint.try_into().unwrap(),
2773                ) < 0
2774                    && (forward_idx < 0
2775                        || helpers::get_relative_dist(
2776                            enable_order_hint,
2777                            order_hint_bits,
2778                            ref_hint.try_into().unwrap(),
2779                            forward_hint,
2780                        ) > 0)
2781                {
2782                    forward_idx = i32::try_from(i).unwrap();
2783                    forward_hint = ref_hint.try_into().unwrap();
2784                } else if helpers::get_relative_dist(
2785                    enable_order_hint,
2786                    order_hint_bits,
2787                    ref_hint.try_into().unwrap(),
2788                    fh.order_hint.try_into().unwrap(),
2789                ) > 0
2790                    && (backward_idx < 0 || {
2791                        helpers::get_relative_dist(
2792                            enable_order_hint,
2793                            order_hint_bits,
2794                            ref_hint.try_into().unwrap(),
2795                            backward_hint,
2796                        ) < 0
2797                    })
2798                {
2799                    backward_idx = i32::try_from(i).unwrap();
2800                    backward_hint = ref_hint.try_into().unwrap();
2801                }
2802            }
2803
2804            if forward_idx < 0 {
2805                skip_mode_allowed = false;
2806            } else if backward_idx >= 0 {
2807                skip_mode_allowed = true;
2808                fh.skip_mode_frame[0] = ReferenceFrameType::Last as u32
2809                    + u32::try_from(std::cmp::min(forward_idx, backward_idx)).unwrap();
2810                fh.skip_mode_frame[1] = ReferenceFrameType::Last as u32
2811                    + u32::try_from(std::cmp::max(forward_idx, backward_idx)).unwrap();
2812            } else {
2813                let mut second_forward_idx = -1;
2814                let mut second_forward_hint = 0;
2815                for i in 0..REFS_PER_FRAME {
2816                    let ref_hint = self.ref_info[fh.ref_frame_idx[i] as usize].ref_order_hint;
2817                    if helpers::get_relative_dist(
2818                        enable_order_hint,
2819                        order_hint_bits,
2820                        ref_hint.try_into().unwrap(),
2821                        forward_hint,
2822                    ) < 0
2823                        && (second_forward_idx < 0
2824                            || helpers::get_relative_dist(
2825                                enable_order_hint,
2826                                order_hint_bits,
2827                                ref_hint.try_into().unwrap(),
2828                                second_forward_hint,
2829                            ) > 0)
2830                    {
2831                        second_forward_idx = i32::try_from(i).unwrap();
2832                        second_forward_hint = ref_hint.try_into().unwrap();
2833                    }
2834                }
2835
2836                if second_forward_idx < 0 {
2837                    skip_mode_allowed = false;
2838                } else {
2839                    skip_mode_allowed = true;
2840                    fh.skip_mode_frame[0] = ReferenceFrameType::Last as u32
2841                        + u32::try_from(std::cmp::min(forward_idx, second_forward_idx)).unwrap();
2842                    fh.skip_mode_frame[1] = ReferenceFrameType::Last as u32
2843                        + u32::try_from(std::cmp::max(forward_idx, second_forward_idx)).unwrap();
2844                }
2845            }
2846        }
2847
2848        if skip_mode_allowed {
2849            fh.skip_mode_present = r.0.read_bit()?;
2850        } else {
2851            fh.skip_mode_present = false;
2852        }
2853
2854        Ok(())
2855    }
2856
2857    fn parse_frame_reference_mode(r: &mut Reader, fh: &mut FrameHeaderObu) -> Result<(), String> {
2858        if fh.frame_is_intra {
2859            fh.reference_select = false;
2860        } else {
2861            fh.reference_select = r.0.read_bit()?;
2862        }
2863        Ok(())
2864    }
2865
2866    fn seg_feature_active_idx(seg: &SegmentationParams, idx: u32, feature: u32) -> bool {
2867        seg.segmentation_enabled && seg.feature_enabled[idx as usize][feature as usize]
2868    }
2869
2870    fn get_qindex(fh: &FrameHeaderObu, ignore_deltaq: bool, segment_id: u32) -> i32 {
2871        let base_q_idx = i32::try_from(fh.quantization_params.base_q_idx).unwrap();
2872        if Self::seg_feature_active_idx(&fh.segmentation_params, segment_id, SEG_LVL_ALT_Q as u32) {
2873            let data = fh.segmentation_params.feature_data[segment_id as usize][SEG_LVL_ALT_Q];
2874            let mut qindex = base_q_idx + i32::from(data);
2875            if !ignore_deltaq && fh.quantization_params.delta_q_present {
2876                qindex += i32::try_from(fh.quantization_params.delta_q_res).unwrap();
2877            }
2878            helpers::clip3(0, 255, qindex)
2879        } else {
2880            base_q_idx
2881        }
2882    }
2883
2884    fn setup_shear(warp_params: &[i32; 6]) -> Result<bool, String> {
2885        let mut default = true;
2886        for (i, param) in warp_params.iter().enumerate() {
2887            let default_value = if i % 3 == 2 { 1 << WARPEDMODEL_PREC_BITS } else { 0 };
2888            if *param != default_value {
2889                default = false;
2890                break;
2891            }
2892        }
2893
2894        /* assume the default params to be valid */
2895        if default {
2896            return Ok(true);
2897        }
2898
2899        let alpha0 = helpers::clip3(-32768, 32767, warp_params[2] - (1 << WARPEDMODEL_PREC_BITS));
2900        let beta0 = helpers::clip3(-32768, 32767, warp_params[3]);
2901
2902        let (div_shift, div_factor) = helpers::resolve_divisor(warp_params[2])?;
2903
2904        let v = i64::from(warp_params[4] << WARPEDMODEL_PREC_BITS);
2905        let v = (v * i64::from(div_factor)) as i32;
2906        let gamma0 = helpers::clip3(-32678, 32767, helpers::round2signed(v, div_shift)?);
2907
2908        let w = warp_params[3] * warp_params[4];
2909
2910        let delta0 = helpers::clip3(
2911            -32768,
2912            32767,
2913            warp_params[5]
2914                - helpers::round2signed(w * div_factor, div_shift)?
2915                - (1 << WARPEDMODEL_PREC_BITS),
2916        );
2917
2918        let alpha =
2919            helpers::round2signed(alpha0, WARP_PARAM_REDUCE_BITS)? << WARP_PARAM_REDUCE_BITS;
2920        let beta = helpers::round2signed(beta0, WARP_PARAM_REDUCE_BITS)? << WARP_PARAM_REDUCE_BITS;
2921        let gamma =
2922            helpers::round2signed(gamma0, WARP_PARAM_REDUCE_BITS)? << WARP_PARAM_REDUCE_BITS;
2923        let delta =
2924            helpers::round2signed(delta0, WARP_PARAM_REDUCE_BITS)? << WARP_PARAM_REDUCE_BITS;
2925
2926        #[allow(clippy::needless_bool)]
2927        let warp_valid = if 4 * alpha.abs() + 7 * beta.abs() >= (1 << WARPEDMODEL_PREC_BITS)
2928            || 4 * gamma.abs() + 4 * delta.abs() >= (1 << WARPEDMODEL_PREC_BITS)
2929        {
2930            false
2931        } else {
2932            true
2933        };
2934
2935        Ok(warp_valid)
2936    }
2937
2938    fn read_global_param(
2939        reader: &mut Reader,
2940        type_: WarpModelType,
2941        ref_frame: usize,
2942        idx: usize,
2943        allow_high_precision_mv: bool,
2944        prev_gm_params: &[[i32; 6]; NUM_REF_FRAMES],
2945        gm_params: &mut [[i32; 6]; NUM_REF_FRAMES],
2946    ) -> Result<(), String> {
2947        let mut abs_bits = GM_ABS_ALPHA_BITS;
2948        let mut prec_bits = GM_ALPHA_PREC_BITS;
2949        if idx < 2 {
2950            if type_ == WarpModelType::Translation {
2951                abs_bits = GM_ABS_TRANS_ONLY_BITS - !allow_high_precision_mv as u32;
2952                prec_bits = GM_TRANS_ONLY_PREC_BITS - !allow_high_precision_mv as u32;
2953            } else {
2954                abs_bits = GM_ABS_TRANS_BITS;
2955                prec_bits = GM_TRANS_PREC_BITS;
2956            }
2957        }
2958
2959        let prec_diff = WARPEDMODEL_PREC_BITS - prec_bits;
2960
2961        let (round, sub) =
2962            if (idx % 3) == 2 { (1 << WARPEDMODEL_PREC_BITS, 1 << prec_bits) } else { (0, 0) };
2963
2964        let mx = 1 << abs_bits;
2965        let r = (prev_gm_params[ref_frame][idx] >> prec_diff) - sub;
2966        gm_params[ref_frame][idx] =
2967            (reader.decode_signed_subexp_with_ref(-mx, mx + 1, r)? << prec_diff) + round;
2968
2969        Ok(())
2970    }
2971
2972    fn parse_global_motion_params(
2973        &mut self,
2974        r: &mut Reader,
2975        fh: &mut FrameHeaderObu,
2976    ) -> Result<(), String> {
2977        let gm = &mut fh.global_motion_params;
2978        let mut type_;
2979        let mut prev_gm_params: [[i32; 6]; NUM_REF_FRAMES] = Default::default();
2980
2981        for ref_frame in ReferenceFrameType::Last as usize..=ReferenceFrameType::AltRef as usize {
2982            gm.gm_type[ref_frame] = WarpModelType::Identity;
2983            for i in 0..6 {
2984                gm.gm_params[ref_frame][i] = if i % 3 == 2 { 1 << WARPEDMODEL_PREC_BITS } else { 0 }
2985            }
2986            gm.warp_valid[ref_frame] = true;
2987        }
2988
2989        if fh.frame_is_intra {
2990            return Ok(());
2991        }
2992
2993        // Following libgav1: implement part of setup_past_independence() and
2994        // load_previous(), i.e.: the parts that refer to the global motion
2995        // parameters.
2996        if fh.primary_ref_frame == PRIMARY_REF_NONE {
2997            // setup_past_independence()
2998            #[allow(clippy::needless_range_loop)]
2999            for ref_frame in ReferenceFrameType::Last as usize..ReferenceFrameType::AltRef as usize
3000            {
3001                for i in 0..5 {
3002                    prev_gm_params[ref_frame][i] =
3003                        if i % 3 == 2 { 1 << WARPEDMODEL_PREC_BITS } else { 0 }
3004                }
3005            }
3006        } else {
3007            // load_previous():
3008            // 1. The variable prevFrame is set equal to ref_frame_idx[ primary_ref_frame ].
3009            // 2. PrevGmParams is set equal to SavedGmParams[ prevFrame ].
3010            let prev_frame = fh.ref_frame_idx[fh.primary_ref_frame as usize];
3011            prev_gm_params = self.ref_info[prev_frame as usize].global_motion_params.gm_params;
3012        }
3013
3014        for ref_frame in ReferenceFrameType::Last as usize..=ReferenceFrameType::AltRef as usize {
3015            gm.is_global[ref_frame] = r.0.read_bit()?;
3016            if gm.is_global[ref_frame] {
3017                gm.is_rot_zoom[ref_frame] = r.0.read_bit()?;
3018                if gm.is_rot_zoom[ref_frame] {
3019                    type_ = WarpModelType::RotZoom;
3020                } else {
3021                    gm.is_translation[ref_frame] = r.0.read_bit()?;
3022                    if gm.is_translation[ref_frame] {
3023                        type_ = WarpModelType::Translation;
3024                    } else {
3025                        type_ = WarpModelType::Affine;
3026                    }
3027                }
3028            } else {
3029                type_ = WarpModelType::Identity;
3030            }
3031
3032            gm.gm_type[ref_frame] = type_;
3033            if gm.gm_type[ref_frame] as u32 >= WarpModelType::RotZoom as u32 {
3034                Self::read_global_param(
3035                    r,
3036                    type_,
3037                    ref_frame,
3038                    2,
3039                    fh.allow_high_precision_mv,
3040                    &prev_gm_params,
3041                    &mut gm.gm_params,
3042                )?;
3043
3044                Self::read_global_param(
3045                    r,
3046                    type_,
3047                    ref_frame,
3048                    3,
3049                    fh.allow_high_precision_mv,
3050                    &prev_gm_params,
3051                    &mut gm.gm_params,
3052                )?;
3053
3054                if type_ == WarpModelType::Affine {
3055                    Self::read_global_param(
3056                        r,
3057                        type_,
3058                        ref_frame,
3059                        4,
3060                        fh.allow_high_precision_mv,
3061                        &prev_gm_params,
3062                        &mut gm.gm_params,
3063                    )?;
3064
3065                    Self::read_global_param(
3066                        r,
3067                        type_,
3068                        ref_frame,
3069                        5,
3070                        fh.allow_high_precision_mv,
3071                        &prev_gm_params,
3072                        &mut gm.gm_params,
3073                    )?;
3074                } else {
3075                    gm.gm_params[ref_frame][4] = -gm.gm_params[ref_frame][3];
3076                    gm.gm_params[ref_frame][5] = gm.gm_params[ref_frame][2];
3077                }
3078            }
3079
3080            if gm.gm_type[ref_frame] as u32 >= WarpModelType::Translation as u32 {
3081                Self::read_global_param(
3082                    r,
3083                    type_,
3084                    ref_frame,
3085                    0,
3086                    fh.allow_high_precision_mv,
3087                    &prev_gm_params,
3088                    &mut gm.gm_params,
3089                )?;
3090
3091                Self::read_global_param(
3092                    r,
3093                    type_,
3094                    ref_frame,
3095                    1,
3096                    fh.allow_high_precision_mv,
3097                    &prev_gm_params,
3098                    &mut gm.gm_params,
3099                )?;
3100            }
3101
3102            gm.warp_valid[ref_frame] = Self::setup_shear(&gm.gm_params[ref_frame])?;
3103        }
3104
3105        Ok(())
3106    }
3107
3108    fn parse_film_grain_parameters(
3109        &self,
3110        r: &mut Reader,
3111        fh: &mut FrameHeaderObu,
3112        film_grain_params_present: bool,
3113        mono_chrome: bool,
3114        subsampling_x: bool,
3115        subsampling_y: bool,
3116    ) -> Result<(), String> {
3117        let fg = &mut fh.film_grain_params;
3118
3119        if !film_grain_params_present || (!fh.show_frame && !fh.showable_frame) {
3120            *fg = Default::default();
3121            return Ok(());
3122        }
3123
3124        fg.apply_grain = r.0.read_bit()?;
3125        if !fg.apply_grain {
3126            *fg = Default::default();
3127            return Ok(());
3128        }
3129
3130        fg.grain_seed = r.0.read_bits::<u32>(16)? as u16;
3131        if fh.frame_type == FrameType::InterFrame {
3132            fg.update_grain = r.0.read_bit()?;
3133        } else {
3134            fg.update_grain = true;
3135        }
3136
3137        if !fg.update_grain {
3138            fg.film_grain_params_ref_idx = r.0.read_bits::<u32>(3)? as u8;
3139            let temp_grain_seed = fg.grain_seed;
3140
3141            if !fh
3142                .ref_frame_idx
3143                .iter()
3144                .any(|&ref_frame_idx| ref_frame_idx == fg.film_grain_params_ref_idx)
3145            {
3146                return Err("Invalid film_grain_params_ref_idx".into());
3147            }
3148
3149            // load_grain_params()
3150            *fg = self.ref_info[fg.film_grain_params_ref_idx as usize].film_grain_params.clone();
3151
3152            fg.grain_seed = temp_grain_seed;
3153
3154            return Ok(());
3155        }
3156
3157        fg.num_y_points = r.0.read_bits::<u32>(4)? as u8;
3158        fg.point_y_value
3159            .iter_mut()
3160            .zip(fg.point_y_scaling.iter_mut())
3161            .take(fg.num_y_points as usize)
3162            .try_for_each(|(point_y_value, point_y_scaling)| {
3163                *point_y_value = r.0.read_bits::<u32>(8)? as u8;
3164                *point_y_scaling = r.0.read_bits::<u32>(8)? as u8;
3165                Ok::<_, String>(())
3166            })?;
3167
3168        if mono_chrome {
3169            fg.chroma_scaling_from_luma = false;
3170        } else {
3171            fg.chroma_scaling_from_luma = r.0.read_bit()?;
3172        }
3173
3174        if mono_chrome
3175            || fg.chroma_scaling_from_luma
3176            || (subsampling_x && subsampling_y && fg.num_y_points == 0)
3177        {
3178            fg.num_cb_points = 0;
3179            fg.num_cr_points = 0;
3180        } else {
3181            fg.num_cb_points = r.0.read_bits::<u32>(4)? as u8;
3182            if fg.num_cb_points > 10 {
3183                return Err(format!("Invalid num_cb_points {}", fg.num_cb_points));
3184            }
3185
3186            for i in 0..fg.num_cb_points as usize {
3187                fg.point_cb_value[i] = r.0.read_bits::<u32>(8)? as u8;
3188                if i > 0 && fg.point_cb_value[i - 1] >= fg.point_cb_value[i] {
3189                    return Err(format!("Invalid point_cb_value[{}] {}", i, fg.point_cb_value[i]));
3190                }
3191                fg.point_cb_scaling[i] = r.0.read_bits::<u32>(8)? as u8;
3192            }
3193
3194            fg.num_cr_points = r.0.read_bits::<u32>(4)? as u8;
3195            for i in 0..fg.num_cr_points as usize {
3196                fg.point_cr_value[i] = r.0.read_bits::<u32>(8)? as u8;
3197                if i > 0 && fg.point_cr_value[i - 1] >= fg.point_cr_value[i] {
3198                    return Err(format!("Invalid point_cr_value[{}] {}", i, fg.point_cr_value[i]));
3199                }
3200                fg.point_cr_scaling[i] = r.0.read_bits::<u32>(8)? as u8;
3201            }
3202        }
3203
3204        fg.grain_scaling_minus_8 = r.0.read_bits::<u32>(2)? as u8;
3205        fg.ar_coeff_lag = r.0.read_bits::<u32>(2)?;
3206
3207        let num_pos_luma = 2 * fg.ar_coeff_lag * (fg.ar_coeff_lag + 1);
3208        let num_pos_chroma = if fg.num_y_points > 0 {
3209            for i in 0..num_pos_luma as usize {
3210                fg.ar_coeffs_y_plus_128[i] = r.0.read_bits::<u32>(8)? as u8;
3211            }
3212            num_pos_luma + 1
3213        } else {
3214            num_pos_luma
3215        };
3216
3217        if fg.chroma_scaling_from_luma || fg.num_cb_points > 0 {
3218            for i in 0..num_pos_chroma as usize {
3219                fg.ar_coeffs_cb_plus_128[i] = r.0.read_bits::<u32>(8)? as u8;
3220            }
3221        }
3222
3223        if fg.chroma_scaling_from_luma || fg.num_cr_points > 0 {
3224            for i in 0..num_pos_chroma as usize {
3225                fg.ar_coeffs_cr_plus_128[i] = r.0.read_bits::<u32>(8)? as u8;
3226            }
3227        }
3228
3229        fg.ar_coeff_shift_minus_6 = r.0.read_bits::<u32>(2)? as u8;
3230        fg.grain_scale_shift = r.0.read_bits::<u32>(2)? as u8;
3231
3232        if fg.num_cb_points > 0 {
3233            fg.cb_mult = r.0.read_bits::<u32>(8)? as u8;
3234            fg.cb_luma_mult = r.0.read_bits::<u32>(8)? as u8;
3235            fg.cb_offset = r.0.read_bits::<u32>(9)? as u16;
3236        }
3237
3238        if fg.num_cr_points > 0 {
3239            fg.cr_mult = r.0.read_bits::<u32>(8)? as u8;
3240            fg.cr_luma_mult = r.0.read_bits::<u32>(8)? as u8;
3241            fg.cr_offset = r.0.read_bits::<u32>(9)? as u16;
3242        }
3243
3244        fg.overlap_flag = r.0.read_bit()?;
3245        fg.clip_to_restricted_range = r.0.read_bit()?;
3246
3247        Ok(())
3248    }
3249
3250    fn sequence(&self) -> Result<&SequenceHeaderObu, String> {
3251        let Some(seq) = self.sequence_header.as_ref() else {
3252            return Err("No sequence header parsed yet".into());
3253        };
3254
3255        Ok(seq)
3256    }
3257
3258    fn parse_uncompressed_frame_header(&mut self, obu: &Obu) -> Result<FrameHeaderObu, String> {
3259        let mut r = Reader::new(obu.as_ref());
3260
3261        let mut fh = FrameHeaderObu { obu_header: obu.header.clone(), ..Default::default() };
3262
3263        // Section 6.8.1: It is a requirement of bitstream conformance that a
3264        // sequence header OBU has been received before a frame header OBU.
3265        let &SequenceHeaderObu {
3266            operating_points_cnt_minus_1,
3267            seq_force_integer_mv,
3268            additional_frame_id_length_minus_1,
3269            delta_frame_id_length_minus_2,
3270            decoder_model_info_present_flag,
3271            reduced_still_picture_header,
3272            frame_id_numbers_present_flag,
3273            use_128x128_superblock,
3274            enable_order_hint,
3275            seq_force_screen_content_tools,
3276            order_hint_bits,
3277            enable_cdef,
3278            enable_restoration,
3279            enable_warped_motion,
3280            color_config:
3281                ColorConfig { subsampling_x, subsampling_y, separate_uv_delta_q, mono_chrome, .. },
3282            timing_info: TimingInfo { equal_picture_interval, .. },
3283            decoder_model_info:
3284                DecoderModelInfo {
3285                    frame_presentation_time_length_minus_1,
3286                    buffer_removal_time_length_minus_1,
3287                    ..
3288                },
3289            num_planes,
3290            film_grain_params_present,
3291            ..
3292        } = self.sequence()?;
3293
3294        let mut id_len = 0;
3295
3296        if frame_id_numbers_present_flag {
3297            id_len = additional_frame_id_length_minus_1 + delta_frame_id_length_minus_2 + 3;
3298        }
3299
3300        const ALL_FRAMES: u32 = (1 << NUM_REF_FRAMES) - 1;
3301
3302        if reduced_still_picture_header {
3303            fh.show_existing_frame = false;
3304            fh.frame_type = FrameType::KeyFrame;
3305            fh.frame_is_intra = true;
3306            fh.show_frame = true;
3307            fh.showable_frame = false;
3308        } else {
3309            fh.show_existing_frame = r.0.read_bit()?;
3310            if matches!(obu.header.obu_type, ObuType::Frame) && fh.show_existing_frame {
3311                return Err("If obu_type is equal to OBU_FRAME, it is a requirement of bitstream conformance that show_existing_frame is equal to 0.".into());
3312            }
3313            if fh.show_existing_frame {
3314                fh.frame_to_show_map_idx = r.0.read_bits::<u32>(3)? as u8;
3315
3316                if decoder_model_info_present_flag && !equal_picture_interval {
3317                    fh.frame_presentation_time =
3318                        r.0.read_bits::<u32>(frame_presentation_time_length_minus_1 as usize + 1)?;
3319                }
3320
3321                let ref_frame = &self.ref_info[fh.frame_to_show_map_idx as usize];
3322
3323                fh.refresh_frame_flags = 0;
3324                if frame_id_numbers_present_flag {
3325                    if id_len == 0 {
3326                        return Err(format!("Invalid id_len {}", id_len));
3327                    }
3328                    fh.display_frame_id = r.0.read_bits::<u32>(id_len.try_into().unwrap())?;
3329                    if ref_frame.display_frame_id != fh.display_frame_id || !ref_frame.ref_valid {
3330                        return Err("Invalid display_frame_id".into());
3331                    }
3332                }
3333
3334                if !ref_frame.showable_frame {
3335                    return Err("Invalid bitstream: can't show this past frame".into());
3336                }
3337
3338                // In decode_frame_wrapup():
3339                //
3340                // Otherwise (show_existing_frame is equal to 1), if frame_type
3341                // is equal to KEY_FRAME, the reference frame loading process as
3342                // specified in section 7.21 is invoked (this process loads
3343                // frame state from the reference frames into the current frame
3344                // state variables)
3345                //
3346                // The following ordered steps now apply:
3347                //
3348                // 1. The reference frame update process as specified in section
3349                // 7.20 is invoked (this process saves the current frame state
3350                // into the reference frames).
3351                //
3352                // 2. If show_frame is equal to 1 or show_existing_frame is
3353                // equal to 1, the output process as specified in section 7.18
3354                // is invoked (this will output the current frame or a saved
3355                // frame).
3356                //
3357                // We implement 1. here while 2. is left to the actual decoder
3358                self.load_reference_frame(&mut fh)?;
3359                if fh.frame_type == FrameType::KeyFrame {
3360                    fh.refresh_frame_flags = ALL_FRAMES;
3361                }
3362
3363                if film_grain_params_present {
3364                    // load_grain_params()
3365                    fh.film_grain_params =
3366                        self.ref_info[fh.frame_to_show_map_idx as usize].film_grain_params.clone();
3367                }
3368
3369                // See 5.10.
3370                if matches!(obu.header.obu_type, ObuType::Frame) {
3371                    r.byte_alignment()?;
3372                }
3373
3374                fh.header_bytes = usize::try_from(r.0.position() / 8).unwrap();
3375                return Ok(fh);
3376            }
3377
3378            fh.frame_type = FrameType::try_from(r.0.read_bits::<u32>(2)?)?;
3379            fh.frame_is_intra =
3380                matches!(fh.frame_type, FrameType::IntraOnlyFrame | FrameType::KeyFrame);
3381
3382            fh.show_frame = r.0.read_bit()?;
3383
3384            if fh.show_frame && decoder_model_info_present_flag && equal_picture_interval {
3385                fh.frame_presentation_time =
3386                    r.0.read_bits::<u32>(frame_presentation_time_length_minus_1 as usize + 1)?;
3387            }
3388
3389            if fh.show_frame {
3390                fh.showable_frame = !matches!(fh.frame_type, FrameType::KeyFrame);
3391            } else {
3392                fh.showable_frame = r.0.read_bit()?;
3393            }
3394
3395            if fh.frame_type == FrameType::SwitchFrame
3396                || (fh.frame_type == FrameType::KeyFrame && fh.show_frame)
3397            {
3398                fh.error_resilient_mode = true;
3399            } else {
3400                fh.error_resilient_mode = r.0.read_bit()?;
3401            }
3402        }
3403
3404        if fh.frame_type == FrameType::KeyFrame && fh.show_frame {
3405            for i in 0..NUM_REF_FRAMES {
3406                self.ref_info[i].ref_valid = false;
3407                self.ref_info[i].ref_order_hint = 0;
3408            }
3409            for i in 0..REFS_PER_FRAME {
3410                fh.order_hints[ReferenceFrameType::Last as usize + i] = 0;
3411            }
3412        }
3413
3414        fh.disable_cdf_update = r.0.read_bit()?;
3415        if seq_force_screen_content_tools == SELECT_SCREEN_CONTENT_TOOLS as u32 {
3416            fh.allow_screen_content_tools = r.0.read_bit()? as u32;
3417        } else {
3418            fh.allow_screen_content_tools = seq_force_screen_content_tools;
3419        }
3420
3421        if fh.allow_screen_content_tools > 0 {
3422            if seq_force_integer_mv == SELECT_INTEGER_MV as u32 {
3423                fh.force_integer_mv = r.0.read_bit()? as u32;
3424            } else {
3425                fh.force_integer_mv = seq_force_integer_mv;
3426            }
3427        } else {
3428            fh.force_integer_mv = 0;
3429        }
3430
3431        if fh.frame_is_intra {
3432            fh.force_integer_mv = 1;
3433        }
3434
3435        if frame_id_numbers_present_flag {
3436            self.prev_frame_id = self.current_frame_id;
3437            self.current_frame_id = r.0.read_bits::<u32>(id_len.try_into().unwrap())?;
3438            fh.current_frame_id = self.current_frame_id;
3439
3440            /* conformance checking, as per aom */
3441            let have_prev_frame_id =
3442                !(self.is_first_frame || fh.frame_type == FrameType::KeyFrame && fh.show_frame);
3443
3444            if have_prev_frame_id {
3445                let frame_id_length =
3446                    additional_frame_id_length_minus_1 + delta_frame_id_length_minus_2 + 3;
3447
3448                let diff_frame_id = if self.current_frame_id > self.prev_frame_id {
3449                    self.current_frame_id - self.prev_frame_id
3450                } else {
3451                    if frame_id_length > 16 {
3452                        return Err(format!("Invalid frame_id_length {}", frame_id_length));
3453                    }
3454                    (1 << frame_id_length) + self.current_frame_id - self.prev_frame_id
3455                };
3456
3457                if self.prev_frame_id == self.current_frame_id
3458                    || diff_frame_id >= (1 << (frame_id_length - 1))
3459                {
3460                    return Err(format!(
3461                        "Invalid frame_id: prev_frame_id = {}, current_frame_id = {}",
3462                        self.prev_frame_id, self.current_frame_id
3463                    ));
3464                }
3465            }
3466
3467            /* mark_ref_frames (idLen) */
3468            let diff_len = delta_frame_id_length_minus_2 + 2;
3469            let shifted_diff_len = 1 << diff_len;
3470            let shifted_id_len = 1 << id_len;
3471
3472            for i in 0..NUM_REF_FRAMES {
3473                if self.current_frame_id > shifted_diff_len {
3474                    if self.ref_info[i].ref_frame_id > self.current_frame_id
3475                        || self.ref_info[i].ref_frame_id
3476                            < (self.current_frame_id - shifted_diff_len)
3477                    {
3478                        self.ref_info[i].ref_valid = false;
3479                    }
3480                } else if self.ref_info[i].ref_frame_id > self.current_frame_id
3481                    && self.ref_info[i].ref_frame_id
3482                        < shifted_id_len + self.current_frame_id - shifted_diff_len
3483                {
3484                    self.ref_info[i].ref_valid = false;
3485                }
3486            }
3487        } else {
3488            self.current_frame_id = 0;
3489            self.prev_frame_id = self.current_frame_id;
3490            fh.current_frame_id = self.current_frame_id;
3491        }
3492
3493        if fh.frame_type == FrameType::SwitchFrame {
3494            fh.frame_size_override_flag = true;
3495        } else if reduced_still_picture_header {
3496            fh.frame_size_override_flag = false;
3497        } else {
3498            fh.frame_size_override_flag = r.0.read_bit()?;
3499        }
3500
3501        fh.order_hint = r.0.read_bits::<u32>(order_hint_bits.try_into().unwrap())?;
3502
3503        if fh.frame_is_intra || fh.error_resilient_mode {
3504            fh.primary_ref_frame = PRIMARY_REF_NONE;
3505        } else {
3506            fh.primary_ref_frame = r.0.read_bits::<u32>(3)?;
3507        }
3508
3509        let operating_points = &self.sequence()?.operating_points;
3510        if decoder_model_info_present_flag {
3511            fh.buffer_removal_time_present_flag = r.0.read_bit()?;
3512            if fh.buffer_removal_time_present_flag {
3513                #[allow(clippy::needless_range_loop)]
3514                for op_num in 0..=operating_points_cnt_minus_1 as usize {
3515                    if operating_points[op_num].decoder_model_present_for_this_op {
3516                        let op_pt_idc = operating_points[op_num].idc;
3517                        let in_temporal_layer = (op_pt_idc >> fh.obu_header.temporal_id) & 1 != 0;
3518                        let in_spatial_layer =
3519                            (op_pt_idc >> (fh.obu_header.spatial_id + 8)) & 1 != 0;
3520
3521                        if op_pt_idc == 0 || (in_temporal_layer && in_spatial_layer) {
3522                            let n = buffer_removal_time_length_minus_1 + 1;
3523                            fh.buffer_removal_time[op_num] = r.0.read_bits::<u32>(n as usize)?;
3524                        }
3525                    }
3526                }
3527            }
3528        }
3529
3530        fh.allow_high_precision_mv = false;
3531        fh.use_ref_frame_mvs = false;
3532        fh.allow_intrabc = false;
3533        if fh.frame_type == FrameType::SwitchFrame
3534            || (fh.frame_type == FrameType::KeyFrame && fh.show_frame)
3535        {
3536            fh.refresh_frame_flags = ALL_FRAMES;
3537        } else {
3538            fh.refresh_frame_flags = r.0.read_bits::<u32>(8)?;
3539        }
3540
3541        /* equivalent boolean expression */
3542        if (!fh.frame_is_intra || fh.refresh_frame_flags != ALL_FRAMES)
3543            && fh.error_resilient_mode
3544            && enable_order_hint
3545        {
3546            for i in 0..NUM_REF_FRAMES {
3547                fh.ref_order_hint[i] = r.0.read_bits::<u32>(order_hint_bits.try_into().unwrap())?;
3548                if fh.ref_order_hint[i] != self.ref_info[i].ref_order_hint {
3549                    self.ref_info[i].ref_valid = false;
3550                }
3551            }
3552        }
3553
3554        if fh.frame_is_intra {
3555            self.parse_frame_size(&mut fh, &mut r)?;
3556            Self::parse_render_size(&mut fh, &mut r)?;
3557            if fh.allow_screen_content_tools > 0 && fh.upscaled_width == fh.frame_width {
3558                fh.allow_intrabc = r.0.read_bit()?;
3559            }
3560        } else {
3561            if !enable_order_hint {
3562                fh.frame_refs_short_signaling = false;
3563            } else {
3564                fh.frame_refs_short_signaling = r.0.read_bit()?;
3565                if fh.frame_refs_short_signaling {
3566                    fh.last_frame_idx = r.0.read_bits::<u32>(3)? as u8;
3567                    fh.gold_frame_idx = r.0.read_bits::<u32>(3)? as u8;
3568                    let ref_order_hints = self
3569                        .ref_info
3570                        .iter()
3571                        .map(|i| i.ref_order_hint)
3572                        .collect::<Vec<_>>()
3573                        .try_into()
3574                        .unwrap();
3575                    self.set_frame_refs(&mut fh, &ref_order_hints)?;
3576                }
3577            }
3578
3579            let mut expected_frame_id = [0; REFS_PER_FRAME];
3580            #[allow(clippy::needless_range_loop)]
3581            for i in 0..REFS_PER_FRAME {
3582                if !fh.frame_refs_short_signaling {
3583                    fh.ref_frame_idx[i] = r.0.read_bits::<u32>(3)?.try_into().unwrap();
3584                }
3585
3586                if frame_id_numbers_present_flag {
3587                    /* DeltaFrameId */
3588                    let delta_frame_id =
3589                        r.0.read_bits::<u32>(delta_frame_id_length_minus_2 as usize + 2)? + 1;
3590
3591                    if id_len == 0 {
3592                        return Err(format!("Invalid id_len {}", id_len));
3593                    }
3594
3595                    let shifted_id_len = 1 << id_len;
3596
3597                    expected_frame_id[i] =
3598                        (self.current_frame_id + shifted_id_len - delta_frame_id) % shifted_id_len;
3599
3600                    let actual_frame_id = self.ref_info[fh.ref_frame_idx[i] as usize].ref_frame_id;
3601
3602                    if expected_frame_id[i] != actual_frame_id {
3603                        return Err(format!(
3604                            "Invalid frame id, expected {} got {}",
3605                            expected_frame_id[i], actual_frame_id
3606                        ));
3607                    }
3608                }
3609            }
3610
3611            if fh.frame_size_override_flag && !fh.error_resilient_mode {
3612                self.frame_size_with_refs(&mut fh, &mut r)?;
3613            } else {
3614                self.parse_frame_size(&mut fh, &mut r)?;
3615                Self::parse_render_size(&mut fh, &mut r)?;
3616            }
3617
3618            if fh.force_integer_mv > 0 {
3619                fh.allow_high_precision_mv = false;
3620            } else {
3621                fh.allow_high_precision_mv = r.0.read_bit()?;
3622            }
3623
3624            /* read_interpolation_filter */
3625            fh.is_filter_switchable = r.0.read_bit()?;
3626            if fh.is_filter_switchable {
3627                fh.interpolation_filter = InterpolationFilter::Switchable;
3628            } else {
3629                fh.interpolation_filter = InterpolationFilter::try_from(r.0.read_bits::<u32>(2)?)?;
3630            }
3631
3632            fh.is_motion_mode_switchable = r.0.read_bit()?;
3633
3634            if fh.error_resilient_mode || !self.sequence()?.enable_ref_frame_mvs {
3635                fh.use_ref_frame_mvs = false;
3636            } else {
3637                fh.use_ref_frame_mvs = r.0.read_bit()?;
3638            }
3639
3640            for i in 0..REFS_PER_FRAME {
3641                let ref_frame = ReferenceFrameType::Last as usize + i;
3642                let hint = self.ref_info[fh.ref_frame_idx[i] as usize].ref_order_hint;
3643                fh.order_hints[ref_frame] = hint;
3644
3645                if !enable_order_hint {
3646                    fh.ref_frame_sign_bias[i] = false;
3647                } else {
3648                    fh.ref_frame_sign_bias[i] = helpers::get_relative_dist(
3649                        enable_order_hint,
3650                        order_hint_bits,
3651                        hint.try_into().unwrap(),
3652                        fh.order_hint.try_into().unwrap(),
3653                    ) > 0;
3654                }
3655            }
3656        }
3657
3658        if reduced_still_picture_header || fh.disable_cdf_update {
3659            fh.disable_frame_end_update_cdf = true;
3660        } else {
3661            fh.disable_frame_end_update_cdf = r.0.read_bit()?;
3662        }
3663
3664        if fh.primary_ref_frame == PRIMARY_REF_NONE {
3665            Self::setup_past_independence(&mut fh);
3666        } else {
3667            /* load from the past reference */
3668            let prev_frame =
3669                &self.ref_info[fh.ref_frame_idx[fh.primary_ref_frame as usize] as usize];
3670
3671            if !prev_frame.ref_valid {
3672                return Err("Reference is invalid".into());
3673            }
3674
3675            /* load_loop_filter_params: load ref_deltas and mode_deltas */
3676            fh.loop_filter_params.loop_filter_ref_deltas =
3677                prev_frame.loop_filter_params.loop_filter_ref_deltas;
3678            fh.loop_filter_params.loop_filter_mode_deltas =
3679                prev_frame.loop_filter_params.loop_filter_mode_deltas;
3680
3681            /* load_segmentation_params: load feature_enabled and feature_data */
3682            fh.segmentation_params.feature_enabled = prev_frame.segmentation_params.feature_enabled;
3683            fh.segmentation_params.feature_data = prev_frame.segmentation_params.feature_data;
3684        }
3685
3686        // TODO: we can live without this for now.
3687        // if fh.use_ref_frame_mvs {
3688        //     // motion_field_estimators()
3689        // }
3690
3691        self.parse_tile_info(&mut r, &mut fh.tile_info)?;
3692        Self::parse_quantization_params(
3693            &mut r,
3694            &mut fh.quantization_params,
3695            num_planes,
3696            separate_uv_delta_q,
3697        )?;
3698        self.parse_segmentation_params(&mut r, &mut fh)?;
3699        Self::parse_delta_q_params(&mut r, &mut fh.quantization_params)?;
3700        Self::parse_delta_lf_params(
3701            &mut r,
3702            &mut fh.loop_filter_params,
3703            fh.quantization_params.delta_q_present,
3704            fh.allow_intrabc,
3705        )?;
3706
3707        fh.coded_lossless = true;
3708        for segment_id in 0..MAX_SEGMENTS {
3709            let q_index = Self::get_qindex(&fh, true, segment_id as _);
3710            let q = &fh.quantization_params;
3711            fh.lossless_array[segment_id] = q_index == 0
3712                && q.delta_q_y_dc == 0
3713                && q.delta_q_u_ac == 0
3714                && q.delta_q_u_dc == 0
3715                && q.delta_q_v_ac == 0
3716                && q.delta_q_v_dc == 0;
3717            if !fh.lossless_array[segment_id] {
3718                fh.coded_lossless = false;
3719            }
3720            if q.using_qmatrix {
3721                if fh.lossless_array[segment_id] {
3722                    fh.seg_qm_level[0][segment_id] = 15;
3723                    fh.seg_qm_level[1][segment_id] = 15;
3724                    fh.seg_qm_level[2][segment_id] = 15;
3725                } else {
3726                    fh.seg_qm_level[0][segment_id] = q.qm_y;
3727                    fh.seg_qm_level[1][segment_id] = q.qm_u;
3728                    fh.seg_qm_level[2][segment_id] = q.qm_v;
3729                }
3730            }
3731        }
3732
3733        fh.all_lossless = fh.coded_lossless && fh.frame_width == fh.upscaled_width;
3734        Self::parse_loop_filter_parameters(&mut r, &mut fh, num_planes)?;
3735        Self::parse_cdef_params(&mut r, &mut fh, enable_cdef, num_planes)?;
3736        Self::parse_loop_restoration_params(
3737            &mut r,
3738            &mut fh,
3739            enable_restoration,
3740            num_planes,
3741            use_128x128_superblock,
3742            subsampling_x,
3743            subsampling_y,
3744        )?;
3745        Self::read_tx_mode(&mut r, &mut fh)?;
3746        Self::parse_frame_reference_mode(&mut r, &mut fh)?;
3747        self.parse_skip_mode_params(&mut r, &mut fh, enable_order_hint, order_hint_bits)?;
3748
3749        if fh.frame_is_intra || fh.error_resilient_mode || !enable_warped_motion {
3750            fh.allow_warped_motion = false;
3751        } else {
3752            fh.allow_warped_motion = r.0.read_bit()?;
3753        }
3754
3755        fh.reduced_tx_set = r.0.read_bit()?;
3756        self.parse_global_motion_params(&mut r, &mut fh)?;
3757        self.parse_film_grain_parameters(
3758            &mut r,
3759            &mut fh,
3760            film_grain_params_present,
3761            mono_chrome,
3762            subsampling_x,
3763            subsampling_y,
3764        )?;
3765
3766        Self::skip_and_check_trailing_bits(&mut r, obu)?;
3767
3768        // See 5.10
3769        if matches!(obu.header.obu_type, ObuType::Frame) {
3770            r.byte_alignment()?;
3771        }
3772
3773        fh.header_bytes = usize::try_from(r.0.position() / 8).unwrap();
3774        Ok(fh)
3775    }
3776
3777    fn parse_tile_group_obu<'a>(&mut self, obu: Obu<'a>) -> Result<TileGroupObu<'a>, String> {
3778        let mut tg = TileGroupObu { obu, ..Default::default() };
3779
3780        let mut r = Reader::new(tg.obu.as_ref());
3781
3782        if r.0.num_bits_left() % 8 != 0 {
3783            return Err("Bitstream is not byte aligned".into());
3784        }
3785
3786        let mut sz: u64 = r.0.num_bits_left() as u64 / 8;
3787
3788        let num_tiles = self.tile_rows * self.tile_cols;
3789        let start_bit_pos = r.0.position();
3790
3791        if num_tiles > 1 {
3792            tg.tile_start_and_end_present_flag = r.0.read_bit()?;
3793        }
3794
3795        if num_tiles == 1 || !tg.tile_start_and_end_present_flag {
3796            tg.tg_start = 0;
3797            tg.tg_end = num_tiles - 1;
3798        } else {
3799            let tile_bits = (self.tile_cols_log2 + self.tile_rows_log2) as usize;
3800            tg.tg_start = r.0.read_bits::<u32>(tile_bits)?;
3801            tg.tg_end = r.0.read_bits::<u32>(tile_bits)?;
3802        }
3803
3804        r.byte_alignment()?;
3805
3806        let end_bit_pos = r.0.position();
3807        let header_bytes = (end_bit_pos - start_bit_pos) / 8;
3808        sz -= header_bytes;
3809
3810        let mut tile_num = tg.tg_start;
3811        while tile_num <= tg.tg_end {
3812            let tile_row = tile_num / self.tile_cols;
3813            let tile_col = tile_num % self.tile_cols;
3814            let last_tile = tile_num == tg.tg_end;
3815            let tile_size;
3816
3817            if last_tile {
3818                tile_size = u32::try_from(sz).unwrap();
3819            } else {
3820                tile_size = r.0.read_le::<u32>(self.tile_size_bytes.try_into().unwrap())? + 1;
3821                sz -= u64::from(tile_size + self.tile_size_bytes);
3822            }
3823
3824            let tile = Tile {
3825                tile_offset: u32::try_from(r.0.position()).unwrap() / 8,
3826                tile_size,
3827                tile_row,
3828                tile_col,
3829                mi_row_start: self.mi_row_starts[tile_row as usize],
3830                mi_row_end: self.mi_row_starts[tile_row as usize + 1],
3831                mi_col_start: self.mi_row_starts[tile_col as usize],
3832                mi_col_end: self.mi_row_starts[tile_col as usize + 1],
3833            };
3834
3835            tg.tiles.push(tile);
3836
3837            // init_symbol, decode_tile() and exit_symbol() left to the accelerator.
3838
3839            // Skip the actual tile data
3840            if tile_num < tg.tg_end {
3841                r.0.skip_bits(tile_size as usize * 8)?;
3842            }
3843
3844            tile_num += 1;
3845        }
3846
3847        if tg.tg_end == num_tiles - 1 {
3848            // left to the accelerator:
3849            // if ( !disable_frame_end_update_cdf ) {
3850            //  frame_end_update_cdf( )
3851            // }
3852            // decode_frame_wrapup( )
3853            self.seen_frame_header = false;
3854        }
3855
3856        Ok(tg)
3857    }
3858
3859    fn parse_frame_obu<'a>(&mut self, obu: Obu<'a>) -> Result<FrameObu<'a>, String> {
3860        if !matches!(obu.header.obu_type, ObuType::Frame) {
3861            return Err(format!("Expected a FrameOBU, got {:?}", obu.header.obu_type));
3862        }
3863
3864        let frame_header_obu = self.parse_frame_header_obu(&obu)?;
3865        let obu = Obu {
3866            header: obu.header,
3867            data: match obu.data {
3868                Cow::Borrowed(d) => Cow::Borrowed(&d[frame_header_obu.header_bytes..]),
3869                Cow::Owned(d) => Cow::Owned(d[frame_header_obu.header_bytes..].to_owned()),
3870            },
3871            bytes_used: obu.bytes_used,
3872        };
3873        let tile_group_obu = self.parse_tile_group_obu(obu)?;
3874
3875        Ok(FrameObu { header: frame_header_obu, tile_group: tile_group_obu })
3876    }
3877
3878    pub fn parse_frame_header_obu(&mut self, obu: &Obu) -> Result<FrameHeaderObu, String> {
3879        if !matches!(obu.header.obu_type, ObuType::FrameHeader | ObuType::Frame) {
3880            return Err(format!("Expected a FrameHeaderOBU, got {:?}", obu.header.obu_type));
3881        }
3882
3883        if self.seen_frame_header {
3884            Ok(self
3885                .last_frame_header
3886                .clone()
3887                .take()
3888                .ok_or::<String>("Broken stream: no previous frame header to copy".into())?)
3889        } else {
3890            self.seen_frame_header = true;
3891            let header = self.parse_uncompressed_frame_header(obu)?;
3892            if header.show_existing_frame {
3893                self.last_frame_header = None;
3894                self.seen_frame_header = false;
3895            } else {
3896                /* TileNum = 0 */
3897                self.seen_frame_header = true;
3898                self.last_frame_header = Some(header.clone());
3899            }
3900
3901            Ok(header)
3902        }
3903    }
3904
3905    /// Implements 7.20. This function should be called right after decoding a
3906    /// frame.
3907    pub fn ref_frame_update(&mut self, fh: &FrameHeaderObu) -> Result<(), String> {
3908        // This was found as a bug otherwise by Nicolas Dufresne in GStreamer's
3909        // av1parse.
3910        if fh.show_existing_frame && !matches!(fh.frame_type, FrameType::KeyFrame) {
3911            return Ok(());
3912        }
3913
3914        if matches!(fh.frame_type, FrameType::IntraOnlyFrame) && fh.refresh_frame_flags == 0xff {
3915            return Err("Intra-only frames cannot refresh all of the DPB as per the spec.".into());
3916        }
3917
3918        let &SequenceHeaderObu {
3919            color_config: ColorConfig { subsampling_x, subsampling_y, .. },
3920            film_grain_params_present,
3921            bit_depth,
3922            ..
3923        } = self.sequence()?;
3924
3925        for (i, ref_info) in self.ref_info.iter_mut().enumerate() {
3926            if ((fh.refresh_frame_flags >> i) & 1) != 0 {
3927                ref_info.ref_valid = true;
3928
3929                ref_info.ref_frame_id = fh.current_frame_id;
3930                ref_info.ref_frame_type = fh.frame_type;
3931                ref_info.ref_upscaled_width = fh.upscaled_width;
3932                ref_info.ref_frame_width = fh.frame_width;
3933                ref_info.ref_frame_height = fh.frame_height;
3934                ref_info.ref_render_width = fh.render_width;
3935                ref_info.ref_render_height = fh.render_height;
3936                ref_info.ref_order_hint = fh.order_hint;
3937                ref_info.ref_mi_cols = self.mi_cols;
3938                ref_info.ref_mi_rows = self.mi_rows;
3939                ref_info.ref_subsampling_x = subsampling_x;
3940                ref_info.ref_subsampling_y = subsampling_y;
3941                ref_info.ref_bit_depth = bit_depth;
3942                ref_info.segmentation_params = fh.segmentation_params.clone();
3943                ref_info.global_motion_params = fh.global_motion_params.clone();
3944                ref_info.loop_filter_params = fh.loop_filter_params.clone();
3945                ref_info.tile_info = fh.tile_info.clone();
3946                ref_info.display_frame_id = fh.display_frame_id;
3947                ref_info.showable_frame = fh.showable_frame;
3948
3949                if film_grain_params_present {
3950                    ref_info.film_grain_params = fh.film_grain_params.clone();
3951                }
3952            }
3953        }
3954
3955        Ok(())
3956    }
3957
3958    pub fn highest_operating_point(&self) -> Option<u32> {
3959        if self.operating_point_idc == 0 {
3960            /* No scalability information, all OBUs must be decoded */
3961            None
3962        } else {
3963            Some(helpers::floor_log2((self.operating_point_idc >> 8) as u32))
3964        }
3965    }
3966
3967    /// Fully parse an OBU.
3968    pub fn parse_obu<'a>(&mut self, obu: Obu<'a>) -> Result<ParsedObu<'a>, String> {
3969        match obu.header.obu_type {
3970            ObuType::Reserved => Ok(ParsedObu::Reserved),
3971            ObuType::SequenceHeader => {
3972                self.parse_sequence_header_obu(&obu).map(ParsedObu::SequenceHeader)
3973            }
3974            ObuType::TemporalDelimiter => {
3975                self.parse_temporal_delimiter_obu().map(|_| ParsedObu::TemporalDelimiter)
3976            }
3977            ObuType::FrameHeader => self.parse_frame_header_obu(&obu).map(ParsedObu::FrameHeader),
3978            ObuType::TileGroup => self.parse_tile_group_obu(obu).map(ParsedObu::TileGroup),
3979            ObuType::Metadata => Ok(ParsedObu::Metadata),
3980            ObuType::Frame => self.parse_frame_obu(obu).map(ParsedObu::Frame),
3981            ObuType::RedundantFrameHeader => Ok(ParsedObu::RedundantFrameHeader),
3982            ObuType::TileList => Ok(ParsedObu::TileList),
3983            ObuType::Reserved2 => Ok(ParsedObu::Reserved2),
3984            ObuType::Reserved3 => Ok(ParsedObu::Reserved3),
3985            ObuType::Reserved4 => Ok(ParsedObu::Reserved4),
3986            ObuType::Reserved5 => Ok(ParsedObu::Reserved5),
3987            ObuType::Reserved6 => Ok(ParsedObu::Reserved6),
3988            ObuType::Reserved7 => Ok(ParsedObu::Reserved7),
3989            ObuType::Padding => Ok(ParsedObu::Padding),
3990        }
3991    }
3992}
3993
3994impl Default for Parser {
3995    fn default() -> Self {
3996        Self {
3997            stream_format: StreamFormat::LowOverhead,
3998            operating_point: Default::default(),
3999            seen_frame_header: Default::default(),
4000            last_frame_header: Default::default(),
4001            operating_point_idc: Default::default(),
4002            should_probe_for_annexb: true,
4003            is_first_frame: Default::default(),
4004            mi_cols: Default::default(),
4005            mi_rows: Default::default(),
4006            prev_frame_id: Default::default(),
4007            current_frame_id: Default::default(),
4008            ref_info: Default::default(),
4009            mi_col_starts: [0; MAX_TILE_COLS + 1],
4010            mi_row_starts: [0; MAX_TILE_ROWS + 1],
4011            tile_cols_log2: Default::default(),
4012            tile_cols: Default::default(),
4013            tile_rows_log2: Default::default(),
4014            tile_rows: Default::default(),
4015            tile_size_bytes: Default::default(),
4016            sequence_header: Default::default(),
4017        }
4018    }
4019}
4020
4021impl Clone for Parser {
4022    fn clone(&self) -> Self {
4023        let sequence_header = self.sequence_header.as_ref().map(|s| Rc::new((**s).clone()));
4024
4025        Self {
4026            stream_format: self.stream_format.clone(),
4027            operating_point: self.operating_point,
4028            seen_frame_header: self.seen_frame_header,
4029            last_frame_header: self.last_frame_header.clone(),
4030            operating_point_idc: self.operating_point_idc,
4031            should_probe_for_annexb: self.should_probe_for_annexb,
4032            is_first_frame: self.is_first_frame,
4033            ref_info: self.ref_info.clone(),
4034            mi_cols: self.mi_cols,
4035            mi_rows: self.mi_rows,
4036            prev_frame_id: self.prev_frame_id,
4037            current_frame_id: self.current_frame_id,
4038            mi_col_starts: self.mi_col_starts,
4039            mi_row_starts: self.mi_row_starts,
4040            tile_cols_log2: self.tile_cols_log2,
4041            tile_cols: self.tile_cols,
4042            tile_rows_log2: self.tile_rows_log2,
4043            tile_rows: self.tile_rows,
4044            tile_size_bytes: self.tile_size_bytes,
4045            sequence_header,
4046        }
4047    }
4048}
4049
4050#[cfg(test)]
4051mod tests {
4052    use crate::bitstream_utils::IvfIterator;
4053    use crate::codec::av1::parser::{ObuAction, Parser, StreamFormat};
4054
4055    use super::ObuType;
4056
4057    /// Same as test-25fps.av1.ivf from Chromium
4058    const STREAM_TEST_25_FPS: &[u8] = include_bytes!("test_data/test-25fps.ivf.av1");
4059
4060    /// Encoded with
4061    ///
4062    /// gst-launch-1.0 videotestsrc num-buffers=1 !
4063    /// video/x-raw,format=I420,width=64,height=64 ! filesink
4064    /// location=aom_input.yuv
4065    ///
4066    /// And:
4067    ///
4068    /// aomenc -p 1 --ivf -w 64 -h 64 -o av1-annexb.ivf.av1 aom_input.yuv --annexb=1
4069    const STREAM_ANNEXB: &[u8] = include_bytes!("test_data/av1-annexb.ivf.av1");
4070
4071    #[test]
4072    fn parse_test25fps() {
4073        let mut parser = Parser::default();
4074        let ivf_iter = IvfIterator::new(STREAM_TEST_25_FPS);
4075        let mut num_obus = 0;
4076
4077        for packet in ivf_iter {
4078            let mut consumed = 0;
4079
4080            while let Ok(obu) = parser.read_obu(&packet[consumed..]) {
4081                let obu = match obu {
4082                    ObuAction::Process(obu) => obu,
4083                    // This OBU should be dropped.
4084                    ObuAction::Drop(length) => {
4085                        consumed += usize::try_from(length).unwrap();
4086                        continue;
4087                    }
4088                };
4089                consumed += obu.bytes_used;
4090                num_obus += 1;
4091            }
4092        }
4093
4094        // Manually checked with GStreamer under GDB by using a hitcount on
4095        // "gst_av1_parse_identify_one_obu" *after* the stream format has been
4096        // detected.
4097        assert_eq!(num_obus, 525);
4098    }
4099
4100    #[test]
4101    /// Test that we can correctly identify streams in both "low-overhead" and
4102    /// Annex B formats.
4103    fn parse_annexb() {
4104        let mut parser = Parser::default();
4105        let mut ivf_iter = IvfIterator::new(STREAM_TEST_25_FPS);
4106        let packet = ivf_iter.next().unwrap();
4107
4108        parser.read_obu(packet).unwrap();
4109        assert!(matches!(parser.stream_format, StreamFormat::LowOverhead));
4110
4111        let mut parser = Parser::default();
4112        let mut ivf_iter = IvfIterator::new(STREAM_ANNEXB);
4113        let packet = ivf_iter.next().unwrap();
4114
4115        parser.read_obu(packet).unwrap();
4116        assert!(matches!(parser.stream_format, StreamFormat::AnnexB { .. }));
4117    }
4118
4119    #[test]
4120    /// Test that we can correctly identify streams in both "low-overhead" and
4121    /// Annex B formats and identify all the OBUs in the stream until the end.
4122    fn parse_annexb_full() {
4123        let mut parser = Parser::default();
4124        let ivf_iter = IvfIterator::new(STREAM_TEST_25_FPS);
4125
4126        for packet in ivf_iter {
4127            let mut consumed = 0;
4128
4129            while let Ok(obu) = parser.read_obu(&packet[consumed..]) {
4130                let obu = match obu {
4131                    ObuAction::Process(obu) => obu,
4132                    // This OBU should be dropped.
4133                    ObuAction::Drop(length) => {
4134                        consumed += usize::try_from(length).unwrap();
4135                        continue;
4136                    }
4137                };
4138                assert!(matches!(parser.stream_format, StreamFormat::LowOverhead));
4139                consumed += obu.bytes_used;
4140            }
4141        }
4142
4143        let mut parser = Parser::default();
4144        let ivf_iter = IvfIterator::new(STREAM_ANNEXB);
4145        let mut num_obus = 0;
4146
4147        for packet in ivf_iter {
4148            let mut consumed = 0;
4149
4150            while let Ok(obu) = parser.read_obu(&packet[consumed..]) {
4151                let obu = match obu {
4152                    ObuAction::Process(obu) => obu,
4153                    // This OBU should be dropped.
4154                    ObuAction::Drop(length) => {
4155                        consumed += usize::try_from(length).unwrap();
4156                        continue;
4157                    }
4158                };
4159                assert!(matches!(parser.stream_format, StreamFormat::AnnexB { .. }));
4160                consumed += obu.bytes_used;
4161                num_obus += 1;
4162            }
4163        }
4164
4165        assert_eq!(num_obus, 3);
4166        let annexb_state = match parser.stream_format {
4167            StreamFormat::AnnexB(annexb_state) => annexb_state,
4168            _ => panic!("Wrong StreamFormat, expected AnnexB"),
4169        };
4170        assert_eq!(annexb_state.temporal_unit_consumed, annexb_state.temporal_unit_size);
4171        assert_eq!(annexb_state.frame_unit_consumed, annexb_state.frame_unit_size);
4172    }
4173
4174    #[test]
4175    fn parse_test25fps_obus() {
4176        let mut parser = Parser::default();
4177        let ivf_iter = IvfIterator::new(STREAM_TEST_25_FPS);
4178
4179        for packet in ivf_iter {
4180            let mut consumed = 0;
4181
4182            while let Ok(obu) = parser.read_obu(&packet[consumed..]) {
4183                let obu = match obu {
4184                    ObuAction::Process(obu) => obu,
4185                    // This OBU should be dropped.
4186                    ObuAction::Drop(length) => {
4187                        consumed += usize::try_from(length).unwrap();
4188                        continue;
4189                    }
4190                };
4191
4192                let data_len = obu.bytes_used;
4193
4194                match obu.header.obu_type {
4195                    ObuType::SequenceHeader => {
4196                        parser.parse_sequence_header_obu(&obu).unwrap();
4197                    }
4198                    ObuType::FrameHeader | ObuType::RedundantFrameHeader => {
4199                        let fh = parser.parse_frame_header_obu(&obu).unwrap();
4200                        parser.ref_frame_update(&fh).unwrap();
4201                    }
4202                    ObuType::TileGroup => {
4203                        parser.parse_tile_group_obu(obu).unwrap();
4204                    }
4205                    ObuType::Frame => {
4206                        let frame = parser.parse_frame_obu(obu).unwrap();
4207                        parser.ref_frame_update(&frame.header).unwrap();
4208                    }
4209                    _ => {}
4210                };
4211
4212                consumed += data_len;
4213            }
4214        }
4215    }
4216}