rusty_h264_accel/mectx.rs
1//! H-14 R3: `MeCtx` — the per-search motion-estimation evaluation context.
2//!
3//! The reconciliation (WHYS H-14 R2) measured ~23 ns/eval of GLUE around a
4//! 16-18 ns SATD kernel: per-candidate slice re-derivation, bounds asserts,
5//! phase match ladder, wrapper hops. This context collects that chain: the
6//! plane geometry is validated ONCE at construction, the kernel function
7//! pointers are chosen ONCE (size × ISA), and `eval` does only integer bounds,
8//! a phase pick, one offset multiply, and the raw kernel call.
9//!
10//! The `unsafe` stays quarantined in this crate; the encoder remains
11//! `#![forbid(unsafe_code)]`. Every value returned is EXACTLY what the safe
12//! path computes (`2·WelsSampleSatd` for full/half phases, `Σ|H·d|` fused-avg
13//! for quarter phases), so an eval served here instead of there cannot change
14//! the bitstream — pinned by `mectx_matches_safe_path`.
15
16use crate::satd_avg::{satd_avg_w16, satd_avg_w8};
17
18type WelsSatd = unsafe extern "C" fn(*const u8, i32, *const u8, i32) -> i32;
19type AvgSatd = unsafe fn(*const u8, usize, *const u8, *const u8, usize, usize) -> u32;
20
21/// Plane indices into [`MeCtx::planes`].
22const PF: usize = 0;
23const PH: usize = 1;
24const PV: usize = 2;
25const PC: usize = 3;
26
27pub struct MeCtx<'a> {
28 src: &'a [u8],
29 cw: usize,
30 planes: [&'a [u8]; 4], // f, h, v, c — each pw×ph, stride == pw
31 stride: usize,
32 pad: isize,
33 /// Valid top-left range for a candidate's padded plane position, precomputed
34 /// with the same `+1` slack the safe `hpel_ref`/`hpel_qpel_refs` guards use
35 /// (the quarter phases read one sample past the block on either axis).
36 px_max: isize,
37 py_max: isize,
38 lx: isize,
39 ly: isize,
40 w: usize,
41 h: usize,
42 satd: WelsSatd,
43 avg: AvgSatd,
44}
45
46impl<'a> MeCtx<'a> {
47 /// Validates the whole search geometry once. Returns `None` when AVX2 is
48 /// unavailable, the shape is uncovered, or any slice is short — the caller
49 /// then uses the safe per-eval path for the entire search.
50 #[allow(clippy::too_many_arguments)]
51 pub fn new(
52 src: &'a [u8],
53 cw: usize,
54 f: &'a [u8],
55 h_pl: &'a [u8],
56 v: &'a [u8],
57 c: &'a [u8],
58 stride: usize,
59 pad: usize,
60 pw: usize,
61 ph: usize,
62 lx: usize,
63 ly: usize,
64 w: usize,
65 h: usize,
66 ) -> Option<Self> {
67 if !crate::has_avx2() || stride != pw {
68 return None;
69 }
70 let (satd, avg): (WelsSatd, AvgSatd) = match (w, h) {
71 (16, 16) => (crate::WelsSampleSatd16x16_avx2 as WelsSatd, satd_avg_w16 as AvgSatd),
72 (16, 8) => (crate::WelsSampleSatd16x8_avx2 as WelsSatd, satd_avg_w16 as AvgSatd),
73 (8, 16) => (crate::WelsSampleSatd8x16_avx2 as WelsSatd, satd_avg_w8 as AvgSatd),
74 (8, 8) => (crate::WelsSampleSatd8x8_avx2 as WelsSatd, satd_avg_w8 as AvgSatd),
75 _ => return None,
76 };
77 if src.len() < (h - 1) * cw + w {
78 return None;
79 }
80 let need = pw.checked_mul(ph)?;
81 if f.len() < need || h_pl.len() < need || v.len() < need || c.len() < need {
82 return None;
83 }
84 // px/py are padded-plane coordinates of the candidate's top-left sample;
85 // the +1 covers the quarter phases' shifted operand (offset 1 or stride).
86 let px_max = pw as isize - w as isize - 1;
87 let py_max = ph as isize - h as isize - 1;
88 if px_max < 0 || py_max < 0 {
89 return None;
90 }
91 Some(MeCtx {
92 src,
93 cw,
94 planes: [f, h_pl, v, c],
95 stride,
96 pad: pad as isize,
97 px_max,
98 py_max,
99 lx: lx as isize,
100 ly: ly as isize,
101 w,
102 h,
103 satd,
104 avg,
105 })
106 }
107
108 /// SATD distortion of candidate `(mvx, mvy)` (quarter-pel units) — the exact
109 /// value the safe dispatch computes — or `None` when the candidate leaves the
110 /// validated window (caller falls back; identical value there too).
111 #[inline]
112 pub fn eval(&self, mvx: i32, mvy: i32) -> Option<u32> {
113 let px = self.lx + (mvx >> 2) as isize + self.pad;
114 let py = self.ly + (mvy >> 2) as isize + self.pad;
115 if px < 0 || py < 0 || px > self.px_max || py > self.py_max {
116 return None;
117 }
118 let base = py as usize * self.stride + px as usize;
119 let (fx, fy) = (mvx & 3, mvy & 3);
120 let st = self.stride;
121 // SAFETY (whole match): `base + oa/ob + (h-1)·stride + w (+1 slack)` is
122 // inside every plane by the constructor's `pw·ph` length check together
123 // with the px/py window test above; `src` covers `(h-1)·cw + w`.
124 unsafe {
125 if fx & 1 == 0 && fy & 1 == 0 {
126 // Full- and half-pel: one plane, read in place.
127 let p = match (fx, fy) {
128 (0, 0) => self.planes[PF],
129 (2, 0) => self.planes[PH],
130 (0, 2) => self.planes[PV],
131 _ => self.planes[PC], // (2, 2)
132 };
133 let v = (self.satd)(
134 self.src.as_ptr(),
135 self.cw as i32,
136 p.as_ptr().add(base),
137 st as i32,
138 );
139 return Some(2 * v as u32);
140 }
141 // Quarter phases: the spec's (a+b+1)>>1 of two planes, operand table
142 // identical to `hpel_qpel_refs` (pinned by the oracle test).
143 let (pa, oa, pb, ob) = match (fx, fy) {
144 (1, 0) => (PF, 0, PH, 0),
145 (3, 0) => (PF, 1, PH, 0),
146 (0, 1) => (PF, 0, PV, 0),
147 (0, 3) => (PF, st, PV, 0),
148 (1, 1) => (PH, 0, PV, 0),
149 (3, 1) => (PH, 0, PV, 1),
150 (1, 3) => (PH, st, PV, 0),
151 (3, 3) => (PH, st, PV, 1),
152 (2, 1) => (PH, 0, PC, 0),
153 (2, 3) => (PH, st, PC, 0),
154 (1, 2) => (PV, 0, PC, 0),
155 _ => (PV, 1, PC, 0), // (3, 2)
156 };
157 Some((self.avg)(
158 self.src.as_ptr(),
159 self.cw,
160 self.planes[pa].as_ptr().add(base + oa),
161 self.planes[pb].as_ptr().add(base + ob),
162 st,
163 self.h,
164 ))
165 }
166 }
167}