Skip to main content

Crate rusty_h264_accel

Crate rusty_h264_accel 

Source
Expand description

SIMD acceleration for rusty_h264 — pure Rust, no assembly. The vendored openh264 NASM this crate grew around was fully ripped on 2026-08-12; every kernel is now portable Rust (x86-64 SSE2/AVX2 intrinsics + aarch64 NEON + scalar oracles), no nasm, no build script, no FFI.

This crate is deliberately not #![forbid(unsafe_code)]: it is the one place unsafe lives, behind safe wrappers, so the codec core stays forbid(unsafe).

§Structure, and where it is going

docs/add_SIMD_rip_ASM.md is ripping the assembly out kernel by kernel. Two things follow from that, and this file is arranged around them:

  • x86_asm holds everything still backed by openh264 NASM. It is gated on target_arch = "x86_64" and shrinks with every phase of the campaign.
  • Portable modules (chroma_mc, …) hold Rust intrinsics with an x86-64 path, an aarch64 NEON path, and a scalar reference that all three are tested bit-identical against. These compile and run on every architecture.

Until the campaign finishes, the crate is a mix. The whole crate used to be #![cfg(target_arch = "x86_64")] — compiled to nothing on ARM, which is why aarch64 ran fully scalar. That gate now sits on the x86_asm module alone, so portable kernels reach ARM as they land.

Order matters: replace, then rip. The vendored assembly measures ~1.94x on decode (paired, N=5, 34/35 reps above 1.0), so deleting a kernel before its portable replacement is bit-identical and no slower would ship a real regression.

openh264 asm is BSD-2 licensed; attribution lives in vendor/LICENSE.openh264.

Structs§

MeCtx

Functions§

