#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct VlcEntry {
pub code: u32,
pub bits: u8,
}
impl VlcEntry {
#[must_use]
pub const fn new(code: u32, bits: u8) -> Self {
Self { code, bits }
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct TcoefEntry {
pub run: u8,
pub level: i16,
pub last: bool,
}
impl TcoefEntry {
#[must_use]
pub const fn new(run: u8, level: i16, last: bool) -> Self {
Self { run, level, last }
}
}
pub const MCBPC_I: &[(u8, u8)] = &[
(3, 0), (3, 1), (3, 2), (3, 3), (4, 0), (4, 1), (4, 2), (4, 3), ];
pub const MCBPC_P: &[(u8, u8)] = &[
(0, 0), (0, 1), (0, 2), (0, 3), (3, 0), (1, 0), (3, 1), (1, 1), (3, 2), (1, 2), (3, 3), (1, 3), (2, 0), (4, 0), (2, 1), (4, 1), (2, 2), (4, 2), (2, 3), (4, 3), ];
pub const MCBPC_I_VLC: &[VlcEntry] = &[
VlcEntry::new(0b1, 1), VlcEntry::new(0b01, 2), VlcEntry::new(0b001, 3), VlcEntry::new(0b0001, 4), VlcEntry::new(0b00001, 5), VlcEntry::new(0b000001, 6), VlcEntry::new(0b0000001, 7), VlcEntry::new(0b00000001, 8), ];
pub const MCBPC_P_VLC: &[VlcEntry] = &[
VlcEntry::new(0b1, 1), VlcEntry::new(0b0011, 4), VlcEntry::new(0b0010, 4), VlcEntry::new(0b000101, 6), VlcEntry::new(0b00011, 5), VlcEntry::new(0b000100, 6), VlcEntry::new(0b00000011, 8), VlcEntry::new(0b00000010, 8), VlcEntry::new(0b000000011, 9), VlcEntry::new(0b000000010, 9), VlcEntry::new(0b00000000011, 11), VlcEntry::new(0b00000000010, 11), VlcEntry::new(0b00000111, 8), VlcEntry::new(0b00000110, 8), VlcEntry::new(0b00000101, 8), VlcEntry::new(0b00000100, 8), VlcEntry::new(0b000000011, 9), VlcEntry::new(0b000000010, 9), VlcEntry::new(0b0000000001, 10), VlcEntry::new(0b00000000001, 11), ];
pub const CBPY_VLC: &[VlcEntry] = &[
VlcEntry::new(0b0011, 4), VlcEntry::new(0b00101, 5), VlcEntry::new(0b00111, 5), VlcEntry::new(0b01001, 5), VlcEntry::new(0b01011, 5), VlcEntry::new(0b01101, 5), VlcEntry::new(0b01111, 5), VlcEntry::new(0b00001, 5), VlcEntry::new(0b10001, 5), VlcEntry::new(0b10011, 5), VlcEntry::new(0b10101, 5), VlcEntry::new(0b10111, 5), VlcEntry::new(0b11001, 5), VlcEntry::new(0b11011, 5), VlcEntry::new(0b11101, 5), VlcEntry::new(0b0010, 4), ];
pub const CBPY_INTRA_VLC: &[VlcEntry] = &[
VlcEntry::new(0b0010, 4), VlcEntry::new(0b11101, 5), VlcEntry::new(0b11011, 5), VlcEntry::new(0b11001, 5), VlcEntry::new(0b10111, 5), VlcEntry::new(0b10101, 5), VlcEntry::new(0b10011, 5), VlcEntry::new(0b10001, 5), VlcEntry::new(0b00001, 5), VlcEntry::new(0b01111, 5), VlcEntry::new(0b01101, 5), VlcEntry::new(0b01011, 5), VlcEntry::new(0b01001, 5), VlcEntry::new(0b00111, 5), VlcEntry::new(0b00101, 5), VlcEntry::new(0b0011, 4), ];
pub const MVD_VLC: &[VlcEntry] = &[
VlcEntry::new(0b0000000001101, 13), VlcEntry::new(0b0000000001111, 13), VlcEntry::new(0b0000000010001, 13), VlcEntry::new(0b0000000010011, 13), VlcEntry::new(0b0000000010101, 13), VlcEntry::new(0b0000000010111, 13), VlcEntry::new(0b0000000011001, 13), VlcEntry::new(0b0000000011011, 13), VlcEntry::new(0b0000000011101, 13), VlcEntry::new(0b0000000011111, 13), VlcEntry::new(0b0000000100001, 13), VlcEntry::new(0b0000000100011, 13), VlcEntry::new(0b0000000100101, 13), VlcEntry::new(0b0000000100111, 13), VlcEntry::new(0b0000000101001, 13), VlcEntry::new(0b0000000101011, 13), VlcEntry::new(0b00000001011, 11), VlcEntry::new(0b00000001111, 11), VlcEntry::new(0b00000010011, 11), VlcEntry::new(0b00000010111, 11), VlcEntry::new(0b00000011011, 11), VlcEntry::new(0b00000011111, 11), VlcEntry::new(0b00000100011, 11), VlcEntry::new(0b00000100111, 11), VlcEntry::new(0b0000001011, 10), VlcEntry::new(0b0000001111, 10), VlcEntry::new(0b0000010011, 10), VlcEntry::new(0b0000010111, 10), VlcEntry::new(0b000000011, 9), VlcEntry::new(0b000001011, 9), VlcEntry::new(0b0000011, 7), VlcEntry::new(0b000011, 6), VlcEntry::new(0b1, 1), VlcEntry::new(0b000010, 6), VlcEntry::new(0b0000010, 7), VlcEntry::new(0b000001010, 9), VlcEntry::new(0b000000010, 9), VlcEntry::new(0b0000010110, 10), VlcEntry::new(0b0000010010, 10), VlcEntry::new(0b0000001110, 10), VlcEntry::new(0b0000001010, 10), VlcEntry::new(0b00000100110, 11), VlcEntry::new(0b00000100010, 11), VlcEntry::new(0b00000011110, 11), VlcEntry::new(0b00000011010, 11), VlcEntry::new(0b00000010110, 11), VlcEntry::new(0b00000010010, 11), VlcEntry::new(0b00000001110, 11), VlcEntry::new(0b00000001010, 11), VlcEntry::new(0b0000000101010, 13), VlcEntry::new(0b0000000101000, 13), VlcEntry::new(0b0000000100110, 13), VlcEntry::new(0b0000000100100, 13), VlcEntry::new(0b0000000100010, 13), VlcEntry::new(0b0000000100000, 13), VlcEntry::new(0b0000000011110, 13), VlcEntry::new(0b0000000011100, 13), VlcEntry::new(0b0000000011010, 13), VlcEntry::new(0b0000000011000, 13), VlcEntry::new(0b0000000010110, 13), VlcEntry::new(0b0000000010100, 13), VlcEntry::new(0b0000000010010, 13), VlcEntry::new(0b0000000010000, 13), VlcEntry::new(0b0000000001110, 13), VlcEntry::new(0b0000000001100, 13), ];
pub const TCOEF_VLC: &[(TcoefEntry, VlcEntry)] = &[
(TcoefEntry::new(0, 1, false), VlcEntry::new(0b10, 2)),
(TcoefEntry::new(0, 2, false), VlcEntry::new(0b0101, 4)),
(TcoefEntry::new(0, 3, false), VlcEntry::new(0b00101, 5)),
(TcoefEntry::new(0, 4, false), VlcEntry::new(0b0000110, 7)),
(TcoefEntry::new(0, 5, false), VlcEntry::new(0b00100110, 8)),
(TcoefEntry::new(0, 6, false), VlcEntry::new(0b00100001, 8)),
(TcoefEntry::new(0, 7, false), VlcEntry::new(0b00011110, 8)),
(TcoefEntry::new(0, 8, false), VlcEntry::new(0b00011011, 8)),
(TcoefEntry::new(0, 9, false), VlcEntry::new(0b00011000, 8)),
(TcoefEntry::new(0, 10, false), VlcEntry::new(0b00010101, 8)),
(TcoefEntry::new(0, 11, false), VlcEntry::new(0b00010010, 8)),
(TcoefEntry::new(0, 12, false), VlcEntry::new(0b00001111, 8)),
(TcoefEntry::new(1, 1, false), VlcEntry::new(0b011, 3)),
(TcoefEntry::new(1, 2, false), VlcEntry::new(0b000110, 6)),
(TcoefEntry::new(1, 3, false), VlcEntry::new(0b00100101, 8)),
(TcoefEntry::new(2, 1, false), VlcEntry::new(0b0100, 4)),
(TcoefEntry::new(2, 2, false), VlcEntry::new(0b00100100, 8)),
(TcoefEntry::new(3, 1, false), VlcEntry::new(0b000101, 6)),
(TcoefEntry::new(4, 1, false), VlcEntry::new(0b00100011, 8)),
(TcoefEntry::new(5, 1, false), VlcEntry::new(0b00100010, 8)),
(TcoefEntry::new(6, 1, false), VlcEntry::new(0b00100000, 8)),
(TcoefEntry::new(7, 1, false), VlcEntry::new(0b00011111, 8)),
(TcoefEntry::new(8, 1, false), VlcEntry::new(0b00011101, 8)),
(TcoefEntry::new(9, 1, false), VlcEntry::new(0b00011100, 8)),
(TcoefEntry::new(10, 1, false), VlcEntry::new(0b00011010, 8)),
(TcoefEntry::new(11, 1, false), VlcEntry::new(0b00011001, 8)),
(TcoefEntry::new(12, 1, false), VlcEntry::new(0b00010111, 8)),
(TcoefEntry::new(13, 1, false), VlcEntry::new(0b00010110, 8)),
(TcoefEntry::new(14, 1, false), VlcEntry::new(0b00010100, 8)),
(TcoefEntry::new(15, 1, false), VlcEntry::new(0b00010011, 8)),
(TcoefEntry::new(16, 1, false), VlcEntry::new(0b00010001, 8)),
(TcoefEntry::new(17, 1, false), VlcEntry::new(0b00010000, 8)),
(TcoefEntry::new(18, 1, false), VlcEntry::new(0b00001110, 8)),
(TcoefEntry::new(19, 1, false), VlcEntry::new(0b00001101, 8)),
(TcoefEntry::new(20, 1, false), VlcEntry::new(0b00001100, 8)),
(TcoefEntry::new(21, 1, false), VlcEntry::new(0b00001011, 8)),
(TcoefEntry::new(22, 1, false), VlcEntry::new(0b00001010, 8)),
(TcoefEntry::new(23, 1, false), VlcEntry::new(0b00001001, 8)),
(TcoefEntry::new(24, 1, false), VlcEntry::new(0b00001000, 8)),
(TcoefEntry::new(25, 1, false), VlcEntry::new(0b00000111, 8)),
(TcoefEntry::new(26, 1, false), VlcEntry::new(0b00000110, 8)),
(TcoefEntry::new(0, 1, true), VlcEntry::new(0b0110, 4)),
(TcoefEntry::new(0, 2, true), VlcEntry::new(0b00111, 5)),
(TcoefEntry::new(0, 3, true), VlcEntry::new(0b000111, 6)),
(TcoefEntry::new(0, 4, true), VlcEntry::new(0b00011010, 8)),
(TcoefEntry::new(0, 5, true), VlcEntry::new(0b00011001, 8)),
(TcoefEntry::new(0, 6, true), VlcEntry::new(0b00010111, 8)),
(TcoefEntry::new(1, 1, true), VlcEntry::new(0b00110, 5)),
(TcoefEntry::new(1, 2, true), VlcEntry::new(0b00010110, 8)),
(TcoefEntry::new(2, 1, true), VlcEntry::new(0b000100, 6)),
(TcoefEntry::new(3, 1, true), VlcEntry::new(0b00010101, 8)),
];
pub const INTRA_DC_LUMA_VLC: &[VlcEntry] = &[
VlcEntry::new(0b00, 2), VlcEntry::new(0b010, 3), VlcEntry::new(0b011, 3), VlcEntry::new(0b100, 3), VlcEntry::new(0b101, 3), VlcEntry::new(0b110, 3), VlcEntry::new(0b1110, 4), VlcEntry::new(0b11110, 5), VlcEntry::new(0b111110, 6), VlcEntry::new(0b1111110, 7), VlcEntry::new(0b11111110, 8), VlcEntry::new(0b111111110, 9), ];
pub const INTRA_DC_CHROMA_VLC: &[VlcEntry] = &[
VlcEntry::new(0b00, 2), VlcEntry::new(0b01, 2), VlcEntry::new(0b10, 2), VlcEntry::new(0b110, 3), VlcEntry::new(0b1110, 4), VlcEntry::new(0b11110, 5), VlcEntry::new(0b111110, 6), VlcEntry::new(0b1111110, 7), VlcEntry::new(0b11111110, 8), VlcEntry::new(0b111111110, 9), VlcEntry::new(0b1111111110, 10), VlcEntry::new(0b11111111110, 11), ];
pub const MODB_VLC: &[VlcEntry] = &[
VlcEntry::new(0b0, 1), VlcEntry::new(0b10, 2), VlcEntry::new(0b11, 2), ];
#[must_use]
pub fn decode_mvd(code: u32, bits: u8) -> Option<i32> {
for (idx, entry) in MVD_VLC.iter().enumerate() {
if entry.code == code && entry.bits == bits {
return Some((idx as i32) - 32);
}
}
None
}
#[must_use]
pub fn encode_mvd(mvd: i32) -> Option<VlcEntry> {
if !(-32..=32).contains(&mvd) {
return None;
}
let idx = (mvd + 32) as usize;
Some(MVD_VLC[idx])
}
#[must_use]
pub fn decode_cbpy(code: u32, bits: u8, intra: bool) -> Option<u8> {
let table = if intra { CBPY_INTRA_VLC } else { CBPY_VLC };
for (pattern, entry) in table.iter().enumerate() {
if entry.code == code && entry.bits == bits {
return Some(pattern as u8);
}
}
None
}
#[must_use]
pub fn encode_cbpy(pattern: u8, intra: bool) -> Option<VlcEntry> {
if pattern > 15 {
return None;
}
let table = if intra { CBPY_INTRA_VLC } else { CBPY_VLC };
Some(table[pattern as usize])
}
pub fn find_tcoef_entry(code: u32, bits: u8) -> Option<TcoefEntry> {
for (entry, vlc) in TCOEF_VLC {
if vlc.code == code && vlc.bits == bits {
return Some(*entry);
}
}
None
}
pub fn find_tcoef_vlc(entry: &TcoefEntry) -> Option<VlcEntry> {
for (tcoef, vlc) in TCOEF_VLC {
if tcoef.run == entry.run && tcoef.level == entry.level && tcoef.last == entry.last {
return Some(*vlc);
}
}
None
}
#[must_use]
pub fn decode_mcbpc_i(code: u32, bits: u8) -> Option<(u8, u8)> {
for (idx, entry) in MCBPC_I_VLC.iter().enumerate() {
if entry.code == code && entry.bits == bits {
if idx < MCBPC_I.len() {
return Some(MCBPC_I[idx]);
}
}
}
None
}
#[must_use]
pub fn decode_mcbpc_p(code: u32, bits: u8) -> Option<(u8, u8)> {
for (idx, entry) in MCBPC_P_VLC.iter().enumerate() {
if entry.code == code && entry.bits == bits {
if idx < MCBPC_P.len() {
return Some(MCBPC_P[idx]);
}
}
}
None
}
#[must_use]
pub fn encode_mcbpc_i(mb_type: u8, cbpc: u8) -> Option<VlcEntry> {
for (idx, &(mbt, cbp)) in MCBPC_I.iter().enumerate() {
if mbt == mb_type && cbp == cbpc && idx < MCBPC_I_VLC.len() {
return Some(MCBPC_I_VLC[idx]);
}
}
None
}
#[must_use]
pub fn encode_mcbpc_p(mb_type: u8, cbpc: u8) -> Option<VlcEntry> {
for (idx, &(mbt, cbp)) in MCBPC_P.iter().enumerate() {
if mbt == mb_type && cbp == cbpc && idx < MCBPC_P_VLC.len() {
return Some(MCBPC_P_VLC[idx]);
}
}
None
}