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