use crate::dct::{
dct4x4_t, dct4x8_t, dct8x8_t, dct8x16_t, dct16x16, dct16x16_t, dct16x32_t, dct32x32, dct32x32_t,
};
pub(crate) fn dc_q(base_q_idx: u8, bd: u8) -> u16 {
let t: &[u16; 256] = match bd {
10 => &crate::coef_q::DC_QLOOKUP_10,
12 => &crate::coef_q::DC_QLOOKUP_12,
_ => &crate::coef_q::DC_QLOOKUP_8,
};
t[base_q_idx as usize]
}
pub(crate) fn ac_q(base_q_idx: u8, bd: u8) -> u16 {
let t: &[u16; 256] = match bd {
10 => &crate::coef_q::AC_QLOOKUP_10,
12 => &crate::coef_q::AC_QLOOKUP_12,
_ => &crate::coef_q::AC_QLOOKUP_8,
};
t[base_q_idx as usize]
}
pub(crate) fn chroma_dc_delta(base_q_idx: u8) -> i32 {
let q = base_q_idx as i32;
if q <= 160 {
0
} else {
-((q - 160) / 3).min(32)
}
}
pub(crate) fn itx_clips(bd: u8) -> (i32, i32, i32, i32, i32) {
if bd <= 8 {
let (mn, mx) = (i16::MIN as i32, i16::MAX as i32);
(mn, mx, mn, mx, 32767)
} else {
let row_max = (1i32 << (bd + 7)) - 1;
let col_max = (1i32 << (bd + 5)) - 1;
(!row_max, row_max, !col_max, col_max, row_max)
}
}
pub(crate) trait Dct {
fn dc_q(&self) -> i32;
fn ac_q(&self) -> i32;
fn clips(&self) -> (i32, i32, i32, i32, i32);
fn q_mult_dc(&self) -> i32;
fn q_mult_ac(&self) -> i32;
}
#[derive(Clone, Copy)]
pub(crate) struct Quant {
dc: i32,
ac: i32,
q_mult_dc: i32,
q_mult_ac: i32,
rmin: i32,
rmax: i32,
cmin: i32,
cmax: i32,
cf_max: i32,
}
impl Quant {
pub(crate) fn new(base_q_idx: u8, bd: u8) -> Self {
let (rmin, rmax, cmin, cmax, cf_max) = itx_clips(bd);
let dc = dc_q(base_q_idx, bd) as i32;
let ac = ac_q(base_q_idx, bd) as i32;
Quant {
dc,
ac,
q_mult_dc: (65536.0_f64 / dc as f64).round() as i32,
q_mult_ac: (65536.0_f64 / ac as f64).round() as i32,
rmin,
rmax,
cmin,
cmax,
cf_max,
}
}
pub(crate) fn new_chroma(base_q_idx: u8, bd: u8) -> Self {
Self::new_chroma_with_delta(base_q_idx, chroma_dc_delta(base_q_idx), bd)
}
pub(crate) fn new_chroma_with_delta(base_q_idx: u8, dc_delta: i32, bd: u8) -> Self {
let dc_idx = (base_q_idx as i32 + dc_delta).clamp(0, 255) as u8;
let (rmin, rmax, cmin, cmax, cf_max) = itx_clips(bd);
let dc = dc_q(dc_idx, bd) as i32;
let ac = ac_q(base_q_idx, bd) as i32;
Quant {
dc,
ac,
q_mult_dc: (65536.0_f64 / dc as f64).round() as i32,
q_mult_ac: (65536.0_f64 / ac as f64).round() as i32,
rmin,
rmax,
cmin,
cmax,
cf_max,
}
}
}
impl Dct for Quant {
#[inline]
fn dc_q(&self) -> i32 {
self.dc
}
#[inline]
fn ac_q(&self) -> i32 {
self.ac
}
#[inline]
fn clips(&self) -> (i32, i32, i32, i32, i32) {
(self.rmin, self.rmax, self.cmin, self.cmax, self.cf_max)
}
#[inline]
fn q_mult_dc(&self) -> i32 {
self.q_mult_dc
}
#[inline]
fn q_mult_ac(&self) -> i32 {
self.q_mult_ac
}
}
pub(crate) fn forward_dct_quant_8x8_t(
residual: &[i32; 64],
q: &impl Dct,
) -> ([i32; 64], [f64; 64]) {
dct8x8_t(residual, q)
}
pub(crate) fn forward_dct_quant_16x16(residual: &mut [i32; 256], q: &impl Dct) {
dct16x16(residual, q)
}
pub(crate) fn forward_dct_quant_16x16_t(
residual: &[i32; 256],
q: &impl Dct,
) -> ([i32; 256], [f64; 256]) {
dct16x16_t(residual, q)
}
#[allow(unused)]
pub(crate) fn forward_dct_quant_32x32(residual: &mut [i32; 1024], q: &impl Dct) {
dct32x32(residual, q)
}
pub(crate) fn forward_dct_quant_32x32_t(
residual: &[i32; 1024],
q: &impl Dct,
) -> ([i32; 1024], [f64; 1024]) {
dct32x32_t(residual, q)
}
pub(crate) fn forward_dct_quant_4x8_t(
residual: &[i32; 32],
q: &impl Dct,
) -> ([i32; 32], [f64; 32]) {
dct4x8_t(residual, q)
}
pub(crate) fn forward_dct_quant_8x16_t(
residual: &[i32; 128],
q: &impl Dct,
) -> ([i32; 128], [f64; 128]) {
dct8x16_t(residual, q)
}
pub(crate) fn forward_dct_quant_16x32_t(
residual: &[i32; 512],
q: &impl Dct,
) -> ([i32; 512], [f64; 512]) {
dct16x32_t(residual, q)
}
pub(crate) fn forward_dct_quant_4x4_t(
residual: &[i32; 16],
q: &impl Dct,
) -> ([i32; 16], [f64; 16]) {
dct4x4_t(residual, q)
}