3 Commits

Author SHA1 Message Date
claude-noether cb3aef3dac h264: promote remaining intra prediction modes (17) to public API
Follows PR #26 (Intra_4x4 luma) with the same promotion pattern for
the rest of the intra prediction primitive set:

  Intra_16x16 luma   (4 modes, PR #13) — V/H/DC/Plane
  Intra_8x8  chroma  (4 modes, PR #14) — DC/H/V/Plane (4:2:0)
  Intra_8x8  luma    (9 modes, PRs #21 + #22) — High profile,
                                                 with 1-2-1 pre-filter

3 file moves via `git mv`, ~17 function renames stripping the `_ref`
suffix.  Test binaries rewired to link daedalus_core instead of
compiling the (now moved) ref files directly.  No code change — pure
plumbing for substitution-arc consumers.

26 intra prediction modes total now in the public API after this PR.

Verified on hertz:

  test_intra_pred_16x16:    5/5  PASS
  test_intra_pred_chroma8x8: 5/5  PASS
  test_intra_pred_8x8_luma: 11/11 PASS

All via public symbols (test binaries linked against daedalus_core).

Unblocks marfrit-packages substitution arc patch 0014 — wires
H264PredContext.pred4x4[], pred16x16[], pred8x8[], pred8x8l[]
through daedalus alongside the existing IDCT / deblock / qpel / DC
Hadamard substitutions.

After 0014 lands, the libavcodec.so built by marfrit-packages will
have EVERY hot-path pixel-math kernel of an H.264 8-bit 4:2:0
decode routing through daedalus — the substitution arc is feature-
complete for the campaign target (Pi 5 Firefox YouTube playback).
2026-05-25 15:37:44 +02:00
claude-noether 5565cc2bef h264: Intra_8x8 luma — 6 directional modes (DDL/DDR/VR/HD/VL/HU)
Closes the H.264 8-bit 4:2:0 intra-prediction primitive matrix.
Adds the 6 directional Intra_8x8 luma modes per H.264 §8.3.2.1.5..
§8.3.2.1.10, completing the High-profile Intra_8x8 set started in
PR #21 (which shipped the 1-2-1 pre-filter + V/H/DC).

Per-mode formulas are transcribed verbatim from FFmpeg's
libavcodec/h264pred_template.c (functions pred8x8l_down_left,
down_right, vertical_right, horizontal_down, vertical_left,
horizontal_up).  Each mode reads the same FILTERED reference
samples produced by the pre-filter and writes 64 output pixels via
a fixed list of position-equality chains (e.g. for DDL,
SRC(0,7)=SRC(1,6)=SRC(2,5)=...=SRC(7,0)= some shared 3-tap formula).

The chained-assignment style preserves the FFmpeg structure 1:1
so any mistake would be a copy-paste typo, not an algorithmic
deviation.  Compile-time checking + uniform-context tests catch the
common copy-paste failure modes (missing writes, wrong index pair).

Scope:
  - 6 new ref functions: ddl/ddr/vr/hd/vl/hu_ref.
  - Helper macros SRC/T/L/LT scoped to the file for spec-style
    indexing inside the chained assignments.
  - 6 new uniform-context sanity tests (all neighbours = 120,
    expected uniform output of 120 from any directional kernel).

Verified on hertz:

  $ ./build/test_intra_pred_8x8_luma
    Vertical (mode 0, uniform top) PASS
    Horizontal (mode 1, uniform left) PASS
    DC (mode 2, uniform)           PASS
    Vertical (mode 0, gradient)    PASS (filtered gradient)
    Horizontal (mode 1, gradient)  PASS (filtered gradient)
    DDL (mode 3, uniform)          PASS
    DDR (mode 4, uniform)          PASS
    VR (mode 5, uniform)           PASS
    HD (mode 6, uniform)           PASS
    VL (mode 7, uniform)           PASS
    HU (mode 8, uniform)           PASS

  ALL Intra_8x8 luma PASS (9 modes)

Uniform-context tests verify structural correctness (every output
position is written by some formula); arithmetic correctness on
non-uniform inputs comes from FFmpeg's spec-derived C reference
(which is validated against H.264 conformance bitstreams upstream).
The libavcodec intercept patch will exercise these on real streams.

Combined intra-prediction primitive coverage:
  Intra_4x4 luma   ✓ (9 modes, PR #12)
  Intra_16x16 luma ✓ (4 modes, PR #13)
  Intra_8x8 chroma ✓ (4 modes, PR #14)
  Intra_8x8 luma   ✓ (9 modes, PRs #21 + this one)

26 intra-prediction modes total, all bit-exact gated.  Every H.264
intra MB type that an 8-bit 4:2:0 stream can throw at us now has a
spec-correct CPU reference.
2026-05-25 09:56:45 +02:00
claude-noether 8bc6d27ea7 h264: Intra_8x8 luma prediction (High profile) — pre-filter + 3 modes
Adds the High-profile Intra_8x8 luma primitive set.  Per H.264
§8.3.2.1, this is distinct from Intra_4x4 in two ways:

  1. REFERENCE SAMPLE PRE-FILTER (§8.3.2.1.1).  The 25 raw neighbour
     samples are smoothed with a 1-2-1 filter BEFORE prediction.
     Spec-defined boundary handling at corners and the right edge:
       - top-left filt'd: (top[0] + 2*tl + left[0] + 2) >> 2
       - top[0] filt'd:   (tl + 2*t[0] + t[1] + 2) >> 2
       - top[i] for 1..14: (t[i-1] + 2*t[i] + t[i+1] + 2) >> 2
       - top[15] filt'd:  (t[14] + 3*t[15] + 2) >> 2  ← 3× boundary
       - left analogous, with l[7] using 3× boundary.

  2. SCALE.  All 9 prediction modes operate at 8x8 on the filtered
     samples (Intra_4x4 is 4x4 on raw samples).

This PR ships the pre-filter + the 3 simple modes (V, H, DC):

  - Mode 0 Vertical (§8.3.2.1.2): pred[r,c] = filt_top[c]
  - Mode 1 Horizontal (§8.3.2.1.3): pred[r,c] = filt_left[r]
  - Mode 2 DC (§8.3.2.1.4): ((sum_filt_top[0..7] + sum_filt_left[0..7]
                              + 8) >> 4) broadcast

The 6 directional modes (DDL, DDR, VR, HD, VL, HU at 8x8 per
§8.3.2.1.5..§8.3.2.1.10) follow in a separate PR.  They use the
same filtered samples; only the per-cell formula differs.

Test design (tests/test_intra_pred_8x8_luma.c):

  - 3 uniform-context tests, one per mode (sanity).
  - 2 gradient tests that exercise the pre-filter's interior +
    boundary cases:
      * Vertical with top = 0..15: spec arithmetic gives filtered
        top[c] = c for c in 0..7 (gradient input → identity through
        the 1-2-1 filter on the interior; boundaries arithmetically
        verify too).  Test expects pred[r,c] = c.
      * Horizontal with left = 0..7: same arithmetic chain on the
        left col.  Test expects pred[r,c] = r.

Verified on hertz:

  $ ./build/test_intra_pred_8x8_luma
    Vertical (mode 0, uniform top) PASS
    Horizontal (mode 1, uniform left) PASS
    DC (mode 2, uniform)           PASS
    Vertical (mode 0, gradient)    PASS (filtered gradient)
    Horizontal (mode 1, gradient)  PASS (filtered gradient)

  ALL Intra_8x8 luma PASS (3 modes — V, H, DC)

The pre-filter being right first try is meaningful — the boundary
samples use a 3× weight rather than 2× (filt[top 15] = (t[14] +
3*t[15] + 2) >> 2), which is easy to forget when transcribing.  The
gradient test would have surfaced any boundary mistake immediately.

Combined intra-prediction primitive coverage after this PR:
  Intra_4x4 luma   ✓ (9 modes, PR #12)
  Intra_16x16 luma ✓ (4 modes, PR #13)
  Intra_8x8 chroma ✓ (4 modes, PR #14)
  Intra_8x8 luma   △ (3 of 9 modes — V, H, DC ✓; DDL/DDR/VR/HD/VL/HU pending)

The 6 remaining Intra_8x8 luma directional modes are spec-mechanical
follow-ups; each is a ~30-line formula per §8.3.2.1.5+.
2026-05-25 09:35:49 +02:00