#![forbid(unsafe_code)]
#![allow(
clippy::cast_possible_truncation,
reason = "mb_type arithmetic below is bounded by the ue(v) match arms (0..=25) that \
guard every cast site; values provably fit the narrower integer type"
)]
use super::bitreader::BitReader;
use super::error::H264Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MbType {
INxN,
I16x16 {
pred_mode: u8,
cbp_luma: u8,
cbp_chroma: u8,
},
IPcm,
}
impl MbType {
pub const fn from_raw(mb_type: u32) -> Result<Self, H264Error> {
match mb_type {
0 => Ok(Self::INxN),
1..=24 => {
let base = mb_type - 1;
let pred_mode = (base % 4) as u8;
let cbp_chroma = ((base / 4) % 3) as u8;
let cbp_luma = if base / 12 == 0 { 0 } else { 15 };
Ok(Self::I16x16 {
pred_mode,
cbp_luma,
cbp_chroma,
})
}
25 => Ok(Self::IPcm),
_ => Err(H264Error::InvalidMbType),
}
}
}
pub(super) fn read_intra_chroma_pred_mode(reader: &mut BitReader<'_>) -> Result<u8, H264Error> {
let mode = reader.read_ue()?;
u8::try_from(mode)
.ok()
.filter(|&m| m <= 3)
.ok_or(H264Error::InvalidMbType)
}
#[cfg(test)]
#[path = "macroblock_tests.rs"]
mod tests;