Refactor av1enc for strict Clippy checks

This commit is contained in:
Dylan M. Taylor
2026-10-28 06:09:21 +00:00
parent 7c27d88030
commit 8e67bfce47
6 changed files with 121 additions and 49 deletions
+9 -1
View File
@@ -2,7 +2,15 @@
//! init_coeff_cdfs that its syntax uses). Layout as in filmcraft-av1: each innermost array
//! holds N cumulative values (the last is 32768) plus the adaptation counter.
use crate::tables::*;
use crate::tables::{
DEFAULT_ANGLE_DELTA_CDF, DEFAULT_COEFF_BASE_CDF, DEFAULT_COEFF_BASE_EOB_CDF, DEFAULT_COEFF_BR_CDF, DEFAULT_DC_SIGN_CDF, DEFAULT_DRL_MODE_CDF,
DEFAULT_EOB_EXTRA_CDF, DEFAULT_EOB_PT_16_CDF, DEFAULT_EOB_PT_32_CDF, DEFAULT_EOB_PT_64_CDF, DEFAULT_EOB_PT_128_CDF, DEFAULT_EOB_PT_256_CDF,
DEFAULT_EOB_PT_512_CDF, DEFAULT_EOB_PT_1024_CDF, DEFAULT_INTER_TX_TYPE_SET3_CDF, DEFAULT_INTRA_TX_TYPE_SET2_CDF, DEFAULT_IS_INTER_CDF, DEFAULT_MV_BIT_CDF,
DEFAULT_MV_CLASS_CDF, DEFAULT_MV_CLASS0_BIT_CDF, DEFAULT_MV_CLASS0_FR_CDF, DEFAULT_MV_FR_CDF, DEFAULT_MV_JOINT_CDF, DEFAULT_MV_SIGN_CDF,
DEFAULT_NEW_MV_CDF, DEFAULT_PARTITION_W8_CDF, DEFAULT_PARTITION_W16_CDF, DEFAULT_PARTITION_W32_CDF, DEFAULT_PARTITION_W64_CDF, DEFAULT_REF_MV_CDF,
DEFAULT_SINGLE_REF_CDF, DEFAULT_SKIP_CDF, DEFAULT_TXB_SKIP_CDF, DEFAULT_UV_MODE_CFL_ALLOWED_CDF, DEFAULT_UV_MODE_CFL_NOT_ALLOWED_CDF, DEFAULT_Y_MODE_CDF,
DEFAULT_ZERO_MV_CDF,
};
#[derive(Clone)]
pub(crate) struct Cdfs {
+30 -9
View File
@@ -3,8 +3,12 @@
//! processes, so the reconstruction built here is exactly what a decoder produces; the syntax
//! is written afterwards by `writer.rs`.
use crate::pred::*;
use crate::tables::*;
use crate::pred::{INTRA_MODES_USED, InterBlock, IntraEdge, Plane, edges, predict_inter, predict_intra, subpel_plane};
use crate::tables::{
AC_QLOOKUP, BLOCK_8X8, BLOCK_64X64, DC_PRED, DC_QLOOKUP, DCT_DCT, DEFAULT_SCAN_4X4, DEFAULT_SCAN_8X8, DEFAULT_SCAN_16X16, DEFAULT_SCAN_32X32, MODE_TO_TXFM,
NEWMV, NUM_4X4_BLOCKS_WIDE, PARTITION_SPLIT, PARTITION_SUBSIZE, TX_4X4, TX_8X8, TX_16X16, TX_32X32, TX_64X64, TX_SET_DCTONLY, TX_SET_INTER_3,
TX_SET_INTRA_2, TX_SIZE_SQR_UP, TX_TYPE_IN_SET_INTER, TX_TYPE_IN_SET_INTRA,
};
use crate::transform::{forward_2d, inverse_2d};
/// Decisions for one coded block.
@@ -100,6 +104,17 @@ pub(crate) fn intra_uv_tx_type(uv_mode: usize, uv_tx: usize) -> usize {
if tx_in_set(tx_set(uv_tx, false), false, t) { t } else { DCT_DCT }
}
/// Geometry and coding mode of one square transform block.
#[derive(Clone, Copy)]
struct TransformBlock {
plane: usize,
x: usize,
y: usize,
log2: u32,
tx_type: usize,
intra: bool,
}
struct TxResult {
levels: Vec<i32>,
nonzero: bool,
@@ -362,7 +377,7 @@ impl<'a> Decider<'a> {
types.push(alt);
}
for &t in &types {
let (res, recon) = self.try_tx(0, c * 4, r * 4, log2, t, &pred[..n * n], true);
let (res, recon) = self.try_tx(TransformBlock { plane: 0, x: c * 4, y: r * 4, log2, tx_type: t, intra: true }, &pred[..n * n]);
let type_bits = if !res.nonzero || tx_set(tx_y, false) == TX_SET_DCTONLY {
0.0
} else if t == DCT_DCT {
@@ -422,7 +437,7 @@ impl<'a> Decider<'a> {
let uv_type = intra_uv_tx_type(uv_mode, uv_tx);
let mut code_uv = |i: usize| {
predict_intra(&ced[i], &ce[i], uv_mode, &mut pred);
let t = self.code_tx(1 + i, c * 2, r * 2, clog2, uv_type, &pred[..cn * cn], true);
let t = self.code_tx(TransformBlock { plane: 1 + i, x: c * 2, y: r * 2, log2: clog2, tx_type: uv_type, intra: true }, &pred[..cn * cn]);
self.mark_decoded(1 + i, r, c, n4);
t
};
@@ -450,13 +465,17 @@ impl<'a> Decider<'a> {
let (vw, vh) = self.g.visible(p);
let pn = n >> s;
let (x, y) = ((c * 4) >> s, (r * 4) >> s);
predict_inter(&refr.planes[p], vw as i32 - 1, vh as i32 - 1, x, y, pn, pn, mv, s, self.bd, &mut pred[..pn * pn]);
predict_inter(
&refr.planes[p],
&InterBlock { last_x: vw as i32 - 1, last_y: vh as i32 - 1, x, y, width: pn, height: pn, mv, subsampling: s, bit_depth: self.bd },
&mut pred[..pn * pn],
);
if bsize == BLOCK_64X64 {
// coded as a skip block: the prediction is the reconstruction
dist += self.sse(p, x, y, pn, &pred[..pn * pn]);
self.put(p, x, y, pn, &pred[..pn * pn]);
} else {
let t = self.code_tx(p, x, y, log2 - s as u32, DCT_DCT, &pred[..pn * pn], false);
let t = self.code_tx(TransformBlock { plane: p, x, y, log2: log2 - s as u32, tx_type: DCT_DCT, intra: false }, &pred[..pn * pn]);
dist += t.dist;
tx.push(t);
}
@@ -771,8 +790,9 @@ impl<'a> Decider<'a> {
/// Transform, quantise and reconstruct one square transform block of `plane` at (x, y)
/// over the prediction `pred`; the reconstruction is written to `rec`.
fn code_tx(&mut self, p: usize, x: usize, y: usize, log2: u32, tx_type: usize, pred: &[u16], intra: bool) -> TxResult {
let (res, recon) = self.try_tx(p, x, y, log2, tx_type, pred, intra);
fn code_tx(&mut self, block: TransformBlock, pred: &[u16]) -> TxResult {
let TransformBlock { plane: p, x, y, log2, .. } = block;
let (res, recon) = self.try_tx(block, pred);
let n = 1usize << log2;
self.put(p, x, y, n, recon.as_deref().unwrap_or(pred));
res
@@ -780,7 +800,8 @@ impl<'a> Decider<'a> {
/// Transform and quantise one block; returns the result and its reconstruction (None: the
/// prediction) without writing it.
fn try_tx(&self, p: usize, x: usize, y: usize, log2: u32, tx_type: usize, pred: &[u16], intra: bool) -> (TxResult, Option<Vec<u16>>) {
fn try_tx(&self, block: TransformBlock, pred: &[u16]) -> (TxResult, Option<Vec<u16>>) {
let TransformBlock { plane: p, x, y, log2, tx_type, intra } = block;
let n = 1usize << log2;
let tx_sz = tx_size_for(log2);
let bd = self.bd;
+17 -5
View File
@@ -3,7 +3,7 @@
//! is 0 in the frames this encoder writes.
use crate::pred::Plane;
use crate::tables::*;
use crate::tables::{MAX_LOOP_FILTER, NUM_4X4_BLOCKS_HIGH, NUM_4X4_BLOCKS_WIDE, SUBSAMPLED_SIZE, TX_HEIGHT, TX_WIDTH};
/// Mode info the loop filter reads (per 4x4 luma unit, row stride `mi_cols`), and the
/// transform size per 4x4 unit of each plane (`LoopfilterTxSizes`, row stride `mi_cols + 32`).
@@ -39,7 +39,7 @@ pub(crate) fn loop_filter(planes: &mut [Plane; 3], info: &LfInfo, level: [u32; 4
}
let mut col = 0;
while col < info.mi_cols {
edge(pl, info, level, bit_depth, plane, pass, row, col);
edge(pl, info, level, bit_depth, plane, pass, (row, col));
col += step;
}
row += step;
@@ -48,7 +48,8 @@ pub(crate) fn loop_filter(planes: &mut [Plane; 3], info: &LfInfo, level: [u32; 4
}
}
fn edge(pl: &mut Plane, info: &LfInfo, level: [u32; 4], bd: u32, plane: usize, pass: usize, row: usize, col: usize) {
fn edge(pl: &mut Plane, info: &LfInfo, level: [u32; 4], bd: u32, plane: usize, pass: usize, position: (usize, usize)) {
let (row, col) = position;
let s = (plane > 0) as usize;
let (dx, dy) = if pass == 0 { (1usize, 0usize) } else { (0, 1) };
let x = col * 4;
@@ -88,13 +89,24 @@ fn edge(pl: &mut Plane, info: &LfInfo, level: [u32; 4], bd: u32, plane: usize, p
let limit = lvl.max(1);
let blimit = 2 * (lvl + 2) + limit;
let thresh = lvl >> 4;
let strength = FilterStrength { limit, blimit, thresh };
for k in 0..4 {
sample_filter(pl, xp + dy * k, yp + dx * k, plane, limit, blimit, thresh, dx as isize, dy as isize, filter_size, bd);
sample_filter(pl, (xp + dy * k, yp + dx * k), plane, &strength, (dx as isize, dy as isize), filter_size, bd);
}
}
/// Thresholds derived from the loop-filter level (spec 7.14.4).
struct FilterStrength {
limit: i32,
blimit: i32,
thresh: i32,
}
#[inline]
fn sample_filter(pl: &mut Plane, x: usize, y: usize, plane: usize, limit: i32, blimit: i32, thresh: i32, dx: isize, dy: isize, filter_size: usize, bd: u32) {
fn sample_filter(pl: &mut Plane, position: (usize, usize), plane: usize, strength: &FilterStrength, direction: (isize, isize), filter_size: usize, bd: u32) {
let (x, y) = position;
let (dx, dy) = direction;
let FilterStrength { limit, blimit, thresh } = *strength;
let stride = pl.stride as isize;
let step = dy * stride + dx;
let base = y as isize * stride + x as isize;
+23 -15
View File
@@ -2,7 +2,10 @@
//! modes plus V_PRED / H_PRED without edge filtering, 7.11.3 block inter prediction without
//! reference scaling) so that the encoder predicts exactly like a decoder.
use crate::tables::*;
use crate::tables::{
DC_PRED, EIGHTTAP, H_PRED, PAETH_PRED, SM_WEIGHTS_TX_4X4, SM_WEIGHTS_TX_8X8, SM_WEIGHTS_TX_16X16, SM_WEIGHTS_TX_32X32, SMOOTH_H_PRED, SMOOTH_PRED,
SMOOTH_V_PRED, SUBPEL_FILTERS, V_PRED,
};
use crate::transform::round2;
/// A plane buffer (padded to whole superblocks).
@@ -184,19 +187,20 @@ pub(crate) fn predict_intra(ed: &Edges, e: &IntraEdge, mode: usize, pred: &mut [
/// final rounding is the identity) of the `w x h` block at plane position (x, y) displaced by
/// `mv` (1/8 luma sample units, [row, col]). `last_x` / `last_y` are the largest sample
/// coordinates of the reference plane; the result goes to `pred` (row stride `w`).
pub(crate) fn predict_inter(
refp: &Plane,
last_x: i32,
last_y: i32,
x: usize,
y: usize,
w: usize,
h: usize,
mv: [i32; 2],
ss: usize,
bit_depth: u32,
pred: &mut [u16],
) {
pub(crate) struct InterBlock {
pub last_x: i32,
pub last_y: i32,
pub x: usize,
pub y: usize,
pub width: usize,
pub height: usize,
pub mv: [i32; 2],
pub subsampling: usize,
pub bit_depth: u32,
}
pub(crate) fn predict_inter(refp: &Plane, block: &InterBlock, pred: &mut [u16]) {
let InterBlock { last_x, last_y, x, y, width: w, height: h, mv, subsampling: ss, bit_depth } = *block;
// positions in 1/16 sample units ((startX >> 6) & 15 is the filter phase)
let px = ((x as i32) << 4) + ((2 * mv[1]) >> ss);
let py = ((y as i32) << 4) + ((2 * mv[0]) >> ss);
@@ -340,7 +344,11 @@ mod tests {
for (bx, by) in [(0i32, 0i32), (8, 8), (24, 16), (-5, 20), (30, -3)] {
let mut pred = vec![0u16; 64];
let mv = [by * 8 + fy as i32 / 2, bx * 8 + fx as i32 / 2];
predict_inter(&p, w as i32 - 1, h as i32 - 1, 0, 0, 8, 8, mv, 0, 8, &mut pred);
predict_inter(
&p,
&InterBlock { last_x: w as i32 - 1, last_y: h as i32 - 1, x: 0, y: 0, width: 8, height: 8, mv, subsampling: 0, bit_depth: 8 },
&mut pred,
);
for r in 0..8 {
for c in 0..8 {
let (x, y) = ((bx + c).clamp(0, w as i32 - 1), (by + r).clamp(0, h as i32 - 1));
+12 -1
View File
@@ -4,7 +4,7 @@
use std::sync::OnceLock;
use crate::tables::*;
use crate::tables::{ADST_ADST, ADST_DCT, COS128_LOOKUP, DCT_ADST, DCT_DCT, TRANSFORM_ROW_SHIFT, TX_WIDTH_LOG2};
#[inline(always)]
fn round2_64(x: i64, n: u32) -> i32 {
@@ -71,6 +71,12 @@ fn inverse_dct(t: &mut [i32], n: u32, r: u32) {
for i in 0..len {
t[i] = copy[brev(n, i)];
}
inverse_dct_initial_stages(t, n, r);
inverse_dct_final_stages(t, n, r);
}
/// Rotate the high-frequency branches before the four-point core.
fn inverse_dct_initial_stages(t: &mut [i32], n: u32, r: u32) {
if n >= 5 {
for i in 0..8 {
bf(t, 16 + i, 31 - i, 6 + ((brev(3, 7 - i) as i32) << 3), false);
@@ -103,6 +109,10 @@ fn inverse_dct(t: &mut [i32], n: u32, r: u32) {
}
}
}
}
/// Evaluate the four-point core and merge progressively larger branches.
fn inverse_dct_final_stages(t: &mut [i32], n: u32, r: u32) {
for i in 0..2 {
bf(t, 2 * i, 2 * i + 1, 32 + 16 * i as i32, i == 0);
}
@@ -454,6 +464,7 @@ pub(crate) fn forward_2d(residual: &[i32], out: &mut [f32], n: usize, tx_type: u
#[cfg(test)]
mod tests {
use super::*;
use crate::tables::{TX_4X4, TX_8X8, TX_16X16, TX_32X32};
/// forward (float) then the normative inverse reproduces the residual: the forward basis
/// and scale match the decoder's inverse transforms for every supported size and type.
+30 -18
View File
@@ -8,7 +8,15 @@ use crate::cdf::Cdfs;
use crate::decide::{FrameGeom, Leaf, Node, intra_uv_tx_type, scan_for, tx_in_set, tx_set, tx_size_for};
use crate::loopfilter::LfInfo;
use crate::symbol::SymbolWriter;
use crate::tables::*;
use crate::tables::{
ADST_ADST, ADST_DCT, ALTREF_FRAME, ALTREF2_FRAME, BLOCK_8X8, BLOCK_64X64, BR_CDF_SIZE, BWDREF_FRAME, CLASS0_SIZE, COEFF_BASE_CTX_OFFSET, COEFF_BASE_RANGE,
D67_PRED, DC_PRED, DCT_ADST, DCT_DCT, DEFAULT_INTRA_FRAME_Y_MODE_CDF, GLOBALMV, GOLDEN_FRAME, INTRA_FRAME, INTRA_MODE_CONTEXT, LAST_FRAME, LAST2_FRAME,
LAST3_FRAME, MAG_REF_OFFSET_WITH_TX_CLASS, MAX_ANGLE_DELTA, MAX_REF_MV_STACK_SIZE, MI_HEIGHT_LOG2, MI_WIDTH_LOG2, MV_BORDER, MV_CLASS_0, NEARESTMV, NEARMV,
NEWMV, NUM_4X4_BLOCKS_HIGH, NUM_4X4_BLOCKS_WIDE, NUM_BASE_LEVELS, PARTITION_HORZ, PARTITION_HORZ_4, PARTITION_HORZ_A, PARTITION_HORZ_B, PARTITION_NONE,
PARTITION_SPLIT, PARTITION_SUBSIZE, PARTITION_VERT, PARTITION_VERT_4, PARTITION_VERT_A, PARTITION_VERT_B, REF_CAT_LEVEL, SIG_REF_DIFF_OFFSET, SIZE_GROUP,
SUBSAMPLED_SIZE, TX_32X32, TX_CLASS_2D, TX_HEIGHT, TX_HEIGHT_LOG2, TX_SIZE_SQR, TX_SIZE_SQR_UP, TX_TYPE_INTER_INV_SET3, TX_TYPE_INTRA_INV_SET2, TX_WIDTH,
TX_WIDTH_LOG2, V_PRED,
};
type MvP = [i32; 2];
@@ -455,23 +463,7 @@ impl<'a> TileWriter<'a> {
}
} else {
if plane == 0 {
// transform_type( )
let set = tx_set(tx_sz, b.is_inter);
let t = b.tx_type_y;
if set > 0 && self.qidx > 0 {
let sqr = TX_SIZE_SQR[tx_sz] as usize;
if b.is_inter {
// The decision only picks types of this set (DCT_DCT otherwise).
let s = TX_TYPE_INTER_INV_SET3.iter().position(|&v| v as usize == t).unwrap_or_default();
self.sw.symbol(s, &mut self.cdf.inter_tx_type_set3[sqr]);
} else {
let s = TX_TYPE_INTRA_INV_SET2.iter().position(|&v| v as usize == t).unwrap_or_default();
self.sw.symbol(s, &mut self.cdf.intra_tx_type_set2[sqr][b.y_mode]);
}
} else {
assert_eq!(t, DCT_DCT);
}
self.set_tx_types(x4, y4, tx_sz, t);
self.write_transform_type(x4, y4, tx_sz, b);
}
let plane_tx_type = self.compute_tx_type(plane, tx_sz, x4, y4, b);
debug_assert!(plane_tx_type == DCT_DCT || matches!(plane_tx_type, ADST_DCT | DCT_ADST | ADST_ADST));
@@ -571,6 +563,26 @@ impl<'a> TileWriter<'a> {
}
}
fn write_transform_type(&mut self, x4: usize, y4: usize, tx_sz: usize, b: &Leaf) {
// transform_type( )
let set = tx_set(tx_sz, b.is_inter);
let t = b.tx_type_y;
if set > 0 && self.qidx > 0 {
let sqr = TX_SIZE_SQR[tx_sz] as usize;
if b.is_inter {
// The decision only picks types of this set (DCT_DCT otherwise).
let s = TX_TYPE_INTER_INV_SET3.iter().position(|&v| v as usize == t).unwrap_or_default();
self.sw.symbol(s, &mut self.cdf.inter_tx_type_set3[sqr]);
} else {
let s = TX_TYPE_INTRA_INV_SET2.iter().position(|&v| v as usize == t).unwrap_or_default();
self.sw.symbol(s, &mut self.cdf.intra_tx_type_set2[sqr][b.y_mode]);
}
} else {
assert_eq!(t, DCT_DCT);
}
self.set_tx_types(x4, y4, tx_sz, t);
}
fn set_tx_types(&mut self, x4: usize, y4: usize, tx_sz: usize, t: usize) {
for i in 0..(TX_WIDTH[tx_sz] as usize >> 2) {
for j in 0..(TX_HEIGHT[tx_sz] as usize >> 2) {