use crate::av2::cdfs_qctx::*;
use crate::av2::entropy::RangeEncoder;
use crate::av2::lossless::SCAN_4X4;
use crate::av2::tables::*;
use crate::av2::tables_tx32::*;
pub(crate) type Coeff = (usize, i32);
fn floor_log2(x: u32) -> u32 {
31 - x.leading_zeros()
}
const PLVL_STRIDE: i32 = 36;
const PLVL_BUF: usize = (PLVL_STRIDE as usize) * 40;
#[inline]
fn plvl(rc: i32) -> i32 {
(rc >> 5) * PLVL_STRIDE + (rc & 31)
}
fn plvl_w(rc: i32, bwl: i32) -> i32 {
(rc >> bwl) * PLVL_STRIDE + (rc & ((1 << bwl) - 1))
}
fn luma_coeff_context(levels: &[i32], rc: i32, xy: i32) -> (usize, usize) {
luma_coeff_context_w(levels, rc, xy, 5)
}
fn luma_coeff_context_w(levels: &[i32], rc: i32, xy: i32, bwl: i32) -> (usize, usize) {
let low_freq = xy < 4;
let mut limit: i32 = if low_freq { 5 } else { 3 };
let p = plvl_w(rc, bwl);
let neighbor = |dy: i32, dx: i32| -> i32 { levels[(p + dy * PLVL_STRIDE + dx) as usize] };
let mut low_mag = 0i32;
let mut hi_mag = 0i32;
for (dy, dx) in [(0, 1), (1, 0), (1, 1)] {
let v = neighbor(dy, dx);
low_mag += v.min(limit);
hi_mag += v.min(5);
}
low_mag += neighbor(0, 2).min(limit) + neighbor(2, 0).min(limit);
let offset;
if low_freq {
offset = if xy == 0 {
0
} else if xy < 2 {
9
} else {
16
};
limit = if xy == 0 {
8
} else if xy < 2 {
6
} else {
4
};
} else {
offset = if xy < 6 {
0
} else if xy < 8 {
5
} else {
10
};
limit = 4;
}
let hi_range_ctx = (if low_freq && xy > 0 { 7 } else { 0 }) + ((hi_mag + 1) >> 1).min(6);
let base_ctx = offset + ((low_mag + 1) >> 1).min(limit);
(base_ctx as usize, hi_range_ctx as usize)
}
fn chroma_coeff_context(levels: &[i32], rc: i32, xy: i32, plane_offset: usize) -> (usize, usize) {
chroma_coeff_context_w(levels, rc, xy, plane_offset, 5)
}
fn chroma_coeff_context_w(
levels: &[i32],
rc: i32,
xy: i32,
plane_offset: usize,
bwl: i32,
) -> (usize, usize) {
let add_limit: i32 = if xy < 1 { 5 } else { 3 };
let p = plvl_w(rc, bwl);
let neighbor = |dy: i32, dx: i32| -> i32 { levels[(p + dy * PLVL_STRIDE + dx) as usize] };
let (right, below, below_right) = (neighbor(0, 1), neighbor(1, 0), neighbor(1, 1));
let low_mag = right.min(add_limit) + below.min(add_limit) + below_right.min(add_limit);
let hi_mag = right.min(5) + below.min(5) + below_right.min(5);
let base_ctx = plane_offset + (((low_mag + 1) >> 1).min(3)) as usize;
let hi_range_ctx = (((hi_mag + 1) >> 1).min(3)) as usize;
(base_ctx, hi_range_ctx)
}
fn get_adaptive_param(ctx: i32) -> u32 {
const TABLE: [i32; 5] = [4, 8, 16, 32, 64];
let mut m = 0usize;
while m < TABLE.len() && ctx >= TABLE[m] {
m += 1;
}
m as u32 + 1
}
fn write_exp_golomb(enc: &mut RangeEncoder, level: u32, k: u32) {
let x = level + (1 << k);
let length = floor_log2(x) + 1; for _ in 0..(length - 1 - k) {
enc.encode_bypass(0, 1);
}
for b in (0..length).rev() {
enc.encode_bypass((x >> b) & 1, 1);
}
}
fn write_truncated_rice(enc: &mut RangeEncoder, level: u32, m: u32, k: u32, cmax: u32) {
let q = level >> m;
if q >= cmax {
for _ in 0..cmax {
enc.encode_bypass(0, 1);
}
write_exp_golomb(enc, level - (cmax << m), k);
} else {
for _ in 0..q {
enc.encode_bypass(0, 1);
}
enc.encode_bypass(1, 1);
let mask = (1u32 << m) - 1;
for b in (0..m).rev() {
enc.encode_bypass(((level & mask) >> b) & 1, 1);
}
}
}
fn encode_high_range(enc: &mut RangeEncoder, hr: u32, running_avg: i32) -> i32 {
let m = get_adaptive_param(running_avg);
write_truncated_rice(enc, hr, m, m + 1, (m + 4).min(6));
(running_avg + hr as i32) >> 1
}
fn encode_luma_base_range(
enc: &mut RangeEncoder,
level: u32,
hi_range_ctx: usize,
high_freq: bool,
) {
let limit = if high_freq { 3u32 } else { 5u32 };
let over = level - limit;
if high_freq {
if over <= 2 {
enc.sym_br_hf(hi_range_ctx, over as usize, 3);
} else {
enc.sym_br_hf(hi_range_ctx, 3, 3);
}
} else {
if over <= 2 {
enc.sym_br(hi_range_ctx, over as usize, 3);
} else {
enc.sym_br(hi_range_ctx, 3, 3);
}
}
}
#[derive(Copy, Clone)]
pub(crate) enum EobCdf {
EobBin,
Eob64Luma,
Eob128Luma,
Eob256,
Eob512,
ChrEobBin,
ChrEob256,
ChrEob512,
#[allow(unused)]
Eob16Q0(usize), ChrEob128,
ChrEob32,
ChrEob64,
}
#[inline]
fn eob_sym(enc: &mut RangeEncoder, tbl: EobCdf, s: usize, nsyms: usize) {
match tbl {
EobCdf::EobBin => enc.sym_eob_bin(s, nsyms),
EobCdf::Eob64Luma => enc.sym_eob64_luma(s, nsyms),
EobCdf::Eob128Luma => enc.sym_eob128_luma(s, nsyms),
EobCdf::Eob256 => enc.sym_eob256(s, nsyms),
EobCdf::Eob512 => enc.sym_eob512(s, nsyms),
EobCdf::ChrEobBin => enc.sym_chr_eob_bin(s, nsyms),
EobCdf::ChrEob256 => enc.sym_chr_eob256(s, nsyms),
EobCdf::ChrEob512 => enc.sym_chr_eob512(s, nsyms),
EobCdf::Eob16Q0(ctx) => enc.sym_eob16_q0(ctx, s, nsyms),
EobCdf::ChrEob128 => enc.sym_chr_eob128(s, nsyms),
EobCdf::ChrEob32 => enc.sym_chr_eob32(s, nsyms),
EobCdf::ChrEob64 => enc.sym_chr_eob64(s, nsyms),
}
}
#[inline]
fn eob_sym_esc(enc: &mut RangeEncoder, tbl: EobCdf, s: usize, nsyms: usize) {
eob_sym(enc, tbl, s, nsyms);
}
fn encode_eob(
enc: &mut RangeEncoder,
eob: usize,
eob_cdf: EobCdf,
eob_hi_bit: u16,
esc_bits: u32,
pt_nsyms: usize,
) {
if eob <= 1 {
eob_sym(enc, eob_cdf, eob, pt_nsyms);
return;
}
let mut bin = 2usize;
while (2usize << (bin - 1)) <= eob {
bin += 1;
}
if bin < pt_nsyms {
eob_sym(enc, eob_cdf, bin, pt_nsyms);
} else if esc_bits == 0 {
eob_sym_esc(enc, eob_cdf, bin, pt_nsyms);
} else {
eob_sym_esc(enc, eob_cdf, pt_nsyms, pt_nsyms);
enc.encode_bypass((bin - pt_nsyms) as u32, esc_bits);
}
let extra_bits = bin - 2;
let hi = (eob >> extra_bits) & 1;
enc.bool_eob_extra(eob_hi_bit as u32, hi as u32);
if extra_bits > 0 {
let low = eob & ((1 << extra_bits) - 1);
for k in (0..extra_bits).rev() {
enc.encode_bypass(((low >> k) & 1) as u32, 1);
}
}
}
static TOK_LOG2_LUT: std::sync::OnceLock<Vec<f64>> = std::sync::OnceLock::new();
#[inline]
fn tok_log2_lut() -> &'static [f64] {
TOK_LOG2_LUT.get_or_init(|| {
let mut v = vec![0.0f64; 32769];
for (d, slot) in v.iter_mut().enumerate().skip(1) {
*slot = (32768.0 / d as f64).log2();
}
v[0] = v[1];
v
})
}
fn tok_cost(icdf: &[u16], s: usize) -> f64 {
let hi = if s == 0 { 32768i32 } else { icdf[s - 1] as i32 };
let lo = if s < icdf.len() { icdf[s] as i32 } else { 0 };
tok_log2_lut()[(hi - lo).max(1) as usize]
}
#[inline]
fn rice_tail_bits(hr: u32) -> f64 {
2.0 * ((hr + 1) as f64).log2() + 2.0
}
fn base_range_bits(level: u32, hi_range_ctx: usize, high_freq: bool, qc: usize) -> f64 {
let limit = if high_freq { 3u32 } else { 5u32 };
let over = level - limit;
let cdf: &[u16] = if high_freq {
&BR_TOK_HF_QC[qc][hi_range_ctx]
} else {
&BR_TOK_QC[qc][hi_range_ctx]
};
if over <= 2 {
tok_cost(cdf, over as usize)
} else {
tok_cost(cdf, 3) + rice_tail_bits(level - (limit + 3))
}
}
fn luma_level_bits(
level: u32,
is_eob: bool,
base_ctx: usize,
hi_range_ctx: usize,
high_freq: bool,
qc: usize,
) -> f64 {
let mut bits = if !high_freq {
if is_eob {
if level <= 4 {
tok_cost(&LUMA32_EOB_TOK_LF_QC[qc][base_ctx], (level - 1) as usize)
} else {
tok_cost(&LUMA32_EOB_TOK_LF_QC[qc][base_ctx], 4)
+ base_range_bits(level, hi_range_ctx, false, qc)
}
} else if level <= 4 {
tok_cost(&LUMA32_BASE_TOK_LF_QC[qc][base_ctx], level as usize)
} else {
tok_cost(&LUMA32_BASE_TOK_LF_QC[qc][base_ctx], 5)
+ base_range_bits(level, hi_range_ctx, false, qc)
}
} else if is_eob {
if level <= 2 {
tok_cost(&LUMA32_EOB_TOK_HF_QC[qc][base_ctx], (level - 1) as usize)
} else {
tok_cost(&LUMA32_EOB_TOK_HF_QC[qc][base_ctx], 2)
+ base_range_bits(level, hi_range_ctx, true, qc)
}
} else if level <= 2 {
tok_cost(&LUMA32_BASE_TOK_HF_QC[qc][base_ctx], level as usize)
} else {
tok_cost(&LUMA32_BASE_TOK_HF_QC[qc][base_ctx], 3)
+ base_range_bits(level, hi_range_ctx, true, qc)
};
if level > 0 {
bits += 1.0;
}
bits
}
pub(crate) fn rdoq_luma(
prm: &[f32],
lev: &mut [f32],
qc: usize,
scan: &[u16],
area: usize,
lambda: f64,
) -> f64 {
let n = lev.len();
let mut eob = 0usize;
for (k, &lev) in lev[..n].iter().enumerate() {
if lev != 0.0 {
eob = k;
}
}
if lev[eob] == 0.0 {
return 0.0;
}
let (th1, th2) = (area / 8, area / 4);
let mut levels = vec![0i32; PLVL_BUF];
let ctx_at = |levels: &[i32], k: usize, is_eob: bool| -> (usize, usize) {
if is_eob {
let high_freq = k >= LUMA_HI_TO_LOW;
(
1 + (k > th1) as usize + (k > th2) as usize,
if high_freq { 0 } else { 7 },
)
} else {
let rc = scan[k] as i32;
luma_coeff_context(levels, rc, (rc >> 5) + (rc & 31))
}
};
let store = |levels: &mut [i32], k: usize, mag: i32| {
let rc = scan[k] as i32;
let high_freq = k >= LUMA_HI_TO_LOW;
let limit = if high_freq { 3 } else { 5 };
levels[plvl(rc) as usize] = if mag < limit {
mag
} else {
limit + (mag - limit).min(3)
};
};
let mut total_bits = 0.0f64;
for k in (0..=eob).rev() {
let is_eob = k == eob;
let high_freq = k >= LUMA_HI_TO_LOW;
let a = prm[k] as f64;
let q = lev[k].abs() as u32;
let (bc, hc) = ctx_at(&levels, k, is_eob);
let lo = if is_eob { 1u32 } else { 0u32 };
let hi = q.max(lo);
let mut best_l = hi;
let mut best_cost = f64::INFINITY;
for l in lo..=hi {
let d = (a - l as f64) * (a - l as f64);
let r = luma_level_bits(l, is_eob, bc, hc, high_freq, qc);
let cost = d + lambda * r;
if cost < best_cost {
best_cost = cost;
best_l = l;
}
}
lev[k] = best_l as f32 * lev[k].signum();
store(&mut levels, k, best_l as i32);
total_bits += luma_level_bits(best_l, is_eob, bc, hc, high_freq, qc);
}
loop {
let mut last = None;
for (k, &lev) in lev[..=eob].iter().enumerate() {
if lev != 0.0 {
last = Some(k);
}
}
let Some(p) = last else { break };
if p == 0 {
break;
}
let high_freq = p >= LUMA_HI_TO_LOW;
let (bc, hc) = ctx_at(&levels, p, true);
let a = prm[p] as f64;
let drop_bits = luma_level_bits(lev[p].abs() as u32, true, bc, hc, high_freq, qc);
if lambda * drop_bits > a * a {
lev[p] = 0.0;
let rc = scan[p] as i32;
levels[plvl(rc) as usize] = 0;
total_bits -= drop_bits;
} else {
break;
}
}
total_bits
}
fn chroma_level_bits(
level: u32,
is_eob: bool,
is_dc: bool,
base_ctx: usize,
hi_range_ctx: usize,
qc: usize,
) -> f64 {
let mut bits = if is_dc {
if is_eob {
if level <= 4 {
tok_cost(&CHROMA_EOB_TOK_LF_QC[qc][0], (level - 1) as usize)
} else {
tok_cost(&CHROMA_EOB_TOK_LF_QC[qc][0], 4)
+ chroma_base_range_bits(level, hi_range_ctx, true, qc)
}
} else if level <= 4 {
tok_cost(&CHROMA_BASE_TOK_LF_QC[qc][base_ctx], level as usize)
} else {
tok_cost(&CHROMA_BASE_TOK_LF_QC[qc][base_ctx], 5)
+ chroma_base_range_bits(level, hi_range_ctx, true, qc)
}
} else if is_eob {
if level <= 2 {
tok_cost(&CHROMA_EOB_TOK_HF_QC[qc][base_ctx], (level - 1) as usize)
} else {
tok_cost(&CHROMA_EOB_TOK_HF_QC[qc][base_ctx], 2)
+ chroma_base_range_bits(level, hi_range_ctx, false, qc)
}
} else if level <= 2 {
tok_cost(&CHROMA_BASE_TOK_HF_QC[qc][base_ctx], level as usize)
} else {
tok_cost(&CHROMA_BASE_TOK_HF_QC[qc][base_ctx], 3)
+ chroma_base_range_bits(level, hi_range_ctx, false, qc)
};
if level > 0 {
bits += 1.0;
}
bits
}
fn chroma_base_range_bits(level: u32, hi_range_ctx: usize, is_dc: bool, qc: usize) -> f64 {
let over = level - 3; let bits = if over <= 2 {
tok_cost(&CHROMA_BR_TOK_HF_QC[qc][hi_range_ctx], over as usize)
} else {
tok_cost(&CHROMA_BR_TOK_HF_QC[qc][hi_range_ctx], 3)
};
let max_base_range = if is_dc { 5u32 } else { 6u32 };
if level >= max_base_range {
bits + rice_tail_bits(level - max_base_range)
} else {
bits
}
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn rdoq_chroma(
prm: &[f32],
lev: &mut [f32],
qc: usize,
scan: &[u16],
area: usize,
plane_offset: usize,
lambda: f64,
) -> f64 {
let n = lev.len();
let mut eob = 0usize;
for (k, &l) in lev[..n].iter().enumerate() {
if l != 0.0 {
eob = k;
}
}
if lev[eob] == 0.0 {
return 0.0;
}
let (th1, th2) = (area / 8, area / 4);
let mut levels = vec![0i32; PLVL_BUF];
let ctx_at = |levels: &[i32], k: usize, is_eob: bool, is_dc: bool| -> (usize, usize) {
if is_eob {
if is_dc {
(0, 0)
} else {
(1 + (k > th1) as usize + (k > th2) as usize, 0)
}
} else {
let rc = scan[k] as i32;
chroma_coeff_context(levels, rc, (rc >> 5) + (rc & 31), plane_offset)
}
};
let store = |levels: &mut [i32], k: usize, mag: i32| {
let rc = scan[k] as i32;
levels[plvl(rc) as usize] = mag.min(5);
};
let mut total_bits = 0.0f64;
for k in (0..=eob).rev() {
let is_eob = k == eob;
let is_dc = k == 0;
let a = prm[k] as f64;
let q = lev[k].abs() as u32;
let (bc, hc) = ctx_at(&levels, k, is_eob, is_dc);
let lo = if is_eob { 1u32 } else { 0u32 };
let hi = q.max(lo);
let mut best_l = hi;
let mut best_cost = f64::INFINITY;
for l in lo..=hi {
let d = (a - l as f64) * (a - l as f64);
let r = chroma_level_bits(l, is_eob, is_dc, bc, hc, qc);
let cost = d + lambda * r;
if cost < best_cost {
best_cost = cost;
best_l = l;
}
}
lev[k] = best_l as f32 * lev[k].signum();
store(&mut levels, k, best_l as i32);
total_bits += chroma_level_bits(best_l, is_eob, is_dc, bc, hc, qc);
}
loop {
let mut last = None;
for (k, &l) in lev[..=eob].iter().enumerate() {
if l != 0.0 {
last = Some(k);
}
}
let Some(p) = last else { break };
if p == 0 {
break;
}
let is_dc = p == 0;
let (bc, hc) = ctx_at(&levels, p, true, is_dc);
let a = prm[p] as f64;
let drop_bits = chroma_level_bits(lev[p].abs() as u32, true, is_dc, bc, hc, qc);
if lambda * drop_bits > a * a {
lev[p] = 0.0;
let rc = scan[p] as i32;
levels[plvl(rc) as usize] = 0;
total_bits -= drop_bits;
} else {
break;
}
}
total_bits
}
fn level_at(coeffs: &[Coeff], scan_pos: usize) -> i32 {
coeffs
.iter()
.find(|&&(s, _)| s == scan_pos)
.map(|&(_, l)| l)
.unwrap_or(0)
}
#[rustfmt::skip]
static REORDERED_DIR_Y_MODE: [u8; 8] = [3, 8, 1, 5, 4, 6, 2, 7];
#[rustfmt::skip]
static DEFAULT_MODE_LIST_Y: [u8; 56] = [
17, 45, 3, 10, 24, 31, 38, 52, 15, 19, 43, 47, 1, 5, 8, 12, 22, 26, 29, 33, 36, 40, 50, 54,
16, 18, 44, 46, 2, 4, 9, 11, 23, 25, 30, 32, 37, 39, 51, 53, 14, 20, 42, 48, 0, 6, 7, 13, 21,
27, 28, 34, 35, 41, 49, 55,
];
pub(crate) fn emit_delta_q(enc: &mut RangeEncoder, signaled: i32) {
let a = signaled.unsigned_abs() as usize;
debug_assert!(a <= 6, "delta_q magnitude {a} would hit the escape symbol");
enc.sym_delta_q(a, 7);
if a != 0 {
enc.encode_bypass((signaled < 0) as u32, 1);
}
}
pub(crate) fn maybe_emit_ccso(enc: &mut RangeEncoder) {
if enc.ccso_pending && (enc.ccso_u_enable || enc.ccso_v_enable) {
let (r, c) = enc.ccso_sb_rc;
let cols = enc.ccso_cols;
let grid_u = &enc.ccso_grid;
let idx = r * cols + c;
let u_on = if enc.ccso_u_enable {
if grid_u.is_empty() {
1
} else {
grid_u[idx] as usize
}
} else {
0
};
let v_on = if enc.ccso_v_enable {
if enc.ccso_grid_v.is_empty() {
1
} else {
enc.ccso_grid_v[idx] as usize
}
} else {
0
};
if enc.ccso_u_enable {
let left = if c == 0 {
0
} else if grid_u.is_empty() {
1
} else {
grid_u[idx - 1] as usize
};
let ctx = if c == 0 {
0
} else if left != 0 {
2
} else {
0
};
enc.sym_ccso(1, ctx, u_on);
}
if enc.ccso_v_enable {
let left = if c == 0 {
0
} else if enc.ccso_grid_v.is_empty() {
1
} else {
enc.ccso_grid_v[idx - 1] as usize
};
let ctx = if c == 0 {
0
} else if left != 0 {
2
} else {
0
};
enc.sym_ccso(2, ctx, v_on);
}
enc.ccso_pending = false;
}
}
pub(crate) fn maybe_emit_delta_q(enc: &mut RangeEncoder) {
if enc.delta_q_present && enc.delta_q_pending {
emit_delta_q(enc, enc.delta_q_signaled);
enc.delta_q_pending = false;
}
}
const NO_MIDX: u8 = 0xff;
fn internal_dir_to_ymode(m: usize) -> u8 {
match m {
5 => 1,
6 => 2,
7 => 3,
8 => 4,
9 => 5,
10 => 6,
11 => 7,
_ => 8,
}
}
fn nominal_midx(y_mode: u8) -> u8 {
let p = REORDERED_DIR_Y_MODE
.iter()
.position(|&m| m == y_mode)
.unwrap();
(p * 7 + 3) as u8
}
fn build_dir_list_y(bw4: usize, bh4: usize, lmidx: u8, amidx: u8) -> Vec<u8> {
if bw4 * bh4 <= 2 {
return DEFAULT_MODE_LIST_Y.to_vec();
}
let mut list = [0u8; 56];
let mut mask = 0u64;
let mut ptr = 0usize;
if lmidx != NO_MIDX {
list[ptr] = lmidx;
mask |= 1 << lmidx;
ptr += 1;
}
if amidx != NO_MIDX && (ptr == 0 || amidx != list[0]) {
list[ptr] = amidx;
mask |= 1 << amidx;
ptr += 1;
}
let n_dirs = ptr;
if n_dirs == 0 {
return DEFAULT_MODE_LIST_Y.to_vec();
}
if bw4 * bh4 > 4 {
for i in 1..5i32 {
for n in 0..n_dirs {
let c = list[n] as i32;
for d in [-i, i] {
let dm = ((c + d + 56) % 56) as u8;
if mask & (1 << dm) == 0 {
list[ptr] = dm;
mask |= 1 << dm;
ptr += 1;
}
}
}
}
}
for &fm in DEFAULT_MODE_LIST_Y.iter() {
if mask & (1 << fm) == 0 {
list[ptr] = fm;
ptr += 1;
}
}
list[..ptr].to_vec()
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn encode_intra_modes_dir(
enc: &mut RangeEncoder,
mode_idx: usize,
angle_delta: i8,
has_chroma: bool,
partition_cdf: Option<u32>,
bw4: usize,
bh4: usize,
lmidx: u8,
amidx: u8,
) -> u8 {
if let Some(cdf) = partition_cdf {
enc.bool_do_split(cdf, 0);
}
if enc.mhccp {
let allowed = crate::av2::cfl::is_mhccp_allowed(bw4, bh4, enc.mhccp_ssx, enc.mhccp_ssy);
enc.mhccp_allowed = allowed;
if allowed {
enc.mhccp_size_group = crate::av2::cfl::mhccp_size_group_wh4(bw4, bh4);
if !(bw4 == 16 && bh4 == 16) {
enc.mhccp_use = false; }
} else {
enc.mhccp_use = false;
}
}
maybe_emit_ccso(enc);
maybe_emit_delta_q(enc);
#[allow(clippy::needless_late_init)]
let midx;
if mode_idx < 5 {
let y_ctx = (lmidx != NO_MIDX) as usize + (amidx != NO_MIDX) as usize;
enc.sym_y_set(0);
enc.sym_y_idx0(y_ctx, mode_idx, 7);
midx = NO_MIDX;
} else {
let y_mode = internal_dir_to_ymode(mode_idx);
let target = (nominal_midx(y_mode) as i32 + angle_delta as i32) as u8;
let list = build_dir_list_y(bw4, bh4, lmidx, amidx);
let dir_idx = list
.iter()
.position(|&m| m == target)
.expect("target midx in list");
let y_mode_idx = dir_idx + 5;
let y_set = (y_mode_idx + 3) / 16; let y_ctx = (lmidx != NO_MIDX) as usize + (amidx != NO_MIDX) as usize;
if y_set == 3 {
enc.sym_y_set(3);
} else {
enc.sym_y_set(y_set);
}
if y_set == 0 {
if y_mode_idx < 7 {
enc.sym_y_idx0(y_ctx, y_mode_idx, 7);
} else {
enc.sym_y_idx0(y_ctx, 7, 7);
let i1 = y_mode_idx - 7;
if i1 == 5 {
enc.sym_y_idx1(y_ctx, 5, 5);
} else {
enc.sym_y_idx1(y_ctx, i1, 5);
}
}
} else {
let bits = (y_mode_idx - (y_set * 16 - 3)) as u32;
enc.encode_bypass(bits, 4);
}
midx = target;
}
if has_chroma {
if enc.cfl || (enc.mhccp && enc.mhccp_allowed) {
let isc = crate::av2::cfl::CFL_IS_CDF[enc.cfl_ctx];
if enc.cfl_use {
enc.bool_cfl_is(enc.cfl_ctx, isc as u32, 1);
if enc.mhccp && enc.mhccp_allowed {
if enc.cfl {
enc.bool_cfl_mhccp(
crate::av2::cfl::CFL_MHCCP_SWITCH_CDF as u32,
enc.mhccp_use as u32,
);
}
if !enc.mhccp_use {
enc.bool_cfl_index(crate::av2::cfl::CFL_INDEX_CDF as u32, 0);
}
} else {
enc.bool_cfl_index(crate::av2::cfl::CFL_INDEX_CDF as u32, 0);
}
if enc.mhccp && enc.mhccp_allowed && enc.mhccp_use {
enc.sym_mh_dir(enc.mhccp_size_group as usize, enc.mhccp_dir as usize);
return midx;
}
enc.sym_cfl_sign(enc.cfl_js as usize);
let su = crate::av2::cfl::cfl_sign_u(enc.cfl_js);
let sv = crate::av2::cfl::cfl_sign_v(enc.cfl_js);
if su != 0 {
enc.sym_cfl_alpha(enc.cfl_ctx_u, enc.cfl_mag_u as usize);
}
if sv != 0 {
enc.sym_cfl_alpha(enc.cfl_ctx_v, enc.cfl_mag_v as usize);
}
return midx;
}
enc.bool_cfl_is(enc.cfl_ctx, isc as u32, 0);
}
let uv_ctx = (midx != NO_MIDX) as usize;
let uv_idx = uv_ctx + enc.uv_mode;
emit_uv_mode_idx(enc, uv_ctx, uv_idx);
}
midx
}
fn emit_uv_mode_idx(enc: &mut RangeEncoder, uv_ctx: usize, uv_idx: usize) {
if uv_idx < 7 {
enc.sym_uv_mode(uv_ctx, uv_idx, 7);
} else {
enc.sym_uv_mode(uv_ctx, 7, 7);
enc.encode_bypass((uv_idx - 7) as u32, 3);
}
}
fn encode_intra_modes(
enc: &mut RangeEncoder,
mode_idx: usize,
has_chroma: bool,
lossless: bool,
partition_cdf: Option<u32>,
_cfl_allowed: bool,
) {
if enc.mhccp {
enc.mhccp_allowed = crate::av2::cfl::is_mhccp_allowed(
enc.cur_bw4,
enc.cur_bh4,
enc.mhccp_ssx,
enc.mhccp_ssy,
);
if enc.mhccp_allowed && !enc.mhccp_use {
enc.mhccp_size_group = crate::av2::cfl::mhccp_size_group_wh4(enc.cur_bw4, enc.cur_bh4);
}
if !enc.mhccp_allowed {
enc.mhccp_use = false;
}
} else {
enc.mhccp_allowed = false;
enc.mhccp_use = false;
}
if let Some(cdf) = partition_cdf {
enc.bool_do_split(cdf, 0);
}
maybe_emit_ccso(enc);
maybe_emit_delta_q(enc);
if lossless {
enc.encode_bool(16384, 0);
}
enc.sym_y_set(0); enc.sym_y_idx0(0, mode_idx, 7); if has_chroma {
if lossless {
enc.encode_bool(16384, 0);
}
if enc.cfl || (enc.mhccp && enc.mhccp_allowed) {
let isc = crate::av2::cfl::CFL_IS_CDF[enc.cfl_ctx];
if enc.cfl_use {
enc.bool_cfl_is(enc.cfl_ctx, isc as u32, 1);
if enc.mhccp && enc.mhccp_allowed {
if enc.cfl {
enc.bool_cfl_mhccp(
crate::av2::cfl::CFL_MHCCP_SWITCH_CDF as u32,
enc.mhccp_use as u32,
);
}
if !enc.mhccp_use {
enc.bool_cfl_index(crate::av2::cfl::CFL_INDEX_CDF as u32, 0);
}
} else {
enc.bool_cfl_index(crate::av2::cfl::CFL_INDEX_CDF as u32, 0);
}
if enc.mhccp && enc.mhccp_allowed && enc.mhccp_use {
enc.sym_mh_dir(enc.mhccp_size_group as usize, enc.mhccp_dir as usize);
return;
}
enc.sym_cfl_sign(enc.cfl_js as usize);
let su = crate::av2::cfl::cfl_sign_u(enc.cfl_js);
let sv = crate::av2::cfl::cfl_sign_v(enc.cfl_js);
if su != 0 {
enc.sym_cfl_alpha(enc.cfl_ctx_u, enc.cfl_mag_u as usize);
}
if sv != 0 {
enc.sym_cfl_alpha(enc.cfl_ctx_v, enc.cfl_mag_v as usize);
}
return;
}
enc.bool_cfl_is(enc.cfl_ctx, isc as u32, 0);
}
let uv_idx = enc.uv_mode;
emit_uv_mode_idx(enc, 0, uv_idx);
}
}
type LumaStored = (i32, i32, i32, i32, bool);
fn encode_luma_signs(
enc: &mut RangeEncoder,
_coeffs: &[Coeff],
stored: &[LumaStored],
dc_sign_ctx: usize,
) {
let mut running_avg = 0i32;
for &(_rc, x, y, level, high_freq) in stored {
if level == 0 {
continue;
}
let mag = level.unsigned_abs();
let sign = if level < 0 { 1u32 } else { 0u32 };
if x == 0 && y == 0 {
enc.bool_dc_sign(DC_SIGN_QC[enc.qc][dc_sign_ctx] as u32, sign);
} else {
enc.encode_bypass(sign, 1);
}
let max_base_range = if high_freq { 6 } else { 8 };
if mag >= max_base_range {
running_avg = encode_high_range(enc, mag - max_base_range, running_avg);
}
}
}
type ChromaStored = (i32, bool);
fn encode_chroma_tokens(
enc: &mut RangeEncoder,
coeffs: &[Coeff],
eob: usize,
plane_offset: usize,
) -> Vec<ChromaStored> {
encode_chroma_tokens_scan(enc, coeffs, eob, plane_offset, &SCAN, 1024)
}
fn encode_chroma_tokens_scan(
enc: &mut RangeEncoder,
coeffs: &[Coeff],
eob: usize,
plane_offset: usize,
scan: &[u16],
area: usize,
) -> Vec<ChromaStored> {
encode_chroma_tokens_scan_w(enc, coeffs, eob, plane_offset, scan, area, 5)
}
fn encode_chroma_tokens_scan_w(
enc: &mut RangeEncoder,
coeffs: &[Coeff],
eob: usize,
plane_offset: usize,
scan: &[u16],
area: usize,
bwl: i32,
) -> Vec<ChromaStored> {
let height = area >> bwl;
let t1 = (height << bwl) / 8;
let t2 = (height << bwl) / 4;
let mut levels = vec![0u8; PLVL_BUF];
let mut stored: Vec<ChromaStored> = vec![];
let mask = (1 << bwl) - 1;
for scan_pos in (0..=eob).rev() {
let level = level_at(coeffs, scan_pos);
let rc = scan[scan_pos] as usize;
let row = rc >> bwl;
let col = rc & mask;
let mag = level.unsigned_abs();
let is_eob = scan_pos == eob;
let lf = (row + col) < 1;
let (base_ctx, hi_ctx) = if is_eob {
let c = scan_pos;
let e = if c == 0 {
0
} else if c <= t1 {
1
} else if c <= t2 {
2
} else {
3
};
(e, 0)
} else if lf {
(ctx_lf_2d_chroma_w(&levels, rc, plane_offset, bwl), 0)
} else {
(
ctx_2d_chroma_w(&levels, rc, plane_offset, bwl),
br_ctx_2d_chroma_w(&levels, rc, bwl),
)
};
if std::env::var("CBE").is_ok() && bwl == 4 && plane_offset == 0 && !is_eob && !lf {
eprintln!("CBE pos={} ctx={} mag={}", rc, base_ctx, mag);
}
let sl = encode_chroma4_token(enc, mag, is_eob, base_ctx, hi_ctx, lf);
levels[pidx_w(rc, bwl)] = sl as u8;
stored.push((level, !lf));
}
stored
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn encode_chroma_block_rect(
enc: &mut RangeEncoder,
coeffs: &[Coeff],
skip_cdf: u32,
is_u_plane: bool,
scan: &[u16],
eob_cdf: EobCdf,
eob_hi: u16,
area: usize,
) {
encode_chroma_block_rect_w(
enc, coeffs, skip_cdf, is_u_plane, scan, eob_cdf, eob_hi, area, 5,
)
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn encode_chroma_block_rect_w(
enc: &mut RangeEncoder,
coeffs: &[Coeff],
skip_cdf: u32,
is_u_plane: bool,
scan: &[u16],
eob_cdf: EobCdf,
eob_hi: u16,
area: usize,
bwl: i32,
) {
let nonzero: Vec<Coeff> = coeffs.iter().cloned().filter(|&(_, l)| l != 0).collect();
let skip_tbl: u8 = if is_u_plane { 1 } else { 2 };
if nonzero.is_empty() {
enc.bool_skip_tbl(skip_cdf, 1, skip_tbl);
return;
}
enc.bool_skip_tbl(skip_cdf, 0, skip_tbl);
let eob = nonzero.iter().map(|&(s, _)| s).max().unwrap();
encode_eob(
enc,
eob,
eob_cdf,
eob_hi,
if area <= 128 {
0
} else if area == 256 {
1
} else {
2
},
if area == 32 {
5
} else if area == 64 {
6
} else {
7
},
);
let plane_offset = if is_u_plane { 0 } else { 4 };
let stored = encode_chroma_tokens_scan_w(enc, &nonzero, eob, plane_offset, scan, area, bwl);
encode_chroma_signs(enc, &stored);
}
fn encode_chroma_signs(enc: &mut RangeEncoder, stored: &[ChromaStored]) {
let mut running_avg = 0i32;
for &(level, high_freq) in stored {
if level == 0 {
continue;
}
let mag = level.unsigned_abs();
enc.encode_bypass(if level < 0 { 1 } else { 0 }, 1);
let max_base_range = if high_freq { 6u32 } else { 5u32 };
if std::env::var("SGE").is_ok() {
eprintln!(
"SGE mag={} hf={} maxbr={} hr={}",
mag,
high_freq,
max_base_range,
mag.saturating_sub(max_base_range)
);
}
if mag >= max_base_range {
running_avg = encode_high_range(enc, mag - max_base_range, running_avg);
}
}
}
pub(crate) fn encode_chroma_block(
enc: &mut RangeEncoder,
coeffs: &[Coeff],
skip_cdf: u32,
is_u_plane: bool,
) {
encode_chroma_block_ex(enc, coeffs, skip_cdf, is_u_plane, true)
}
pub(crate) fn encode_chroma_block_ex(
enc: &mut RangeEncoder,
coeffs: &[Coeff],
skip_cdf: u32,
is_u_plane: bool,
u_tx64: bool,
) {
let nonzero: Vec<Coeff> = coeffs.iter().cloned().filter(|&(_, l)| l != 0).collect();
let emit = |enc: &mut RangeEncoder, bit: u32| {
let ctx = skip_cdf as usize;
if !is_u_plane {
enc.bool_v_skip(ctx, bit);
} else if u_tx64 {
enc.bool_u_skip64(ctx, bit);
} else {
enc.bool_u_skip32(ctx, bit);
}
};
if nonzero.is_empty() {
emit(enc, 1);
return;
}
emit(enc, 0);
let eob = nonzero.iter().map(|&(s, _)| s).max().unwrap();
encode_eob(
enc,
eob,
EobCdf::ChrEobBin,
CHROMA_EOB_HI_BIT_QC[enc.qc],
2,
7,
);
let plane_offset = if is_u_plane { 0 } else { 4 };
let stored = encode_chroma_tokens(enc, &nonzero, eob, plane_offset);
encode_chroma_signs(enc, &stored);
}
fn encode_luma32_token(
enc: &mut RangeEncoder,
level: u32,
is_eob: bool,
base_ctx: usize,
hi_range_ctx: usize,
high_freq: bool,
) -> i32 {
let limit = if high_freq { 3 } else { 5 };
if !high_freq {
if is_eob {
if level <= 4 {
enc.sym_luma32_eob_lf(base_ctx, (level - 1) as usize, 4);
} else {
enc.sym_luma32_eob_lf(base_ctx, 4, 4);
encode_luma_base_range(enc, level, hi_range_ctx, high_freq);
}
} else if level <= 4 {
enc.sym_luma32_lf(base_ctx, level as usize);
} else {
enc.sym_luma32_lf(base_ctx, 5);
encode_luma_base_range(enc, level, hi_range_ctx, high_freq);
}
} else if is_eob {
if level <= 2 {
enc.sym_luma32_eob_hf(base_ctx, (level - 1) as usize, 2);
} else {
enc.sym_luma32_eob_hf(base_ctx, 2, 2);
encode_luma_base_range(enc, level, hi_range_ctx, high_freq);
}
} else if level <= 2 {
enc.sym_luma32_hf(base_ctx, level as usize);
} else {
enc.sym_luma32_hf(base_ctx, 3);
encode_luma_base_range(enc, level, hi_range_ctx, high_freq);
}
if (level as i32) < limit {
level as i32
} else {
limit + (level as i32 - limit).min(3)
}
}
fn encode_luma32_tokens(enc: &mut RangeEncoder, coeffs: &[Coeff], eob: usize) -> Vec<LumaStored> {
encode_luma_tokens_scan(enc, coeffs, eob, &SCAN, 1024)
}
fn encode_luma16_token(
enc: &mut RangeEncoder,
level: u32,
is_eob: bool,
base_ctx: usize,
hi_range_ctx: usize,
high_freq: bool,
) -> i32 {
let limit = if high_freq { 3 } else { 5 };
if !high_freq {
if is_eob {
if level <= 4 {
enc.sym_luma16_eob_lf(base_ctx, (level - 1) as usize, 4);
} else {
enc.sym_luma16_eob_lf(base_ctx, 4, 4);
encode_luma_base_range(enc, level, hi_range_ctx, high_freq);
}
} else if level <= 4 {
enc.sym_luma16_lf(base_ctx, level as usize);
} else {
enc.sym_luma16_lf(base_ctx, 5);
encode_luma_base_range(enc, level, hi_range_ctx, high_freq);
}
} else if is_eob {
if level <= 2 {
enc.sym_luma16_eob_hf(base_ctx, (level - 1) as usize, 2);
} else {
enc.sym_luma16_eob_hf(base_ctx, 2, 2);
encode_luma_base_range(enc, level, hi_range_ctx, high_freq);
}
} else if level <= 2 {
enc.sym_luma16_hf(base_ctx, level as usize);
} else {
enc.sym_luma16_hf(base_ctx, 3);
encode_luma_base_range(enc, level, hi_range_ctx, high_freq);
}
if (level as i32) < limit {
level as i32
} else {
limit + (level as i32 - limit).min(3)
}
}
fn encode_luma16_tokens_scan_w(
enc: &mut RangeEncoder,
coeffs: &[Coeff],
eob: usize,
scan: &[u16],
area: usize,
bwl: i32,
) -> Vec<LumaStored> {
let (th1, th2) = (area / 8, area / 4);
let mut levels = vec![0i32; PLVL_BUF];
let mut stored: Vec<LumaStored> = vec![];
let mask = (1 << bwl) - 1;
for scan_pos in (0..=eob).rev() {
let level = level_at(coeffs, scan_pos);
let rc = scan[scan_pos] as i32;
let x = rc >> bwl;
let y = rc & mask;
let mag = level.unsigned_abs();
let is_eob = scan_pos == eob;
let high_freq = if bwl >= 5 {
scan_pos >= LUMA_HI_TO_LOW
} else {
(x + y) >= 4
};
let (base_ctx, hi_range_ctx) = if is_eob {
if eob == 0 {
(0usize, 0usize)
} else {
(
1 + (eob > th1) as usize + (eob > th2) as usize,
if high_freq || eob == 0 { 0 } else { 7 },
)
}
} else {
luma_coeff_context_w(&levels, rc, x + y, bwl)
};
let stored_level = encode_luma16_token(enc, mag, is_eob, base_ctx, hi_range_ctx, high_freq);
levels[plvl_w(rc, bwl) as usize] = stored_level;
stored.push((rc, x, y, level, high_freq));
}
stored
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn encode_luma_leaf_16x16_full(
enc: &mut RangeEncoder,
tu: &[Coeff],
skip_cdf: u32,
dc_sign_ctx: usize,
mode_idx: usize,
has_chroma: bool,
part_cdf: u32,
do_part_cdf: u32,
tx_type_idx: usize,
) -> u32 {
enc.cur_bw4 = 4;
enc.cur_bh4 = 4;
encode_intra_modes(enc, mode_idx, has_chroma, false, Some(part_cdf), false);
enc.bool_txfm_part(do_part_cdf, 0); let nonzero: Vec<Coeff> = tu.iter().cloned().filter(|&(_, l)| l != 0).collect();
if nonzero.is_empty() {
enc.bool_txb_skip(skip_cdf, 1);
return 0;
}
enc.bool_txb_skip(skip_cdf, 0);
let eob = nonzero.iter().map(|&(s, _)| s).max().unwrap();
encode_eob(enc, eob, EobCdf::Eob256, EOB_HI_BIT_QC[enc.qc], 1, 7);
if eob >= 1 {
enc.sym_intra_ext_tx16(tx_type_idx, 6); }
let stored = encode_luma16_tokens_scan_w(enc, &nonzero, eob, &SCAN16, 256, 4);
encode_luma_signs(enc, &nonzero, &stored, dc_sign_ctx);
nonzero
.iter()
.map(|&(_, l)| l.unsigned_abs())
.sum::<u32>()
.min(63)
}
pub(crate) static TXTP_EXT8: [u16; 6] = [17858, 7511, 5804, 3445, 2531, 1233];
fn encode_luma8_token(
enc: &mut RangeEncoder,
level: u32,
is_eob: bool,
base_ctx: usize,
hi_range_ctx: usize,
high_freq: bool,
) -> i32 {
let limit = if high_freq { 3 } else { 5 };
if !high_freq {
if is_eob {
if level <= 4 {
enc.sym_luma8_eob_lf(base_ctx, (level - 1) as usize, 4);
} else {
enc.sym_luma8_eob_lf(base_ctx, 4, 4);
encode_luma_base_range(enc, level, hi_range_ctx, high_freq);
}
} else if level <= 4 {
enc.sym_luma8_lf(base_ctx, level as usize);
} else {
enc.sym_luma8_lf(base_ctx, 5);
encode_luma_base_range(enc, level, hi_range_ctx, high_freq);
}
} else if is_eob {
if level <= 2 {
enc.sym_luma8_eob_hf(base_ctx, (level - 1) as usize, 2);
} else {
enc.sym_luma8_eob_hf(base_ctx, 2, 2);
encode_luma_base_range(enc, level, hi_range_ctx, high_freq);
}
} else if level <= 2 {
enc.sym_luma8_hf(base_ctx, level as usize);
} else {
enc.sym_luma8_hf(base_ctx, 3);
encode_luma_base_range(enc, level, hi_range_ctx, high_freq);
}
if (level as i32) < limit {
level as i32
} else {
limit + (level as i32 - limit).min(3)
}
}
fn encode_luma8_tokens_scan_w(
enc: &mut RangeEncoder,
coeffs: &[Coeff],
eob: usize,
scan: &[u16],
area: usize,
bwl: i32,
) -> Vec<LumaStored> {
let (th1, th2) = (area / 8, area / 4);
let mut levels = vec![0i32; PLVL_BUF];
let mut stored: Vec<LumaStored> = vec![];
let mask = (1 << bwl) - 1;
for scan_pos in (0..=eob).rev() {
let level = level_at(coeffs, scan_pos);
let rc = scan[scan_pos] as i32;
let x = rc >> bwl;
let y = rc & mask;
let mag = level.unsigned_abs();
let is_eob = scan_pos == eob;
let high_freq = if bwl >= 5 {
scan_pos >= LUMA_HI_TO_LOW
} else {
(x + y) >= 4
};
let (base_ctx, hi_range_ctx) = if is_eob {
if eob == 0 {
(0usize, 0usize)
} else {
(
1 + (eob > th1) as usize + (eob > th2) as usize,
if high_freq || eob == 0 { 0 } else { 7 },
)
}
} else {
luma_coeff_context_w(&levels, rc, x + y, bwl)
};
let stored_level = encode_luma8_token(enc, mag, is_eob, base_ctx, hi_range_ctx, high_freq);
levels[plvl_w(rc, bwl) as usize] = stored_level;
stored.push((rc, x, y, level, high_freq));
}
stored
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn encode_luma_leaf_8x8(
enc: &mut RangeEncoder,
tu: &[Coeff],
skip_cdf: u32,
dc_sign_ctx: usize,
mode_idx: usize,
has_chroma: bool,
part_cdf: u32,
do_part_cdf: u32,
tx_type_cdf: Option<(&'static [u16], usize, usize)>, ) -> u32 {
enc.cur_bw4 = 2;
enc.cur_bh4 = 2;
encode_intra_modes(enc, mode_idx, has_chroma, false, Some(part_cdf), false);
enc.bool_txfm_part(do_part_cdf, 0); let nonzero: Vec<Coeff> = tu.iter().cloned().filter(|&(_, l)| l != 0).collect();
if nonzero.is_empty() {
enc.bool_txb_skip(skip_cdf, 1);
return 0;
}
enc.bool_txb_skip(skip_cdf, 0);
let eob = nonzero.iter().map(|&(s, _)| s).max().unwrap();
encode_eob(enc, eob, EobCdf::Eob64Luma, EOB_HI_BIT_QC[enc.qc], 0, 6);
if eob >= 1
&& let Some((cdf, idx, nsym)) = tx_type_cdf
{
enc.encode_symbol(cdf, idx, nsym);
}
let stored = encode_luma8_tokens_scan_w(enc, &nonzero, eob, &SCAN8X8, 64, 3);
encode_luma_signs(enc, &nonzero, &stored, dc_sign_ctx);
nonzero
.iter()
.map(|&(_, l)| l.unsigned_abs())
.sum::<u32>()
.min(63)
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn encode_luma_leaf_rect128(
enc: &mut RangeEncoder,
tu: &[Coeff],
skip_cdf: u32,
dc_sign_ctx: usize,
mode_idx: usize,
has_chroma: bool,
bw4: usize,
bh4: usize,
part_cdf: u32,
do_part_cdf: u32,
scan: &'static [u16],
tx_type_cdf: Option<(&'static [u16], usize, usize)>,
) -> u32 {
enc.cur_bw4 = bw4;
enc.cur_bh4 = bh4;
encode_intra_modes(enc, mode_idx, has_chroma, false, Some(part_cdf), false);
enc.bool_txfm_part(do_part_cdf, 0); let nonzero: Vec<Coeff> = tu.iter().cloned().filter(|&(_, l)| l != 0).collect();
if nonzero.is_empty() {
enc.bool_txb_skip(skip_cdf, 1);
return 0;
}
enc.bool_txb_skip(skip_cdf, 0);
let eob = nonzero.iter().map(|&(s, _)| s).max().unwrap();
encode_eob(enc, eob, EobCdf::Eob128Luma, EOB_HI_BIT_QC[enc.qc], 0, 7);
if eob >= 1
&& let Some((cdf, idx, nsym)) = tx_type_cdf
{
enc.encode_symbol(cdf, idx, nsym);
}
let bwl = (bw4 * 4).trailing_zeros() as i32;
let stored = encode_luma16_tokens_scan_w(enc, &nonzero, eob, scan, 128, bwl);
encode_luma_signs(enc, &nonzero, &stored, dc_sign_ctx);
nonzero
.iter()
.map(|&(_, l)| l.unsigned_abs())
.sum::<u32>()
.min(127)
}
fn encode_luma_tokens_scan(
enc: &mut RangeEncoder,
coeffs: &[Coeff],
eob: usize,
scan: &[u16],
area: usize,
) -> Vec<LumaStored> {
encode_luma_tokens_scan_w(enc, coeffs, eob, scan, area, 5)
}
fn encode_luma_tokens_scan_w(
enc: &mut RangeEncoder,
coeffs: &[Coeff],
eob: usize,
scan: &[u16],
area: usize,
bwl: i32,
) -> Vec<LumaStored> {
let (th1, th2) = (area / 8, area / 4);
let mut levels = vec![0i32; PLVL_BUF];
let mut stored: Vec<LumaStored> = vec![];
let mask = (1 << bwl) - 1;
for scan_pos in (0..=eob).rev() {
let level = level_at(coeffs, scan_pos);
let rc = scan[scan_pos] as i32;
let x = rc >> bwl;
let y = rc & mask;
let mag = level.unsigned_abs();
let is_eob = scan_pos == eob;
let high_freq = if bwl >= 5 {
scan_pos >= LUMA_HI_TO_LOW
} else {
(x + y) >= 4
};
let (base_ctx, hi_range_ctx) = if is_eob {
if eob == 0 {
(0usize, 0usize)
} else {
(
1 + (eob > th1) as usize + (eob > th2) as usize,
if high_freq || eob == 0 { 0 } else { 7 },
)
}
} else {
luma_coeff_context_w(&levels, rc, x + y, bwl)
};
let stored_level = encode_luma32_token(enc, mag, is_eob, base_ctx, hi_range_ctx, high_freq);
levels[plvl_w(rc, bwl) as usize] = stored_level;
stored.push((rc, x, y, level, high_freq));
}
stored
}
pub(crate) fn encode_luma_tu32(
enc: &mut RangeEncoder,
coeffs: &[Coeff],
skip_cdf: u32,
dc_sign_ctx: usize,
) -> u32 {
let nonzero: Vec<Coeff> = coeffs.iter().cloned().filter(|&(_, l)| l != 0).collect();
if nonzero.is_empty() {
enc.bool_txb_skip(skip_cdf, 1);
return 0;
}
enc.bool_txb_skip(skip_cdf, 0);
let eob = nonzero.iter().map(|&(s, _)| s).max().unwrap();
encode_eob(enc, eob, EobCdf::EobBin, EOB_HI_BIT_QC[enc.qc], 2, 7);
let stored = encode_luma32_tokens(enc, &nonzero, eob);
encode_luma_signs(enc, &nonzero, &stored, dc_sign_ctx);
nonzero
.iter()
.map(|&(_, l)| l.unsigned_abs())
.sum::<u32>()
.min(63)
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn encode_luma_tu_rect(
enc: &mut RangeEncoder,
coeffs: &[Coeff],
skip_cdf: u32,
dc_sign_ctx: usize,
scan: &[u16],
eob_cdf: EobCdf,
eob_hi: u16,
area: usize,
) -> u32 {
encode_luma_tu_rect_w(
enc,
coeffs,
skip_cdf,
dc_sign_ctx,
scan,
eob_cdf,
eob_hi,
area,
5,
)
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn encode_luma_tu_rect_w(
enc: &mut RangeEncoder,
coeffs: &[Coeff],
skip_cdf: u32,
dc_sign_ctx: usize,
scan: &[u16],
eob_cdf: EobCdf,
eob_hi: u16,
area: usize,
bwl: i32,
) -> u32 {
let nonzero: Vec<Coeff> = coeffs.iter().cloned().filter(|&(_, l)| l != 0).collect();
if nonzero.is_empty() {
enc.bool_txb_skip(skip_cdf, 1);
return 0;
}
enc.bool_txb_skip(skip_cdf, 0);
let eob = nonzero.iter().map(|&(s, _)| s).max().unwrap();
encode_eob(
enc,
eob,
eob_cdf,
eob_hi,
if area <= 128 {
0
} else if area == 256 {
1
} else {
2
},
if area == 64 { 6 } else { 7 },
);
if eob >= 1 {
enc.sym_tx_short_side(1, 0);
}
let stored = encode_luma_tokens_scan_w(enc, &nonzero, eob, scan, area, bwl);
encode_luma_signs(enc, &nonzero, &stored, dc_sign_ctx);
nonzero
.iter()
.map(|&(_, l)| l.unsigned_abs())
.sum::<u32>()
.min(63)
}
pub(crate) fn encode_luma_block_split(
enc: &mut RangeEncoder,
tus: &[Vec<Coeff>; 4],
skip_cdfs: &[u32; 4],
dc_sign_ctxs: &[usize; 4],
mode_idx: usize,
has_chroma: bool,
part_cdf: u32,
) -> [u32; 4] {
enc.cur_bw4 = 16;
enc.cur_bh4 = 16;
encode_intra_modes(enc, mode_idx, has_chroma, false, Some(part_cdf), false);
enc.bool_txfm_part(TX_SPLIT_64 as u32, 1); enc.sym_tx_part_64(0, 6); let mut cul = [0u32; 4];
for i in 0..4 {
cul[i] = encode_luma_tu32(enc, &tus[i], skip_cdfs[i], dc_sign_ctxs[i]);
}
cul
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn encode_luma_block_split_dir(
enc: &mut RangeEncoder,
tus: &[Vec<Coeff>; 4],
skip_cdfs: &[u32; 4],
dc_sign_ctxs: &[usize; 4],
mode_idx: usize,
angle_delta: i8,
has_chroma: bool,
part_cdf: u32,
lmidx: u8,
amidx: u8,
) -> ([u32; 4], u8) {
let midx = encode_intra_modes_dir(
enc,
mode_idx,
angle_delta,
has_chroma,
Some(part_cdf),
16,
16,
lmidx,
amidx,
);
enc.bool_txfm_part(TX_SPLIT_64 as u32, 1);
enc.sym_tx_part_64(0, 6);
let mut cul = [0u32; 4];
for i in 0..4 {
cul[i] = encode_luma_tu32(enc, &tus[i], skip_cdfs[i], dc_sign_ctxs[i]);
}
(cul, midx)
}
pub(crate) fn encode_luma_block_vert4(
enc: &mut RangeEncoder,
tus: &[Vec<Coeff>; 4],
skip_cdfs: &[u32; 4],
dc_sign_ctxs: &[usize; 4],
mode_idx: usize,
has_chroma: bool,
part_cdf: u32,
) -> [u32; 4] {
enc.cur_bw4 = 16;
enc.cur_bh4 = 16;
encode_intra_modes(enc, mode_idx, has_chroma, false, Some(part_cdf), false);
enc.bool_txfm_part(TX_SPLIT_64 as u32, 1); enc.sym_tx_part_64(4, 6); let mut cul = [0u32; 4];
for i in 0..4 {
cul[i] = encode_luma_tu_rect_w(
enc,
&tus[i],
skip_cdfs[i],
dc_sign_ctxs[i],
&SCAN16X32,
EobCdf::Eob512,
EOB_HI_BIT_QC[enc.qc],
512,
4,
);
}
cul
}
pub(crate) fn encode_luma_block_horz4(
enc: &mut RangeEncoder,
tus: &[Vec<Coeff>; 4],
skip_cdfs: &[u32; 4],
dc_sign_ctxs: &[usize; 4],
mode_idx: usize,
has_chroma: bool,
part_cdf: u32,
) -> [u32; 4] {
encode_intra_modes(enc, mode_idx, has_chroma, false, Some(part_cdf), false);
enc.bool_txfm_part(TX_SPLIT_64 as u32, 1); enc.sym_tx_part_64(3, 6); let mut cul = [0u32; 4];
for i in 0..4 {
cul[i] = encode_luma_tu_rect(
enc,
&tus[i],
skip_cdfs[i],
dc_sign_ctxs[i],
&SCAN32X16,
EobCdf::Eob512,
EOB_HI_BIT_QC[enc.qc],
512,
);
}
cul
}
const TX_DO_PART_64X32: u32 = 16816;
pub(crate) fn encode_luma_leaf_64x32(
enc: &mut RangeEncoder,
tus: &[Vec<Coeff>; 2],
skip_cdfs: &[u32; 2],
dc_sign_ctxs: &[usize; 2],
mode_idx: usize,
has_chroma: bool,
part_cdf: u32,
) -> [u32; 2] {
enc.cur_bw4 = 16;
enc.cur_bh4 = 8;
encode_intra_modes(enc, mode_idx, has_chroma, false, Some(part_cdf), false);
enc.bool_txfm_part(TX_DO_PART_64X32, 1); enc.sym_tx_part_64x32(2, 6); let mut cul = [0u32; 2];
for i in 0..2 {
cul[i] = encode_luma_tu32(enc, &tus[i], skip_cdfs[i], dc_sign_ctxs[i]);
}
cul
}
const TX_DO_PART_32X32: u32 = 17377;
pub(crate) fn encode_luma_leaf_32x64(
enc: &mut RangeEncoder,
tus: &[Vec<Coeff>; 2],
skip_cdfs: &[u32; 2],
dc_sign_ctxs: &[usize; 2],
mode_idx: usize,
has_chroma: bool,
part_cdf: u32,
) -> [u32; 2] {
enc.cur_bw4 = 8;
enc.cur_bh4 = 16;
encode_intra_modes(enc, mode_idx, has_chroma, false, Some(part_cdf), false);
enc.bool_txfm_part(TX_DO_PART_64X32, 1); enc.sym_tx_part_32x64(1, 6); let mut cul = [0u32; 2];
for i in 0..2 {
cul[i] = encode_luma_tu32(enc, &tus[i], skip_cdfs[i], dc_sign_ctxs[i]);
}
cul
}
pub(crate) fn encode_luma_leaf_16x64(
enc: &mut RangeEncoder,
tu: &[Coeff],
skip_cdf: u32,
dc_sign_ctx: usize,
mode_idx: usize,
has_chroma: bool,
part_cdf: u32,
) -> u32 {
enc.cur_bw4 = 4;
enc.cur_bh4 = 16;
encode_intra_modes(enc, mode_idx, has_chroma, false, Some(part_cdf), false);
enc.bool_txfm_part(18958, 0); encode_luma_tu_rect_w(
enc,
tu,
skip_cdf,
dc_sign_ctx,
&SCAN16X32,
EobCdf::Eob512,
EOB_HI_BIT_QC[enc.qc],
512,
4,
)
}
pub(crate) fn encode_luma_leaf_64x16_vert(
enc: &mut RangeEncoder,
tus: &[Vec<Coeff>; 2],
skip_cdfs: &[u32; 2],
dc_sign_ctxs: &[usize; 2],
mode_idx: usize,
has_chroma: bool,
part_cdf: u32,
) -> [u32; 2] {
enc.cur_bw4 = 16;
enc.cur_bh4 = 4;
encode_intra_modes(enc, mode_idx, has_chroma, false, Some(part_cdf), false);
enc.bool_txfm_part(18958, 1);
enc.sym_tx_part_64x16(2, 6);
let mut cul = [0u32; 2];
for i in 0..2 {
cul[i] = encode_luma_tu_rect_long32(
enc,
&tus[i],
skip_cdfs[i],
dc_sign_ctxs[i],
&SCAN32X16,
EobCdf::Eob512,
EOB_HI_BIT_QC[enc.qc],
512,
&[5853, 357, 20],
false,
);
}
cul
}
pub(crate) fn encode_luma_leaf_16x64_horz(
enc: &mut RangeEncoder,
tus: &[Vec<Coeff>; 2],
skip_cdfs: &[u32; 2],
dc_sign_ctxs: &[usize; 2],
mode_idx: usize,
has_chroma: bool,
part_cdf: u32,
) -> [u32; 2] {
enc.cur_bw4 = 4;
enc.cur_bh4 = 16;
encode_intra_modes(enc, mode_idx, has_chroma, false, Some(part_cdf), false);
enc.bool_txfm_part(18958, 1);
enc.sym_tx_part_16x64(1, 6);
let mut cul = [0u32; 2];
for i in 0..2 {
cul[i] = encode_luma_tu_rect_long32_w(
enc,
&tus[i],
skip_cdfs[i],
dc_sign_ctxs[i],
&SCAN16X32,
EobCdf::Eob512,
EOB_HI_BIT_QC[enc.qc],
512,
&[5853, 357, 20],
false,
4,
);
}
cul
}
pub(crate) fn encode_luma_leaf_64x16(
enc: &mut RangeEncoder,
tu: &[Coeff],
skip_cdf: u32,
dc_sign_ctx: usize,
mode_idx: usize,
has_chroma: bool,
part_cdf: u32,
) -> u32 {
enc.cur_bw4 = 16;
enc.cur_bh4 = 4;
encode_intra_modes(enc, mode_idx, has_chroma, false, Some(part_cdf), false);
enc.bool_txfm_part(18958, 0); encode_luma_tu_rect(
enc,
tu,
skip_cdf,
dc_sign_ctx,
&SCAN32X16,
EobCdf::Eob512,
EOB_HI_BIT_QC[enc.qc],
512,
)
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn encode_luma_tu_rect_long32(
enc: &mut RangeEncoder,
coeffs: &[Coeff],
skip_cdf: u32,
dc_sign_ctx: usize,
scan: &[u16],
eob_cdf: EobCdf,
eob_hi: u16,
area: usize,
short_cdf: &[u16; 3],
ctx2: bool,
) -> u32 {
encode_luma_tu_rect_long32_w(
enc,
coeffs,
skip_cdf,
dc_sign_ctx,
scan,
eob_cdf,
eob_hi,
area,
short_cdf,
ctx2,
5,
)
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn encode_luma_tu_rect_long32_w(
enc: &mut RangeEncoder,
coeffs: &[Coeff],
skip_cdf: u32,
dc_sign_ctx: usize,
scan: &[u16],
eob_cdf: EobCdf,
eob_hi: u16,
area: usize,
short_cdf: &[u16; 3],
ctx2: bool,
bwl: i32,
) -> u32 {
let nonzero: Vec<Coeff> = coeffs.iter().cloned().filter(|&(_, l)| l != 0).collect();
if nonzero.is_empty() {
enc.bool_txb_skip(skip_cdf, 1);
return 0;
}
enc.bool_txb_skip(skip_cdf, 0);
let eob = nonzero.iter().map(|&(s, _)| s).max().unwrap();
encode_eob(
enc,
eob,
eob_cdf,
eob_hi,
if area <= 128 {
0
} else if area == 256 {
1
} else {
2
},
if area == 64 { 6 } else { 7 },
);
if eob >= 1 {
enc.bool_txfm_part(32732, 1);
let ss_ctx = if short_cdf[0] == 6068 { 0 } else { 1 };
enc.sym_tx_short_side(ss_ctx, 0);
}
let stored = if ctx2 {
encode_luma16_tokens_scan_w(enc, &nonzero, eob, scan, area, bwl)
} else {
encode_luma_tokens_scan_w(enc, &nonzero, eob, scan, area, bwl)
};
encode_luma_signs(enc, &nonzero, &stored, dc_sign_ctx);
nonzero
.iter()
.map(|&(_, l)| l.unsigned_abs())
.filter(|&a| a > 0)
.count() as u32
}
pub(crate) fn encode_luma_leaf_16x32(
enc: &mut RangeEncoder,
tu: &[Coeff],
skip_cdf: u32,
dc_sign_ctx: usize,
mode_idx: usize,
has_chroma: bool,
part_cdf: u32,
) -> u32 {
enc.cur_bw4 = 4;
enc.cur_bh4 = 8;
encode_intra_modes(enc, mode_idx, has_chroma, false, Some(part_cdf), false);
enc.bool_txfm_part(19451, 0); encode_luma_tu_rect_long32_w(
enc,
tu,
skip_cdf,
dc_sign_ctx,
&SCAN16X32,
EobCdf::Eob512,
EOB_HI_BIT_QC[enc.qc],
512,
&[5853, 357, 20], false,
4,
)
}
pub(crate) fn encode_luma_leaf_32x16(
enc: &mut RangeEncoder,
tu: &[Coeff],
skip_cdf: u32,
dc_sign_ctx: usize,
mode_idx: usize,
has_chroma: bool,
part_cdf: u32,
) -> u32 {
enc.cur_bw4 = 8;
enc.cur_bh4 = 4;
encode_intra_modes(enc, mode_idx, has_chroma, false, Some(part_cdf), false);
enc.bool_txfm_part(19451, 0); encode_luma_tu_rect_long32(
enc,
tu,
skip_cdf,
dc_sign_ctx,
&SCAN32X16,
EobCdf::Eob512,
EOB_HI_BIT_QC[enc.qc],
512,
&[5853, 357, 20], false,
)
}
pub(crate) fn encode_luma_leaf_8x32(
enc: &mut RangeEncoder,
tu: &[Coeff],
skip_cdf: u32,
dc_sign_ctx: usize,
mode_idx: usize,
has_chroma: bool,
part_cdf: u32,
) -> u32 {
enc.cur_bw4 = 2;
enc.cur_bh4 = 8;
encode_intra_modes(enc, mode_idx, has_chroma, false, Some(part_cdf), false);
enc.bool_txfm_part(18958, 0); encode_luma_tu_rect_long32_w(
enc,
tu,
skip_cdf,
dc_sign_ctx,
&SCAN8X32,
EobCdf::Eob256,
EOB_HI_BIT_QC[enc.qc],
256,
&[6068, 608, 20], true,
3, )
}
pub(crate) fn encode_luma_leaf_32x8(
enc: &mut RangeEncoder,
tu: &[Coeff],
skip_cdf: u32,
dc_sign_ctx: usize,
mode_idx: usize,
has_chroma: bool,
part_cdf: u32,
) -> u32 {
enc.cur_bw4 = 8;
enc.cur_bh4 = 2;
encode_intra_modes(enc, mode_idx, has_chroma, false, Some(part_cdf), false);
enc.bool_txfm_part(18958, 0); encode_luma_tu_rect_long32(
enc,
tu,
skip_cdf,
dc_sign_ctx,
&SCAN32X8,
EobCdf::Eob256,
EOB_HI_BIT_QC[enc.qc],
256,
&[6068, 608, 20], true,
)
}
pub(crate) fn encode_luma_leaf_32x32(
enc: &mut RangeEncoder,
tu: &[Coeff],
skip_cdf: u32,
dc_sign_ctx: usize,
mode_idx: usize,
has_chroma: bool,
part_cdf: u32,
) -> u32 {
enc.cur_bw4 = 8;
enc.cur_bh4 = 8;
encode_intra_modes(enc, mode_idx, has_chroma, false, Some(part_cdf), false);
enc.bool_txfm_part(TX_DO_PART_32X32, 0); encode_luma_tu32(enc, tu, skip_cdf, dc_sign_ctx)
}
#[inline]
fn pidx(rc: usize) -> usize {
rc + (rc >> 2) * 4
}
fn pidx_w(rc: usize, bwl: i32) -> usize {
let row = rc >> bwl;
let col = rc & ((1 << bwl) - 1);
row * ((1 << bwl) + 4) + col
}
fn ctx_lf_2d_chroma_w(levels: &[u8], rc: usize, voff: usize, bwl: i32) -> usize {
let b = pidx_w(rc, bwl);
let s = (1 << bwl) + 4;
let mag =
levels[b + 1].min(5) as i32 + levels[b + s].min(5) as i32 + levels[b + s + 1].min(5) as i32;
((mag + 1) >> 1).min(3) as usize + voff
}
fn ctx_2d_chroma_w(levels: &[u8], rc: usize, voff: usize, bwl: i32) -> usize {
let b = pidx_w(rc, bwl);
let s = (1 << bwl) + 4;
let mag =
levels[b + 1].min(3) as i32 + levels[b + s].min(3) as i32 + levels[b + s + 1].min(3) as i32;
((mag + 1) >> 1).min(3) as usize + voff
}
fn br_ctx_2d_chroma_w(levels: &[u8], rc: usize, bwl: i32) -> usize {
let b = pidx_w(rc, bwl);
let s = (1 << bwl) + 4;
let mag =
levels[b + 1].min(5) as i32 + levels[b + s].min(5) as i32 + levels[b + s + 1].min(5) as i32;
((mag + 1) >> 1).min(3) as usize
}
#[inline]
fn ctx_eob4(c: usize) -> usize {
if c == 0 {
0
} else if c <= 2 {
1
} else if c <= 4 {
2
} else {
3
}
}
fn ctx_lf_2d(levels: &[u8], rc: usize) -> usize {
let b = pidx(rc);
let mag = levels[b + 1].min(5) as i32
+ levels[b + 8].min(5) as i32
+ levels[b + 9].min(5) as i32
+ levels[b + 2].min(5) as i32
+ levels[b + 16].min(5) as i32;
let ctx = (mag + 1) >> 1;
let row = (rc >> 2) as i32;
let col = (rc & 3) as i32;
if rc == 0 {
return ctx.min(8) as usize;
}
if row + col < 2 {
return (ctx.min(6) + 9) as usize;
}
(ctx.min(4) + 16) as usize
}
fn ctx_2d(levels: &[u8], rc: usize) -> usize {
let b = pidx(rc);
let mag = levels[b + 1].min(3) as i32
+ levels[b + 8].min(3) as i32
+ levels[b + 9].min(3) as i32
+ levels[b + 2].min(3) as i32
+ levels[b + 16].min(3) as i32;
let ctx = ((mag + 1) >> 1).min(4);
let row = (rc >> 2) as i32;
let col = (rc & 3) as i32;
if row + col < 6 {
ctx as usize
} else if row + col < 8 {
(ctx + 5) as usize
} else {
(ctx + 10) as usize
}
}
fn br_lf_ctx(levels: &[u8], rc: usize) -> usize {
let b = pidx(rc);
let mag =
levels[b + 1].min(5) as i32 + levels[b + 8].min(5) as i32 + levels[b + 9].min(5) as i32;
let m = ((mag + 1) >> 1).min(6);
if rc == 0 {
m as usize
} else {
(m + 7) as usize
}
}
fn br_hf_ctx(levels: &[u8], rc: usize) -> usize {
let b = pidx(rc);
let mag =
levels[b + 1].min(5) as i32 + levels[b + 8].min(5) as i32 + levels[b + 9].min(5) as i32;
(((mag + 1) >> 1).min(6)) as usize
}
fn encode_br4(enc: &mut RangeEncoder, level: u32, ctx: usize, lf: bool) {
let limit = if lf { 5u32 } else { 3u32 };
let over = level - limit;
if lf {
if over <= 2 {
enc.sym_br_lf_q0(ctx, over as usize, 3);
} else {
enc.sym_br_lf_q0(ctx, 3, 3);
}
} else {
if over <= 2 {
enc.sym_br_q0(ctx, over as usize, 3);
} else {
enc.sym_br_q0(ctx, 3, 3);
}
}
}
fn encode_luma4_token(
enc: &mut RangeEncoder,
level: u32,
is_eob: bool,
base_ctx: usize,
hi_ctx: usize,
lf: bool,
) -> i32 {
let limit = if lf { 5 } else { 3 };
if lf {
if is_eob {
if level <= 4 {
enc.sym_base_lf_eob_tx4(base_ctx, (level - 1) as usize, 4);
} else {
enc.sym_base_lf_eob_tx4(base_ctx, 4, 4);
encode_br4(enc, level, hi_ctx, true);
}
} else if level <= 4 {
enc.sym_base_lf_tx4(base_ctx, 0, level as usize);
} else {
enc.sym_base_lf_tx4(base_ctx, 0, 5);
encode_br4(enc, level, hi_ctx, true);
}
} else if is_eob {
if level <= 2 {
enc.sym_base_eob_tx4(base_ctx, (level - 1) as usize, 2);
} else {
enc.sym_base_eob_tx4(base_ctx, 2, 2);
encode_br4(enc, level, hi_ctx, false);
}
} else if level <= 2 {
enc.sym_base_tx4(base_ctx, 0, level as usize);
} else {
enc.sym_base_tx4(base_ctx, 0, 3);
encode_br4(enc, level, hi_ctx, false);
}
if (level as i32) < limit {
level as i32
} else {
limit + (level as i32 - limit).min(3)
}
}
fn encode_eob_4x4(enc: &mut RangeEncoder, eob_count: usize, plctx: usize) {
let (pt, start, obits): (usize, usize, usize) = match eob_count {
1 => (1, 1, 0),
2 => (2, 2, 0),
3 | 4 => (3, 3, 1),
5..=8 => (4, 5, 2),
_ => (5, 9, 3),
};
if pt - 1 <= 3 {
enc.sym_eob16_q0(plctx, pt - 1, 4);
} else {
enc.sym_eob16_q0(plctx, 4, 4);
}
if obits > 0 {
let extra = eob_count - start;
let msb = (extra >> (obits - 1)) & 1;
enc.bool_eob_extra(EOB_HI_BIT_QC[enc.qc] as u32, msb as u32);
for k in (0..obits - 1).rev() {
enc.encode_bypass(((extra >> k) & 1) as u32, 1);
}
}
}
fn encode_luma4_tokens(
enc: &mut RangeEncoder,
coeffs: &[Coeff],
eob_count: usize,
) -> ([LumaStored; 16], usize) {
let mut levels = [0u8; 64];
let mut full = [0i32; 16];
for &(p, l) in coeffs {
full[p] = l;
}
let mut stored = [(0i32, 0i32, 0i32, 0i32, false); 16];
let mut ns = 0usize;
let last = eob_count - 1;
for c in (0..=last).rev() {
let level = full[c];
let rc = SCAN_4X4[c] as usize;
let row = rc >> 2;
let col = rc & 3;
let mag = level.unsigned_abs();
let is_eob = c == last;
let lf = (row + col) < 4;
let (base_ctx, hi_ctx) = if is_eob {
let hctx = if lf { if rc == 0 { 0 } else { 7 } } else { 0 };
(ctx_eob4(c), hctx)
} else if lf {
(ctx_lf_2d(&levels, rc), br_lf_ctx(&levels, rc))
} else {
(ctx_2d(&levels, rc), br_hf_ctx(&levels, rc))
};
let sl = encode_luma4_token(enc, mag, is_eob, base_ctx, hi_ctx, lf);
levels[pidx(rc)] = sl as u8;
stored[ns] = (rc as i32, col as i32, row as i32, level, !lf);
ns += 1;
}
(stored, ns)
}
fn encode_luma4_signs(
enc: &mut RangeEncoder,
_coeffs: &[Coeff],
stored: &[LumaStored],
dc_sign_ctx: usize,
) {
let mut running_avg = 0i32;
for &(_rc, x, y, level, high_freq) in stored {
if level == 0 {
continue;
}
let mag = level.unsigned_abs();
let sign = if level < 0 { 1u32 } else { 0u32 };
if x == 0 && y == 0 {
enc.bool_dc_sign(DC_SIGN_QC[enc.qc][dc_sign_ctx] as u32, sign);
} else {
enc.encode_bypass(sign, 1);
}
let max_base_range = if high_freq { 6 } else { 8 };
if mag >= max_base_range {
running_avg = encode_high_range(enc, mag - max_base_range, running_avg);
}
}
}
pub(crate) fn encode_luma_tu4(
enc: &mut RangeEncoder,
coeffs: &[Coeff],
skip_cdf: u32,
dc_sign_ctx: usize,
) -> u32 {
if coeffs.is_empty() {
enc.bool_txb_skip(skip_cdf, 1);
return 0;
}
enc.bool_txb_skip(skip_cdf, 0);
let eob_count = coeffs.iter().map(|&(s, _)| s).max().unwrap() + 1; encode_eob_4x4(enc, eob_count, 0); let (stored, ns) = encode_luma4_tokens(enc, coeffs, eob_count);
encode_luma4_signs(enc, coeffs, &stored[..ns], dc_sign_ctx);
coeffs
.iter()
.map(|&(_, l)| l.unsigned_abs())
.sum::<u32>()
.min(63)
}
fn ctx_lf_2d_chroma(levels: &[u8], rc: usize, voff: usize) -> usize {
let b = pidx(rc);
let mag =
levels[b + 1].min(5) as i32 + levels[b + 8].min(5) as i32 + levels[b + 9].min(5) as i32;
((mag + 1) >> 1).min(3) as usize + voff
}
fn ctx_2d_chroma(levels: &[u8], rc: usize, voff: usize) -> usize {
let b = pidx(rc);
let mag =
levels[b + 1].min(3) as i32 + levels[b + 8].min(3) as i32 + levels[b + 9].min(3) as i32;
((mag + 1) >> 1).min(3) as usize + voff
}
fn br_ctx_2d_chroma(levels: &[u8], rc: usize) -> usize {
let b = pidx(rc);
let mag =
levels[b + 1].min(5) as i32 + levels[b + 8].min(5) as i32 + levels[b + 9].min(5) as i32;
((mag + 1) >> 1).min(3) as usize
}
fn encode_br_uv(enc: &mut RangeEncoder, level: u32, ctx: usize) {
let over = level - 3;
if over <= 2 {
enc.sym_br_uv(ctx, over as usize, 3);
} else {
enc.sym_br_uv(ctx, 3, 3);
}
}
fn encode_chroma4_token(
enc: &mut RangeEncoder,
level: u32,
is_eob: bool,
base_ctx: usize,
hi_ctx: usize,
lf: bool,
) -> i32 {
if lf {
if is_eob {
if level <= 4 {
enc.sym_base_lf_eob_uv(base_ctx, (level - 1) as usize, 4);
} else {
enc.sym_base_lf_eob_uv(base_ctx, 4, 4);
}
} else if level <= 4 {
enc.sym_base_lf_uv(base_ctx, level as usize);
} else {
enc.sym_base_lf_uv(base_ctx, 5);
}
if level <= 4 { level as i32 } else { 5 } } else {
if is_eob {
if level <= 2 {
enc.sym_base_eob_uv(base_ctx, (level - 1) as usize, 2);
} else {
enc.sym_base_eob_uv(base_ctx, 2, 2);
encode_br_uv(enc, level, hi_ctx);
}
} else if level <= 2 {
enc.sym_base_uv(base_ctx, level as usize);
} else {
enc.sym_base_uv(base_ctx, 3);
encode_br_uv(enc, level, hi_ctx);
}
if (level as i32) <= 2 {
level as i32
} else {
3 + (level as i32 - 3).min(3)
}
}
}
pub(crate) fn encode_chroma_tu4(
enc: &mut RangeEncoder,
coeffs: &[Coeff],
skip_cdf: u32,
plane_v: bool,
) -> u32 {
if coeffs.is_empty() {
enc.bool_txb_skip(skip_cdf, 1);
return 0;
}
enc.bool_txb_skip(skip_cdf, 0);
let eob_count = coeffs.iter().map(|&(s, _)| s).max().unwrap() + 1;
encode_eob_4x4(enc, eob_count, 2); let voff = if plane_v { 4 } else { 0 };
let mut levels = [0u8; 64];
let mut full = [0i32; 16];
for &(p, l) in coeffs {
full[p] = l;
}
let mut stored = [(0i32, 0i32, 0i32, 0i32, false); 16];
let mut ns = 0usize;
let last = eob_count - 1;
for c in (0..=last).rev() {
let level = full[c];
let rc = SCAN_4X4[c] as usize;
let row = rc >> 2;
let col = rc & 3;
let mag = level.unsigned_abs();
let is_eob = c == last;
let lf = (row + col) < 1; let (base_ctx, hi_ctx) = if is_eob {
(ctx_eob4(c), 0)
} else if lf {
(ctx_lf_2d_chroma(&levels, rc, voff), 0)
} else {
(
ctx_2d_chroma(&levels, rc, voff),
br_ctx_2d_chroma(&levels, rc),
)
};
let sl = encode_chroma4_token(enc, mag, is_eob, base_ctx, hi_ctx, lf);
levels[pidx(rc)] = sl as u8;
stored[ns] = (rc as i32, col as i32, row as i32, level, !lf);
ns += 1;
}
let mut running_avg = 0i32;
for &(_, _, _, level, high_freq) in &stored[..ns] {
if level == 0 {
continue;
}
let mag = level.unsigned_abs();
enc.encode_bypass(if level < 0 { 1 } else { 0 }, 1);
let max_base_range = if high_freq { 6 } else { 5 };
if mag >= max_base_range {
running_avg = encode_high_range(enc, mag - max_base_range, running_avg);
}
}
coeffs
.iter()
.map(|&(_, l)| l.unsigned_abs())
.sum::<u32>()
.min(63)
}
pub(crate) static SCAN4X4_LOSSY: [u16; 16] = [0, 1, 4, 2, 5, 8, 3, 6, 9, 12, 7, 10, 13, 11, 14, 15];
pub(crate) static SCAN4X4_LOSSY_PACKED: [u16; 16] =
[0, 32, 1, 64, 33, 2, 96, 65, 34, 3, 97, 66, 35, 98, 67, 99];
pub(crate) fn encode_chroma_tu4_scan(
enc: &mut RangeEncoder,
coeffs: &[Coeff],
skip_cdf: u32,
plane_v: bool,
scan: &[u16],
skip_ctx: usize,
) -> u32 {
if coeffs.is_empty() {
enc.bool_txb_skip_tx4_ctx(skip_cdf, 1, plane_v, skip_ctx);
return 0;
}
enc.bool_txb_skip_tx4_ctx(skip_cdf, 0, plane_v, skip_ctx);
let eob_count = coeffs.iter().map(|&(s, _)| s).max().unwrap() + 1;
encode_eob_4x4(enc, eob_count, 2);
let voff = if plane_v { 4 } else { 0 };
let mut levels = [0u8; 64];
let mut full = [0i32; 16];
for &(p, l) in coeffs {
full[p] = l;
}
let mut stored = [(0i32, 0i32, 0i32, 0i32, false); 16];
let mut ns = 0usize;
let last = eob_count - 1;
for c in (0..=last).rev() {
let level = full[c];
let rc = scan[c] as usize;
let row = rc >> 2;
let col = rc & 3;
let mag = level.unsigned_abs();
let is_eob = c == last;
let lf = (row + col) < 1;
let (base_ctx, hi_ctx) = if is_eob {
(ctx_eob4(c), 0)
} else if lf {
(ctx_lf_2d_chroma(&levels, rc, voff), 0)
} else {
(
ctx_2d_chroma(&levels, rc, voff),
br_ctx_2d_chroma(&levels, rc),
)
};
let sl = encode_chroma4_token(enc, mag, is_eob, base_ctx, hi_ctx, lf);
levels[pidx(rc)] = sl as u8;
stored[ns] = (rc as i32, col as i32, row as i32, level, !lf);
ns += 1;
}
let mut running_avg = 0i32;
for &(_, _, _, level, high_freq) in &stored[..ns] {
if level == 0 {
continue;
}
let mag = level.unsigned_abs();
enc.encode_bypass(if level < 0 { 1 } else { 0 }, 1);
let max_base_range = if high_freq { 6 } else { 5 };
if mag >= max_base_range {
running_avg = encode_high_range(enc, mag - max_base_range, running_avg);
}
}
coeffs
.iter()
.map(|&(_, l)| l.unsigned_abs())
.sum::<u32>()
.min(63)
}
pub(crate) fn encode_lossless_luma_sb(
enc: &mut RangeEncoder,
tus: &[Vec<Coeff>],
skip_cdfs: &[u32],
dc_sign_ctxs: &[usize],
mode_idx: usize,
has_chroma: bool,
partition_cdf: Option<u32>,
) {
encode_intra_modes(enc, mode_idx, has_chroma, true, partition_cdf, false);
for (i, tu) in tus.iter().enumerate() {
encode_luma_tu4(enc, tu, skip_cdfs[i], dc_sign_ctxs[i]);
}
}