X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-itu%2Fsrc%2Fcodecs%2Fh264%2Fcavlc.rs;fp=nihav-itu%2Fsrc%2Fcodecs%2Fh264%2Fcavlc.rs;h=4c598a48c90e0f1aa4a28b92f1263f4c484f5f70;hb=696e4e20bf7167121352f247893370cb83213d5c;hp=0000000000000000000000000000000000000000;hpb=8480761d25359f1f88c6d6df020127a7a7ea6c74;p=nihav.git diff --git a/nihav-itu/src/codecs/h264/cavlc.rs b/nihav-itu/src/codecs/h264/cavlc.rs new file mode 100644 index 0000000..4c598a4 --- /dev/null +++ b/nihav-itu/src/codecs/h264/cavlc.rs @@ -0,0 +1,676 @@ +use nihav_core::codecs::{DecoderResult, DecoderError}; +use nihav_core::io::bitreader::*; +use nihav_core::io::codebook::*; +use nihav_core::io::intcode::*; +use super::*; +use super::dsp::{CHROMA_DC_SCAN, ZIGZAG, ZIGZAG1}; +use super::slice::SliceHeader; + +fn map_i_type(idx: usize) -> MBType { + if idx == 0 { + MBType::Intra4x4 + } else if idx == 25 { + MBType::PCM + } else { + let imode = ((idx - 1) & 3) as u8; + let cbpc = ((idx - 1) / 4) as u8; + let (cbpy, cbpc) = if cbpc >= 3 { (0xF, cbpc - 3) } else { (0x0, cbpc) }; + MBType::Intra16x16(imode, cbpy, cbpc) + } +} + +const NUM_I_TYPES: usize = 26; + +const P_TYPES: [MBType; 5] = [ + MBType::P16x16, MBType::P16x8, MBType::P8x16, MBType::P8x8, MBType::P8x8Ref0 +]; + +const B_TYPES: [MBType; 23] = [ + MBType::Direct, + MBType::B16x16(BMode::L0), + MBType::B16x16(BMode::L1), + MBType::B16x16(BMode::Bi), + MBType::B16x8(BMode::L0, BMode::L0), + MBType::B8x16(BMode::L0, BMode::L0), + MBType::B16x8(BMode::L1, BMode::L1), + MBType::B8x16(BMode::L1, BMode::L1), + MBType::B16x8(BMode::L0, BMode::L1), + MBType::B8x16(BMode::L0, BMode::L1), + MBType::B16x8(BMode::L1, BMode::L0), + MBType::B8x16(BMode::L1, BMode::L0), + MBType::B16x8(BMode::L0, BMode::Bi), + MBType::B8x16(BMode::L0, BMode::Bi), + MBType::B16x8(BMode::L1, BMode::Bi), + MBType::B8x16(BMode::L1, BMode::Bi), + MBType::B16x8(BMode::Bi, BMode::L0), + MBType::B8x16(BMode::Bi, BMode::L0), + MBType::B16x8(BMode::Bi, BMode::L1), + MBType::B8x16(BMode::Bi, BMode::L1), + MBType::B16x8(BMode::Bi, BMode::Bi), + MBType::B8x16(BMode::Bi, BMode::Bi), + MBType::B8x8, +]; + +pub fn decode_mb_type_cavlc(br: &mut BitReader, slice_hdr: &SliceHeader) -> DecoderResult { + let mb_type_id = br.read_ue()? as usize; + match slice_hdr.slice_type { + SliceType::I => { + validate!(mb_type_id < NUM_I_TYPES); + Ok(map_i_type(mb_type_id)) + }, + SliceType::SI => { + validate!(mb_type_id < NUM_I_TYPES + 1); + if mb_type_id == 0 { + Ok(MBType::Intra4x4) // special SI one + } else { + Ok(map_i_type(mb_type_id - 1)) + } + }, + SliceType::P | SliceType::SP => { + validate!(mb_type_id < NUM_I_TYPES + P_TYPES.len()); + if mb_type_id < P_TYPES.len() { + Ok(P_TYPES[mb_type_id]) + } else { + Ok(map_i_type(mb_type_id - P_TYPES.len())) + } + }, + SliceType::B => { + validate!(mb_type_id < NUM_I_TYPES + B_TYPES.len()); + if mb_type_id < B_TYPES.len() { + Ok(B_TYPES[mb_type_id]) + } else { + Ok(map_i_type(mb_type_id - B_TYPES.len())) + } + }, + } +} + +fn read_refs(br: &mut BitReader, dst: &mut [PicRef], num_refs: usize) -> DecoderResult<()> { + if num_refs > 1 { + for pic_ref in dst.iter_mut() { + *pic_ref = PicRef::new(br.read_te(num_refs as u32 - 1)? as u8); + } + } else { + for pic_ref in dst.iter_mut() { + *pic_ref = ZERO_REF; + } + } + Ok(()) +} + +fn read_mvs(br: &mut BitReader, mvs: &mut [MV]) -> DecoderResult<()> { + for mv in mvs.iter_mut() { + mv.x = br.read_se()? as i16; + mv.y = br.read_se()? as i16; + } + Ok(()) +} + +pub fn decode_mb_pred_cavlc(br: &mut BitReader, slice_hdr: &SliceHeader, mb_type: MBType, sstate: &mut SliceState, mb_info: &mut CurrentMBInfo) -> DecoderResult<()> { + mb_info.mb_type = mb_type; + let num_l0 = slice_hdr.num_ref_idx_l0_active; + let num_l1 = slice_hdr.num_ref_idx_l1_active; + match mb_type { + MBType::Intra4x4 => { + for &(x, y) in I4X4_SCAN.iter() { + let x = x as usize; + let y = y as usize; + let top_pred = sstate.get_top_blk4(x + y * 4).ipred; + let left_pred = sstate.get_left_blk4(x + y * 4).ipred; + + let top_idx = top_pred.into_pred_idx(); + let left_idx = left_pred.into_pred_idx(); + let pred_mode = top_idx.min(left_idx); + let mut pred_mode = if pred_mode != -1 { pred_mode as u8 } else { 2 }; + if !br.read_bool()? { + let new_mode = br.read(3)? as u8; + pred_mode = if new_mode >= pred_mode { + new_mode + 1 + } else { new_mode }; + } + mb_info.ipred[x + y * 4] = pred_mode.into(); + sstate.get_cur_blk4(x + y * 4).ipred = (pred_mode as u8).into(); + } + mb_info.chroma_ipred = br.read_ue_lim(3)? as u8; + }, + MBType::Intra8x8 => { + for part in 0..4 { + let blk4 = (part & 1) * 2 + (part & 2) * 4; + let top_pred = sstate.get_top_blk4(blk4).ipred; + let left_pred = sstate.get_left_blk4(blk4).ipred; + + let top_idx = top_pred.into_pred_idx(); + let left_idx = left_pred.into_pred_idx(); + let pred_mode = top_idx.min(left_idx); + let mut pred_mode = if pred_mode != -1 { pred_mode as u8 } else { 2 }; + if !br.read_bool()? { + let new_mode = br.read(3)? as u8; + pred_mode = if new_mode >= pred_mode { + new_mode + 1 + } else { new_mode }; + } + mb_info.ipred[blk4] = pred_mode.into(); + mb_info.ipred[blk4 + 1] = pred_mode.into(); + mb_info.ipred[blk4 + 4] = pred_mode.into(); + mb_info.ipred[blk4 + 5] = pred_mode.into(); + sstate.get_cur_blk4(blk4).ipred = (pred_mode as u8).into(); + sstate.get_cur_blk4(blk4 + 1).ipred = (pred_mode as u8).into(); + sstate.get_cur_blk4(blk4 + 4).ipred = (pred_mode as u8).into(); + sstate.get_cur_blk4(blk4 + 5).ipred = (pred_mode as u8).into(); + } + mb_info.chroma_ipred = br.read_ue_lim(3)? as u8; + }, + MBType::Intra16x16(_ipred, _, _) => { + sstate.fill_ipred(IntraPredMode::DC); + mb_info.chroma_ipred = br.read_ue_lim(3)? as u8; + }, + MBType::P16x16 | MBType::P16x8 | MBType::P8x16 => { + let nparts = mb_type.num_parts(); + read_refs(br, &mut mb_info.ref_l0[..nparts], num_l0)?; + read_mvs(br, &mut mb_info.mv_l0[..nparts])?; + }, + MBType::B16x16(mode) => { + if mode != BMode::L1 { + read_refs(br, &mut mb_info.ref_l0[..1], num_l0)?; + } + if mode != BMode::L0 { + read_refs(br, &mut mb_info.ref_l1[..1], num_l1)?; + } + if mode != BMode::L1 { + read_mvs(br, &mut mb_info.mv_l0[..1])?; + } + if mode != BMode::L0 { + read_mvs(br, &mut mb_info.mv_l1[..1])?; + } + }, + MBType::B16x8(mode0, mode1) | MBType::B8x16(mode0, mode1) => { + if num_l0 > 1 { + if mode0 != BMode::L1 { + read_refs(br, &mut mb_info.ref_l0[0..1], num_l0)?; + } + if mode1 != BMode::L1 { + read_refs(br, &mut mb_info.ref_l0[1..2], num_l0)?; + } + } + if num_l1 > 1 { + if mode0 != BMode::L0 { + read_refs(br, &mut mb_info.ref_l1[0..1], num_l1)?; + } + if mode1 != BMode::L0 { + read_refs(br, &mut mb_info.ref_l1[1..2], num_l1)?; + } + } + if mode0 != BMode::L1 { + read_mvs(br, &mut mb_info.mv_l0[0..1])?; + } + if mode1 != BMode::L1 { + read_mvs(br, &mut mb_info.mv_l0[1..2])?; + } + if mode0 != BMode::L0 { + read_mvs(br, &mut mb_info.mv_l1[0..1])?; + } + if mode1 != BMode::L0 { + read_mvs(br, &mut mb_info.mv_l1[1..2])?; + } + }, + MBType::P8x8 | MBType::P8x8Ref0 | MBType::B8x8 => { + for sub_mb in mb_info.sub_mb_type.iter_mut() { + *sub_mb = decode_sub_mb_type(br, mb_type != MBType::B8x8)?; + } + for (part, &sub_mb) in mb_info.sub_mb_type.iter().enumerate() { + if num_l0 > 1 && mb_type != MBType::P8x8Ref0 && sub_mb != SubMBType::Direct8x8 && !sub_mb.is_l1() { + read_refs(br, &mut mb_info.ref_l0[part..][..1], num_l0)?; + } + } + for (part, &sub_mb) in mb_info.sub_mb_type.iter().enumerate() { + if num_l1 > 1 && sub_mb != SubMBType::Direct8x8 && !sub_mb.is_l0() { + read_refs(br, &mut mb_info.ref_l1[part..][..1], num_l1)?; + } + } + for (part, &sub_mb) in mb_info.sub_mb_type.iter().enumerate() { + if sub_mb != SubMBType::Direct8x8 && !sub_mb.is_l1() { + let num_subparts = sub_mb.num_parts(); + read_mvs(br, &mut mb_info.mv_l0[part * 4..][..num_subparts])?; + } + } + for (part, &sub_mb) in mb_info.sub_mb_type.iter().enumerate() { + if sub_mb != SubMBType::Direct8x8 && !sub_mb.is_l0() { + let num_subparts = sub_mb.num_parts(); + read_mvs(br, &mut mb_info.mv_l1[part * 4..][..num_subparts])?; + } + } + }, + _ => {}, + }; + Ok(()) +} + +fn decode_sub_mb_type(br: &mut BitReader, is_p: bool) -> DecoderResult { + const SUB_MB_P_TYPES: [SubMBType; 4] = [ + SubMBType::P8x8, SubMBType::P8x4, SubMBType::P4x8, SubMBType::P4x4 + ]; + const SUB_MB_B_TYPES: [SubMBType; 13] = [ + SubMBType::Direct8x8, + SubMBType::B8x8(BMode::L0), SubMBType::B8x8(BMode::L1), SubMBType::B8x8(BMode::Bi), + SubMBType::B8x4(BMode::L0), SubMBType::B4x8(BMode::L0), + SubMBType::B8x4(BMode::L1), SubMBType::B4x8(BMode::L1), + SubMBType::B8x4(BMode::Bi), SubMBType::B4x8(BMode::Bi), + SubMBType::B4x4(BMode::L0), SubMBType::B4x4(BMode::L1), SubMBType::B4x4(BMode::Bi), + ]; + if is_p { + let idx = br.read_ue_lim(SUB_MB_P_TYPES.len() as u32 - 1)? as usize; + Ok(SUB_MB_P_TYPES[idx]) + } else { + let idx = br.read_ue_lim(SUB_MB_B_TYPES.len() as u32 - 1)? as usize; + Ok(SUB_MB_B_TYPES[idx]) + } +} + +fn map_coeff_token(val: u8) -> (usize, usize) { + const TRAILING_ONES: [u8; 6] = [ 0, 0, 1, 0, 1, 2 ]; + const TOTAL_COEFF: [u8; 6] = [0, 1, 1, 2, 2, 2]; + + if val < 6 { + (TRAILING_ONES[val as usize] as usize, TOTAL_COEFF[val as usize] as usize) + } else { + (((val - 6) & 3) as usize, ((val + 6) >> 2) as usize) + } +} + +fn decode_coeffs(br: &mut BitReader, coeffs: &mut [i16], scan: &[usize], cb: &Codebook, tables: &CAVLCTables) -> DecoderResult { + let coeff_token = br.read_cb(cb)?; + let (trail_ones, total_coeff) = map_coeff_token(coeff_token); + let mut level = [0i16; 16]; + let mut run = [0u8; 16]; + if total_coeff > 0 { + let mut suffix_length = (total_coeff > 10 && trail_ones < 3) as u8; + for i in 0..total_coeff { + if i < trail_ones { + if !br.read_bool()? { + level[i] = 1; + } else { + level[i] = -1; + } + } else { + let level_prefix = br.read_code(UintCodeType::UnaryZeroes)?; + validate!(level_prefix <= 19); + let mut level_code = level_prefix.min(15) << suffix_length; + if suffix_length > 0 || level_prefix >= 14 { + let level_suffix_size = if level_prefix == 14 && suffix_length == 0 { + 4 + } else if level_prefix >= 15 { + (level_prefix - 3) as u8 + } else { + suffix_length + }; + let level_suffix = br.read(level_suffix_size)?; + level_code += level_suffix; + } + if level_prefix >= 15 && suffix_length == 0 { + level_code += 15; + } + if level_prefix >= 16 { + level_code += (1 << (level_prefix - 3)) - 4096; + } + if i == trail_ones && trail_ones < 3 { + level_code += 2; + } + level[i] = if (level_code & 1) == 0 { + (level_code as i32 + 2) >> 1 + } else { + -((level_code as i32 + 1) >> 1) + } as i16; + if suffix_length == 0 { + suffix_length = 1; + } + if level[i].abs() > (3 << (suffix_length - 1)) && suffix_length < 6 { + suffix_length += 1; + } + } + } + let mut zeros_left = if total_coeff < coeffs.len() { + let cb = if coeffs.len() > 4 { + &tables.total_zeros_cb[total_coeff - 1] + } else { + &tables.cdc_total_zeros_cb[total_coeff - 1] + }; + br.read_cb(cb)? + } else { 0 }; + for i in 0..total_coeff - 1 { + if zeros_left > 0 { + let run_before = br.read_cb(&tables.run_before_cb[(zeros_left - 1).min(6) as usize])?; + run[i] = run_before; + zeros_left -= run_before; + } + } + run[total_coeff - 1] = zeros_left; + let mut idx = 0; + for i in (0..total_coeff).rev() { + idx += run[i] as usize; + coeffs[scan[idx]] = level[i]; + idx += 1; + } + } + Ok(total_coeff as u8) +} + +fn decode_block(br: &mut BitReader, coeffs: &mut [i16; 16], cb: &Codebook, tables: &CAVLCTables) -> DecoderResult { + decode_coeffs(br, coeffs, &ZIGZAG, cb, tables) +} + +fn decode_block_ac(br: &mut BitReader, coeffs: &mut [i16; 16], cb: &Codebook, tables: &CAVLCTables) -> DecoderResult { + decode_coeffs(br, &mut coeffs[1..], &ZIGZAG1, cb, tables) +} + +fn decode_chroma_dc(br: &mut BitReader, coeffs: &mut [i16; 4], cb: &Codebook, tables: &CAVLCTables) -> DecoderResult { + decode_coeffs(br, coeffs, &CHROMA_DC_SCAN, cb, tables) +} + +fn get_cb_idx(nc: u8) -> usize { + match nc { + 0 | 1 => 0, + 2 | 3 => 1, + 4..=7 => 2, + _ => 3, + } +} + +pub fn decode_residual_cavlc(br: &mut BitReader, sstate: &mut SliceState, mb_info: &mut CurrentMBInfo, tables: &CAVLCTables) -> DecoderResult<()> { + if mb_info.mb_type.is_intra16x16() { + let mut top_nc = sstate.get_top_blk4(0).ncoded; + let mut left_nc = sstate.get_left_blk4(0).ncoded; + if !sstate.has_left { + left_nc = top_nc; + } else if !sstate.has_top { + top_nc = left_nc; + } + let cb_idx = get_cb_idx((left_nc + top_nc + 1) >> 1); + + let nc = decode_block(br, &mut mb_info.coeffs[24], &tables.coeff_token_cb[cb_idx], tables)?; + mb_info.coded[24] = nc != 0; + } + for blk8 in 0..4 { + if (mb_info.cbpy & (1 << blk8)) != 0 { + for blk4 in 0..4 { + let bx = (blk8 & 1) * 2 + (blk4 & 1); + let by = ((blk8 & 2) * 2 + (blk4 & 2)) >> 1; + let blk_no = bx + by * 4; + + let mut top_nc = sstate.get_top_blk4(blk_no).ncoded; + let mut left_nc = sstate.get_left_blk4(blk_no).ncoded; + if bx == 0 && !sstate.has_left { + left_nc = top_nc; + } else if by == 0 && !sstate.has_top { + top_nc = left_nc; + } + let cb_idx = get_cb_idx((left_nc + top_nc + 1) >> 1); + + let nc = if mb_info.mb_type.is_intra16x16() { + decode_block_ac(br, &mut mb_info.coeffs[blk_no], &tables.coeff_token_cb[cb_idx], tables)? + } else { + decode_block(br, &mut mb_info.coeffs[blk_no], &tables.coeff_token_cb[cb_idx], tables)? + }; + sstate.get_cur_blk4(blk_no).ncoded = nc; + mb_info.coded[blk_no] = nc != 0; + } + } + } + if mb_info.transform_size_8x8 { + for y in 0..2 { + for x in 0..2 { + let b0 = &mb_info.coeffs[x + y * 8]; + let b1 = &mb_info.coeffs[x + 1 + y * 8]; + let b2 = &mb_info.coeffs[x + 4 + y * 8]; + let b3 = &mb_info.coeffs[x + 5 + y * 8]; + let dst = &mut mb_info.coeffs8x8[x + y * 2].coeffs; + for (dst, (s0, s1)) in dst.chunks_mut(8).zip(b0.chunks(4).zip(b1.chunks(4))) { + let (d0, d1) = dst.split_at_mut(4); + d0.copy_from_slice(s0); + d1.copy_from_slice(s1); + } + for (dst, (s0, s1)) in dst.chunks_mut(8).skip(4).zip(b2.chunks(4).zip(b3.chunks(4))) { + let (d0, d1) = dst.split_at_mut(4); + d0.copy_from_slice(s0); + d1.copy_from_slice(s1); + } + } + } + } + for chroma in 0..2 { + if (mb_info.cbpc & 3) != 0 { + decode_chroma_dc(br, &mut mb_info.chroma_dc[chroma], &tables.cdc_coeff_token_cb, tables)?; + } + } + for chroma in 0..2 { + if (mb_info.cbpc & 2) != 0 { + for blk4 in 0..4 { + let blk_no = 16 + chroma * 4 + blk4; + let bx = blk4 & 1; + let by = blk4 >> 1; + + let mut top_nc = sstate.get_top_blk8(blk4).ncoded_c[chroma]; + let mut left_nc = sstate.get_left_blk8(blk4).ncoded_c[chroma]; + if bx == 0 && !sstate.has_left { + left_nc = top_nc; + } else if by == 0 && !sstate.has_top { + top_nc = left_nc; + } + let cb_idx = get_cb_idx((left_nc + top_nc + 1) >> 1); + + let nc = decode_block_ac(br, &mut mb_info.coeffs[blk_no], &tables.coeff_token_cb[cb_idx], tables)?; + sstate.get_cur_blk8(blk4).ncoded_c[chroma] = nc; + mb_info.coded[blk_no] = nc != 0; + } + } + } + + Ok(()) +} + +pub struct CAVLCTables { + coeff_token_cb: [Codebook; 4], + cdc_coeff_token_cb: Codebook, + total_zeros_cb: [Codebook; 15], + cdc_total_zeros_cb: [Codebook; 3], + run_before_cb: [Codebook; 7], +} + +fn map_idx(idx: usize) -> u8 { idx as u8 } + +macro_rules! create_cb { + ($bits: expr, $lens: expr) => {{ + let mut reader = TableCodebookDescReader::new($bits, $lens, map_idx); + Codebook::new(&mut reader, CodebookMode::MSB).unwrap() + }} +} + +impl CAVLCTables { + pub fn new() -> Self { + /*let mut reader = TableCodebookDescReader::new(&COEFF_TOKEN_BITS[0], &COEFF_TOKEN_LENS[0], map_idx); + let coef_tok_cb0 = Codebook::new(&mut reader, CodebookMode::MSB).unwrap(); + let mut reader = TableCodebookDescReader::new(&COEFF_TOKEN_BITS[1], &COEFF_TOKEN_LENS[1], map_idx); + let coef_tok_cb1 = Codebook::new(&mut reader, CodebookMode::MSB).unwrap(); + let mut reader = TableCodebookDescReader::new(&COEFF_TOKEN_BITS[2], &COEFF_TOKEN_LENS[2], map_idx); + let coef_tok_cb2 = Codebook::new(&mut reader, CodebookMode::MSB).unwrap(); + let mut reader = TableCodebookDescReader::new(&COEFF_TOKEN_BITS[3], &COEFF_TOKEN_LENS[3], map_idx); + let coef_tok_cb3 = Codebook::new(&mut reader, CodebookMode::MSB).unwrap(); + + let mut reader = TableCodebookDescReader::new(&CHROMA_DC_COEFF_TOKEN_BITS, &CHROMA_DC_COEFF_TOKEN_LENS, map_idx); + let cdc_coeff_token_cb = Codebook::new(&mut reader, CodebookMode::MSB).unwrap();*/ + + let coef_tok_cb0 = create_cb!(&COEFF_TOKEN_BITS[0], &COEFF_TOKEN_LENS[0]); + let coef_tok_cb1 = create_cb!(&COEFF_TOKEN_BITS[1], &COEFF_TOKEN_LENS[1]); + let coef_tok_cb2 = create_cb!(&COEFF_TOKEN_BITS[2], &COEFF_TOKEN_LENS[2]); + let coef_tok_cb3 = create_cb!(&COEFF_TOKEN_BITS[3], &COEFF_TOKEN_LENS[3]); + + let cdc_coeff_token_cb = create_cb!(&CHROMA_DC_COEFF_TOKEN_BITS, &CHROMA_DC_COEFF_TOKEN_LENS); + + let total_zeros0 = create_cb!(&TOTAL_ZERO_BITS[ 0], &TOTAL_ZERO_LENS[ 0]); + let total_zeros1 = create_cb!(&TOTAL_ZERO_BITS[ 1], &TOTAL_ZERO_LENS[ 1]); + let total_zeros2 = create_cb!(&TOTAL_ZERO_BITS[ 2], &TOTAL_ZERO_LENS[ 2]); + let total_zeros3 = create_cb!(&TOTAL_ZERO_BITS[ 3], &TOTAL_ZERO_LENS[ 3]); + let total_zeros4 = create_cb!(&TOTAL_ZERO_BITS[ 4], &TOTAL_ZERO_LENS[ 4]); + let total_zeros5 = create_cb!(&TOTAL_ZERO_BITS[ 5], &TOTAL_ZERO_LENS[ 5]); + let total_zeros6 = create_cb!(&TOTAL_ZERO_BITS[ 6], &TOTAL_ZERO_LENS[ 6]); + let total_zeros7 = create_cb!(&TOTAL_ZERO_BITS[ 7], &TOTAL_ZERO_LENS[ 7]); + let total_zeros8 = create_cb!(&TOTAL_ZERO_BITS[ 8], &TOTAL_ZERO_LENS[ 8]); + let total_zeros9 = create_cb!(&TOTAL_ZERO_BITS[ 9], &TOTAL_ZERO_LENS[ 9]); + let total_zeros10 = create_cb!(&TOTAL_ZERO_BITS[10], &TOTAL_ZERO_LENS[10]); + let total_zeros11 = create_cb!(&TOTAL_ZERO_BITS[11], &TOTAL_ZERO_LENS[11]); + let total_zeros12 = create_cb!(&TOTAL_ZERO_BITS[12], &TOTAL_ZERO_LENS[12]); + let total_zeros13 = create_cb!(&TOTAL_ZERO_BITS[13], &TOTAL_ZERO_LENS[13]); + let total_zeros14 = create_cb!(&TOTAL_ZERO_BITS[14], &TOTAL_ZERO_LENS[14]); + + let cdc_total_zeros_cb0 = create_cb!(&CHROMA_DC_TOTAL_ZERO_BITS[0], &CHROMA_DC_TOTAL_ZERO_LENS[0]); + let cdc_total_zeros_cb1 = create_cb!(&CHROMA_DC_TOTAL_ZERO_BITS[1], &CHROMA_DC_TOTAL_ZERO_LENS[1]); + let cdc_total_zeros_cb2 = create_cb!(&CHROMA_DC_TOTAL_ZERO_BITS[2], &CHROMA_DC_TOTAL_ZERO_LENS[2]); + + let run_before_cb0 = create_cb!(&RUN_BEFORE_BITS[0], &RUN_BEFORE_LENS[0]); + let run_before_cb1 = create_cb!(&RUN_BEFORE_BITS[1], &RUN_BEFORE_LENS[1]); + let run_before_cb2 = create_cb!(&RUN_BEFORE_BITS[2], &RUN_BEFORE_LENS[2]); + let run_before_cb3 = create_cb!(&RUN_BEFORE_BITS[3], &RUN_BEFORE_LENS[3]); + let run_before_cb4 = create_cb!(&RUN_BEFORE_BITS[4], &RUN_BEFORE_LENS[4]); + let run_before_cb5 = create_cb!(&RUN_BEFORE_BITS[5], &RUN_BEFORE_LENS[5]); + let run_before_cb6 = create_cb!(&RUN_BEFORE_BITS[6], &RUN_BEFORE_LENS[6]); + + Self { + coeff_token_cb: [coef_tok_cb0, coef_tok_cb1, coef_tok_cb2, coef_tok_cb3], + cdc_coeff_token_cb, + total_zeros_cb: [total_zeros0, total_zeros1, total_zeros2, + total_zeros3, total_zeros4, total_zeros5, + total_zeros6, total_zeros7, total_zeros8, + total_zeros9, total_zeros10, total_zeros11, + total_zeros12, total_zeros13, total_zeros14 ], + cdc_total_zeros_cb: [cdc_total_zeros_cb0, cdc_total_zeros_cb1, cdc_total_zeros_cb2], + run_before_cb: [ run_before_cb0, run_before_cb1, run_before_cb2, + run_before_cb3, run_before_cb4, run_before_cb5, + run_before_cb6 ], + } + } +} + +const COEFF_TOKEN_BITS: [[u16; 62]; 4] = [ + [ + 0x01, 0x05, 0x01, 0x07, 0x04, 0x01, 0x07, 0x06, + 0x05, 0x03, 0x07, 0x06, 0x05, 0x03, 0x07, 0x06, + 0x05, 0x04, 0x0F, 0x06, 0x05, 0x04, 0x0B, 0x0E, + 0x05, 0x04, 0x08, 0x0A, 0x0D, 0x04, 0x0F, 0x0E, + 0x09, 0x04, 0x0B, 0x0A, 0x0D, 0x0C, 0x0F, 0x0E, + 0x09, 0x0C, 0x0B, 0x0A, 0x0D, 0x08, 0x0F, 0x01, + 0x09, 0x0C, 0x0B, 0x0E, 0x0D, 0x08, 0x07, 0x0A, + 0x09, 0x0C, 0x04, 0x06, 0x05, 0x08 + ], [ + 0x03, 0x0B, 0x02, 0x07, 0x07, 0x03, 0x07, 0x0A, + 0x09, 0x05, 0x07, 0x06, 0x05, 0x04, 0x04, 0x06, + 0x05, 0x06, 0x07, 0x06, 0x05, 0x08, 0x0F, 0x06, + 0x05, 0x04, 0x0B, 0x0E, 0x0D, 0x04, 0x0F, 0x0A, + 0x09, 0x04, 0x0B, 0x0E, 0x0D, 0x0C, 0x08, 0x0A, + 0x09, 0x08, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, + 0x09, 0x0C, 0x07, 0x0B, 0x06, 0x08, 0x09, 0x08, + 0x0A, 0x01, 0x07, 0x06, 0x05, 0x04 + ], [ + 0x0F, 0x0F, 0x0E, 0x0B, 0x0F, 0x0D, 0x08, 0x0C, + 0x0E, 0x0C, 0x0F, 0x0A, 0x0B, 0x0B, 0x0B, 0x08, + 0x09, 0x0A, 0x09, 0x0E, 0x0D, 0x09, 0x08, 0x0A, + 0x09, 0x08, 0x0F, 0x0E, 0x0D, 0x0D, 0x0B, 0x0E, + 0x0A, 0x0C, 0x0F, 0x0A, 0x0D, 0x0C, 0x0B, 0x0E, + 0x09, 0x0C, 0x08, 0x0A, 0x0D, 0x08, 0x0D, 0x07, + 0x09, 0x0C, 0x09, 0x0C, 0x0B, 0x0A, 0x05, 0x08, + 0x07, 0x06, 0x01, 0x04, 0x03, 0x02 + ], [ + 0x03, 0x00, 0x01, 0x04, 0x05, 0x06, 0x08, 0x09, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, + 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, + 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, + 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F + ] +]; +const COEFF_TOKEN_LENS: [[u8; 62]; 4] = [ + [ + 1, 6, 2, 8, 6, 3, 9, 8, 7, 5, 10, 9, 8, 6, 11, 10, + 9, 7, 13, 11, 10, 8, 13, 13, 11, 9, 13, 13, 13, 10, 14, 14, + 13, 11, 14, 14, 14, 13, 15, 15, 14, 14, 15, 15, 15, 14, 16, 15, + 15, 15, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16 + ], [ + 2, 6, 2, 6, 5, 3, 7, 6, 6, 4, 8, 6, 6, 4, 8, 7, + 7, 5, 9, 8, 8, 6, 11, 9, 9, 6, 11, 11, 11, 7, 12, 11, + 11, 9, 12, 12, 12, 11, 12, 12, 12, 11, 13, 13, 13, 12, 13, 13, + 13, 13, 13, 14, 13, 13, 14, 14, 14, 13, 14, 14, 14, 14 + ], [ + 4, 6, 4, 6, 5, 4, 6, 5, 5, 4, 7, 5, 5, 4, 7, 5, + 5, 4, 7, 6, 6, 4, 7, 6, 6, 4, 8, 7, 7, 5, 8, 8, + 7, 6, 9, 8, 8, 7, 9, 9, 8, 8, 9, 9, 9, 8, 10, 9, + 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 + ], [ 6; 62 ] +]; + +const CHROMA_DC_COEFF_TOKEN_BITS: [u8; 14] = [ + 1, 7, 1, 4, 6, 1, 3, 3, 2, 5, 2, 3, 2, 0 +]; +const CHROMA_DC_COEFF_TOKEN_LENS: [u8; 14] = [ + 2, 6, 1, 6, 6, 3, 6, 7, 7, 6, 6, 8, 8, 7 +]; + +const TOTAL_ZERO_BITS: [[u8; 16]; 15] = [ + [ 1, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 1 ], + [ 7, 6, 5, 4, 3, 5, 4, 3, 2, 3, 2, 3, 2, 1, 0, 0 ], + [ 5, 7, 6, 5, 4, 3, 4, 3, 2, 3, 2, 1, 1, 0, 0, 0 ], + [ 3, 7, 5, 4, 6, 5, 4, 3, 3, 2, 2, 1, 0, 0, 0, 0 ], + [ 5, 4, 3, 7, 6, 5, 4, 3, 2, 1, 1, 0, 0, 0, 0, 0 ], + [ 1, 1, 7, 6, 5, 4, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0 ], + [ 1, 1, 5, 4, 3, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0 ], + [ 1, 1, 1, 3, 3, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 1, 0, 1, 3, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 1, 0, 1, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 0, 1, 1, 2, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] +]; +const TOTAL_ZERO_LENS: [[u8; 16]; 15] = [ + [ 1, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 9 ], + [ 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 0 ], + [ 4, 3, 3, 3, 4, 4, 3, 3, 4, 5, 5, 6, 5, 6, 0, 0 ], + [ 5, 3, 4, 4, 3, 3, 3, 4, 3, 4, 5, 5, 5, 0, 0, 0 ], + [ 4, 4, 4, 3, 3, 3, 3, 3, 4, 5, 4, 5, 0, 0, 0, 0 ], + [ 6, 5, 3, 3, 3, 3, 3, 3, 4, 3, 6, 0, 0, 0, 0, 0 ], + [ 6, 5, 3, 3, 3, 2, 3, 4, 3, 6, 0, 0, 0, 0, 0, 0 ], + [ 6, 4, 5, 3, 2, 2, 3, 3, 6, 0, 0, 0, 0, 0, 0, 0 ], + [ 6, 6, 4, 2, 2, 3, 2, 5, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 5, 5, 3, 2, 2, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 4, 4, 3, 3, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 4, 4, 2, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 3, 3, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] +]; + +const CHROMA_DC_TOTAL_ZERO_BITS: [[u8; 4]; 3] = [ + [ 1, 1, 1, 0 ], [ 1, 1, 0, 0 ], [ 1, 0, 0, 0 ] +]; +const CHROMA_DC_TOTAL_ZERO_LENS: [[u8; 4]; 3] = [ + [ 1, 2, 3, 3 ], [ 1, 2, 2, 0 ], [ 1, 1, 0, 0 ] +]; + +const RUN_BEFORE_BITS: [[u8; 15]; 7] = [ + [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 3, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 3, 0, 1, 3, 2, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 ] +]; +const RUN_BEFORE_LENS: [[u8; 15]; 7] = [ + [ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 2, 2, 2, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 2, 2, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 2, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0 ], + [ 3, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] +];