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).
Third intra-prediction primitive after PR #12 (Intra_4x4 luma) and
PR #13 (Intra_16x16 luma). Covers Intra_8x8 chroma per H.264 §8.3.3:
4 modes used for BOTH Cb and Cr planes at 4:2:0.
Mode quirks worth flagging in code review:
- Mode 0 DC is asymmetric per quadrant. The 8x8 chroma block
splits into four 4x4 quadrants with different DC formulas:
(0,0) top-left : (sum_top[0..3] + sum_left[0..3] + 4) >> 3
(0,1) top-right : (sum_top[4..7] + 2) >> 2
(1,0) bot-left : (sum_left[4..7] + 2) >> 2
(1,1) bot-right : (sum_top[4..7] + sum_left[4..7] + 4) >> 3
The top-right quadrant deliberately IGNORES the top-left half
even though it's available — that's per spec §8.3.3.2.
- Mode 3 Plane uses slope coefficient 34 (not 5 like Intra_16x16
luma). Centre is (x-3, y-3) instead of (x-7, y-7). Sums span
4 differences instead of 8. Easy to copy-paste-bug from the
luma Plane if you don't notice the constants change.
Test highlights:
- DC quadrants: distinct expected values per quadrant (16, 16,
40, 28 from asymmetric top/left halves) — any quadrant mix-up
would surface immediately. Hand-derived from the formulas
in the test comment.
- Plane uniform: all-100 context → all-100 output (a = 3200,
H = V = 0, (3200+16) >> 5 = 100 exactly).
- Plane gradient: top + left = 0..7, hand-derives pred[0][0] = 1
and pred[7][7] = 15 via the full arithmetic chain (H = V = 56,
b = c = 30, a = 224). Same hand-traced spec-walkthrough as
the Intra_16x16 Plane gradient test.
Verified on hertz:
$ ./build/test_intra_pred_chroma8x8
Horizontal (mode 1) PASS
Vertical (mode 2) PASS
DC quadrants (mode 0) PASS
Plane uniform (mode 3) PASS
Plane gradient (mode 3) PASS (corners 1, 15)
ALL Intra_8x8 chroma mode references PASS
All 5 tests PASS first try. The DC quadrant correctness is meaningful
(4 different formulas in one kernel) and the Plane gradient corners
validate the slope=34 + centre=(x-3,y-3) constants vs the luma
equivalents.
Combined coverage after this PR:
- Intra_4x4 luma: 9 modes ✓ (PR #12, all 9 PASS)
- Intra_16x16 luma: 4 modes ✓ (PR #13, all 5 tests PASS)
- Intra_8x8 chroma: 4 modes ✓ (this PR, all 5 tests PASS)
- Intra_8x8 luma (High profile): 9 modes + smoothing — pending.
Remaining backlog: Intra_8x8 luma (High profile, 9 modes + 1-2-1
smoothing pre-filter — distinct algorithm from Intra_4x4 because of
the pre-filter), neighbour-availability fallback, dispatch wrappers.