h264: expose chroma DC 2x2 Hadamard as public API

PR #23 added the Hadamard as a test-only spec reference; this PR
promotes it to a public symbol in src/ so consumers (the eventual
marfrit-packages substitution-arc patch 0011) can link against it.

  New: void daedalus_h264_chroma_dc_hadamard_2x2(int16_t c[4]);
       — operates in-place on 4 int16, no QP-dependent scaling
       (caller composes that themselves per §8.5.11.2).

The src/ implementation is byte-for-byte identical to the test-only
ref in tests/h264_chroma_dc_hadamard_ref.c (kept as a separate
spec-validation copy).  A new "public API parity" test case verifies
the two produce identical output for a non-trivial input.

Pure CPU primitive — no substrate-dispatch wrapper because the work
is 4 adds + 4 subs; the substrate machinery would cost more than
the kernel itself.

Verified on hertz:

  $ ./build/test_chroma_dc_hadamard
    all-uniform 5                    PASS
    col gradient [0,10,0,10]         PASS
    row gradient [0,0,10,10]         PASS
    anti-diagonal [10,0,0,10]        PASS
    asymmetric [1,2,3,4]             PASS
    sign-alternating [-5,5,-5,5]     PASS
    double-Hadamard = 4*orig         PASS
    public API parity vs _ref        PASS

  ALL chroma DC Hadamard tests PASS

  $ nm -g build/libdaedalus_core.a | grep chroma_dc_hadamard
  0000000000000000 T daedalus_h264_chroma_dc_hadamard_2x2

Unblocks marfrit-packages 0011 (substituting
H264DSPContext.chroma_dc_dequant_idct, which composes the Hadamard
+ qmul scaling).
This commit is contained in:
2026-05-25 13:32:01 +02:00
parent b21b35c74b
commit 1f07f3cd70
4 changed files with 71 additions and 0 deletions
+34
View File
@@ -0,0 +1,34 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* H.264 chroma DC 2x2 Hadamard pre-pass (public, in-tree CPU).
*
* The 4 DC coefficients of an MB's chroma 4x4 AC blocks go through
* this 2x2 Hadamard before quant-scaling and re-injection into the
* AC blocks' [0,0] coefficient. Algorithm per H.264 §8.5.11.1.
*
* Pure CPU primitive — there's no substrate-dispatch wrapper because
* the work is 4 adds + 4 subs. Callers compose with QP-dependent
* scaling themselves (the scale shape varies by slice/PPS chroma_qp
* offset context and shouldn't be baked into the kernel).
*
* Bit-exact validated against tests/h264_chroma_dc_hadamard_ref.c
* (7-case spec-derived test suite including the H·H = 4·I algebraic
* invariant; see PR #23). Same algorithm; this is the public
* src-tree copy.
*/
#include "daedalus.h"
#include <stdint.h>
void daedalus_h264_chroma_dc_hadamard_2x2(int16_t c[4])
{
int t0 = c[0] + c[1];
int t1 = c[0] - c[1];
int t2 = c[2] + c[3];
int t3 = c[2] - c[3];
c[0] = (int16_t)(t0 + t2); /* f[0,0] = sum of all 4 */
c[1] = (int16_t)(t1 + t3); /* f[0,1] = col-difference */
c[2] = (int16_t)(t0 - t2); /* f[1,0] = row-difference */
c[3] = (int16_t)(t1 - t3); /* f[1,1] = anti-diagonal */
}