use std::cell::RefCell;
#[derive(Default, Clone)]
pub struct Plane {
pub px: Vec<i32>,
pub w: usize,
pub h: usize,
pub stride: usize,
}
impl Plane {
pub(crate) fn alloc(w: usize, h: usize) -> Self {
let stride = w;
Plane { px: vec![0i32; stride * h.max(1)], w, h, stride }
}
pub(crate) fn alloc_padded(vis_w: usize, vis_h: usize, sb: usize) -> Self {
let pw = vis_w.div_ceil(sb) * sb;
let ph = vis_h.div_ceil(sb) * sb;
Plane { px: vec![0i32; pw * ph.max(1)], w: pw, h: ph, stride: pw }
}
#[inline]
#[track_caller]
pub fn at(&self, x: usize, y: usize) -> i32 {
let i = y * self.stride + x;
if std::env::var("ATDBG").is_ok() && i >= self.px.len() {
crate::dlog!("[ATDBG] Plane::at OOB x={x} y={y} w={} h={} len={} caller={}", self.w, self.h, self.px.len(), std::panic::Location::caller());
}
self.px.get(i).copied().unwrap_or(0)
}
#[inline]
pub fn set_at(&mut self, x: usize, y: usize, v: i32) {
let i = y * self.stride + x;
if let Some(p) = self.px.get_mut(i) {
*p = v;
}
}
#[inline]
pub fn set_row(&mut self, x: usize, y: usize, src: &[i32]) {
let base = y * self.stride + x;
let n = src.len().min(self.px.len().saturating_sub(base));
if n > 0 {
self.px[base..base + n].copy_from_slice(&src[..n]);
}
}
}
#[derive(Default)]
pub struct Frame {
pub pl: [Plane; 3],
pub yac: u8,
pub bitdepth_max: i32,
pub edge_filter: bool,
pub ibp: bool,
pub mi_coded: Vec<bool>,
pub mi_coded_sb: (usize, usize),
pub joint: Vec<u8>,
pub iw4: usize,
pub ih4: usize,
pub db_lw: Vec<u8>,
pub db_lh: Vec<u8>,
pub db_left: Vec<bool>,
pub db_top: Vec<bool>,
pub cdb_lw: Vec<u8>,
pub cdb_lh: Vec<u8>,
pub cdb_left: Vec<bool>,
pub cdb_top: Vec<bool>,
pub db_spv: Vec<bool>,
pub db_sph: Vec<bool>,
pub cdb_spv: Vec<bool>,
pub cdb_sph: Vec<bool>,
pub ciw4: usize,
pub cih4: usize,
pub mi_coded_c: Vec<bool>,
pub sm_c: Vec<u8>,
pub cdef_idx: Vec<i8>,
pub cdef_sbw: usize,
pub noskip: Vec<bool>,
pub noskip_stripes: usize,
pub ccso_blk: Vec<bool>,
pub ccso_col256: usize,
pub ccso_n256: usize,
pub ccso_px_shift: u32,
pub gdf_bs_px: usize,
pub gdf_blk: Vec<bool>,
pub gdf_blk_w: usize,
pub lr_noskip: Vec<bool>,
pub sb_qidx: Vec<u16>,
}
impl Frame {
pub fn ensure_sb(&mut self, bx4: usize, by4: usize) {
let sh = crate::av2_recon::sb_step4().trailing_zeros();
let sb = (bx4 >> sh, by4 >> sh);
if sb != self.mi_coded_sb {
for v in self.mi_coded.iter_mut() {
if !crate::av2_recon::work_tick("frm:140") { break; }
*v = false;
}
for v in self.mi_coded_c.iter_mut() {
if !crate::av2_recon::work_tick("frm:143") { break; }
*v = false;
}
self.mi_coded_sb = sb;
}
}
pub fn mi_coded_at(&self, row: i32, col: i32) -> bool {
let st = crate::av2_recon::sb_step4() as i32;
if !(0..st).contains(&row) || !(0..st).contains(&col) {
return false;
}
self.mi_coded[(row * 32 + col) as usize]
}
pub fn mi_coded_c_at(&self, row: i32, col: i32) -> bool {
let st = crate::av2_recon::sb_step4() as i32;
if !(0..st).contains(&row) || !(0..st).contains(&col) {
return false;
}
self.mi_coded_c[(row * 32 + col) as usize]
}
pub fn mark_coded_c(&mut self, bx4: usize, by4: usize, bw4: usize, bh4: usize) {
let st = crate::av2_recon::sb_step4();
let (sr, sc) = (by4 & (st - 1), bx4 & (st - 1));
for r in sr..(sr + bh4).min(st) {
if !crate::av2_recon::work_tick("frm:170") { break; }
for c in sc..(sc + bw4).min(st) {
if !crate::av2_recon::work_tick("frm:171") { break; }
self.mi_coded_c[r * 32 + c] = true;
}
}
}
pub fn mark_coded_c_avail(&mut self, bx4: usize, by4: usize, bw4: usize, bh4: usize) {
self.mark_coded_c(bx4, by4, bw4, bh4);
}
pub fn mark_coded_avail(&mut self, bx4: usize, by4: usize, bw4: usize, bh4: usize) {
let st = crate::av2_recon::sb_step4();
let (sr, sc) = (by4 & (st - 1), bx4 & (st - 1));
for r in sr..(sr + bh4).min(st) {
if !crate::av2_recon::work_tick("frm:191") { break; }
for c in sc..(sc + bw4).min(st) {
if !crate::av2_recon::work_tick("frm:192") { break; }
self.mi_coded[r * 32 + c] = true;
}
}
}
pub fn mark_coded(&mut self, bx4: usize, by4: usize, bw4: usize, bh4: usize, joint: u8) {
let st = crate::av2_recon::sb_step4();
let (sr, sc) = (by4 & (st - 1), bx4 & (st - 1));
for r in sr..(sr + bh4).min(st) {
if !crate::av2_recon::work_tick("frm:200") { break; }
for c in sc..(sc + bw4).min(st) {
if !crate::av2_recon::work_tick("frm:201") { break; }
self.mi_coded[r * 32 + c] = true;
}
}
for r in by4..(by4 + bh4).min(self.ih4) {
if !crate::av2_recon::work_tick("frm:205") { break; }
for c in bx4..(bx4 + bw4).min(self.iw4) {
if !crate::av2_recon::work_tick("frm:206") { break; }
self.joint[r * self.iw4 + c] = joint;
}
}
self.mark_db(bx4, by4, bw4, bh4);
}
pub fn mark_db_lvl(&mut self, bx4: usize, by4: usize, bw4: usize, bh4: usize, lw: u8, lh: u8) {
if self.db_lw.is_empty() {
return;
}
let (iw4, ih4) = (self.iw4, self.ih4);
for r in by4..(by4 + bh4).min(ih4) {
if !crate::av2_recon::work_tick("frm:221") { break; }
for c in bx4..(bx4 + bw4).min(iw4) {
if !crate::av2_recon::work_tick("frm:222") { break; }
let cell = r * iw4 + c;
self.db_lw[cell] = lw;
self.db_lh[cell] = lh;
self.db_left[cell] = c == bx4;
self.db_top[cell] = r == by4;
}
}
}
pub fn mark_db(&mut self, bx4: usize, by4: usize, bw4: usize, bh4: usize) {
if self.db_lw.is_empty() {
return;
}
let lw = (bw4.trailing_zeros()).min(3) as u8; let lh = (bh4.trailing_zeros()).min(3) as u8;
let (iw4, ih4) = (self.iw4, self.ih4);
for r in by4..(by4 + bh4).min(ih4) {
if !crate::av2_recon::work_tick("frm:238") { break; }
for c in bx4..(bx4 + bw4).min(iw4) {
if !crate::av2_recon::work_tick("frm:239") { break; }
let cell = r * iw4 + c;
self.db_lw[cell] = lw;
self.db_lh[cell] = lh;
self.db_left[cell] = c == bx4;
self.db_top[cell] = r == by4;
}
}
}
pub fn mark_db_subpu(&mut self, bx4: usize, by4: usize, bw4: usize, bh4: usize, subpu_l2: usize, fm2: bool) {
if self.db_lw.is_empty() || subpu_l2 >= 3 {
return;
}
let (iw4, ih4) = (self.iw4, self.ih4);
let sl = subpu_l2 as u8;
for r in by4..(by4 + bh4).min(ih4) {
if !crate::av2_recon::work_tick("frm:261") { break; }
for c in bx4..(bx4 + bw4).min(iw4) {
if !crate::av2_recon::work_tick("frm:262") { break; }
let cell = r * iw4 + c;
self.db_lw[cell] = self.db_lw[cell].min(sl);
self.db_lh[cell] = self.db_lh[cell].min(sl);
}
}
let sz = 1usize << subpu_l2;
let mut x = sz;
while x < bw4 {
let c = bx4 + x;
if c < iw4 {
for r in by4..(by4 + bh4).min(ih4) {
if !crate::av2_recon::work_tick("frm:273") { break; }
let cell = r * iw4 + c;
if !self.db_left[cell] {
self.db_left[cell] = true;
if !fm2 && (x & 15) != 0 {
self.db_spv[cell] = true;
}
}
}
}
x += sz;
}
let mut y = sz;
while y < bh4 {
let r = by4 + y;
if r < ih4 {
for c in bx4..(bx4 + bw4).min(iw4) {
if !crate::av2_recon::work_tick("frm:289") { break; }
let cell = r * iw4 + c;
if !self.db_top[cell] {
self.db_top[cell] = true;
if !fm2 && (y & 15) != 0 {
self.db_sph[cell] = true;
}
}
}
}
y += sz;
}
}
pub fn mark_db_subpu_chroma(&mut self, cbx4: usize, cby4: usize, cbw4: usize, cbh4: usize, subpu_l2: usize, ss_hor: usize, ss_ver: usize, fm2: bool) {
if self.cdb_lw.is_empty() || subpu_l2 >= 3 {
return;
}
let (iw4, ih4) = (self.ciw4, self.cih4);
let lw_cap = (subpu_l2 as i32 - ss_hor as i32).clamp(0, 2) as u8;
let lh_cap = (subpu_l2 as i32 - ss_ver as i32).clamp(0, 2) as u8;
for r in cby4..(cby4 + cbh4).min(ih4) {
if !crate::av2_recon::work_tick("frm:312") { break; }
for c in cbx4..(cbx4 + cbw4).min(iw4) {
if !crate::av2_recon::work_tick("frm:313") { break; }
let cell = r * iw4 + c;
self.cdb_lw[cell] = self.cdb_lw[cell].min(lw_cap);
self.cdb_lh[cell] = self.cdb_lh[cell].min(lh_cap);
}
}
let hsz = (1usize << subpu_l2) >> ss_hor;
let vsz = (1usize << subpu_l2) >> ss_ver;
if hsz > 0 {
let mut x = hsz;
while x < cbw4 {
let c = cbx4 + x;
if c < iw4 {
for r in cby4..(cby4 + cbh4).min(ih4) {
if !crate::av2_recon::work_tick("frm:326") { break; }
let cell = r * iw4 + c;
if !self.cdb_left[cell] {
self.cdb_left[cell] = true;
if !fm2 && (x & 15) != 0 {
self.cdb_spv[cell] = true;
}
}
}
}
x += hsz;
}
}
if vsz > 0 {
let mut y = vsz;
while y < cbh4 {
let r = cby4 + y;
if r < ih4 {
for c in cbx4..(cbx4 + cbw4).min(iw4) {
if !crate::av2_recon::work_tick("frm:344") { break; }
let cell = r * iw4 + c;
if !self.cdb_top[cell] {
self.cdb_top[cell] = true;
if !fm2 && (y & 15) != 0 {
self.cdb_sph[cell] = true;
}
}
}
}
y += vsz;
}
}
}
pub fn set_cdef_idx(&mut self, bx4: usize, by4: usize, v: i8) {
if self.cdef_idx.is_empty() {
return;
}
let sb = (by4 >> 4) * self.cdef_sbw + (bx4 >> 4);
if sb < self.cdef_idx.len() {
self.cdef_idx[sb] = v;
}
}
pub fn set_sb_qidx(&mut self, bx4: usize, by4: usize, q: u16) {
if self.sb_qidx.is_empty() {
return;
}
let n64 = crate::av2_recon::sb_step4() / 16;
let rows = self.sb_qidx.len() / self.cdef_sbw.max(1);
for dy in 0..n64 {
if !crate::av2_recon::work_tick("frm:379") { break; }
for dx in 0..n64 {
if !crate::av2_recon::work_tick("frm:380") { break; }
let (cx, cy) = ((bx4 >> 4) + dx, (by4 >> 4) + dy);
if cx < self.cdef_sbw && cy < rows {
self.sb_qidx[cy * self.cdef_sbw + cx] = q;
}
}
}
}
pub fn sb_qidx_at(&self, lx: usize, ly: usize, frame_yac: u32) -> u32 {
if self.sb_qidx.is_empty() {
return frame_yac;
}
let sb = (ly >> 6) * self.cdef_sbw + (lx >> 6);
match self.sb_qidx.get(sb) {
Some(&q) if q != 0 => q as u32,
_ => frame_yac,
}
}
pub fn mark_lr_noskip(&mut self, bx4: usize, by4: usize, bw4: usize, bh4: usize) {
if self.lr_noskip.is_empty() {
return;
}
for r in by4..(by4 + bh4).min(self.ih4) {
if !crate::av2_recon::work_tick("frm:407") { break; }
for c in bx4..(bx4 + bw4).min(self.iw4) {
if !crate::av2_recon::work_tick("frm:408") { break; }
self.lr_noskip[r * self.iw4 + c] = true;
}
}
}
pub fn set_gdf_blk(&mut self, bx4: usize, by4: usize, on: bool) {
if self.gdf_blk.is_empty() {
return;
}
let sh = (self.gdf_bs_px as u32 / 4).trailing_zeros();
let idx = (by4 >> sh) * self.gdf_blk_w + (bx4 >> sh);
if idx < self.gdf_blk.len() {
self.gdf_blk[idx] = on;
}
}
pub fn set_ccso_blk(&mut self, bx4: usize, by4: usize, plane: usize, on: bool) {
if self.ccso_blk.is_empty() {
return;
}
let sh = self.ccso_px_shift - 2;
let block = (by4 >> sh) * self.ccso_col256 + (bx4 >> sh);
let i = plane * self.ccso_n256 + block;
if i < self.ccso_blk.len() {
self.ccso_blk[i] = on;
}
}
pub fn ccso_blk_on(&self, plane: usize, lx: usize, ly: usize) -> bool {
if self.ccso_blk.is_empty() {
return false;
}
let block = (ly >> self.ccso_px_shift) * self.ccso_col256 + (lx >> self.ccso_px_shift);
let i = plane * self.ccso_n256 + block;
i < self.ccso_blk.len() && self.ccso_blk[i]
}
pub fn mark_noskip(&mut self, bx4: usize, by4: usize, bw4: usize, bh4: usize) {
if self.noskip.is_empty() {
return;
}
let (iw4, ns) = (self.iw4, self.noskip_stripes);
let mut y = 0;
while y < bh4 {
let stripe = (by4 >> 1) + (y >> 1);
if stripe < ns {
for c in bx4..(bx4 + bw4).min(iw4) {
if !crate::av2_recon::work_tick("frm:455") { break; }
self.noskip[stripe * iw4 + c] = true;
}
}
y += 2;
}
}
pub fn mark_db_chroma(&mut self, cbx4: usize, cby4: usize, cbw4: usize, cbh4: usize) {
if self.cdb_lw.is_empty() {
return;
}
if std::env::var("DBLK444").is_ok()
&& (cbx4 * 4 <= 208 && (cbx4 + cbw4) * 4 >= 192 && cby4 * 4 <= 124 && (cby4 + cbh4) * 4 >= 112)
{
crate::dlog!("[MMARK] c=({},{}) w={} h={}", cbx4 * 4, cby4 * 4, cbw4 * 4, cbh4 * 4);
}
let lw = (cbw4.trailing_zeros()).min(2) as u8; let lh = (cbh4.trailing_zeros()).min(2) as u8;
let (ciw4, cih4) = (self.ciw4, self.cih4);
for r in cby4..(cby4 + cbh4).min(cih4) {
if !crate::av2_recon::work_tick("frm:476") { break; }
for c in cbx4..(cbx4 + cbw4).min(ciw4) {
if !crate::av2_recon::work_tick("frm:477") { break; }
let cell = r * ciw4 + c;
self.cdb_lw[cell] = lw;
self.cdb_lh[cell] = lh;
self.cdb_left[cell] = c == cbx4;
self.cdb_top[cell] = r == cby4;
}
}
}
pub fn joint_at(&self, bx4: i32, by4: i32) -> u8 {
if bx4 < 0 || by4 < 0 || bx4 >= self.iw4 as i32 || by4 >= self.ih4 as i32 {
return 0;
}
self.joint[(by4 * self.iw4 as i32 + bx4) as usize]
}
pub fn smooth_at(&self, bx4: i32, by4: i32) -> bool {
(1..=3).contains(&self.joint_at(bx4, by4))
}
}
thread_local! {
pub static FRAME: RefCell<Frame> = RefCell::new(Frame::default());
pub static BDMAX: std::cell::Cell<i32> = const { std::cell::Cell::new(255) };
pub static SS: std::cell::Cell<(u32, u32)> = const { std::cell::Cell::new((1, 1)) };
pub static REF_LUMA: RefCell<Option<Plane>> = const { RefCell::new(None) };
pub static REF_SCORE: std::cell::Cell<(u32, u32)> = const { std::cell::Cell::new((0, 0)) };
pub static REF_CHROMA: RefCell<[Option<Plane>; 2]> = const { RefCell::new([None, None]) };
pub static REF_CHROMA_SCORE: std::cell::Cell<(u32, u32, u32)> = const { std::cell::Cell::new((0, 0, 0)) };
pub static RECON_PAD: RefCell<Vec<Plane>> = const { RefCell::new(Vec::new()) };
pub static REF_FRAME1: RefCell<[Option<Plane>; 3]> = const { RefCell::new([None, None, None]) };
pub static STASH_FRAME1: RefCell<[Option<Plane>; 3]> = const { RefCell::new([None, None, None]) };
pub static REF_PICS: RefCell<[Option<[Plane; 3]>; 8]> =
const { RefCell::new([None, None, None, None, None, None, None, None]) };
pub static INTER_SCORE: std::cell::Cell<(u32, u32)> = const { std::cell::Cell::new((0, 0)) };
pub static REF_F2PRED: RefCell<Option<Plane>> = const { RefCell::new(None) };
pub static REF_F2PREDC: RefCell<[Option<Plane>; 2]> = const { RefCell::new([None, None]) };
pub static INTER_SCORE_C: std::cell::Cell<(u32, u32, u32)> = const { std::cell::Cell::new((0, 0, 0)) };
pub static INTER_SCORE_W: std::cell::Cell<(u32, u32)> = const { std::cell::Cell::new((0, 0)) };
pub static INTER_SCORE_WC: std::cell::Cell<(u32, u32, u32)> = const { std::cell::Cell::new((0, 0, 0)) };
pub static REF_F2RECON: RefCell<Option<Plane>> = const { RefCell::new(None) };
pub static REF_F2RECONC: RefCell<[Option<Plane>; 2]> = const { RefCell::new([None, None]) };
pub static INTER_SCORE_RC: std::cell::Cell<(u32, u32, u32)> = const { std::cell::Cell::new((0, 0, 0)) };
pub static INTER_SCORE_R: std::cell::Cell<(u32, u32)> = const { std::cell::Cell::new((0, 0)) };
pub static F2_YAC: std::cell::Cell<u32> = const { std::cell::Cell::new(0) };
pub static F2_DCQ: std::cell::Cell<[u32; 3]> = const { std::cell::Cell::new([0, 0, 0]) };
pub static F2_ACQ: std::cell::Cell<[u32; 3]> = const { std::cell::Cell::new([0, 0, 0]) };
pub static F2_QDELTAS: std::cell::Cell<[i32; 5]> = const { std::cell::Cell::new([0; 5]) };
pub static DECODE_FRAME_N: std::cell::Cell<u32> = const { std::cell::Cell::new(0) };
pub static INTER_DDT: std::cell::Cell<bool> = const { std::cell::Cell::new(false) };
pub static FILTER_GRID: RefCell<Vec<u8>> = RefCell::new(vec![0u8; 128 * 64]);
pub static FILTER_GRID_STRIDE: std::cell::Cell<usize> = const { std::cell::Cell::new(128) };
pub static RECON_ACTIVE: std::cell::Cell<bool> = const { std::cell::Cell::new(false) };
pub static DBG: std::cell::Cell<bool> = const { std::cell::Cell::new(false) };
}
pub fn end_recon_pass() {
RECON_ACTIVE.with(|a| a.set(false));
}
pub fn load_ref_luma(path: &str, w: usize, h: usize) {
if let Ok(bytes) = std::fs::read(path) {
if bytes.len() >= w * h {
let mut p = Plane::alloc(w, h);
for i in 0..w * h {
if !crate::av2_recon::work_tick("frm:598") { break; }
p.px[i] = bytes[i] as i32;
}
REF_LUMA.with(|r| *r.borrow_mut() = Some(p));
REF_SCORE.with(|s| s.set((0, 0)));
RECON_ACTIVE.with(|a| a.set(true));
}
}
}
pub fn load_ref_chroma(path: &str, cw: usize, ch: usize, luma_sz: usize) {
if let Ok(bytes) = std::fs::read(path) {
let csz = cw * ch;
if bytes.len() >= luma_sz + 2 * csz {
let mut pu = Plane::alloc(cw, ch);
let mut pv = Plane::alloc(cw, ch);
for i in 0..csz {
if !crate::av2_recon::work_tick("frm:616") { break; }
pu.px[i] = bytes[luma_sz + i] as i32;
pv.px[i] = bytes[luma_sz + csz + i] as i32;
}
REF_CHROMA.with(|r| *r.borrow_mut() = [Some(pu), Some(pv)]);
REF_CHROMA_SCORE.with(|s| s.set((0, 0, 0)));
}
}
}
pub fn load_ref_frame1(path: &str, w: usize, h: usize) {
if let Ok(bytes) = std::fs::read(path) {
let (cw, ch) = ((w + 1) >> 1, (h + 1) >> 1);
let (luma_sz, csz) = (w * h, cw * ch);
if bytes.len() >= luma_sz + 2 * csz {
let mut py = Plane::alloc(w, h);
let mut pu = Plane::alloc(cw, ch);
let mut pv = Plane::alloc(cw, ch);
for i in 0..luma_sz {
if !crate::av2_recon::work_tick("frm:637") { break; }
py.px[i] = bytes[i] as i32;
}
for i in 0..csz {
if !crate::av2_recon::work_tick("frm:640") { break; }
pu.px[i] = bytes[luma_sz + i] as i32;
pv.px[i] = bytes[luma_sz + csz + i] as i32;
}
REF_FRAME1.with(|r| *r.borrow_mut() = [Some(py), Some(pu), Some(pv)]);
INTER_SCORE.with(|s| s.set((0, 0)));
}
}
}
pub fn reset_stream_state() {
STASH_FRAME1.with(|s| *s.borrow_mut() = [None, None, None]);
REF_PICS.with(|r| *r.borrow_mut() = std::array::from_fn(|_| None));
CCSO_SLOT_MAP.with(|m| *m.borrow_mut() = std::array::from_fn(|_| None));
CCSO_SLOT_CFG.with(|c| *c.borrow_mut() = std::array::from_fn(|_| None));
REF_LUMA.with(|r| *r.borrow_mut() = None);
REF_CHROMA.with(|r| *r.borrow_mut() = [None, None]);
}
pub fn stash_decoded_frame1() {
FRAME.with(|fr| {
let f = fr.borrow();
let planes: [Option<Plane>; 3] =
std::array::from_fn(|i| if f.pl[i].w == 0 { None } else { Some(f.pl[i].clone()) });
STASH_FRAME1.with(|s| *s.borrow_mut() = planes);
});
if let Ok(prefix) = std::env::var("MREFDUMP") {
use std::io::Write;
thread_local! { static DUMP_N: std::cell::Cell<u32> = const { std::cell::Cell::new(0) }; }
let n = DUMP_N.with(|c| { let v = c.get(); c.set(v + 1); v });
FRAME.with(|fr| {
let f = fr.borrow();
if f.pl[0].w == 0 { return; }
let hbd = f.bitdepth_max > 255;
if let Ok(mut fp) = std::fs::File::create(format!("{prefix}_{n}.yuv")) {
for pl in 0..3 {
let p = &f.pl[pl];
if p.w == 0 { continue; }
for y in 0..p.h {
if !crate::av2_recon::work_tick("frm:683") { break; }
for x in 0..p.w {
if !crate::av2_recon::work_tick("frm:684") { break; }
let v = p.px[y * p.stride + x];
if hbd {
let _ = fp.write_all(&(v as u16).to_le_bytes());
} else {
let _ = fp.write_all(&[(v as u8)]);
}
}
}
}
}
});
}
}
pub fn update_ref_pics(refresh: u32) {
FRAME.with(|fr| {
let f = fr.borrow();
if f.pl[0].w == 0 {
return;
}
let planes: [Plane; 3] = std::array::from_fn(|i| f.pl[i].clone());
REF_PICS.with(|r| {
let mut slots = r.borrow_mut();
for i in 0..8 {
if refresh & (1 << i) != 0 {
slots[i] = Some(planes.clone());
}
}
});
});
}
thread_local! {
pub static CUR_REF1_SLOT: std::cell::Cell<usize> = const { std::cell::Cell::new(usize::MAX) };
}
pub fn load_ref_frame1_from_slot(slot: usize) -> bool {
REF_PICS.with(|r| {
let pics = r.borrow();
if let Some(p) = pics.get(slot).and_then(|s| s.as_ref()) {
REF_FRAME1.with(|rf| *rf.borrow_mut() = [Some(p[0].clone()), Some(p[1].clone()), Some(p[2].clone())]);
INTER_SCORE.with(|sc| sc.set((0, 0)));
CUR_REF1_SLOT.with(|c| c.set(slot));
true
} else {
false
}
})
}
pub fn ensure_ref1_slot(slot: usize) {
if CUR_REF1_SLOT.with(|c| c.get()) == slot {
return;
}
load_ref_frame1_from_slot(slot);
}
pub fn load_ref_frame1_from_stash() -> bool {
STASH_FRAME1.with(|s| {
let st = s.borrow();
if st[0].is_some() {
REF_FRAME1.with(|r| *r.borrow_mut() = st.clone());
INTER_SCORE.with(|sc| sc.set((0, 0)));
true
} else {
false
}
})
}
pub fn reset_frame(w: usize, h: usize, yac: u8, edge_filter: bool, ibp: bool, bdmax: i32) {
FRAME_NO.with(|c| c.set(c.get() + 1));
{
let (giw4, gih4) = ((w + 3) / 4, (h + 3) / 4);
let stride = giw4.max(128);
FILTER_GRID_STRIDE.with(|c| c.set(stride));
FILTER_GRID.with(|g| {
let mut v = g.borrow_mut();
v.clear();
v.resize(stride * gih4.max(64), 0);
});
}
let (ss_hor, ss_ver) = SS.with(|c| c.get());
let (cw, ch) = ((w + ss_hor as usize) >> ss_hor, (h + ss_ver as usize) >> ss_ver);
RECON_PAD.with(|p| {
*p.borrow_mut() = vec![
Plane::alloc_padded(w, h, 64),
Plane::alloc_padded(cw, ch, 64 >> ss_hor),
Plane::alloc_padded(cw, ch, 64 >> ss_hor),
];
});
FRAME.with(|f| {
let mut f = f.borrow_mut();
f.pl[0] = Plane::alloc(w, h);
f.pl[1] = Plane::alloc(cw, ch);
f.pl[2] = Plane::alloc(cw, ch);
f.yac = yac;
f.bitdepth_max = bdmax;
BDMAX.with(|b| b.set(bdmax));
f.edge_filter = edge_filter;
f.ibp = ibp;
f.iw4 = w >> 2;
f.ih4 = h >> 2;
f.mi_coded = vec![false; 1024];
f.mi_coded_c = vec![false; 1024];
f.mi_coded_sb = (usize::MAX, usize::MAX);
let n = (w >> 2) * (h >> 2);
f.joint = vec![0u8; n];
f.db_lw = vec![0u8; n];
f.db_lh = vec![0u8; n];
f.db_left = vec![false; n];
f.db_top = vec![false; n];
f.ciw4 = f.pl[1].w >> 2;
f.cih4 = f.pl[1].h >> 2;
let cn = f.ciw4 * f.cih4;
f.cdb_lw = vec![0u8; cn];
f.cdb_lh = vec![0u8; cn];
f.cdb_left = vec![false; cn];
f.cdb_top = vec![false; cn];
f.db_spv = vec![false; n];
f.db_sph = vec![false; n];
f.cdb_spv = vec![false; cn];
f.cdb_sph = vec![false; cn];
f.sm_c = vec![0u8; cn];
f.cdef_sbw = f.iw4.div_ceil(16);
let sbh = f.ih4.div_ceil(16);
f.cdef_idx = vec![-1i8; f.cdef_sbw * sbh];
f.sb_qidx = vec![0u16; f.cdef_sbw * sbh];
f.noskip_stripes = f.ih4.div_ceil(2);
f.noskip = vec![false; f.noskip_stripes * f.iw4];
f.lr_noskip = vec![false; f.iw4 * f.ih4];
let (ccso_u4, gdf_bs4) = crate::av2_recon::FILTER_UNITS.with(|c| c.get());
f.ccso_px_shift = (ccso_u4 as u32 * 4).trailing_zeros();
f.ccso_col256 = f.iw4.div_ceil(ccso_u4);
let crow256 = f.ih4.div_ceil(ccso_u4);
f.ccso_n256 = f.ccso_col256 * crow256;
if f.ccso_blk.len() == 3 * f.ccso_n256 {
let prev = f.ccso_blk.clone();
PREV_CCSO_MAP.with(|m| *m.borrow_mut() = prev);
}
f.ccso_blk = vec![false; 3 * f.ccso_n256];
f.gdf_bs_px = gdf_bs4 * 4;
let gbs = f.gdf_bs_px;
f.gdf_blk_w = 1 + (w - 1) / gbs;
let gbh = 1 + (h - 1) / gbs;
f.gdf_blk = vec![false; f.gdf_blk_w * gbh];
});
BTYPE.with(|b| *b.borrow_mut() = vec![0u8; w * h]);
BTYPE_WH.with(|c| c.set((w, h)));
}
#[derive(Clone, Copy, Default)]
pub struct DeblockCfg {
pub level_y0: bool,
pub level_y1: bool,
pub level_u: bool,
pub level_v: bool,
pub dq_y0: i32,
pub dq_y1: i32,
pub dq_u: i32,
pub dq_v: i32,
pub uac_delta: i32,
pub vac_delta: i32,
pub sub_pu: bool,
}
thread_local! {
pub static DEBLOCK_CFG: std::cell::Cell<DeblockCfg> = const { std::cell::Cell::new(DeblockCfg {
level_y0: false, level_y1: false, level_u: false, level_v: false,
dq_y0: 0, dq_y1: 0, dq_u: 0, dq_v: 0, uac_delta: 0, vac_delta: 0, sub_pu: false,
}) };
pub static CDEF_CFG: std::cell::Cell<CdefCfg> = const { std::cell::Cell::new(CdefCfg {
enabled: false, damping: 3, n_strengths: 1, on_skiptx: false,
y_strength: [0; 8], uv_strength: [0; 8],
}) };
}
#[derive(Clone, Default)]
pub struct CcsoPlaneCfg {
pub enabled: bool,
pub bo_only: bool,
pub quant_step: i32,
pub ext_filter: usize,
pub edge_clf: bool,
pub max_band_log2: u32,
pub filter_offset: Vec<i8>,
pub sb_reuse: bool,
pub reuse_slot: u8,
}
#[derive(Clone, Default)]
pub struct CcsoCfg {
pub enabled: bool,
pub p: Vec<CcsoPlaneCfg>,
}
thread_local! {
pub static CCSO_CFG: RefCell<CcsoCfg> = RefCell::new(CcsoCfg::default());
pub static PREV_CCSO_MAP: RefCell<Vec<bool>> = const { RefCell::new(Vec::new()) };
pub static CCSO_SLOT_MAP: RefCell<[Option<Vec<bool>>; 8]> = RefCell::new(std::array::from_fn(|_| None));
pub static CCSO_SLOT_CFG: RefCell<[Option<CcsoCfg>; 8]> = RefCell::new(std::array::from_fn(|_| None));
pub static BTYPE: RefCell<Vec<u8>> = const { RefCell::new(Vec::new()) };
pub static BTYPE_WH: std::cell::Cell<(usize, usize)> = const { std::cell::Cell::new((0, 0)) };
pub static FRAME_NO: std::cell::Cell<u32> = const { std::cell::Cell::new(0) };
pub static BAWP_ALPHA: std::cell::Cell<i32> = const { std::cell::Cell::new(256) };
pub static GDF_CFG: std::cell::Cell<GdfCfg> = const { std::cell::Cell::new(GdfCfg {
enabled: false, mode: 0, qp_idx: 0, scale_idx: 0, block_size: 128,
}) };
}
pub fn dbg_block_miss(bx4: usize, by4: usize, bw4: usize, bh4: usize, tag: &str) {
if std::env::var("RECONDBG").is_err() {
return;
}
REF_F2RECON.with(|r| {
if let Some(rp) = r.borrow().as_ref() {
FRAME.with(|fr| {
let f = fr.borrow();
if f.pl[0].w == 0 { return; }
let (w, h) = (bw4 * 4, bh4 * 4);
for yy in 0..h {
if !crate::av2_recon::work_tick("frm:952") { break; }
for xx in 0..w {
if !crate::av2_recon::work_tick("frm:953") { break; }
let (px, py) = (bx4 * 4 + xx, by4 * 4 + yy);
if px < rp.w && py < rp.h {
let m = f.pl[0].px[py * f.pl[0].stride + px];
if m != rp.at(px, py) {
crate::dlog!("BLKMISS[{tag}] fn={} ({bx4},{by4}) w={w} h={h} at({xx},{yy}) mine={m} dav={}", DECODE_FRAME_N.with(|c| c.get()), rp.at(px, py));
return;
}
}
}
}
});
}
});
}
pub fn dbg_block_miss_c(px0: usize, py0: usize, w: usize, h: usize, tag: &str) {
if std::env::var("CRECONDBG").is_err() {
return;
}
REF_F2RECONC.with(|r| {
let rb = r.borrow();
FRAME.with(|fr| {
let f = fr.borrow();
if f.pl[1].w == 0 { return; }
for (pl, rpo) in rb.iter().enumerate() {
let Some(rp) = rpo.as_ref() else { continue };
for yy in 0..h {
if !crate::av2_recon::work_tick("frm:983") { break; }
for xx in 0..w {
if !crate::av2_recon::work_tick("frm:984") { break; }
let (px, py) = (px0 + xx, py0 + yy);
if px < rp.w && py < rp.h {
let m = f.pl[pl + 1].px[py * f.pl[pl + 1].stride + px];
if m != 0 && m != rp.at(px, py) {
crate::dlog!("CBLKMISS[{tag}] pl={pl} ({px0},{py0}) w={w} h={h} at({xx},{yy}) mine={m} dav={}", rp.at(px, py));
return;
}
}
}
}
}
});
});
}
pub fn write_recon_pad(plane: usize, px0: usize, py0: usize, pred: &[i32], w: usize, h: usize) {
RECON_PAD.with(|p| {
let mut pad = p.borrow_mut();
if plane >= pad.len() { return; }
let pl = &mut pad[plane];
if pl.w == 0 { return; }
let (pw, ph, stride) = (pl.w, pl.h, pl.stride);
let wc = w.min(pw.saturating_sub(px0));
let hc = h.min(ph.saturating_sub(py0));
let bdmax = BDMAX.with(|c| c.get());
for y in 0..hc {
if !crate::av2_recon::work_tick("frm:1014") { break; }
let dst = (py0 + y) * stride + px0;
for x in 0..wc {
if !crate::av2_recon::work_tick("frm:1016") { break; }
pl.px[dst + x] = pred[y * w + x].clamp(0, bdmax);
}
}
});
}
pub fn mark_btype(bx4: usize, by4: usize, bw4: usize, bh4: usize, t: u8) {
let (fw, fh) = BTYPE_WH.with(|c| c.get());
if fw == 0 { return; }
BTYPE.with(|b| {
let mut m = b.borrow_mut();
if m.len() != fw * fh { return; }
for y in by4 * 4..((by4 + bh4) * 4).min(fh) {
if !crate::av2_recon::work_tick("frm:1031") { break; }
for x in bx4 * 4..((bx4 + bw4) * 4).min(fw) {
if !crate::av2_recon::work_tick("frm:1032") { break; }
m[y * fw + x] = t;
}
}
});
}
#[derive(Clone, Copy)]
pub struct GdfCfg {
pub enabled: bool,
pub mode: i32,
pub qp_idx: i32,
pub scale_idx: i32,
pub block_size: i32,
}
#[derive(Clone, Copy)]
pub struct CdefCfg {
pub enabled: bool,
pub damping: i32,
pub n_strengths: usize,
pub on_skiptx: bool,
pub y_strength: [i32; 8],
pub uv_strength: [i32; 8],
}
#[allow(clippy::too_many_arguments)]
fn verify_plane(
tag: &str,
none: &[u8],
deblk: &[u8],
off: usize,
iw4: usize,
ih4: usize,
w: usize,
h: usize,
grids: (&[u8], &[u8], &[bool], &[bool]),
thr: (i32, i32, i32, i32),
bdmax: i32,
max_width: &[i32],
band_cells: usize,
band_neg_cap: i32,
) {
use crate::av2_deblock::deblock_plane;
let n = w * h;
if off + n > none.len() || off + n > deblk.len() {
crate::dlog!("[C1 {tag}] oracle too short");
return;
}
let mut buf: Vec<i32> = (0..n).map(|i| none[off + i] as i32).collect();
let (lw, lh, left, top) = grids;
let (q_v, s_v, q_h, s_h) = thr;
deblock_plane(&mut buf, iw4, ih4, w, lw, lh, left, top, q_v, s_v, q_h, s_h, None, &[], &[], bdmax, max_width, band_cells, band_neg_cap, true, true, &[]);
if tag == "DEBLOCK-Y" {
let bytes: Vec<u8> = buf.iter().map(|&v| v.clamp(0, 255) as u8).collect();
let _ = std::fs::write(&crate::av2_recon::cap_path("mine_f2deblk_y.bin"), &bytes);
}
let mut mism = 0u32;
let mut dav_changed = 0u32;
let mut first: Vec<(usize, usize, i32, i32)> = Vec::new();
for i in 0..n {
if !crate::av2_recon::work_tick("frm:1099") { break; }
let mine = buf[i].clamp(0, 255) as u8;
let want = deblk[off + i];
if want != none[off + i] {
dav_changed += 1;
}
if mine != want {
mism += 1;
if first.len() < 12 {
first.push((i % w, i / w, mine as i32, want as i32));
}
}
}
crate::dlog!(
"[C1 {tag}] {}/{} px exact ({:.3}%); {mism} mismatch, dav changed {dav_changed}",
n as u32 - mism, n, 100.0 * (n as u32 - mism) as f64 / n as f64
);
for (x, y, m, wv) in &first {
crate::dlog!(" ({x},{y}) mine={m} want={wv}");
}
}
pub fn run_deblock_verify(none_path: &str, deblk_path: &str) {
use crate::av2_deblock::{deblock_quant_thr, deblock_side_thr, MAX_WIDTH_UV_TBL, MAX_WIDTH_Y_TBL};
let (iw4, ih4, w, h, cw, ch, ciw4, cih4, yac, bdmax,
db_lw, db_lh, db_left, db_top, cdb_lw, cdb_lh, cdb_left, cdb_top) = FRAME.with(|fr| {
let f = fr.borrow();
(f.iw4, f.ih4, f.pl[0].w, f.pl[0].h, f.pl[1].w, f.pl[1].h, f.ciw4, f.cih4,
f.yac as i32, f.bitdepth_max,
f.db_lw.clone(), f.db_lh.clone(), f.db_left.clone(), f.db_top.clone(),
f.cdb_lw.clone(), f.cdb_lh.clone(), f.cdb_left.clone(), f.cdb_top.clone())
});
if w == 0 || db_lw.is_empty() {
return;
}
let cfg = DEBLOCK_CFG.with(|c| c.get());
if !cfg.level_y0 && !cfg.level_y1 {
crate::dlog!("[C1] deblock disabled (level_y0={} level_y1={})", cfg.level_y0, cfg.level_y1);
return;
}
let none = match std::fs::read(none_path) {
Ok(b) => b,
_ => { crate::dlog!("[C1] could not read {none_path}"); return; }
};
let deblk = match std::fs::read(deblk_path) {
Ok(b) => b,
_ => { crate::dlog!("[C1] could not read {deblk_path}"); return; }
};
let q_thr_v = deblock_quant_thr(yac + 8 * cfg.dq_y0, 0);
let side_thr_v = deblock_side_thr(yac + 8 * cfg.dq_y0, 0);
let q_thr_h = deblock_quant_thr(yac + 8 * cfg.dq_y1, 0);
let side_thr_h = deblock_side_thr(yac + 8 * cfg.dq_y1, 0);
crate::dlog!(
"[C1] qidx={yac} dq_y0={} dq_y1={} uac={} vac={} → yV(q={q_thr_v},s={side_thr_v}) yH(q={q_thr_h},s={side_thr_h})",
cfg.dq_y0, cfg.dq_y1, cfg.uac_delta, cfg.vac_delta
);
verify_plane(
"DEBLOCK-Y", &none, &deblk, 0, iw4, ih4, w, h,
(&db_lw, &db_lh, &db_left, &db_top),
(q_thr_v, side_thr_v, q_thr_h, side_thr_h),
bdmax, &MAX_WIDTH_Y_TBL, 16, 6,
);
let luma_sz = w * h;
let chroma_sz = cw * ch;
if cfg.level_u {
let uac = yac + cfg.uac_delta + 8 * cfg.dq_u;
let (q, s) = (deblock_quant_thr(uac, 0), deblock_side_thr(uac, 0));
verify_plane(
"DEBLOCK-U", &none, &deblk, luma_sz, ciw4, cih4, cw, ch,
(&cdb_lw, &cdb_lh, &cdb_left, &cdb_top),
(q, s, q, s), bdmax, &MAX_WIDTH_UV_TBL, 8, 2,
);
}
if cfg.level_v {
let vac = yac + cfg.vac_delta + 8 * cfg.dq_v;
let (q, s) = (deblock_quant_thr(vac, 0), deblock_side_thr(vac, 0));
verify_plane(
"DEBLOCK-V", &none, &deblk, luma_sz + chroma_sz, ciw4, cih4, cw, ch,
(&cdb_lw, &cdb_lh, &cdb_left, &cdb_top),
(q, s, q, s), bdmax, &MAX_WIDTH_UV_TBL, 8, 2,
);
}
}
pub fn dump_frame2_luma_wmap(path: &str) {
use crate::av2_deblock::MAX_WIDTH_Y_TBL as MW;
let (iw4, ih4, db_lw, db_lh, db_left, db_top) = FRAME.with(|fr| {
let f = fr.borrow();
(f.iw4, f.ih4, f.db_lw.clone(), f.db_lh.clone(), f.db_left.clone(), f.db_top.clone())
});
if db_lw.is_empty() { return; }
let mut wmap = vec![0i8; 2 * 60 * 108];
for y4 in 0..ih4.min(60) {
if !crate::av2_recon::work_tick("frm:1203") { break; }
for x4 in 1..iw4.min(108) {
if !crate::av2_recon::work_tick("frm:1204") { break; }
let cell = y4 * iw4 + x4;
if db_left[cell] {
let level = db_lw[cell].min(db_lw[cell - 1]) as usize;
wmap[y4 * 108 + x4] = MW[level] as i8;
}
}
}
for y4 in 1..ih4.min(60) {
if !crate::av2_recon::work_tick("frm:1213") { break; }
for x4 in 0..iw4.min(108) {
if !crate::av2_recon::work_tick("frm:1214") { break; }
let cell = y4 * iw4 + x4;
if db_top[cell] {
let level = db_lh[cell].min(db_lh[cell - iw4]) as usize;
wmap[6480 + y4 * 108 + x4] = MW[level] as i8;
}
}
}
let bytes: Vec<u8> = wmap.iter().map(|&v| v as u8).collect();
let _ = std::fs::write(path, &bytes);
}
fn score_filtered(tag: &str, out: &[i32], oracle: &[u8], input: &[u8], off: usize, w: usize, h: usize) {
let n = w * h;
let mut mism = 0u32;
let mut dav_changed = 0u32;
let mut first: Vec<(usize, usize, i32, i32)> = Vec::new();
for i in 0..n {
if !crate::av2_recon::work_tick("frm:1233") { break; }
let mine = out[i].clamp(0, 255) as u8;
let want = oracle[off + i];
if want != input[off + i] {
dav_changed += 1;
}
if mine != want {
mism += 1;
if first.len() < 12 {
first.push((i % w, i / w, mine as i32, want as i32));
}
}
}
crate::dlog!(
"[{tag}] {}/{} px exact ({:.3}%); {mism} mismatch, dav changed {dav_changed}",
n as u32 - mism, n, 100.0 * (n as u32 - mism) as f64 / n as f64
);
for (x, y, m, wv) in &first {
crate::dlog!(" ({x},{y}) mine={m} want={wv}");
}
}
pub fn run_cdef_verify(deblk_path: &str, cdef_path: &str) {
use crate::av2_filter::{adjust_strength, cdef_block, cdef_find_dir};
let (iw4, ih4, w, h, cw, ch, bdmax, cdef_idx, cdef_sbw, noskip) = FRAME.with(|fr| {
let f = fr.borrow();
(f.iw4, f.ih4, f.pl[0].w, f.pl[0].h, f.pl[1].w, f.pl[1].h,
f.bitdepth_max, f.cdef_idx.clone(), f.cdef_sbw, f.noskip.clone())
});
if w == 0 || cdef_idx.is_empty() {
return;
}
let cfg = CDEF_CFG.with(|c| c.get());
if !cfg.enabled {
crate::dlog!("[C2] cdef disabled");
return;
}
let bd_min8 = 0i32; let damping = cfg.damping + bd_min8;
crate::dlog!(
"[C2] damping={damping} n_strengths={} on_skiptx={} y_str={:?} uv_str={:?}",
cfg.n_strengths, cfg.on_skiptx, &cfg.y_strength[..cfg.n_strengths], &cfg.uv_strength[..cfg.n_strengths]
);
let deblk = match std::fs::read(deblk_path) {
Ok(b) => b,
_ => { crate::dlog!("[C2] could not read {deblk_path}"); return; }
};
let cdef = match std::fs::read(cdef_path) {
Ok(b) => b,
_ => { crate::dlog!("[C2] could not read {cdef_path}"); return; }
};
let (gcw, gch) = FRAME.with(|fr| { let f = fr.borrow(); (f.pl[1].w, f.pl[1].h) });
if deblk.len() < w * h + 2 * gcw * gch || cdef.len() < w * h + 2 * gcw * gch {
crate::dlog!("[C2] dump files don't match current plane geometry — skipping harness");
return;
}
let stride = w;
let input: Vec<i32> = (0..w * h).map(|i| deblk[i] as i32).collect();
let mut output = input.clone();
let luma_sz = w * h;
let chroma_sz = cw * ch;
let cin_u: Vec<i32> = (0..chroma_sz).map(|i| deblk[luma_sz + i] as i32).collect();
let cin_v: Vec<i32> = (0..chroma_sz).map(|i| deblk[luma_sz + chroma_sz + i] as i32).collect();
let mut cout_u = cin_u.clone();
let mut cout_v = cin_v.clone();
for by4 in (0..ih4).step_by(2) {
if !crate::av2_recon::work_tick("frm:1304") { break; }
for bx4 in (0..iw4).step_by(2) {
if !crate::av2_recon::work_tick("frm:1305") { break; }
let sb = (by4 >> 4) * cdef_sbw + (bx4 >> 4);
let ci = cdef_idx[sb];
if ci < 0 {
continue;
}
let ci = ci as usize;
let (y_lvl, uv_lvl) = (cfg.y_strength[ci], cfg.uv_strength[ci]);
if y_lvl == 0 && uv_lvl == 0 {
continue;
}
if !cfg.on_skiptx {
let stripe = by4 >> 1;
let m = noskip[stripe * iw4 + bx4] || (bx4 + 1 < iw4 && noskip[stripe * iw4 + bx4 + 1]);
if !m {
continue;
}
}
let y_pri = (y_lvl >> 2) << bd_min8;
let mut y_sec = y_lvl & 3;
y_sec += (y_sec == 3) as i32;
y_sec <<= bd_min8;
let uv_pri = (uv_lvl >> 2) << bd_min8;
let mut uv_sec = uv_lvl & 3;
uv_sec += (uv_sec == 3) as i32;
uv_sec <<= bd_min8;
let (have_top, have_bottom) = (by4 > 0, by4 + 2 < ih4);
let (have_left, have_right) = (bx4 > 0, bx4 + 2 < iw4);
let in_off = (by4 * 4) * stride + bx4 * 4;
let (dir, var) = if y_pri > 0 || uv_pri > 0 {
cdef_find_dir(&input, in_off, stride, bdmax)
} else {
(0, 0)
};
if y_pri > 0 {
let adj = adjust_strength(y_pri, var);
if adj > 0 || y_sec > 0 {
cdef_block(&mut output, in_off, stride, &input, in_off, stride, 8, 8, adj, y_sec, dir, damping, have_top, have_bottom, have_left, have_right, bdmax);
}
} else if y_sec > 0 {
cdef_block(&mut output, in_off, stride, &input, in_off, stride, 8, 8, 0, y_sec, 0, damping, have_top, have_bottom, have_left, have_right, bdmax);
}
if uv_lvl != 0 {
let uvdir = if uv_pri > 0 { dir } else { 0 };
let cin_off = (by4 * 2) * cw + bx4 * 2;
cdef_block(&mut cout_u, cin_off, cw, &cin_u, cin_off, cw, 4, 4, uv_pri, uv_sec, uvdir, damping - 1, have_top, have_bottom, have_left, have_right, bdmax);
cdef_block(&mut cout_v, cin_off, cw, &cin_v, cin_off, cw, 4, 4, uv_pri, uv_sec, uvdir, damping - 1, have_top, have_bottom, have_left, have_right, bdmax);
}
}
}
score_filtered("C2 CDEF-Y", &output, &cdef, &deblk, 0, w, h);
score_filtered("C2 CDEF-U", &cout_u, &cdef, &deblk, luma_sz, cw, ch);
score_filtered("C2 CDEF-V", &cout_v, &cdef, &deblk, luma_sz + chroma_sz, cw, ch);
}
pub fn run_ccso_verify(deblk_path: &str, cdef_path: &str, ccso_path: &str) {
use crate::av2_filter::{ccso_score, CCSO_POS};
let ccso_sh = FRAME.with(|fr| fr.borrow().ccso_px_shift);
let (w, h, cw, ch, ccso_blk, ccso_col256, ccso_n256) = FRAME.with(|fr| {
let f = fr.borrow();
(f.pl[0].w, f.pl[0].h, f.pl[1].w, f.pl[1].h, f.ccso_blk.clone(), f.ccso_col256, f.ccso_n256)
});
if w == 0 {
return;
}
let cfg = CCSO_CFG.with(|c| c.borrow().clone());
if !cfg.enabled {
crate::dlog!("[C3] ccso disabled");
return;
}
let deblk = match std::fs::read(deblk_path) {
Ok(b) => b,
_ => { crate::dlog!("[C3] could not read {deblk_path}"); return; }
};
let cdef = match std::fs::read(cdef_path) {
Ok(b) => b,
_ => { crate::dlog!("[C3] could not read {cdef_path}"); return; }
};
let ccso = match std::fs::read(ccso_path) {
Ok(b) => b,
_ => { crate::dlog!("[C3] could not read {ccso_path}"); return; }
};
let need = w * h + 2 * cw * ch;
if deblk.len() < need || cdef.len() < need || ccso.len() < need {
crate::dlog!("[C3] dump files don't match current plane geometry — skipping harness");
return;
}
let luma_sz = w * h;
let chroma_sz = cw * ch;
let dluma: Vec<i32> = (0..luma_sz).map(|i| deblk[i] as i32).collect();
let (hi, wi) = (h as i32, w as i32);
let cl = |v: i32, m: i32| v.clamp(0, m - 1);
for pl in 0..3 {
let pc = &cfg.p[pl];
let (pw, ph, ss_hor, ss_ver, off) = match pl {
0 => (w, h, 0u32, 0u32, 0usize),
1 => (cw, ch, 1, 1, luma_sz),
_ => (cw, ch, 1, 1, luma_sz + chroma_sz),
};
let mut out: Vec<i32> = (0..pw * ph).map(|i| cdef[off + i] as i32).collect();
crate::dlog!(
"[C3 cfg] pl={pl} en={} bo_only={} ext={} edge_clf={} q={} mbl2={}",
pc.enabled, pc.bo_only, pc.ext_filter, pc.edge_clf, pc.quant_step, pc.max_band_log2
);
if pc.enabled {
let single_band = pc.max_band_log2 == 0;
let shift = 8u32.saturating_sub(pc.max_band_log2);
let (dy, dx) = (CCSO_POS[pc.ext_filter][0] as i32, CCSO_POS[pc.ext_filter][1] as i32);
let q = pc.quant_step;
for py in 0..ph {
if !crate::av2_recon::work_tick("frm:1420") { break; }
for px in 0..pw {
if !crate::av2_recon::work_tick("frm:1421") { break; }
let lx = (px << ss_hor) as i32;
let ly = (py << ss_ver) as i32;
let block = ((ly >> ccso_sh) as usize) * ccso_col256 + ((lx >> ccso_sh) as usize);
if !ccso_blk[pl * ccso_n256 + block] {
continue;
}
let center = dluma[(ly * wi + lx) as usize];
let band = if single_band { 0 } else { center >> shift };
let (cls0, cls1) = if pc.bo_only {
(0u32, 0u32)
} else {
let n0 = dluma[(cl(ly + dy, hi) * wi + cl(lx + dx, wi)) as usize];
let n1 = dluma[(cl(ly - dy, hi) * wi + cl(lx - dx, wi)) as usize];
(ccso_score(n0 - center, q, pc.edge_clf), ccso_score(n1 - center, q, pc.edge_clf))
};
let lut = ((band as usize) << 4) | ((cls0 as usize) << 2) | (cls1 as usize);
let offset = pc.filter_offset.get(lut).copied().unwrap_or(0) as i32;
let idx = py * pw + px;
out[idx] = (out[idx] + offset).clamp(0, 255);
}
}
}
let tag = ["C3 CCSO-Y", "C3 CCSO-U", "C3 CCSO-V"][pl];
score_filtered(tag, &out, &ccso, &cdef, off, pw, ph);
}
}
pub fn run_gdf_verify(ccso_path: &str, all_path: &str, deblk_path: &str) {
let (w, h, yac, gdf_blk, _gbw) = FRAME.with(|fr| {
let f = fr.borrow();
(f.pl[0].w, f.pl[0].h, f.yac as i32, f.gdf_blk.clone(), f.gdf_blk_w)
});
if w == 0 {
return;
}
let cfg = GDF_CFG.with(|c| c.get());
if !cfg.enabled {
crate::dlog!("[C4] gdf disabled");
return;
}
crate::dlog!(
"[C4] mode={} qp_idx={} scale_idx={} block_size={} blocks_on={}/{}",
cfg.mode, cfg.qp_idx, cfg.scale_idx,
FRAME.with(|fr| fr.borrow().gdf_bs_px as i32),
gdf_blk.iter().filter(|&&b| b).count(), gdf_blk.len()
);
let ccso = match std::fs::read(ccso_path) {
Ok(b) => b,
_ => { crate::dlog!("[C4] could not read {ccso_path}"); return; }
};
let all = match std::fs::read(all_path) {
Ok(b) => b,
_ => { crate::dlog!("[C4] could not read {all_path}"); return; }
};
let deblk = match std::fs::read(deblk_path) {
Ok(b) => b,
_ => { crate::dlog!("[C4] could not read {deblk_path}"); return; }
};
let luma: Vec<i32> = (0..w * h).map(|i| ccso[i] as i32).collect();
let dblk: Vec<i32> = (0..w * h).map(|i| deblk[i] as i32).collect();
let mut out = luma.clone();
crate::av2_gdf::gdf_filter_frame(
&luma, &dblk, &mut out, w, h, 8, yac, cfg.mode, cfg.qp_idx, cfg.scale_idx, FRAME.with(|fr| fr.borrow().gdf_bs_px as i32), &gdf_blk, 0,
);
score_filtered("C4 GDF-Y", &out, &all, &ccso, 0, w, h);
}
fn stage_cmp(tag: &str, pl0: &[i32], pl1: &[i32], pl2: &[i32], w: usize, h: usize, cw: usize, ch: usize, path: &str) {
let o = match std::fs::read(path) { Ok(b) => b, _ => return };
let luma = w * h;
let chroma = cw * ch;
if o.len() < luma + 2 * chroma { return; }
for (pl, (buf, pw, ph, off)) in [(pl0, w, h, 0usize), (pl1, cw, ch, luma), (pl2, cw, ch, luma + chroma)].into_iter().enumerate() {
let mut ok = 0usize;
let mut first = None;
let n = pw * ph;
for i in 0..n {
if !crate::av2_recon::work_tick("frm:1507") { break; }
let m = buf[i].clamp(0, 255) as u8;
if m == o[off + i] { ok += 1; } else if first.is_none() { first = Some((i % pw, i / pw, m as i32, o[off + i] as i32)); }
}
crate::dlog!("[{tag} pl={pl}] {ok}/{n} ({:.3}%) first-miss={first:?}", 100.0 * ok as f64 / n as f64);
}
}
pub fn filter_frame_chain(gdf_ref_dst: usize) {
use crate::av2_deblock::{deblock_plane, deblock_quant_thr, deblock_side_thr, MAX_WIDTH_UV_TBL, MAX_WIDTH_Y_TBL};
use crate::av2_filter::{adjust_strength, cdef_block, cdef_find_dir, ccso_score, CCSO_POS};
let (iw4, ih4, w, h, cw, ch, ciw4, cih4, yac, bdmax) = FRAME.with(|fr| {
let f = fr.borrow();
(f.iw4, f.ih4, f.pl[0].w, f.pl[0].h, f.pl[1].w, f.pl[1].h, f.ciw4, f.cih4, f.yac as i32, f.bitdepth_max)
});
if w == 0 {
return;
}
if let Ok(prefix) = std::env::var("MPREF") {
thread_local! { static MPREF_N: std::cell::Cell<u32> = const { std::cell::Cell::new(0) }; }
let n = MPREF_N.with(|c| { let v = c.get(); c.set(v + 1); v });
let mut out: Vec<u8> = Vec::new();
FRAME.with(|fr| {
let f = fr.borrow();
for pl in 0..3 {
let p = &f.pl[pl];
for y in 0..p.h {
if !crate::av2_recon::work_tick("frm:1533") { break; }
for x in 0..p.w {
if !crate::av2_recon::work_tick("frm:1534") { break; }
out.push(p.px[y * p.stride + x].clamp(0, 255) as u8);
}
}
}
});
let _ = std::fs::write(format!("{prefix}_{n}.yuv"), &out);
}
let (mut pl0, mut pl1, mut pl2) = FRAME.with(|fr| {
let f = fr.borrow();
(f.pl[0].px.clone(), f.pl[1].px.clone(), f.pl[2].px.clone())
});
if let Ok(prefix) = std::env::var("PREFDUMP") {
thread_local! { static PREF_N: std::cell::Cell<u32> = const { std::cell::Cell::new(0) }; }
let n = PREF_N.with(|c| { let v = c.get(); c.set(v + 1); v });
let mut out: Vec<u8> = Vec::new();
FRAME.with(|fr| {
let f = fr.borrow();
let hbd = f.bitdepth_max > 255;
for pl in 0..3 {
let p = &f.pl[pl];
for y in 0..p.h {
if !crate::av2_recon::work_tick("frm:1555") { break; }
for x in 0..p.w {
if !crate::av2_recon::work_tick("frm:1556") { break; }
let v = p.px[y * p.stride + x];
if hbd {
out.extend_from_slice(&(v as u16).to_le_bytes());
} else {
out.push(v as u8);
}
}
}
}
});
let _ = std::fs::write(format!("{prefix}_{n}.yuv"), &out);
}
if std::env::var("MDBGRID").is_ok() {
let dc = DEBLOCK_CFG.with(|c| c.get());
crate::dlog!("[MDBCFG] y0={} y1={} u={} v={} sub_pu={} dqy0={} dqy1={} dqu={} dqv={}",
dc.level_y0 as u8, dc.level_y1 as u8, dc.level_u as u8, dc.level_v as u8,
dc.sub_pu as u8, dc.dq_y0, dc.dq_y1, dc.dq_u, dc.dq_v);
FRAME.with(|fr| {
let f = fr.borrow();
if !f.db_lw.is_empty() {
for y4 in 15..18usize {
if !crate::av2_recon::work_tick("frm:1577") { break; }
let mut row = String::new();
for x4 in 12..16usize {
if !crate::av2_recon::work_tick("frm:1579") { break; }
let cell = y4 * f.iw4 + x4;
row.push_str(&format!("Y({x4},{y4}) T{} lh{} | ", f.db_top[cell] as u8, f.db_lh[cell]));
}
crate::dlog!("[MDBGRIDY] {row}");
}
}
if !f.cdb_lw.is_empty() {
for cy in 21..26usize {
if !crate::av2_recon::work_tick("frm:1587") { break; }
let mut row = String::new();
for cx in 49..55usize {
if !crate::av2_recon::work_tick("frm:1589") { break; }
let cell = cy * f.ciw4 + cx;
row.push_str(&format!("({},{}) L{}{} T{}{} lw{} lh{} | ", cx, cy,
f.cdb_left[cell] as u8, f.cdb_spv[cell] as u8,
f.cdb_top[cell] as u8, f.cdb_sph[cell] as u8,
f.cdb_lw[cell], f.cdb_lh[cell]));
}
crate::dlog!("[MDBGRID] {row}");
}
}
});
}
if std::env::var("MDBW").is_ok() {
crate::av2_deblock::QMAP.with(|w| *w.borrow_mut() = vec![-1i16; 6 * 6480]);
}
let mut dcfg = DEBLOCK_CFG.with(|c| c.get());
if std::env::var("NODEBLOCK").is_ok() {
dcfg.level_y0 = false;
dcfg.level_y1 = false;
dcfg.level_u = false;
dcfg.level_v = false;
}
let (db_lw, db_lh, db_left, db_top, cdb_lw, cdb_lh, cdb_left, cdb_top) = FRAME.with(|fr| {
let f = fr.borrow();
(f.db_lw.clone(), f.db_lh.clone(), f.db_left.clone(), f.db_top.clone(), f.cdb_lw.clone(), f.cdb_lh.clone(), f.cdb_left.clone(), f.cdb_top.clone())
});
let (db_spv, db_sph, cdb_spv, cdb_sph) = FRAME.with(|fr| {
let f = fr.borrow();
(f.db_spv.clone(), f.db_sph.clone(), f.cdb_spv.clone(), f.cdb_sph.clone())
});
let ti = crate::av2_recon::TILE_INFO.with(|c| c.get());
let mut tile_v_y: Vec<usize> = Vec::new();
for c in 1..ti.cols as usize {
if !crate::av2_recon::work_tick("frm:1625") { break; }
let x4 = ti.col_start4[c] as usize;
if x4 > 0 && x4 < iw4 {
tile_v_y.push(x4);
}
}
let ss_hor = (ciw4 < iw4) as usize;
let tile_v_c: Vec<usize> = tile_v_y.iter().map(|&x| x >> ss_hor).collect();
let hbd = ((bdmax + 1).trailing_zeros() as i32 - 8) / 2;
let (sbq_grid, sbq_w) = FRAME.with(|fr| {
let f = fr.borrow();
(f.sb_qidx.clone(), f.cdef_sbw)
});
let sb_q = |extra: i32| -> Vec<(i32, i32, i32, i32)> {
sbq_grid.iter().map(|&q0| {
let q = if q0 != 0 { q0 as i32 } else { yac };
(0, 0, 0, 0, q).4
}).map(|q| (q + extra, q + extra, q + extra, q + extra)).collect()
};
let _ = &sb_q;
let (ss_h_c, ss_v_c) = (SS.with(|c| c.get()).0 as u32, SS.with(|c| c.get()).1 as u32);
if dcfg.level_y0 || dcfg.level_y1 {
let (qv, sv) = (deblock_quant_thr(yac + 8 * dcfg.dq_y0, hbd), deblock_side_thr(yac + 8 * dcfg.dq_y0, hbd));
let (qh, sh) = (deblock_quant_thr(yac + 8 * dcfg.dq_y1, hbd), deblock_side_thr(yac + 8 * dcfg.dq_y1, hbd));
let ythr: Vec<(i32, i32, i32, i32)> = sbq_grid.iter().map(|&q0| {
let q = if q0 != 0 { q0 as i32 } else { yac };
(deblock_quant_thr(q + 8 * dcfg.dq_y0, hbd), deblock_side_thr(q + 8 * dcfg.dq_y0, hbd),
deblock_quant_thr(q + 8 * dcfg.dq_y1, hbd), deblock_side_thr(q + 8 * dcfg.dq_y1, hbd))
}).collect();
if std::env::var("DQGRID").is_ok() {
crate::dlog!("[DQGRID] w={sbq_w} len={} grid={:?}", sbq_grid.len(), &sbq_grid[..sbq_grid.len().min(28)]);
crate::dlog!("[DQGRID] ythr[0..8]={:?}", &ythr[..ythr.len().min(8)]);
}
let sbt = if ythr.is_empty() { None } else { Some((ythr.as_slice(), sbq_w, 0u32, 0u32)) };
deblock_plane(&mut pl0, iw4, ih4, w, &db_lw, &db_lh, &db_left, &db_top, qv, sv, qh, sh, sbt, &db_spv, &db_sph, bdmax, &MAX_WIDTH_Y_TBL, 16, 6, dcfg.level_y0, dcfg.level_y1, &tile_v_y);
}
if dcfg.level_u {
let uac = yac + dcfg.uac_delta + 8 * dcfg.dq_u;
let (q, s) = (deblock_quant_thr(uac, hbd), deblock_side_thr(uac, hbd));
let uthr: Vec<(i32, i32, i32, i32)> = sbq_grid.iter().map(|&q0| {
let qq = (if q0 != 0 { q0 as i32 } else { yac }) + dcfg.uac_delta + 8 * dcfg.dq_u;
let (a, b) = (deblock_quant_thr(qq, hbd), deblock_side_thr(qq, hbd));
(a, b, a, b)
}).collect();
let sbt = if uthr.is_empty() { None } else { Some((uthr.as_slice(), sbq_w, ss_h_c, ss_v_c)) };
crate::av2_deblock::DBG_TAG.with(|c| c.set(std::env::var("DBLK444").is_ok()));
deblock_plane(&mut pl1, ciw4, cih4, cw, &cdb_lw, &cdb_lh, &cdb_left, &cdb_top, q, s, q, s, sbt, &cdb_spv, &cdb_sph, bdmax, &MAX_WIDTH_UV_TBL, 16 >> SS.with(|c| c.get()).1, 2, true, true, &tile_v_c);
crate::av2_deblock::DBG_TAG.with(|c| c.set(false));
}
if dcfg.level_v {
let vac = yac + dcfg.vac_delta + 8 * dcfg.dq_v;
let (q, s) = (deblock_quant_thr(vac, hbd), deblock_side_thr(vac, hbd));
let vthr: Vec<(i32, i32, i32, i32)> = sbq_grid.iter().map(|&q0| {
let qq = (if q0 != 0 { q0 as i32 } else { yac }) + dcfg.vac_delta + 8 * dcfg.dq_v;
let (a, b) = (deblock_quant_thr(qq, hbd), deblock_side_thr(qq, hbd));
(a, b, a, b)
}).collect();
let sbt = if vthr.is_empty() { None } else { Some((vthr.as_slice(), sbq_w, ss_h_c, ss_v_c)) };
deblock_plane(&mut pl2, ciw4, cih4, cw, &cdb_lw, &cdb_lh, &cdb_left, &cdb_top, q, s, q, s, sbt, &cdb_spv, &cdb_sph, bdmax, &MAX_WIDTH_UV_TBL, 16 >> SS.with(|c| c.get()).1, 2, true, true, &tile_v_c);
}
stage_cmp("POST-DEBLK", &pl0, &pl1, &pl2, w, h, cw, ch, &crate::av2_recon::cap_path("dav_f2postdeblk.yuv"));
if std::env::var("FORCE_PD").is_ok() {
if let Ok(o) = std::fs::read(&crate::av2_recon::cap_path("dav_f2postdeblk.yuv")) {
for i in 0..(w * h) { pl0[i] = o[i] as i32; }
for i in 0..(cw * ch) { pl1[i] = o[w * h + i] as i32; pl2[i] = o[w * h + cw * ch + i] as i32; }
}
}
let deblk_luma = pl0.clone();
if std::env::var("MDBW").is_ok() {
let oh = crate::av2_recon::CUR_FRAME_REF.with(|c| c.get().0);
dump_frame2_luma_wmap(&(crate::av2_recon::cap_path(&format!("mine_oh{oh}_wmap.bin"))));
crate::av2_deblock::QMAP.with(|w| {
let w = w.borrow();
if w.len() == 6 * 6480 && w.iter().any(|&v| v != -1) {
let bytes: Vec<u8> = w.iter().flat_map(|&v| (v as u16).to_le_bytes()).collect();
let _ = std::fs::write((crate::av2_recon::cap_path(&format!("mine_oh{oh}_qmap.bin"))), &bytes);
}
});
}
if std::env::var("OH1PD").is_ok() {
let mut out = Vec::new();
for y in 0..h {
if !crate::av2_recon::work_tick("frm:1716") { break; }
for x in 0..w {
if !crate::av2_recon::work_tick("frm:1717") { break; }
out.push(pl0[y * w + x] as u8);
}
}
for p in [&pl1, &pl2] {
if !crate::av2_recon::work_tick("frm:1721") { break; }
for y in 0..ch {
if !crate::av2_recon::work_tick("frm:1722") { break; }
for x in 0..cw {
if !crate::av2_recon::work_tick("frm:1723") { break; }
out.push(p[y * cw + x] as u8);
}
}
}
let oh = crate::av2_recon::CUR_FRAME_REF.with(|c| c.get().0);
let path = (crate::av2_recon::cap_path(&format!("mine_oh{oh}_postdeblock.yuv")));
let _ = std::fs::write(path, &out);
}
let ccfg = CDEF_CFG.with(|c| c.get());
let (cdef_idx, cdef_sbw, noskip) = FRAME.with(|fr| {
let f = fr.borrow();
(f.cdef_idx.clone(), f.cdef_sbw, f.noskip.clone())
});
if ccfg.enabled && !cdef_idx.is_empty() && std::env::var("NOCDEF").is_err() {
let bd_min8 = (bdmax + 1).trailing_zeros() as i32 - 8;
let damping = ccfg.damping + bd_min8;
let (yin, uin, vin) = (pl0.clone(), pl1.clone(), pl2.clone());
for by4 in (0..ih4).step_by(2) {
if !crate::av2_recon::work_tick("frm:1743") { break; }
for bx4 in (0..iw4).step_by(2) {
if !crate::av2_recon::work_tick("frm:1744") { break; }
let sb = (by4 >> 4) * cdef_sbw + (bx4 >> 4);
let ci = cdef_idx[sb];
if ci < 0 {
continue;
}
let (y_lvl, uv_lvl) = (ccfg.y_strength[ci as usize], ccfg.uv_strength[ci as usize]);
if y_lvl == 0 && uv_lvl == 0 {
continue;
}
if !ccfg.on_skiptx {
let stripe = by4 >> 1;
let m = noskip[stripe * iw4 + bx4] || (bx4 + 1 < iw4 && noskip[stripe * iw4 + bx4 + 1]);
if !m {
continue;
}
}
let y_pri = (y_lvl >> 2) << bd_min8;
let mut y_sec = y_lvl & 3;
y_sec += (y_sec == 3) as i32;
y_sec <<= bd_min8;
let uv_pri = (uv_lvl >> 2) << bd_min8;
let mut uv_sec = uv_lvl & 3;
uv_sec += (uv_sec == 3) as i32;
uv_sec <<= bd_min8;
let (ht, hb) = (by4 > 0, by4 + 2 < ih4);
let (hl, hr) = (bx4 > 0, bx4 + 2 < iw4);
let in_off = (by4 * 4) * w + bx4 * 4;
let (dir, var) = if y_pri > 0 || uv_pri > 0 { cdef_find_dir(&yin, in_off, w, bdmax) } else { (0, 0) };
if y_pri > 0 {
let adj = adjust_strength(y_pri, var);
if adj > 0 || y_sec > 0 {
cdef_block(&mut pl0, in_off, w, &yin, in_off, w, 8, 8, adj, y_sec, dir, damping, ht, hb, hl, hr, bdmax);
}
} else if y_sec > 0 {
cdef_block(&mut pl0, in_off, w, &yin, in_off, w, 8, 8, 0, y_sec, 0, damping, ht, hb, hl, hr, bdmax);
}
if uv_lvl != 0 {
let uvdir = if uv_pri > 0 { dir } else { 0 };
let (sshf, ssvf) = { let ss = SS.with(|c| c.get()); (ss.0 as usize, ss.1 as usize) };
let (ccw, cch) = (8 >> sshf, 8 >> ssvf);
let cdamp = damping - 1;
let uvdir = if sshf != ssvf {
const CONV422: [usize; 8] = [7, 0, 2, 4, 5, 6, 6, 6];
const CONV440: [usize; 8] = [1, 2, 2, 2, 3, 4, 6, 0];
if sshf == 1 { CONV422[uvdir] } else { CONV440[uvdir] }
} else {
uvdir
};
let cin_off = ((by4 * 4) >> ssvf) * cw + ((bx4 * 4) >> sshf);
cdef_block(&mut pl1, cin_off, cw, &uin, cin_off, cw, ccw, cch, uv_pri, uv_sec, uvdir, cdamp, ht, hb, hl, hr, bdmax);
cdef_block(&mut pl2, cin_off, cw, &vin, cin_off, cw, ccw, cch, uv_pri, uv_sec, uvdir, cdamp, ht, hb, hl, hr, bdmax);
}
}
}
}
if std::env::var("CFGDBG").is_ok() {
crate::dlog!("[MINECFG] cdef damping={} n_str={} on_skiptx={} y_str={:?} uv_str={:?}", ccfg.damping, ccfg.n_strengths, ccfg.on_skiptx, &ccfg.y_strength[..ccfg.n_strengths], &ccfg.uv_strength[..ccfg.n_strengths]);
FRAME.with(|fr| {
let f = fr.borrow();
let sbw = f.cdef_sbw;
let sbh = f.ih4.div_ceil(16);
for r in 0..sbh {
if !crate::av2_recon::work_tick("frm:1812") { break; }
let row: Vec<i8> = (0..sbw).map(|c| f.cdef_idx.get(r * sbw + c).copied().unwrap_or(-9)).collect();
crate::dlog!("[MINECDEFIDX] row{r}: {row:?}");
}
});
}
let sccfg = CCSO_CFG.with(|c| c.borrow().clone());
let ccso_sh = FRAME.with(|fr| fr.borrow().ccso_px_shift);
let (mut ccso_blk, ccso_col256, ccso_n256) = FRAME.with(|fr| {
let f = fr.borrow();
(f.ccso_blk.clone(), f.ccso_col256, f.ccso_n256)
});
CCSO_SLOT_MAP.with(|m| {
let slots = m.borrow();
for pl in 0..3 {
let pc = match sccfg.p.get(pl) {
Some(pc) if pc.sb_reuse => pc,
_ => continue,
};
if let Some(prev) = slots[pc.reuse_slot as usize].as_ref() {
if prev.len() == 3 * ccso_n256 {
for b in 0..ccso_n256 {
if !crate::av2_recon::work_tick("frm:1836") { break; }
ccso_blk[pl * ccso_n256 + b] = prev[pl * ccso_n256 + b];
}
}
}
}
});
FRAME.with(|fr| fr.borrow_mut().ccso_blk = ccso_blk.clone());
if std::env::var("CFGDBG").is_ok() {
for pl in 0..3 {
let p = &sccfg.p[pl];
let on_sbs = (0..ccso_n256).filter(|&b| ccso_blk.get(pl * ccso_n256 + b).copied().unwrap_or(false)).count();
let bands: Vec<i8> = (0..(1usize << p.max_band_log2)).map(|b| p.filter_offset.get(b << 4).copied().unwrap_or(0)).collect();
crate::dlog!("[MINECFG] ccso pl={pl} en={} bo_only={} mbl2={} ON_SBS={on_sbs}/{ccso_n256} band_off={bands:?}", p.enabled, p.bo_only, p.max_band_log2);
}
}
if sccfg.enabled && std::env::var("NOCCSO").is_err() {
let (hi, wi) = (h as i32, w as i32);
let cl = |v: i32, m: i32| v.clamp(0, m - 1);
for pl in 0..3usize {
if !crate::av2_recon::work_tick("frm:1858") { break; }
let pc = &sccfg.p[pl];
if !pc.enabled {
continue;
}
let (pw, ph, ss_hor, ss_ver) = if pl == 0 {
(w, h, 0u32, 0u32)
} else {
let ss = SS.with(|c| c.get());
(cw, ch, ss.0, ss.1)
};
let out = match pl {
0 => &mut pl0,
1 => &mut pl1,
_ => &mut pl2,
};
let single_band = pc.max_band_log2 == 0;
let bd = (bdmax + 1).trailing_zeros();
let shift = bd.saturating_sub(pc.max_band_log2);
let (dy, dx) = (CCSO_POS[pc.ext_filter][0] as i32, CCSO_POS[pc.ext_filter][1] as i32);
let q = pc.quant_step;
for py in 0..ph {
if !crate::av2_recon::work_tick("frm:1880") { break; }
for px in 0..pw {
if !crate::av2_recon::work_tick("frm:1881") { break; }
let (lx, ly) = ((px << ss_hor) as i32, (py << ss_ver) as i32);
let block = ((ly >> ccso_sh) as usize) * ccso_col256 + ((lx >> ccso_sh) as usize);
if !ccso_blk[pl * ccso_n256 + block] {
continue;
}
let center = deblk_luma[(ly * wi + lx) as usize];
let band = if single_band { 0 } else { center >> shift };
let (cls0, cls1) = if pc.bo_only {
(0u32, 0u32)
} else {
let n0 = deblk_luma[(cl(ly + dy, hi) * wi + cl(lx + dx, wi)) as usize];
let n1 = deblk_luma[(cl(ly - dy, hi) * wi + cl(lx - dx, wi)) as usize];
(ccso_score(n0 - center, q, pc.edge_clf), ccso_score(n1 - center, q, pc.edge_clf))
};
let lut = ((band as usize) << 4) | ((cls0 as usize) << 2) | (cls1 as usize);
let offset = pc.filter_offset.get(lut).copied().unwrap_or(0) as i32;
let idx = py * pw + px;
if std::env::var("CCSODBG").is_ok() && pl == 0 && py == 0 && (px == 338 || px == 167) {
crate::dlog!("[MCCSOA] px={px} src={center} band={band} cls={cls0},{cls1} off={offset} dst_in={} thr={q} shift={shift} bo={} eclf={} ext={}", out[idx], pc.bo_only as u8, pc.edge_clf as u8, pc.ext_filter);
}
out[idx] = (out[idx] + offset).clamp(0, bdmax);
}
}
}
}
stage_cmp("POST-CDEF", &pl0, &pl1, &pl2, w, h, cw, ch, &crate::av2_recon::cap_path("dav_f2postcdef.yuv"));
let mut lr_src: Option<Vec<i32>> = None;
if crate::av2_lr::LR_CFG.with(|c| c.borrow().enabled()) && std::env::var("NOLR").is_err() {
let (lr_noskip, f_iw4) = FRAME.with(|fr| {
let f = fr.borrow();
(f.lr_noskip.clone(), f.iw4)
});
crate::av2_lr::LR_CFG.with(|c| {
let cfg = c.borrow();
if cfg.p[1].r_type != 0 || cfg.p[2].r_type != 0 {
crate::dlog!("[rav2d] WARNING: CHROMA loop restoration not implemented (types u={} v={})", cfg.p[1].r_type, cfg.p[2].r_type);
}
});
let src = pl0.clone();
crate::av2_lr::lr_filter_luma(&mut pl0, &src, &deblk_luma, w, h, yac as u32, bdmax, &lr_noskip, f_iw4);
lr_src = Some(src);
}
let gcfg = if std::env::var("NOGDF").is_ok() { GdfCfg { enabled: false, ..GDF_CFG.with(|c| c.get()) } } else { GDF_CFG.with(|c| c.get()) };
let gdf_blk = FRAME.with(|fr| fr.borrow().gdf_blk.clone());
if gcfg.enabled {
let mut out = pl0.clone();
let guided: &Vec<i32> = lr_src.as_ref().unwrap_or(&pl0);
crate::av2_gdf::gdf_filter_frame(guided, &deblk_luma, &mut out, w, h, (bdmax + 1).trailing_zeros() as i32, yac, gcfg.mode, gcfg.qp_idx, gcfg.scale_idx, FRAME.with(|fr| fr.borrow().gdf_bs_px as i32), &gdf_blk, gdf_ref_dst);
pl0 = out;
}
if std::env::var("MFIN").is_ok() {
thread_local! { static FIN_N: std::cell::Cell<u32> = const { std::cell::Cell::new(0) }; }
let n = FIN_N.with(|c| { let v = c.get(); c.set(v + 1); v });
let mut out: Vec<u8> = Vec::with_capacity(w * h * 3 / 2);
for v in &pl0 { out.push((*v).clamp(0, 255) as u8); }
for p in [&pl1, &pl2] {
for v in p.iter() { out.push((*v).clamp(0, 255) as u8); }
if !crate::av2_recon::work_tick("frm:1947") { break; }
}
let _ = std::fs::write((crate::av2_recon::cap_path(&format!("mine_fin_{n}.yuv"))), &out);
}
FRAME.with(|fr| {
let mut f = fr.borrow_mut();
f.pl[0].px = pl0;
f.pl[1].px = pl1;
f.pl[2].px = pl2;
});
}
pub fn gather_edges(
p: &Plane,
x: usize,
y: usize,
w: usize,
h: usize,
have_top: bool,
have_left: bool,
have_top_right: usize, have_bottom_left: usize, base: i32,
) -> (Vec<i32>, Vec<i32>, i32) {
let sz = w + h + 1;
let mut top = vec![base; sz + 16];
let mut left = vec![base; sz + 16];
let corner = if have_top && have_left {
p.at(x - 1, y - 1)
} else if have_top {
p.at(x, y - 1)
} else if have_left {
p.at(x - 1, y)
} else {
base
};
if have_top {
let xmax = p.w - 1;
for i in 0..w {
if !crate::av2_recon::work_tick("frm:1996") { break; }
top[i] = p.at((x + i).min(xmax), y - 1);
}
let tr = have_top_right.min(h);
for i in 0..tr {
if !crate::av2_recon::work_tick("frm:2000") { break; }
top[w + i] = p.at((x + w + i).min(xmax), y - 1);
}
let last = if w + tr > 0 { top[w + tr - 1] } else { corner };
for i in (w + tr)..top.len() {
if !crate::av2_recon::work_tick("frm:2004") { break; }
top[i] = last;
}
} else {
let v = if have_left { p.at(x - 1, y) } else { base - 1 };
for t in top.iter_mut() {
if !crate::av2_recon::work_tick("frm:2012") { break; }
*t = v;
}
}
if have_left {
let ymax = p.h - 1;
for i in 0..h {
if !crate::av2_recon::work_tick("frm:2020") { break; }
left[i] = p.at(x - 1, (y + i).min(ymax));
}
let bl = have_bottom_left.min(w);
for i in 0..bl {
if !crate::av2_recon::work_tick("frm:2025") { break; }
left[h + i] = p.at(x - 1, (y + h + i).min(ymax));
}
let last = if h + bl > 0 { left[h + bl - 1] } else { corner };
for i in (h + bl)..left.len() {
if !crate::av2_recon::work_tick("frm:2029") { break; }
left[i] = last;
}
} else {
let v = if have_top { p.at(x, y - 1) } else { base + 1 };
for l in left.iter_mut() {
if !crate::av2_recon::work_tick("frm:2035") { break; }
*l = v;
}
}
(top, left, corner)
}