Files
marfrit-packages/arch/libva-v4l2-request-ohm-gl-fix/0013-h264-sps-level-idc.patch
T
test0r b47938e0bc
build and publish packages / distcc-avahi-aarch64 (push) Successful in 1m3s
build and publish packages / lmcp-any (push) Successful in 9s
build and publish packages / lmcp-debian (push) Successful in 4s
build and publish packages / claude-his-any (push) Failing after 4s
build and publish packages / ffmpeg-v4l2-request-aarch64 (push) Has been skipped
build and publish packages / claude-his-debian (push) Has been skipped
Add libva-v4l2-request-ohm-gl-fix package
Mirrors phase6/step1/ from the ohm_gl_fix campaign. Contract-correct
hantro multi-planar / chromium-149-era stateless H.264 port of
bootlin's libva-v4l2-request, patches 0001..0018 + fourier-local.

Honest characterisation in README:
  - Builds cleanly on chromium-builder LXC (boltzmann)
  - vainfo enumerates H.264 profiles cleanly with LIBVA_DRIVER_NAME=v4l2_request
  - NOT on Brave's decode path on ohm_gl_fix stack — Brave uses
    Chromium's own V4L2VideoDecoder in media/gpu/v4l2/.
  - Most likely useful for a future Firefox-via-libavcodec-vaapi
    campaign, modulo a separate Mesa-panfrost WSI pitch issue.
  - DEBUG patches (0010, 0011, 0014) intentionally kept in series
    for development; remove for cleaner production runs.

Audit trail in the source repo at ohm_gl_fix:
  phase6/step1/audit_0008_decode_params_2026-05-01.md
  phase6/step1/api_contract_findings_2026-05-01.md
  phase3_remeasure_2026-05-02/B3_decoder_discovery.md (why this
    isn't on Brave's path)
2026-05-02 15:17:10 +00:00

87 lines
3.8 KiB
Diff

From: Markus Fritsche <fritsche.markus@gmail.com>
Date: 2026-05-02
Subject: [PATCH] h264: hardcode SPS level_idc = 51 (intentional over-allocation)
fourier's h264_va_picture_to_v4l2 never assigns sps->level_idc; the
field stays at zero-init. level_idc=0 is invalid per the H.264 spec
(lowest legal value is 10, Level 1.0). Hantro and other stateless
H.264 decoders use level_idc to pre-allocate decoder resources (DPB
size, motion-vector buffers); when fed an invalid level the hantro
kernel driver silently skips the decode-hardware dispatch — the V4L2
request completes with no error, DQBUF returns the CAPTURE buffer
reporting bytesused=3655712 and no V4L2_BUF_FLAG_ERROR, but the
buffer is never written.
VAAPI's decode-side VAPictureParameterBufferH264 structurally does
NOT include level_idc — `grep level_idc va/va.h` returns only hits
inside VAEncSequenceParameterBufferH264 (the encode path). The
H.264 SPS NAL is also not included in VASliceDataBuffer because
ffmpeg-vaapi parses it client-side and forwards only slice data
(verified empirically via patch 0010's hex-dump of the OUTPUT
buffer: it contains "00 00 01 65 ..." — i.e. ANNEX_B start code +
IDR slice NAL byte, no SPS NAL). A SPS-NAL byte extractor is
therefore not viable from the bitstream libva-v4l2-request
receives.
Workaround: hardcode level_idc = 51 (= Level 5.1, max for 1080p
and 4K@30 mainstream consumer profiles). This INTENTIONALLY
OVER-ALLOCATES decoder resources but is sufficient for any stream
up to 4K@30. It is corpus-correct, not contract-correct: a 4K@60
stream (Level 6.x) would under-allocate.
This patch is a known-incomplete intermediate, not a final fix.
The proper upstreamable answer is a level-from-resolution
derivation per H.264 Annex A.3 (max MB rate / max frame size
thresholds). That requires mapping consumer-side framerate which
VAAPI does not expose, so the lookup table is non-trivial. The
TODO is captured inline.
This patch's goal is unblocking decode-hardware engagement on the
ohm_gl_fix corpus while the full level-derivation work proceeds.
Cross-reference: kernel doc
ext-ctrls-codec-stateless.rst V4L2_CID_STATELESS_H264_SPS lists
level_idc as a required field with no "kernel-derives" annotation —
i.e., userspace-required.
Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
---
--- a/src/h264.c
+++ b/src/h264.c
@@ -553,6 +553,35 @@
sps.profile_idc = h264_profile_to_idc(profile);
/*
+ * VAAPI's decode-side VAPictureParameterBufferH264 does not carry
+ * level_idc — see va.h, the field exists only in
+ * VAEncSequenceParameterBufferH264 on the encode path. The H.264
+ * SPS NAL is also not included in VASliceDataBuffer (ffmpeg-vaapi
+ * parses it client-side and forwards only slice data), so a
+ * SPS-NAL byte extractor is not viable from the bitstream we
+ * receive.
+ *
+ * Hantro and other stateless H.264 decoders use level_idc to
+ * pre-allocate decoder resources (DPB, motion-vector buffers); a
+ * zero-init level_idc=0 is invalid (lowest legal is 10 = Level
+ * 1.0) and causes hantro to silently skip the decode hardware
+ * dispatch.
+ *
+ * Hardcode level_idc = 51 (Level 5.1, max for 1080p/4K@30) as a
+ * known-incomplete intermediate. This INTENTIONALLY OVER-ALLOCATES
+ * decoder resources and is sufficient for any stream up to 4K@30.
+ * It is corpus-correct, not contract-correct.
+ *
+ * TODO: derive level_idc from (VAProfile, picture_width_in_mbs,
+ * picture_height_in_mbs) per H.264 Annex A.3 max-MB-per-second
+ * thresholds. That is a small lookup table but requires also
+ * mapping the consumer's framerate, which VAAPI doesn't provide
+ * directly. For now the over-allocation is the upstreamable
+ * compromise.
+ */
+ sps.level_idc = 51;
+
+ /*
* Build the per-request control list incrementally:
* - SPS, PPS, DECODE_PARAMS: always required (in either decode
* mode).