#![allow(unused)]
#![allow(bad_style)]
use crate::{ChromaSubsampling, Error, Result};
use bitreader::BitReader;
use std::num::{NonZeroU8, NonZeroU32};
#[derive(Debug, Clone)]
struct Header {
obu_size: usize,
obu_type: u8,
}
impl Header {
fn is_sequence_header(&self) -> bool {
self.obu_type == 1
}
fn is_frame_header(&self) -> bool {
self.obu_type == 3 || self.obu_type == 6
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct FrameQuantization {
pub base_q_idx: u8,
pub coded_lossless: bool,
}
fn get_byte(data: &mut &[u8]) -> Result<u8> {
let (&b, rest) = (*data).split_first().ok_or(Error::UnexpectedEOF)?;
*data = rest;
Ok(b)
}
const INTRA_FRAME: usize = 0;
const LAST_FRAME: usize = 1;
const LAST2_FRAME: usize = 2;
const LAST3_FRAME: usize = 3;
const GOLDEN_FRAME: usize = 4;
const BWDREF_FRAME: usize = 5;
const ALTREF2_FRAME: usize = 6;
const ALTREF_FRAME: usize = 7;
pub(crate) fn parse_obu(mut data: &[u8]) -> Result<SequenceHeaderObu> {
let (seq, _) = parse_obu_with_frame_info(data)?;
Ok(seq)
}
pub(crate) fn parse_obu_with_frame_info(mut data: &[u8]) -> Result<(SequenceHeaderObu, Option<FrameQuantization>)> {
let mut seq_header: Option<SequenceHeaderObu> = None;
let mut frame_quant: Option<FrameQuantization> = None;
while !data.is_empty() {
let h = obu_header(&mut data)?;
let remaining_data = data.get(..h.obu_size).ok_or(Error::UnexpectedEOF)?;
data = &data[h.obu_size..];
if h.is_sequence_header() {
seq_header = Some(SequenceHeaderObu::read(remaining_data)?);
} else if h.is_frame_header() && seq_header.is_some() && frame_quant.is_none() {
if let Some(ref seq) = seq_header {
frame_quant = parse_frame_header_quantization(remaining_data, seq).ok();
}
}
if seq_header.is_some() && frame_quant.is_some() {
break;
}
}
match seq_header {
Some(seq) => Ok((seq, frame_quant)),
None => Err(Error::UnexpectedEOF),
}
}
impl SequenceHeaderObu {
fn read(data: &[u8]) -> Result<Self> {
let mut b = BitReader::new(data);
let mut enable_superres = false;
let mut enable_cdef = false;
let mut enable_restoration = false;
let seq_profile = b.read_u8(3)?;
if seq_profile > 2 {
return Err(Error::InvalidData("seq_profile"));
}
let still_picture = b.read_bool()?;
let reduced_still_picture_header = b.read_bool()?;
let decoder_model_info_present_flag = false;
if reduced_still_picture_header {
let timing_info_present_flag = 0;
let initial_display_delay_present_flag = 0;
let operating_points_cnt_minus_1 = 0;
let operating_point_idc = 0; let seq_level_idx = b.read_u8(5)?;
let seq_tier = 0; let decoder_model_present_for_this_op = 0; let initial_display_delay_present_for_this_op = 0; } else {
let timing_info_present_flag = b.read_bool()?;
if timing_info_present_flag {
return Err(Error::Unsupported("timing_info_present_flag"));
}
let initial_display_delay_present_flag = b.read_bool()?;
let operating_points_cnt = 1 + b.read_u8(5)?;
for _ in 0..operating_points_cnt {
let operating_point_idc = b.read_u16(12)?;
let seq_level_idx = b.read_u8(5)?;
let seq_tier = if seq_level_idx > 7 { b.read_bool()? } else { false };
let decoder_model_present_for_this_op = if decoder_model_info_present_flag {
b.read_bool()?;
return Err(Error::Unsupported("decoder_model_info_present_flag"));
} else {
false
};
if initial_display_delay_present_flag {
let initial_display_delay_present_for_this_op = b.read_bool()?;
if initial_display_delay_present_for_this_op {
let initial_display_delay = 1 + b.read_u8(4)?;
}
}
}
}
let frame_width_bits = 1 + b.read_u8(4)?;
let frame_height_bits = 1 + b.read_u8(4)?;
let max_frame_width = 1 + b.read_u32(frame_width_bits)?;
let max_frame_height = 1 + b.read_u32(frame_height_bits)?;
let max_frame_width = NonZeroU32::new(max_frame_width).ok_or(Error::InvalidData("overflow"))?;
let max_frame_height = NonZeroU32::new(max_frame_height).ok_or(Error::InvalidData("overflow"))?;
let frame_id_numbers_present_flag = if reduced_still_picture_header { false } else { b.read_bool()? };
let delta_frame_id_length = if frame_id_numbers_present_flag { 2 + b.read_u8(4)? } else { 0 };
let additional_frame_id_length = if frame_id_numbers_present_flag { 1 + b.read_u8(3)? } else { 0 };
let use_128x128_superblock = b.read_bool()?;
let enable_filter_intra = b.read_bool()?;
let enable_intra_edge_filter = b.read_bool()?;
let mut enable_interintra_compound = false;
let mut enable_masked_compound = false;
let mut enable_warped_motion = false;
let mut enable_dual_filter = false;
let mut enable_jnt_comp = false;
let mut enable_ref_frame_mvs = false;
let mut seq_force_screen_content_tools = SELECT_SCREEN_CONTENT_TOOLS;
let mut seq_force_integer_mv = SELECT_INTEGER_MV;
let mut order_hint_bits = 0;
let mut enable_order_hint = false;
if !reduced_still_picture_header {
enable_interintra_compound = b.read_bool()?;
enable_masked_compound = b.read_bool()?;
enable_warped_motion = b.read_bool()?;
enable_dual_filter = b.read_bool()?;
enable_order_hint = b.read_bool()?;
if enable_order_hint {
enable_jnt_comp = b.read_bool()?;
enable_ref_frame_mvs = b.read_bool()?;
}
let seq_choose_screen_content_tools = b.read_bool()?;
if !seq_choose_screen_content_tools {
seq_force_screen_content_tools = b.read_u8(1)?;
}
if seq_force_screen_content_tools > 0 {
let seq_choose_integer_mv = b.read_bool()?;
if !seq_choose_integer_mv {
seq_force_integer_mv = b.read_u8(1)?;
}
}
if enable_order_hint {
order_hint_bits = 1 + b.read_u8(3)?;
}
}
let enable_superres = b.read_bool()?;
let enable_cdef = b.read_bool()?;
let enable_restoration = b.read_bool()?;
let color = color_config(&mut b, seq_profile)?;
let film_grain_params_present = b.read_bool()?;
Ok(Self {
color,
seq_profile,
still_picture,
reduced_still_picture_header,
max_frame_width,
max_frame_height,
frame_width_bits,
frame_height_bits,
enable_superres,
enable_cdef,
enable_restoration,
frame_id_numbers_present_flag,
delta_frame_id_length,
additional_frame_id_length,
film_grain_params_present,
decoder_model_info_present_flag,
seq_force_screen_content_tools,
seq_force_integer_mv,
order_hint_bits,
enable_order_hint,
use_128x128_superblock,
enable_interintra_compound,
enable_masked_compound,
enable_warped_motion,
enable_dual_filter,
enable_jnt_comp,
enable_ref_frame_mvs,
})
}
}
#[derive(Debug, Clone)]
#[allow(clippy::struct_excessive_bools)]
pub(crate) struct SequenceHeaderObu {
pub color: ColorConfig,
pub seq_profile: u8,
pub still_picture: bool,
pub reduced_still_picture_header: bool,
pub max_frame_width: NonZeroU32,
pub max_frame_height: NonZeroU32,
pub frame_width_bits: u8,
pub frame_height_bits: u8,
pub enable_superres: bool,
pub enable_cdef: bool,
pub enable_restoration: bool,
pub frame_id_numbers_present_flag: bool,
pub delta_frame_id_length: u8,
pub additional_frame_id_length: u8,
pub film_grain_params_present: bool,
pub decoder_model_info_present_flag: bool,
pub seq_force_screen_content_tools: u8,
pub seq_force_integer_mv: u8,
pub order_hint_bits: u8,
pub enable_order_hint: bool,
pub use_128x128_superblock: bool,
pub enable_interintra_compound: bool,
pub enable_masked_compound: bool,
pub enable_warped_motion: bool,
pub enable_dual_filter: bool,
pub enable_jnt_comp: bool,
pub enable_ref_frame_mvs: bool,
}
#[derive(Debug, Clone)]
pub(crate) struct ColorConfig {
pub chroma_subsampling: ChromaSubsampling,
pub chroma_sample_position: u8,
pub separate_uv_delta_q: bool,
pub color_range: u8,
pub bit_depth: u8,
pub monochrome: bool,
pub color_primaries: u8,
pub transfer_characteristics: u8,
pub matrix_coefficients: u8,
}
fn color_config(b: &mut BitReader, seq_profile: u8) -> Result<ColorConfig> {
let high_bitdepth = b.read_bool()?;
let bit_depth = if seq_profile == 2 && high_bitdepth {
let twelve_bit = b.read_bool()?;
if twelve_bit {
12
} else {
10
}
} else { if high_bitdepth {
10
} else {
8
}
};
let monochrome = if seq_profile == 1 { false } else { b.read_bool()? };
let num_planes = if monochrome { 1 } else { 3 };
let color_description_present_flag = b.read_bool()?;
let mut color_primaries = 2;
let mut transfer_characteristics = 2;
let matrix_coefficients = if color_description_present_flag {
color_primaries = b.read_u8(8)?;
transfer_characteristics = b.read_u8(8)?;
b.read_u8(8)?
} else {
2
};
let chroma_subsampling;
let chroma_sample_position;
let separate_uv_delta_q;
let color_range;
if monochrome {
color_range = b.read_u8(1)?;
chroma_subsampling = ChromaSubsampling::NONE;
chroma_sample_position = 0;
separate_uv_delta_q = false;
} else if color_primaries == 1 && transfer_characteristics == 13 && matrix_coefficients == 0
{
color_range = 1;
chroma_subsampling = ChromaSubsampling::NONE;
chroma_sample_position = 0;
separate_uv_delta_q = false;
} else {
color_range = b.read_u8(1)?;
if seq_profile == 0 {
chroma_subsampling = ChromaSubsampling::YUV420;
} else if seq_profile == 1 {
chroma_subsampling = ChromaSubsampling::NONE;
} else if bit_depth == 12 {
let x = b.read_bool()?;
chroma_subsampling = if x {
ChromaSubsampling { horizontal: x, vertical: b.read_bool()? }
} else {
ChromaSubsampling::NONE
}
} else {
chroma_subsampling = ChromaSubsampling::YUV422;
}
debug_assert!(!monochrome);
chroma_sample_position = if chroma_subsampling.horizontal && chroma_subsampling.vertical { b.read_u8(2)? } else { 0 };
separate_uv_delta_q = b.read_bool()?;
}
Ok(ColorConfig {
chroma_subsampling,
chroma_sample_position,
separate_uv_delta_q,
color_range,
bit_depth,
monochrome,
color_primaries,
transfer_characteristics,
matrix_coefficients,
})
}
fn read_delta_q(b: &mut BitReader) -> Result<i8> {
let delta_coded = b.read_bool()?;
if delta_coded {
Ok(b.read_i8(7)?)
} else {
Ok(0)
}
}
fn parse_frame_header_quantization(data: &[u8], seq: &SequenceHeaderObu) -> Result<FrameQuantization> {
let mut b = BitReader::new(data);
let num_planes = if seq.color.monochrome { 1 } else { 3 };
let frame_type;
let show_frame;
let error_resilient_mode;
let allow_screen_content_tools;
if seq.reduced_still_picture_header {
frame_type = 0; show_frame = true;
error_resilient_mode = true;
allow_screen_content_tools = false;
} else {
let show_existing_frame = b.read_bool()?;
if show_existing_frame {
return Err(Error::InvalidData("show_existing_frame"));
}
frame_type = b.read_u8(2)?;
show_frame = b.read_bool()?;
if !show_frame {
let _showable_frame = b.read_bool()?;
}
error_resilient_mode = if frame_type == 3 {
true
} else {
b.read_bool()?
};
let _disable_cdf_update = b.read_bool()?;
allow_screen_content_tools = if seq.seq_force_screen_content_tools == SELECT_SCREEN_CONTENT_TOOLS {
b.read_bool()?
} else {
seq.seq_force_screen_content_tools != 0
};
if allow_screen_content_tools
&& seq.seq_force_integer_mv == SELECT_INTEGER_MV
{
let _force_integer_mv = b.read_bool()?;
}
if seq.frame_id_numbers_present_flag {
let id_len = seq.delta_frame_id_length + seq.additional_frame_id_length;
let _current_frame_id = b.read_u32(id_len)?;
}
let frame_size_override_flag = if frame_type == 3 {
true
} else {
b.read_bool()?
};
if seq.enable_order_hint {
let _order_hint = b.read_u32(seq.order_hint_bits)?;
}
if frame_type != 0 && frame_type != 2 && !error_resilient_mode {
let _primary_ref_frame = b.read_u8(3)?;
}
if frame_type == 0 {
let _refresh_frame_flags = b.read_u8(8)?;
if frame_size_override_flag {
let _frame_width = 1 + b.read_u32(seq.frame_width_bits)?;
let _frame_height = 1 + b.read_u32(seq.frame_height_bits)?;
}
if seq.enable_superres {
let use_superres = b.read_bool()?;
if use_superres {
let _coded_denom = b.read_u8(3)?;
}
}
let render_and_frame_size_different = b.read_bool()?;
if render_and_frame_size_different {
let _render_width = 1u32 + b.read_u16(16)? as u32;
let _render_height = 1u32 + b.read_u16(16)? as u32;
}
if allow_screen_content_tools {
let _allow_intrabc = b.read_bool()?;
}
} else if frame_type == 2 {
let _refresh_frame_flags = b.read_u8(8)?;
if frame_size_override_flag {
let _frame_width = 1 + b.read_u32(seq.frame_width_bits)?;
let _frame_height = 1 + b.read_u32(seq.frame_height_bits)?;
}
if seq.enable_superres {
let use_superres = b.read_bool()?;
if use_superres {
let _coded_denom = b.read_u8(3)?;
}
}
let render_and_frame_size_different = b.read_bool()?;
if render_and_frame_size_different {
let _render_width = 1u32 + b.read_u16(16)? as u32;
let _render_height = 1u32 + b.read_u16(16)? as u32;
}
if allow_screen_content_tools {
let _allow_intrabc = b.read_bool()?;
}
} else {
return Err(Error::Unsupported("inter frame in probe"));
}
};
if seq.reduced_still_picture_header {
}
let sb_size = if seq.use_128x128_superblock { 128u32 } else { 64u32 };
let sb_shift = if seq.use_128x128_superblock { 5 } else { 4 };
let mi_cols = seq.max_frame_width.get().div_ceil(4); let mi_rows = seq.max_frame_height.get().div_ceil(4);
let sb_cols = (mi_cols + (1 << sb_shift) - 1) >> sb_shift;
let sb_rows = (mi_rows + (1 << sb_shift) - 1) >> sb_shift;
let uniform_tile_spacing_flag = b.read_bool()?;
if uniform_tile_spacing_flag {
let mut tile_cols_log2 = 0u32;
let max_tile_cols_log2 = tile_log2(1, sb_cols);
while tile_cols_log2 < max_tile_cols_log2 {
if !b.read_bool()? { break; }
tile_cols_log2 += 1;
}
let mut tile_rows_log2 = 0u32;
let max_tile_rows_log2 = tile_log2(1, sb_rows);
while tile_rows_log2 < max_tile_rows_log2 {
if !b.read_bool()? { break; }
tile_rows_log2 += 1;
}
} else {
let mut widest_tile_sb = 1u32;
let mut start_sb = 0u32;
let mut i = 0u32;
while start_sb < sb_cols {
let max_width = sb_cols - start_sb;
let width_bits = tile_log2(1, max_width.min(MAX_TILE_WIDTH as u32 / sb_size));
let width_in_sbs = 1 + b.read_u32(width_bits as u8)?;
widest_tile_sb = widest_tile_sb.max(width_in_sbs);
start_sb += width_in_sbs;
i += 1;
}
start_sb = 0;
while start_sb < sb_rows {
let max_height = sb_rows - start_sb;
let max_tile_area_sb = MAX_TILE_AREA as u32 / (sb_size * sb_size);
let max_tile_height = max_tile_area_sb.max(1) / widest_tile_sb.max(1);
let height_bits = tile_log2(1, max_height.min(max_tile_height.max(1)));
let height_in_sbs = 1 + b.read_u32(height_bits as u8)?;
start_sb += height_in_sbs;
}
}
let base_q_idx = b.read_u8(8)?;
let delta_q_y_dc = read_delta_q(&mut b)?;
let mut delta_q_u_dc = 0i8;
let mut delta_q_u_ac = 0i8;
let mut delta_q_v_dc = 0i8;
let mut delta_q_v_ac = 0i8;
if num_planes > 1 {
if seq.color.separate_uv_delta_q {
delta_q_u_dc = read_delta_q(&mut b)?;
delta_q_u_ac = read_delta_q(&mut b)?;
delta_q_v_dc = read_delta_q(&mut b)?;
delta_q_v_ac = read_delta_q(&mut b)?;
} else {
delta_q_u_dc = read_delta_q(&mut b)?;
delta_q_u_ac = read_delta_q(&mut b)?;
delta_q_v_dc = delta_q_u_dc;
delta_q_v_ac = delta_q_u_ac;
}
let _using_qmatrix = b.read_bool()?;
}
let coded_lossless = base_q_idx == 0
&& delta_q_y_dc == 0
&& delta_q_u_dc == 0
&& delta_q_u_ac == 0
&& delta_q_v_dc == 0
&& delta_q_v_ac == 0;
Ok(FrameQuantization {
base_q_idx,
coded_lossless,
})
}
fn tile_log2(d: u32, n: u32) -> u32 {
if n == 0 || d == 0 {
return 0;
}
let mut k = 0;
while k < 31 {
let Some(shifted) = d.checked_shl(k + 1) else {
break;
};
if shifted > n {
break;
}
k += 1;
}
k
}
fn obu_header(data: &mut &[u8]) -> Result<Header> {
let b = get_byte(data)?;
if 0 != b & 0b1000_0000 {
return Err(Error::InvalidData("not obu"));
}
let obu_type = (b >> 3) & 0x0F;
let obu_extension_flag = 0 != (b & 0b100);
let obu_has_size_field = 0 != (b & 0b010);
if obu_extension_flag {
let _ext = get_byte(data)?;
}
let obu_size = if obu_has_size_field {
leb128::read::unsigned(data)
.map_err(|_| Error::InvalidData("leb"))?
.try_into()
.map_err(|_| Error::UnexpectedEOF)?
} else {
data.len()
};
Ok(Header { obu_size, obu_type })
}
const REFS_PER_FRAME: usize = 7; const TOTAL_REFS_PER_FRAME: usize = 8; const BLOCK_SIZE_GROUPS: usize = 4; const BLOCK_SIZES: usize = 22; const BLOCK_INVALID: usize = 22; const MAX_SB_SIZE: usize = 128; const MI_SIZE: usize = 4; const MI_SIZE_LOG2: usize = 2; const MAX_TILE_WIDTH: usize = 4096; const MAX_TILE_AREA: usize = 4096; const MAX_TILE_ROWS: usize = 64; const MAX_TILE_COLS: usize = 64; const INTRABC_DELAY_PIXELS: usize = 256; const INTRABC_DELAY_SB64: usize = 4; const NUM_REF_FRAMES: usize = 8; const REF_CONTEXTS: usize = 3; const MAX_SEGMENTS: usize = 8; const SEGMENT_ID_CONTEXTS: usize = 3; const SEG_LVL_ALT_Q: usize = 0; const SEG_LVL_ALT_LF_Y_V: usize = 1; const SEG_LVL_REF_FRAME: usize = 5; const SEG_LVL_SKIP: usize = 6; const SEG_LVL_GLOBALMV: usize = 7; const SEG_LVL_MAX: usize = 8; const PLANE_TYPES: usize = 2; const TX_SIZE_CONTEXTS: usize = 3; const INTERP_FILTERS: usize = 3; const INTERP_FILTER_CONTEXTS: usize = 16; const SKIP_MODE_CONTEXTS: usize = 3; const SKIP_CONTEXTS: usize = 3; const PARTITION_CONTEXTS: usize = 4; const TX_SIZES: usize = 5; const TX_SIZES_ALL: usize = 19; const TX_MODES: usize = 3; const DCT_DCT: usize = 0; const ADST_DCT: usize = 1; const DCT_ADST: usize = 2; const ADST_ADST: usize = 3; const FLIPADST_DCT: usize = 4; const DCT_FLIPADST: usize = 5; const FLIPADST_FLIPADST: usize = 6; const ADST_FLIPADST: usize = 7; const FLIPADST_ADST: usize = 8; const IDTX: usize = 9; const V_DCT: usize = 10; const H_DCT: usize = 11; const V_ADST: usize = 12; const H_ADST: usize = 13; const V_FLIPADST: usize = 14; const H_FLIPADST: usize = 15; const TX_TYPES: usize = 16; const MB_MODE_COUNT: usize = 17; const INTRA_MODES: usize = 13; const UV_INTRA_MODES_CFL_NOT_ALLOWED: usize = 13; const UV_INTRA_MODES_CFL_ALLOWED: usize = 14; const COMPOUND_MODES: usize = 8; const COMPOUND_MODE_CONTEXTS: usize = 8; const COMP_NEWMV_CTXS: usize = 5; const NEW_MV_CONTEXTS: usize = 6; const ZERO_MV_CONTEXTS: usize = 2; const REF_MV_CONTEXTS: usize = 6; const DRL_MODE_CONTEXTS: usize = 3; const MV_CONTEXTS: usize = 2; const MV_INTRABC_CONTEXT: usize = 1; const MV_JOINTS: usize = 4; const MV_CLASSES: usize = 11; const CLASS0_SIZE: usize = 2; const MV_OFFSET_BITS: usize = 10; const MAX_LOOP_FILTER: usize = 63; const REF_SCALE_SHIFT: usize = 14; const SUBPEL_BITS: usize = 4; const SUBPEL_MASK: usize = 15; const SCALE_SUBPEL_BITS: usize = 10; const MV_BORDER: usize = 128; const PALETTE_COLOR_CONTEXTS: usize = 5; const PALETTE_MAX_COLOR_CONTEXT_HASH: usize = 8; const PALETTE_BLOCK_SIZE_CONTEXTS: usize = 7; const PALETTE_Y_MODE_CONTEXTS: usize = 3; const PALETTE_UV_MODE_CONTEXTS: usize = 2; const PALETTE_SIZES: usize = 7; const PALETTE_COLORS: usize = 8; const PALETTE_NUM_NEIGHBORS: usize = 3; const DELTA_Q_SMALL: usize = 3; const DELTA_LF_SMALL: usize = 3; const QM_TOTAL_SIZE: usize = 3344; const MAX_ANGLE_DELTA: usize = 3; const DIRECTIONAL_MODES: usize = 8; const ANGLE_STEP: usize = 3; const TX_SET_TYPES_INTRA: usize = 3; const TX_SET_TYPES_INTER: usize = 4; const WARPEDMODEL_PREC_BITS: usize = 16; const IDENTITY: usize = 0; const TRANSLATION: usize = 1; const ROTZOOM: usize = 2; const AFFINE: usize = 3; const GM_ABS_TRANS_BITS: usize = 12; const GM_ABS_TRANS_ONLY_BITS: usize = 9; const GM_ABS_ALPHA_BITS: usize = 12; const DIV_LUT_PREC_BITS: usize = 14; const DIV_LUT_BITS: usize = 8; const DIV_LUT_NUM: usize = 257; const MOTION_MODES: usize = 3; const SIMPLE: usize = 0; const OBMC: usize = 1; const LOCALWARP: usize = 2; const LEAST_SQUARES_SAMPLES_MAX: usize = 8; const LS_MV_MAX: usize = 256; const WARPEDMODEL_TRANS_CLAMP: usize = 1; const WARPEDMODEL_NONDIAGAFFINE_CLAMP: usize = 1; const WARPEDPIXEL_PREC_SHIFTS: usize = 1; const WARPEDDIFF_PREC_BITS: usize = 10; const GM_ALPHA_PREC_BITS: usize = 15; const GM_TRANS_PREC_BITS: usize = 6; const GM_TRANS_ONLY_PREC_BITS: usize = 3; const INTERINTRA_MODES: usize = 4; const MASK_MASTER_SIZE: usize = 64; const SEGMENT_ID_PREDICTED_CONTEXTS: usize = 3; const IS_INTER_CONTEXTS: usize = 4; const FWD_REFS: usize = 4; const BWD_REFS: usize = 3; const SINGLE_REFS: usize = 7; const UNIDIR_COMP_REFS: usize = 4; const COMPOUND_TYPES: usize = 2; const CFL_JOINT_SIGNS: usize = 8; const CFL_ALPHABET_SIZE: usize = 16; const COMP_INTER_CONTEXTS: usize = 5; const COMP_REF_TYPE_CONTEXTS: usize = 5; const CFL_ALPHA_CONTEXTS: usize = 6; const INTRA_MODE_CONTEXTS: usize = 5; const COMP_GROUP_IDX_CONTEXTS: usize = 6; const COMPOUND_IDX_CONTEXTS: usize = 6; const INTRA_EDGE_KERNELS: usize = 3; const INTRA_EDGE_TAPS: usize = 5; const FRAME_LF_COUNT: usize = 4; const MAX_VARTX_DEPTH: usize = 2; const TXFM_PARTITION_CONTEXTS: usize = 21; const REF_CAT_LEVEL: usize = 640; const MAX_REF_MV_STACK_SIZE: usize = 8; const MFMV_STACK_SIZE: usize = 3; const MAX_TX_DEPTH: usize = 2; const WEDGE_TYPES: usize = 16; const FILTER_BITS: usize = 7; const WIENER_COEFFS: usize = 3; const SGRPROJ_PARAMS_BITS: usize = 4; const SGRPROJ_PRJ_SUBEXP_K: usize = 4; const SGRPROJ_PRJ_BITS: usize = 7; const SGRPROJ_RST_BITS: usize = 4; const SGRPROJ_MTABLE_BITS: usize = 20; const SGRPROJ_RECIP_BITS: usize = 12; const SGRPROJ_SGR_BITS: usize = 8; const EC_PROB_SHIFT: usize = 6; const EC_MIN_PROB: usize = 4; const SELECT_SCREEN_CONTENT_TOOLS: u8 = 2; const SELECT_INTEGER_MV: u8 = 2; const RESTORATION_TILESIZE_MAX: usize = 256; const MAX_FRAME_DISTANCE: usize = 31; const MAX_OFFSET_WIDTH: usize = 8; const MAX_OFFSET_HEIGHT: usize = 0; const WARP_PARAM_REDUCE_BITS: usize = 6; const NUM_BASE_LEVELS: usize = 2; const COEFF_BASE_RANGE: usize = 12; const BR_CDF_SIZE: usize = 4; const SIG_COEF_CONTEXTS_EOB: usize = 4; const SIG_COEF_CONTEXTS_2D: usize = 26; const SIG_COEF_CONTEXTS: usize = 42; const SIG_REF_DIFF_OFFSET_NUM: usize = 5; const SUPERRES_NUM: usize = 8; const SUPERRES_DENOM_MIN: usize = 9; const SUPERRES_DENOM_BITS: usize = 3; const SUPERRES_FILTER_BITS: usize = 6; const SUPERRES_FILTER_SHIFTS: usize = 1; const SUPERRES_FILTER_TAPS: usize = 8; const SUPERRES_FILTER_OFFSET: usize = 3; const SUPERRES_SCALE_BITS: usize = 14; const SUPERRES_SCALE_MASK: usize = (1 << 14) - 1; const SUPERRES_EXTRA_BITS: usize = 8; const TXB_SKIP_CONTEXTS: usize = 13; const EOB_COEF_CONTEXTS: usize = 9; const DC_SIGN_CONTEXTS: usize = 3; const LEVEL_CONTEXTS: usize = 21; const TX_CLASS_2D: usize = 0; const TX_CLASS_HORIZ: usize = 1; const TX_CLASS_VERT: usize = 2; const REFMVS_LIMIT: usize = (1 << 12) - 1; const INTRA_FILTER_SCALE_BITS: usize = 4; const INTRA_FILTER_MODES: usize = 5; const COEFF_CDF_Q_CTXS: usize = 4; const PRIMARY_REF_NONE: usize = 7; const BUFFER_POOL_MAX_SIZE: usize = 10;