bs_motion_masks
Safe dispatcher: AVX2 when present, else the SSE2 twin — never None on x86-64 since 2026-08-27 (audit site 18): SSE2 is the x86-64 BASELINE, so before the twin existed, a hypervisor masking AVX2 (or a pre-Haswell CPU) silently dropped the packed-bS arm and everything routed on it back to the scalar per-edge walk. The Option shape is kept for the callers.
bs_motion_masks_two_list
Safe dispatcher for the two-list masks kernel; None when AVX2 is absent.
chroma8x8_pred
8x8 chroma prediction into pred (>= 64 bytes). mode: 2=Vertical, 3(=else)=Plane — the only modes the asm served; DC/Horizontal stay with the caller’s scalar, exactly the old wrapper’s contract.
dct_four_t4
Forward 4x4 transform of an 8x8 region’s residual (four blocks, SUBBLOCKS order). See dct_four_t4_scalar for the reference semantics.
dct_four_t4_scalar
Forward-transform the residual of four 4x4 blocks covering an 8x8 region.
deblock_chroma_eq4_h
Chroma (both planes), vertical edge, bS==4.
deblock_chroma_eq4_v
Chroma (both planes), horizontal edge, bS==4.
deblock_chroma_lt4_h
Chroma (both planes), vertical edge, bS<4. *_p1 point at column p1 of row 0 (q0 is at column 2). NOTE: scalar for now — a vertical chroma edge is 8 rows x 2 planes, and the transpose needed to vectorise it costs more than the 4 filtered samples per row save. Measured before leaving it this way.
deblock_chroma_lt4_v
Chroma (both planes), horizontal edge, bS<4. *_p1 point at the p1 row.
deblock_luma_eq4_h
Luma, vertical edge, bS==4.
deblock_luma_eq4_v
Luma, horizontal edge, bS==4.
deblock_luma_lt4_h
Luma, vertical edge (filter horizontally), bS<4. p4 points at column p3 of row 0.
deblock_luma_lt4_v
Luma, horizontal edge (filter vertically), bS<4. p3 points at the p3 row.
dequant_4x4
Safe dispatcher. None = no AVX2, caller keeps its scalar twin (the oracle).
hpel_fused
Builds the three half-pel planes from the edge-padded full-pel plane f (pw×ph, row stride pw). Returns false (no work done) when no SIMD arm applies (x86-64 without AVX2, other ISAs, or a plane too narrow for the vector interior) — the caller falls back to its scalar/tile path.
i16x16_luma_pred
16x16 luma prediction into pred (>= 256 bytes). rec[base] is the MB top-left; the top row is rec[base - stride ..], the left column rec[base - 1 + y*stride]. mode: 0=V, 1=H, 2=DC, 3=Plane — the caller guarantees the needed neighbours exist (both for DC/Plane), exactly the contract the asm wrapper had.
idct_four_t4_rec
Inverse 4x4 transform + reconstruct of an 8x8 region. See idct_four_t4_rec_scalar for the reference semantics.
idct_four_t4_rec_scalar
Inverse-transform four 4x4 coefficient blocks and add them to pred, writing the reconstruction into rec.
mb_uniform
Safe dispatcher for the uniform-motion test: AVX2 when present, else the SSE2 twin — never None on x86-64 since 2026-08-27 (audit site 18). This test runs on ALL macroblocks (9.5x the masks kernel’s work, per the counts above), so it is the arm a masked-AVX2 VM was losing most of.
mc_centre
Centre half-pel plane: clip((6tap applied twice + 512) >> 10), w in {8, 16}.
mc_centre_hq
Fused centre-adjacent quarter-pel, horizontal flavour ((2,1) fdr=0, (2,3) fdr=1): ONE pass-1 + one fused pass-2/avg instead of the 3-kernel 2-staging compose. Byte-identical by construction: the hor-half is the rounded form of the pass-1 rows the centre already computes.
mc_centre_vq
Fused centre-adjacent quarter-pel, vertical flavour ((1,2) fdc=0, (3,2) fdc=1): vertical-first pass 1, then fused horizontal pass-2/avg.
mc_chroma_w4
Eighth-pel chroma bilinear MC, 4 pixels wide, height rows.
mc_chroma_w8
Eighth-pel chroma bilinear MC, 8 pixels wide, height rows.
mc_hor20
Horizontal half-pel plane: clip((6tap_h + 16) >> 5), w in {8, 16}.
mc_hor_qpel
One-filter horizontal qpel (McHorVer10/30): half-pel 6-tap then pavgb vs full-pel at column +fdc, in one pass (no 256 B scratch store). fdc ∈ {0,1}.
mc_hv_qpel
Fused HV-diagonal qpel: hor-half at (hdr, hdc), ver-half at (vdr, vdc), averaged — one loop, no staging. Offsets follow avg_full’s convention.
mc_ver02
Vertical half-pel plane: clip((6tap_v + 16) >> 5), w in {8, 16}.
mc_ver_qpel
One-filter vertical qpel (McHorVer01/03): half-pel 6-tap then pavgb vs full-pel at row +fdr, in one pass. fdr ∈ {0,1}.
pixel_avg
(a + b + 1) >> 1 of two planes — the quarter-pel average. w in {4, 8, 16}.
quant_four_4x4
openh264 WELS_NEW_QUANT over four 4x4 blocks, in place. See quant_four_4x4_scalar for the reference semantics.
quant_four_4x4_scalar
openh264’s WELS_NEW_QUANT over four 4x4 blocks, in place.
sad_8x16
SAD of two 8x16 blocks.
sad_16x8
SAD of two 16x8 blocks.
sad_16x16
SAD of two 16x16 blocks.
sad_x4
SADs of one w×h source block vs four offsets o into base (stride rs), for every ME partition shape. Values are exactly Σ|a−b| per candidate. None without AVX2 or for an uncovered shape.
satd_4x4
SATD of two 4x4 blocks. Too small for the band kernel (which does four at once).
satd_8x8
SATD of two 8x8 blocks: Σ_4x4 ((Σ|H·d| + 1) >> 1).
satd_8x16
SATD of two 8x16 blocks: Σ_4x4 ((Σ|H·d| + 1) >> 1).
satd_16x8
SATD of two 16x8 blocks: Σ_4x4 ((Σ|H·d| + 1) >> 1).
satd_16x16
SATD of two 16x16 blocks: Σ_4x4 ((Σ|H·d| + 1) >> 1).
satd_avg
Fused SATD(src, (a+b+1)>>1) of a w×h block — Σ|H·d|, the SAME value satd_px computes on the materialized average (NOT the (Σ+1)>>1 the WelsSampleSatd* wrappers return). None when AVX2 is unavailable or the size is unsupported — the caller then materializes and takes the old path, so a non-AVX2 machine is byte-identical by construction.
satd_avg_x4
Four fused avg+SATDs of one w×h source block: (plane_a, off_a, plane_b, off_b) per candidate, shared stride — the quarter-pel ring for every ME partition shape. None without AVX2 or for an uncovered shape.
satd_x4
Σ|H·d| SATDs of one w×h source block vs four offsets o into base (stride rs) — the diamond’s shape, for every ME partition. The exact scalar-Hadamard value (satd_px domain, NOT the (Σ+1)>>1 the Wels wrappers return). None without AVX2 or for an uncovered shape.
satd_x4p
Four SATDs (Σ|H·d|) of one w×h source block vs four INDEPENDENT plane operands (shared stride) — the sub-pel ring’s shape, now for every ME partition. None without AVX2 or for an uncovered shape.
tq_scalar_forced
ORACLE ARM (RFF_TQ_SCALAR=1): pin the three transform/quant dispatchers to their scalar twins at RUNTIME — the differential/bisection anchor the campaign method requires of every kernel family (add_SIMD_rip_ASM.md §3 step 1), previously satisfied here only inside #[cfg(test)] (H10). Output is byte-identical either way — this is a correctness knob, not a speed knob; same cached-atomic shape and cost class as abl_recon above.