pub fn quant_intra_dc(level: i32) -> u8 {
let naive = (level + 4).div_euclid(8);
let mut best: u8 = 1;
let mut best_err: i32 = i32::MAX;
let consider = |v: u8, level: i32, best: &mut u8, best_err: &mut i32| {
let rec = if v == 0xFF { 1024 } else { 8 * v as i32 };
let err = (rec - level).abs();
if err < *best_err {
*best_err = err;
*best = v;
}
};
if (1..=127).contains(&naive) || (129..=254).contains(&naive) {
return naive as u8;
}
for &v in &[1u8, 126, 127, 129, 130, 254, 255] {
consider(v, level, &mut best, &mut best_err);
}
if naive <= 0 {
return 1;
}
if naive >= 255 && level != 1024 {
return 254;
}
best
}
pub fn quant_ac(coeff: i32, quant: u32) -> i32 {
debug_assert!((1..=31).contains(&quant), "H.261 QUANT must be in 1..=31");
let step = 2 * quant as i64;
let abs = (coeff as i64).unsigned_abs() as i64;
let mag = abs / step;
let sign = if coeff < 0 { -1i64 } else { 1i64 };
let level = sign * mag;
level.clamp(-127, 127) as i32
}
#[cfg(test)]
mod tests {
use super::*;
use crate::block::dequant_ac;
#[test]
fn intra_dc_roundtrip_simple() {
assert_eq!(quant_intra_dc(128), 16);
assert_eq!(quant_intra_dc(8), 1);
assert_eq!(quant_intra_dc(16), 2);
assert_eq!(quant_intra_dc(1024), 0xFF);
}
#[test]
fn intra_dc_avoids_forbidden_codes() {
assert_eq!(quant_intra_dc(1024), 0xFF);
for level in 0..=2040 {
let v = quant_intra_dc(level);
assert_ne!(v, 0, "forbidden code 0 emitted for level {level}");
assert_ne!(v, 128, "forbidden code 128 emitted for level {level}");
}
assert_eq!(quant_intra_dc(-10), 1);
assert_eq!(quant_intra_dc(4000), 254);
}
#[test]
fn ac_quant_dead_zone() {
for q in [1u32, 2, 8, 15, 31] {
let step = (2 * q) as i32;
for c in -(step - 1)..=(step - 1) {
assert_eq!(quant_ac(c, q), 0, "dead zone coeff={c} q={q}");
}
}
}
#[test]
fn ac_quant_roundtrip_odd_q() {
assert_eq!(quant_ac(3, 1), 1);
assert_eq!(dequant_ac(1, 1), 3);
assert_eq!(quant_ac(5, 1), 2);
assert_eq!(dequant_ac(2, 1), 5);
}
#[test]
fn ac_quant_roundtrip_even_q() {
assert_eq!(quant_ac(5, 2), 1);
assert_eq!(dequant_ac(1, 2), 5);
assert_eq!(quant_ac(-5, 2), -1);
assert_eq!(dequant_ac(-1, 2), -5);
}
#[test]
fn ac_quant_round_trip_all_levels_q8() {
let q = 8u32;
for level in -127i32..=127 {
if level == 0 {
continue;
}
let rec = dequant_ac(level, q);
let requant = quant_ac(rec, q);
assert_eq!(
requant, level,
"q=8 level={level} rec={rec} requant={requant}"
);
}
}
#[test]
fn ac_quant_saturates() {
assert_eq!(quant_ac(i32::MAX, 1), 127);
assert_eq!(quant_ac(i32::MIN, 1), -127);
}
}