Browse / github.com/storytold/effectcraft / patch
av1enc: build the three half-sample reference planes in one pass
av1enc: build the three half-sample reference planes in one pass Part of #2387 (A-I4 only; the other items of that issue are separate) ## What - New `pred::half_planes` builds the three half-sample planes (8,0), (0,8), (8,8) in one pass instead of three `subpel_plane` calls: the horizontal half-sample pass is shared by (8,0) and (8,8), the phase-0 kernels are exact shifts (`Round2(128*v, 11) = Round2(v, 4)`, `Round2(16*s, 11) = Round2(s, 7)`), and interior pixels skip the per-tap clamps. - `subpel_plane` becomes test-only (`#[cfg(test)]`) and serves as the reference: the new unit test `half_planes_match_subpel_plane` compares all three planes bit for bit (
- Status
- open
- Score
- 0.00
- Adopters
- 0 other operators
- Author
- vangel76 (imported from pull request #2401, open)
- Base
991904888a20b7da72b2a4880b21c7d912154736- Size
- +77 −2 in 2 files
- Review
- pending
- Shared
- 2026-10-28
- Id
f436e063649b84dbcd456729
How it went
No other operator has reported using it yet.
Diff
raw · crates/av1enc/src/decide.rs crates/av1enc/src/pred.rs
@@ -163,7 +163,7 @@ impl<'a> Decider<'a> { lambda, lambda_sad: lambda.sqrt(), half: match refr {- Some(rf) => [(8, 0), (0, 8), (8, 8)].map(|(fx, fy)| subpel_plane(&rf.planes[0], g.width, g.height, fx, fy, bd)),+ Some(rf) => half_planes(&rf.planes[0], g.width, g.height, bd), None => Default::default(), }, }@@ -293,7 +293,8 @@ pub(crate) fn predict_inter( /// The visible `w x h` area of a reference plane interpolated at the sub-sample phase /// (`fx`, `fy`) (1/16 units) with the EIGHTTAP filter, as `predict_inter` computes it for-/// blocks wider and taller than 4. Used for motion search.+/// blocks wider and taller than 4. The reference for `half_planes`, which the encoder uses.+#[cfg(test)] pub(crate) fn subpel_plane(refp: &Plane, w: usize, h: usize, fx: usize, fy: usize, bit_depth: u32) -> Vec<u16> { let kh = &SUBPEL_FILTERS[EIGHTTAP][fx]; let kv = &SUBPEL_FILTERS[EIGHTTAP][fy];@@ -323,6 +324,66 @@ pub(crate) fn subpel_plane(refp: &Plane, w: usize, h: usize, fx: usize, fy: usiz out } +/// The three half-sample planes (8, 0), (0, 8), (8, 8) of `subpel_plane` in one pass: the+/// horizontal half-sample pass is shared by (8, 0) and (8, 8), and the phase-0 kernels reduce to+/// exact shifts (Round2( 128 * v, 11 ) = Round2( v, 4 ), Round2( 16 * s, 11 ) = Round2( s, 7 )),+/// so the result equals three `subpel_plane` calls bit for bit.+pub(crate) fn half_planes(refp: &Plane, w: usize, h: usize, bit_depth: u32) -> [Vec<u16>; 3] {+ let k = &SUBPEL_FILTERS[EIGHTTAP][8];+ let max = (1i32 << bit_depth) - 1;+ let (lx, ly) = (w as i32 - 1, h as i32 - 1);+ // horizontal pass at phase 8: Round2( sum, 3 )+ let mut hp = vec![0i32; w * h];+ for y in 0..h {+ let row = &refp.row(y)[..w];+ let out = &mut hp[y * w..y * w + w];+ let tap = |x: i32| -> i32 {+ let mut s = 0i32;+ for t in 0..8 {+ s += k[t] as i32 * row[(x + t as i32 - 3).clamp(0, lx) as usize] as i32;+ }+ round2(s, 3)+ };+ if w >= 8 {+ for x in 0..3 {+ out[x] = tap(x as i32);+ }+ for (x, o) in out.iter_mut().enumerate().take(w - 4).skip(3) {+ let seg = &row[x - 3..x + 5];+ let mut s = 0i32;+ for t in 0..8 {+ s += k[t] as i32 * seg[t] as i32;+ }+ *o = round2(s, 3);+ }+ for x in w - 4..w {+ out[x] = tap(x as i32);+ }+ } else {+ for (x, o) in out.iter_mut().enumerate() {+ *o = tap(x as i32);+ }+ }+ }+ let p80: Vec<u16> = hp.iter().map(|&v| round2(v, 4).clamp(0, max) as u16).collect();+ let mut p08 = vec![0u16; w * h];+ let mut p88 = vec![0u16; w * h];+ for y in 0..h {+ let rows: [usize; 8] = std::array::from_fn(|t| (y as i32 + t as i32 - 3).clamp(0, ly) as usize);+ let (o08, o88) = (&mut p08[y * w..y * w + w], &mut p88[y * w..y * w + w]);+ for x in 0..w {+ let (mut a, mut b) = (0i32, 0i32);+ for t in 0..8 {+ a += k[t] as i32 * refp.data[rows[t] * refp.stride + x] as i32;+ b += k[t] as i32 * hp[rows[t] * w + x];+ }+ o08[x] = round2(a, 7).clamp(0, max) as u16;+ o88[x] = round2(b, 11).clamp(0, max) as u16;+ }+ }+ [p80, p08, p88]+}+ #[cfg(test)] mod tests { use super::*;@@ -353,6 +414,20 @@ mod tests { } } + #[test]+ fn half_planes_match_subpel_plane() {+ for (w, h) in [(37usize, 29usize), (5, 3), (1, 1), (64, 64)] {+ let mut p = Plane::new(64, 64);+ for (i, v) in p.data.iter_mut().enumerate() {+ *v = ((i * 7919) % 1024) as u16;+ }+ let hp = half_planes(&p, w, h, 10);+ for (i, (fx, fy)) in [(8, 0), (0, 8), (8, 8)].into_iter().enumerate() {+ assert_eq!(hp[i], subpel_plane(&p, w, h, fx, fy, 10), "{w}x{h} phase ({fx}, {fy})");+ }+ }+ }+ #[test] fn phase_zero_filters_are_impulses() { for f in SUBPEL_FILTERS.iter() {