#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum BitDepth {
Eight,
Ten,
Twelve,
}
impl BitDepth {
pub fn from_bits(bits: u8) -> Self {
match bits {
8 => BitDepth::Eight,
10 => BitDepth::Ten,
12 => BitDepth::Twelve,
other => panic!("unsupported bit depth: {other} (only 8, 10, 12 supported)"),
}
}
pub fn bits(self) -> u8 {
match self {
BitDepth::Eight => 8,
BitDepth::Ten => 10,
BitDepth::Twelve => 12,
}
}
pub fn minus8(self) -> u8 {
self.bits() - 8
}
pub fn max_val(self) -> u16 {
(1u16 << self.bits()) - 1
}
pub fn neutral(self) -> u16 {
1u16 << (self.bits() - 1)
}
pub fn qp_bd_offset(self) -> u8 {
6 * self.minus8()
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ChromaFormat {
Monochrome,
Yuv420,
Yuv422,
Yuv444,
}
impl ChromaFormat {
pub fn idc(self) -> u32 {
match self {
ChromaFormat::Monochrome => 0,
ChromaFormat::Yuv420 => 1,
ChromaFormat::Yuv422 => 2,
ChromaFormat::Yuv444 => 3,
}
}
pub fn is_monochrome(self) -> bool {
matches!(self, ChromaFormat::Monochrome)
}
pub fn sub_w(self) -> usize {
match self {
ChromaFormat::Yuv420 | ChromaFormat::Yuv422 => 2,
ChromaFormat::Yuv444 | ChromaFormat::Monochrome => 1,
}
}
pub fn sub_h(self) -> usize {
match self {
ChromaFormat::Yuv420 => 2,
ChromaFormat::Yuv422 | ChromaFormat::Yuv444 | ChromaFormat::Monochrome => 1,
}
}
pub fn chroma_tb_size(self) -> usize {
match self {
ChromaFormat::Yuv420 | ChromaFormat::Yuv422 => 4,
ChromaFormat::Yuv444 => 8,
ChromaFormat::Monochrome => 0,
}
}
pub fn chroma_tbs_per_cu(self) -> usize {
match self {
ChromaFormat::Monochrome => 0,
ChromaFormat::Yuv420 => 1,
ChromaFormat::Yuv422 => 2,
ChromaFormat::Yuv444 => 1,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn bitdepth_derived_quantities() {
assert_eq!(BitDepth::Eight.bits(), 8);
assert_eq!(BitDepth::Ten.bits(), 10);
assert_eq!(BitDepth::Twelve.bits(), 12);
assert_eq!(BitDepth::Eight.minus8(), 0);
assert_eq!(BitDepth::Ten.minus8(), 2);
assert_eq!(BitDepth::Twelve.minus8(), 4);
assert_eq!(BitDepth::Eight.max_val(), 255);
assert_eq!(BitDepth::Ten.max_val(), 1023);
assert_eq!(BitDepth::Twelve.max_val(), 4095);
assert_eq!(BitDepth::Eight.neutral(), 128);
assert_eq!(BitDepth::Ten.neutral(), 512);
assert_eq!(BitDepth::Twelve.neutral(), 2048);
assert_eq!(BitDepth::Eight.qp_bd_offset(), 0);
assert_eq!(BitDepth::Ten.qp_bd_offset(), 12);
assert_eq!(BitDepth::Twelve.qp_bd_offset(), 24);
}
#[test]
fn bitdepth_from_bits_roundtrip() {
assert_eq!(BitDepth::from_bits(8), BitDepth::Eight);
assert_eq!(BitDepth::from_bits(10), BitDepth::Ten);
assert_eq!(BitDepth::from_bits(12), BitDepth::Twelve);
}
#[test]
#[should_panic]
fn bitdepth_rejects_unsupported() {
let _ = BitDepth::from_bits(16);
}
}