1use 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
55pub const FEATURE_BITS: [u8; SEG_LVL_MAX] = [8, 6, 6, 6, 6, 3, 0, 0];
57pub const FEATURE_SIGNED: [bool; SEG_LVL_MAX] = [true, true, true, true, true, false, false, false];
59pub const FEATURE_MAX: [i32; SEG_LVL_MAX] = [255, 63, 63, 63, 63, 7, 0, 0];
61
62pub enum ParsedObu<'a> {
63 Process(Obu<'a>),
65 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 #[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 pub header: ObuHeader,
124 pub data: Cow<'a, [u8]>,
126 pub start_offset: usize,
128 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 pub tile_offset: u32,
142 pub tile_size: u32,
144 pub tile_row: u32,
146 pub tile_col: u32,
148 pub mi_row_start: u32,
150 pub mi_row_end: u32,
152 pub mi_col_start: u32,
154 pub mi_col_end: u32,
156}
157
158#[derive(Clone, Debug, Default, PartialEq, Eq)]
159pub struct TileGroupObu<'a> {
160 pub obu: Obu<'a>,
162 pub tile_start_and_end_present_flag: bool,
165 pub tg_start: u32,
168 pub tg_end: u32,
171 pub tiles: Vec<Tile>,
176}
177
178#[derive(Clone, Debug, Default, PartialEq, Eq)]
179pub struct OperatingPoint {
180 pub seq_level_idx: u8,
183 pub seq_tier: u8,
186 pub idc: u16,
189 pub decoder_model_present_for_this_op: bool,
193 pub decoder_buffer_delay: u32,
199 pub encoder_buffer_delay: u32,
204 pub low_delay_mode_flag: bool,
209 pub initial_display_delay_present_for_this_op: bool,
213 pub initial_display_delay_minus_1: u32,
220}
221
222#[derive(Clone, Debug, Default, PartialEq, Eq)]
223pub struct TimingInfo {
224 pub num_units_in_display_tick: u32,
229 pub time_scale: u32,
231 pub equal_picture_interval: bool,
237 pub num_ticks_per_picture_minus_1: u32,
240}
241
242#[derive(Clone, Debug, Default, PartialEq, Eq)]
243pub struct DecoderModelInfo {
244 pub buffer_delay_length_minus_1: u8,
247 pub num_units_in_decoding_tick: u32,
250 pub buffer_removal_time_length_minus_1: u8,
253 pub frame_presentation_time_length_minus_1: u32,
256}
257
258#[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 pub high_bitdepth: bool,
343 pub twelve_bit: bool,
346 pub mono_chrome: bool,
349 pub color_description_present_flag: bool,
354 pub color_primaries: ColorPrimaries,
356 pub transfer_characteristics: TransferCharacteristics,
359 pub matrix_coefficients: MatrixCoefficients,
362 pub color_range: bool,
368 pub subsampling_x: bool,
370 pub subsampling_y: bool,
372 pub chroma_sample_position: ChromaSamplePosition,
374 pub separate_uv_delta_q: bool,
378}
379
380#[derive(Clone, Debug, Default, PartialEq, Eq)]
381pub struct SequenceHeaderObu {
382 pub obu_header: ObuHeader,
384 pub seq_profile: Profile,
386 pub still_picture: bool,
390 pub reduced_still_picture_header: bool,
393 pub frame_width_bits_minus_1: u8,
396 pub frame_height_bits_minus_1: u8,
399 pub max_frame_width_minus_1: u16,
402 pub max_frame_height_minus_1: u16,
405 pub frame_id_numbers_present_flag: bool,
408 pub delta_frame_id_length_minus_2: u32,
411 pub additional_frame_id_length_minus_1: u32,
414 pub use_128x128_superblock: bool,
419 pub enable_filter_intra: bool,
423 pub enable_intra_edge_filter: bool,
425 pub enable_interintra_compound: bool,
429 pub enable_masked_compound: bool,
433 pub enable_warped_motion: bool,
437 pub enable_order_hint: bool,
441 pub enable_dual_filter: bool,
446 pub enable_jnt_comp: bool,
449 pub enable_ref_frame_mvs: bool,
453 pub seq_choose_screen_content_tools: bool,
458 pub seq_force_screen_content_tools: u32,
463 pub seq_choose_integer_mv: bool,
467 pub seq_force_integer_mv: u32,
472 pub order_hint_bits_minus_1: i32,
474 pub order_hint_bits: i32,
476 pub enable_superres: bool,
481 pub enable_cdef: bool,
484 pub enable_restoration: bool,
487 pub film_grain_params_present: bool,
490 pub operating_points_cnt_minus_1: u32,
494 pub operating_points: [OperatingPoint; MAX_NUM_OPERATING_POINTS],
496 pub decoder_model_info_present_flag: bool,
499 pub decoder_model_info: DecoderModelInfo,
501 pub initial_display_delay_present_flag: bool,
504 pub timing_info_present_flag: bool,
506 pub timing_info: TimingInfo,
508 pub color_config: ColorConfig,
510
511 pub bit_depth: BitDepth,
513 pub num_planes: u32,
514}
515
516#[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#[derive(Clone, Debug, Default, PartialEq, Eq)]
596pub struct FrameHeaderObu {
597 pub obu_header: ObuHeader,
600 pub show_existing_frame: bool,
603 pub frame_to_show_map_idx: u8,
606 pub frame_presentation_time: u32,
609 pub display_frame_id: u32,
611 pub frame_type: FrameType,
613 pub show_frame: bool,
618 pub showable_frame: bool,
622 pub error_resilient_mode: bool,
626 pub disable_cdf_update: bool,
629 pub allow_screen_content_tools: u32,
632 pub force_integer_mv: u32,
635 pub current_frame_id: u32,
640 pub frame_size_override_flag: bool,
645 pub order_hint: u32,
648 pub primary_ref_frame: u32,
651 pub buffer_removal_time_present_flag: bool,
654 pub buffer_removal_time: Vec<u32>,
660 pub refresh_frame_flags: u32,
663 pub ref_order_hint: [u32; NUM_REF_FRAMES],
665 pub allow_intrabc: bool,
668 pub frame_refs_short_signaling: bool,
672 pub last_frame_idx: u8,
674 pub gold_frame_idx: u8,
676 pub ref_frame_idx: [u8; REFS_PER_FRAME],
678 pub allow_high_precision_mv: bool,
682 pub is_motion_mode_switchable: bool,
684 pub use_ref_frame_mvs: bool,
688 pub disable_frame_end_update_cdf: bool,
691 pub allow_warped_motion: bool,
695 pub reduced_tx_set: bool,
698 pub render_and_frame_size_different: bool,
702 pub use_superres: bool,
705 pub is_filter_switchable: bool,
709 pub interpolation_filter: InterpolationFilter,
711 pub loop_filter_params: LoopFilterParams,
713 pub quantization_params: QuantizationParams,
715 pub segmentation_params: SegmentationParams,
717 pub tile_info: TileInfo,
719 pub cdef_params: CdefParams,
721 pub loop_restoration_params: LoopRestorationParams,
723 pub tx_mode_select: u32,
725 pub skip_mode_present: bool,
728 pub reference_select: bool,
733 pub global_motion_params: GlobalMotionParams,
735 pub film_grain_params: FilmGrainParams,
737
738 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 pub loop_filter_level: [u8; 4],
766 pub loop_filter_sharpness: u8,
770 pub loop_filter_delta_enabled: bool,
774 pub loop_filter_delta_update: bool,
779 pub loop_filter_ref_deltas: [i8; TOTAL_REFS_PER_FRAME],
783 pub loop_filter_mode_deltas: [i8; 2],
787 pub delta_lf_present: bool,
789 pub delta_lf_res: u8,
792 pub delta_lf_multi: bool,
797}
798
799#[derive(Clone, Debug, Default, PartialEq, Eq)]
800pub struct QuantizationParams {
801 pub base_q_idx: u32,
804 pub diff_uv_delta: bool,
807 pub using_qmatrix: bool,
809 pub qm_y: u32,
812 pub qm_u: u32,
815 pub qm_v: u32,
818 pub delta_q_present: bool,
820 pub delta_q_res: u32,
823 pub delta_q_y_dc: i32,
825 pub delta_q_u_dc: i32,
827 pub delta_q_u_ac: i32,
829 pub delta_q_v_dc: i32,
831 pub delta_q_v_ac: i32,
833}
834
835#[derive(Clone, Debug, Default, PartialEq, Eq)]
836pub struct SegmentationParams {
837 pub segmentation_enabled: bool,
840 pub segmentation_update_map: bool,
844 pub segmentation_temporal_update: bool,
849 pub segmentation_update_data: bool,
853 pub feature_enabled: [[bool; SEG_LVL_MAX]; MAX_SEGMENTS],
856 pub feature_data: [[i16; SEG_LVL_MAX]; MAX_SEGMENTS],
858 pub seg_id_pre_skip: bool,
860 pub last_active_seg_id: u8,
862}
863
864#[derive(Clone, Debug, PartialEq, Eq)]
865pub struct TileInfo {
866 pub uniform_tile_spacing_flag: bool,
871 pub increment_tile_rows_log2: u32,
873 pub width_in_sbs_minus_1: [u32; MAX_TILE_COLS],
875 pub height_in_sbs_minus_1: [u32; MAX_TILE_ROWS],
877 pub context_update_tile_id: u32,
879 pub mi_col_starts: [u32; MAX_TILE_COLS + 1],
882 pub mi_row_starts: [u32; MAX_TILE_ROWS + 1],
885 pub tile_cols_log2: u32,
888 pub tile_cols: u32,
890 pub tile_rows_log2: u32,
893 pub tile_rows: u32,
895 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 pub cdef_damping: u32,
922 pub cdef_bits: u32,
925 pub cdef_y_pri_strength: [u32; CDEF_MAX],
927 pub cdef_y_sec_strength: [u32; CDEF_MAX],
929 pub cdef_uv_pri_strength: [u32; CDEF_MAX],
931 pub cdef_uv_sec_strength: [u32; CDEF_MAX],
933}
934
935#[derive(Clone, Debug, Default, PartialEq, Eq)]
936pub struct LoopRestorationParams {
937 pub lr_unit_shift: u8,
939 pub lr_uv_shift: u8,
942 pub frame_restoration_type: [FrameRestorationType; MAX_NUM_PLANES],
944 pub loop_restoration_size: [u16; MAX_NUM_PLANES],
946 pub uses_lr: bool,
948 pub uses_chroma_lr: bool,
950}
951
952#[derive(Clone, Debug, Default, PartialEq, Eq)]
953pub struct GlobalMotionParams {
954 pub is_global: [bool; NUM_REF_FRAMES],
957 pub is_rot_zoom: [bool; NUM_REF_FRAMES],
960 pub is_translation: [bool; NUM_REF_FRAMES],
963 pub gm_params: [[i32; 6]; NUM_REF_FRAMES],
967 pub warp_valid: [bool; NUM_REF_FRAMES],
969 pub gm_type: [WarpModelType; NUM_REF_FRAMES],
971}
972
973#[derive(Clone, Debug, Default, PartialEq, Eq)]
974pub struct FilmGrainParams {
975 pub apply_grain: bool,
978 pub grain_seed: u16,
981 pub update_grain: bool,
984 pub film_grain_params_ref_idx: u8,
987 pub num_y_points: u8,
990 pub point_y_value: [u8; MAX_NUM_Y_POINTS],
996 pub point_y_scaling: [u8; MAX_NUM_Y_POINTS],
999 pub chroma_scaling_from_luma: bool,
1001 pub num_cb_points: u8,
1004 pub point_cb_value: [u8; MAX_NUM_CB_POINTS],
1008 pub point_cb_scaling: [u8; MAX_NUM_CB_POINTS],
1011 pub num_cr_points: u8,
1014 pub point_cr_value: [u8; MAX_NUM_CR_POINTS],
1018 pub point_cr_scaling: [u8; MAX_NUM_CR_POINTS],
1021 pub grain_scaling_minus_8: u8,
1025 pub ar_coeff_lag: u32,
1027 pub ar_coeffs_y_plus_128: [u8; MAX_NUM_POS_LUMA],
1029 pub ar_coeffs_cb_plus_128: [u8; MAX_NUM_POS_LUMA],
1031 pub ar_coeffs_cr_plus_128: [u8; MAX_NUM_POS_LUMA],
1033 pub ar_coeff_shift_minus_6: u8,
1037 pub grain_scale_shift: u8,
1040 pub cb_mult: u8,
1043 pub cb_luma_mult: u8,
1046 pub cb_offset: u16,
1049 pub cr_mult: u8,
1052 pub cr_luma_mult: u8,
1055 pub cr_offset: u16,
1058 pub overlap_flag: bool,
1062 pub clip_to_restricted_range: bool,
1068}
1069
1070#[derive(Clone, Debug, Default, PartialEq, Eq)]
1073struct ReferenceFrameInfo {
1074 ref_valid: bool,
1080 ref_frame_id: u32,
1082 ref_upscaled_width: u32,
1084 ref_frame_width: u32,
1086 ref_frame_height: u32,
1088 ref_render_width: u32,
1090 ref_render_height: u32,
1092 ref_mi_cols: u32,
1094 ref_mi_rows: u32,
1096 ref_frame_type: FrameType,
1098 ref_subsampling_x: bool,
1100 ref_subsampling_y: bool,
1102 ref_bit_depth: BitDepth,
1104 ref_order_hint: u32,
1106 segmentation_params: SegmentationParams,
1108 global_motion_params: GlobalMotionParams,
1110 loop_filter_params: LoopFilterParams,
1112 film_grain_params: FilmGrainParams,
1114 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 seen_frame_header: bool,
1140 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 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 pub sequence_header: Option<Rc<SequenceHeaderObu>>,
1162}
1163
1164impl Parser {
1165 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 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 let header = Self::parse_obu_header(&mut r.clone())?;
1192 if !matches!(header.obu_type, ObuType::TemporalDelimiter) {
1193 return Ok(false);
1194 }
1195
1196 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 return Ok(true);
1220 }
1221
1222 if num_bytes_read >= frame_unit_size {
1223 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 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 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 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 fn skip_and_check_trailing_bits(r: &mut Reader, obu: &Obu) -> anyhow::Result<()> {
1453 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); 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 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 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 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 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 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 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 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 s.max_frame_width_minus_1 = r.read_bits(s.frame_width_bits_minus_1 + 1)? as u16;
1828 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 self.choose_operating_point(0)?;
1914
1915 Ok(rc)
1916 }
1917
1918 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 let seq = self.sequence()?;
1928
1929 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 if fh.frame_type == FrameType::KeyFrame {
1939 fh.current_frame_id = rf.ref_frame_id;
1940 fh.mi_cols = rf.ref_mi_cols;
1942 fh.mi_rows = rf.ref_mi_rows;
1943 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 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 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 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 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 if fh.primary_ref_frame == PRIMARY_REF_NONE {
2740 #[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 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 *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 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 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 fh.film_grain_params = self.ref_info[fh.frame_to_show_map_idx as usize]
3138 .film_grain_params
3139 .clone();
3140 }
3141
3142 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 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 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 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 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 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 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 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 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 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 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 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 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 self.seen_frame_header = true;
3686 self.last_frame_header = Some(header.clone());
3687 }
3688
3689 Ok(header)
3690 }
3691 }
3692
3693 pub fn ref_frame_update(&mut self, fh: &FrameHeaderObu) -> anyhow::Result<()> {
3696 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 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 const STREAM_TEST_25_FPS: &[u8] = include_bytes!("test_data/test-25fps.ivf.av1");
3831
3832 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 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 assert_eq!(num_obus, 525);
3870 }
3871
3872 #[test]
3873 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 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 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 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 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}