pub const INTER_CBP_CODENUM_TO_VALUE: [u8; 48] = [
0, 16, 1, 2, 4, 8, 32, 3, 5, 10, 12, 15, 47, 7, 11, 13, 14, 6, 9, 31, 35, 37, 42, 44, 33,
34, 36, 40, 39, 43, 45, 46, 17, 18, 20, 24, 19, 21, 26, 28, 23, 27, 29, 30, 22, 25, 38, 41,
];
pub fn cbp_to_codenum_inter(cbp: u8) -> Option<u32> {
INTER_CBP_CODENUM_TO_VALUE
.iter()
.position(|&v| v == cbp)
.map(|i| i as u32)
}
pub fn cbp_to_codenum_intra(cbp: u8) -> Option<u32> {
crate::codec::h264::macroblock::CBP_INTRA_TABLE
.iter()
.position(|&v| v as u8 == cbp)
.map(|i| i as u32)
}
pub fn pack_cbp(cbp_luma_8x8_mask: u8, cbp_chroma: u8) -> u8 {
debug_assert!(cbp_luma_8x8_mask <= 0xF);
debug_assert!(cbp_chroma <= 2);
(cbp_chroma << 4) | cbp_luma_8x8_mask
}
pub fn luma_8x8_cbp_mask(nonzero_ac: &[bool; 16]) -> u8 {
let mut mask = 0u8;
for (k, &nz) in nonzero_ac.iter().enumerate() {
if nz {
mask |= 1 << (k / 4);
}
}
mask
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn cbp_codenum_zero_maps_to_zero() {
assert_eq!(cbp_to_codenum_inter(0), Some(0));
}
#[test]
fn cbp_codenum_inter_full_table_known_values() {
assert_eq!(cbp_to_codenum_inter(16), Some(1));
assert_eq!(cbp_to_codenum_inter(1), Some(2));
assert_eq!(cbp_to_codenum_inter(15), Some(11));
assert_eq!(cbp_to_codenum_inter(47), Some(12));
}
#[test]
fn cbp_codenum_out_of_range() {
assert_eq!(cbp_to_codenum_inter(48), None);
assert_eq!(cbp_to_codenum_inter(255), None);
}
#[test]
fn pack_cbp_basic() {
assert_eq!(pack_cbp(0, 0), 0);
assert_eq!(pack_cbp(15, 0), 15);
assert_eq!(pack_cbp(0, 1), 16); assert_eq!(pack_cbp(0, 2), 32); assert_eq!(pack_cbp(15, 2), 47); }
#[test]
fn luma_8x8_mask_from_ac_flags() {
assert_eq!(luma_8x8_cbp_mask(&[false; 16]), 0);
let mut flags = [false; 16];
flags[0] = true;
assert_eq!(luma_8x8_cbp_mask(&flags), 0b0001);
let mut flags = [false; 16];
flags[5] = true;
assert_eq!(luma_8x8_cbp_mask(&flags), 0b0010);
assert_eq!(luma_8x8_cbp_mask(&[true; 16]), 0b1111);
}
}