diff --git a/crates/av1/README.md b/crates/av1/README.md index 0654c599a..e046584bd 100644 --- a/crates/av1/README.md +++ b/crates/av1/README.md @@ -25,7 +25,7 @@ reference) is used only as an external test oracle. | Tiles and tile groups (uniform and explicit spacing, tile size bytes) | 5.11 | done (tiles decoded in parallel) | | Intra frame mode info: partitions, skip, segment id, CDEF index, delta q / lf, y / uv modes, angle deltas, CfL alphas, palette (colors, cache, color index map), filter intra, tx size (incl. var-tx syntax) | 5.11 | done, bit-exact | | Coefficients (all_zero, eob, base / br levels, Golomb, dc sign, tx type sets, scans) | 5.11.39 | done, bit-exact | -| Dequantisation incl. quantiser matrices | 7.12 | done (qmatrix not yet oracle-tested) | +| Dequantisation incl. quantiser matrices | 7.12 | done | | Inverse transforms: DCT 4–64, ADST 4/8/16, flip ADST, identity 4–32, WHT (lossless), rectangular | 7.13 | done, bit-exact | | Intra prediction: DC, V/H + directional with edge filter and upsampling, smooth (3), Paeth, recursive filter intra, CfL, palette | 7.11.2, 7.11.4, 7.11.5 | done, bit-exact | | Inter mode info: segment id prediction, skip mode, reference frames (single / compound, uni / bi), modes, DRL, MV coding, inter-intra, motion mode, compound type, interpolation filters | 5.11.18–5.11.32 | done, bit-exact | diff --git a/crates/av1/src/tile.rs b/crates/av1/src/tile.rs index 0a9f0df26..91bd665a5 100644 --- a/crates/av1/src/tile.rs +++ b/crates/av1/src/tile.rs @@ -113,7 +113,8 @@ pub(crate) struct TileDecoder<'a, 'f> { pub b: Block, pub mvs: crate::mvpred::MvStack, pub nb: crate::inter_info::Neighbours, - /// Quant[] for the current transform block (raster order, stride per Adjusted size). + /// Quant[] for the current transform block (raster order, stride per Adjusted size); all + /// zero between transform blocks (`reconstruct` clears what it reads). quant: Vec, dequant: Vec, residual: Vec, diff --git a/crates/av1/src/tile/coeffs.rs b/crates/av1/src/tile/coeffs.rs index 35aaac9d2..209bcbacb 100644 --- a/crates/av1/src/tile/coeffs.rs +++ b/crates/av1/src/tile/coeffs.rs @@ -174,8 +174,6 @@ impl<'a, 'f> TileDecoder<'a, 'f> { pub(super) fn coeffs(&mut self, plane: usize, start_x: usize, start_y: usize, tx_sz: usize) -> usize { let pos = TxbPos { x4: start_x >> 2, y4: start_y >> 2, w4: TX_WIDTH[tx_sz] as usize >> 2, h4: TX_HEIGHT[tx_sz] as usize >> 2 }; let tx_sz_ctx = (TX_SIZE_SQR[tx_sz] as usize + TX_SIZE_SQR_UP[tx_sz] as usize + 1) >> 1; - let seg_eob = if tx_sz == TX_16X64 || tx_sz == TX_64X16 { 512 } else { 1024.min(TX_WIDTH[tx_sz] as usize * TX_HEIGHT[tx_sz] as usize) }; - self.quant[..seg_eob].iter_mut().for_each(|q| *q = 0); let mut eob = 0usize; let mut cul_level = 0u32; let mut dc_category = 0u8; @@ -458,10 +456,11 @@ impl<'a, 'f> TileDecoder<'a, 'f> { /// Reconstruct process (7.12.3). pub(super) fn reconstruct(&mut self, plane: usize, x: usize, y: usize, tx_sz: usize, dc_only: bool) { - let dq_denom: i64 = match tx_sz { - TX_32X32 | TX_16X32 | TX_32X16 | TX_16X64 | TX_64X16 => 2, - TX_64X64 | TX_32X64 | TX_64X32 => 4, - _ => 1, + // dqDenom (7.12.3) is 1, 2 or 4 and the dividend is non-negative. + let dq_shift = match tx_sz { + TX_32X32 | TX_16X32 | TX_32X16 | TX_16X64 | TX_64X16 => 1, + TX_64X64 | TX_32X64 | TX_64X32 => 2, + _ => 0, }; let log2w = TX_WIDTH_LOG2[tx_sz] as u32; let log2h = TX_HEIGHT_LOG2[tx_sz] as u32; @@ -492,7 +491,7 @@ impl<'a, 'f> TileDecoder<'a, 'f> { } for i in 0..th { for j in 0..tw { - let qv = self.quant[i * tw + j]; + let qv = std::mem::take(&mut self.quant[i * tw + j]); if qv == 0 { continue; } @@ -504,7 +503,7 @@ impl<'a, 'f> TileDecoder<'a, 'f> { q }; let dq = qv as i64 * q2; - let mag = (dq.abs() & 0xFFFFFF) / dq_denom; + let mag = (dq.abs() & 0xFFFFFF) >> dq_shift; let dq2 = if dq < 0 { -mag } else { mag }; self.dequant[i * 64 + j] = dq2.clamp(-lim, lim - 1) as i32; } diff --git a/crates/av1/tests/it/oracle_inter.rs b/crates/av1/tests/it/oracle_inter.rs index 5d443194f..65a229752 100644 --- a/crates/av1/tests/it/oracle_inter.rs +++ b/crates/av1/tests/it/oracle_inter.rs @@ -15,12 +15,14 @@ fn specs() -> Vec { ] } -/// Super-resolution (denominator 12 on the inter frames) and film grain synthesis. +/// Super-resolution (denominator 12 on the inter frames), film grain synthesis and quantiser +/// matrices. fn specs_tools() -> Vec { let p = |params: &'static str| -> Vec<&'static str> { vec!["-preset", "6", "-crf", "35", "-svtav1-params", params] }; vec![ Spec::new("inter_superres", "testsrc2=s=416x240:r=25", 8, "yuv420p", &p("superres-mode=1:superres-denom=12:superres-kf-denom=13")), Spec::new("inter_film_grain", "testsrc2=s=352x288:r=25,noise=alls=20:allf=t", 8, "yuv420p", &p("film-grain=10")), + Spec::new("inter_qmatrix_10bit", "mandelbrot=s=352x288:r=25", 8, "yuv420p10le", &p("enable-qm=1:qm-min=0:qm-max=8")), ] } diff --git a/crates/av1/tests/it/oracle_intra.rs b/crates/av1/tests/it/oracle_intra.rs index d002af67e..1b879d853 100644 --- a/crates/av1/tests/it/oracle_intra.rs +++ b/crates/av1/tests/it/oracle_intra.rs @@ -34,6 +34,7 @@ fn specs_filters() -> Vec { Spec::new("intra_lr_mandel", "mandelbrot=s=352x288:r=25", 2, "yuv420p", &p("4", "40", "enable-cdef=0:keyint=1")), Spec::new("intra_all_testsrc", "testsrc2=s=640x360:r=25", 2, "yuv420p", &p("4", "45", "keyint=1")), Spec::new("intra_all_10bit", "mandelbrot=s=320x240:r=25", 2, "yuv420p10le", &p("4", "40", "keyint=1")), + Spec::new("intra_qmatrix_noise", "testsrc2=s=352x288:r=25,noise=alls=10:allf=t", 2, "yuv420p", &p("6", "30", "enable-qm=1:qm-min=0:qm-max=8:keyint=1")), Spec::new("intra_all_noise_odd", "testsrc2=s=250x150:r=25,noise=alls=20:allf=t", 2, "yuv420p", &p("3", "35", "keyint=1")), // 128x128 superblocks, intra edge filter off, Wiener LR on all planes Spec::new("intra_all_grad_noise_10bit", "gradients=s=640x360:r=25,noise=alls=25:allf=t", 1, "yuv420p10le", &p("1", "50", "keyint=1")),