Files
marfrit-packages/arch/libva-v4l2-request-ohm-gl-fix/PKGBUILD
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

256 lines
13 KiB
Bash

# Maintainer: Markus Fritsche <fritsche.markus@gmail.com>
# Campaign: ohm_gl_fix Phase 6 Step 1
#
# Forks libva-v4l2-request to add hantro-vpu multiplanar + modern
# stateless UAPI support. Conflicts/replaces stock libva-v4l2-request.
#
# Build target: fermi LXD on hertz (Arch ARM aarch64) via marfrit-packages
# Gitea Actions; alternative: boltzmann via his subagent.
pkgname=libva-v4l2-request-ohm-gl-fix
_upstreampkg=libva-v4l2-request
pkgver=1.0.0.r0.ga3c2476
pkgrel=2
pkgdesc="VA-API backend for V4L2 stateless decoders, hantro-vpu multiplanar fork"
arch=('aarch64')
url="https://github.com/bootlin/libva-v4l2-request"
license=('LGPL2.1' 'MIT')
depends=('libva' 'libdrm' 'systemd-libs')
makedepends=('meson' 'ninja' 'pkgconf' 'git')
provides=("${_upstreampkg}=${pkgver}" 'libva-driver')
conflicts=("${_upstreampkg}")
replaces=("${_upstreampkg}")
# Bootlin upstream tarball — pinned to last meaningful commit 2019-05-17.
# Use full SHA: github extracts the archive to <repo>-<full-sha>/, so the
# short form would mismatch ${srcdir}/${_upstreampkg}-${_commit}.
_commit=a3c2476de19e6635458273ceeaeceff124fabd63
source=(
"${_upstreampkg}-${_commit}.tar.gz::https://github.com/bootlin/libva-v4l2-request/archive/${_commit}.tar.gz"
"fourier-local.patch"
"0001-mplane-multiplanar-port.patch"
"0002-pre-streamon-controls-and-output-pool.patch"
"0003-v4l2-query-helpers.patch"
"0004-context-request-pool.patch"
"0005-h264-conditional-pred-weights.patch"
"0006-h264-frame-based-omit-slice-controls.patch"
"0007-context-h264-start-code-annex-b.patch"
"0008-h264-fill-decode-params-from-vaapi.patch"
"0009-surface-no-capture-sfmt.patch"
"0010-DEBUG-hex-dump-output-capture.patch"
"0011-DEBUG-sentinel-capture-buffer.patch"
"0012-h264-omit-scaling-matrix-frame-based.patch"
"0013-h264-sps-level-idc.patch"
"0014-DEBUG-vapic-bytes-dump.patch"
"0015-h264-strip-ffmpeg-poc-sentinel.patch"
"0016-h264-derive-pframe-bframe-flags.patch"
"0017-h264-dpb-picnum-correctness.patch"
"0018-h264-level-idc-from-annex-a3.patch"
)
sha256sums=(
'92b523050561d64f7b6016edb53ca00524805f9f31a8b566baf457bbb15716fa'
'1577ff1e2fd7944d2af85bba07658c26b2c54787175c2cc9024174ad2425d3ac'
'7637c8c76f86a4b745516cdfd1ee89484b7fe7ce88425ff38460bd4494e1451e'
'5309582759f260456b15635be610c2fe6fe25cbdf427cf8ad851f74991dc8c6e'
'4e38eacc2b2dc26094cbad38964e8dc8bec19d2ad408a37a3ee21952003e6c38'
'e5b61965921093292912136ae21727c9c792d0417201d86dc90b2e622f1edbb0'
'c7a8e02f2e84c6248586d1ceacf25f4c26578f2f365044c3b4a011080ec016e8'
'5ea1f8b193a3cba21631b00ac3d9cb8c6016754f0af47b33fcccce9e0114b32a'
'092abc79f639ecb7ac698a48fb544edc3b6eff3cb9b711efa2cc452365c17ed0'
'ac81992783f562128f55620dc54507b70026342519bb7c7d3efadf6275387861'
'6b2c26feeeaf253f87e0ef0517191b636c6945e374660a13574f3114331aaed6'
'ef8706062302fd7f13535501b5b2e8aed5325dbb0d4d56a88674bef53ca96eee'
'242a42e10ff09e4e82bcadb8824e036dddab94cf6dc9c5f6c80eb4c2cc5dda50'
'417c39397dfbc86db2cabc6217f54d9072de26dedcacf9a965b909fc998de052'
'472deb316ff3ad282c6be028cfaf033d69ddfee845dcd519c28a0692f298bb6a'
'835378dd0b7c126a6101b8df0c015951d88f5139f9586a618af6b3ee503d67b6'
'380d334a88213185183a05e7e55380de503e388fc29d8b11d96909dafcbbeb65'
'eaf1e363de111ee43d7ca3e4b161d9a3a3f6b1c9ca3d8642871abe70f18fbf95'
'7b6f0f63fdde32a411cf3230cabeb610ef8a6bd09777976a06dbd274daa540c7'
'15a0a40b918988e77e5f36eebf15e9f45b2c13a6628b5640efdac528c57aab80'
)
prepare() {
cd "${srcdir}/${_upstreampkg}-${_commit}"
# Patch 0: fourier's stateless-control modernization.
# - src/h264.c + src/picture.c → V4L2_CID_STATELESS_H264_*
# - include/hevc-ctrls.h → redirect shim to <linux/v4l2-controls.h>
# - src/meson.build: h265.c/h265.h commented out (HEVC excluded)
patch -p1 < "${srcdir}/fourier-local.patch"
# Hygiene: include/h264-ctrls.h is dead post-fourier (no source
# includes it, no install_headers directive). Drop it so the
# built source tree has no stale UAPI carry-over.
rm -f include/h264-ctrls.h
# Patch 1: ohm-gl-fix multiplanar port.
# - V4L2_BUF_TYPE_VIDEO_{OUTPUT,CAPTURE} -> *_MPLANE in src/v4l2.c
# - per-plane VIDIOC_EXPBUF in src/surface.c
# - struct v4l2_plane planes[] threading throughout
# - image.c plane-stride adjustments
patch -p1 < "${srcdir}/0001-mplane-multiplanar-port.patch"
# Patch 2: pre-STREAMON device controls + minimum OUTPUT pool.
# - context.c: floor OUTPUT pool to 4 buffers (not surfaces_count)
# - context.c: set V4L2_CID_STATELESS_H264_{DECODE_MODE,START_CODE}
# device-wide before VIDIOC_STREAMON
# THROWAWAY: superseded inline by patches 4 (request_pool) and 5
# (probe-then-set DECODE_MODE) per upstreamable_design.md §5.
patch -p1 < "${srcdir}/0002-pre-streamon-controls-and-output-pool.patch"
# Patch 3 (commit 2 in revised plan): QUERYCTRL/QUERYMENU helpers.
# Pure utility additions to src/v4l2.{c,h}, no behaviour change.
# Unblocks the request_pool and probe-then-set commits.
patch -p1 < "${srcdir}/0003-v4l2-query-helpers.patch"
# Patch 4 (commit 3 in revised plan): request_pool decoupling.
# NEW src/request_pool.{c,h}; context.c uses pool instead of
# per-surface OUTPUT loop; picture.c borrows on Begin, releases
# on Sync after DQBUF. Deletes 0002's "floor to 4" hunk inline
# — the pool's count parameter supersedes it. 0002's
# set_controls block remains until probe-then-set commit lands.
patch -p1 < "${srcdir}/0004-context-request-pool.patch"
# Patch 5: conditional PRED_WEIGHTS submission. Defect-fix found
# via ohm smoke testing (kernel rejects PRED_WEIGHTS at
# error_idx=5 on Main-profile clips without weighted prediction).
# Not part of Sonnet's planned series, but unblocks per-frame
# decode on every backing driver.
patch -p1 < "${srcdir}/0005-h264-conditional-pred-weights.patch"
# Patch 6: omit per-slice controls in FRAME_BASED mode. Identified
# via cross-reference against GStreamer's gstv4l2codech264dec.c
# (commit 9e3e775). FRAME_BASED requests must contain only
# SPS/PPS/SCALING_MATRIX/DECODE_PARAMS — submitting SLICE_PARAMS
# triggers V4L2 cluster validation EINVAL at error_idx=count.
# Hardcodes slice_based=false for now since 0002 sets FRAME_BASED;
# promotes to runtime probe via context->decode_mode in a
# follow-up commit.
patch -p1 < "${srcdir}/0006-h264-frame-based-omit-slice-controls.patch"
# Patch 7: enable ANNEX_B start-code emission in
# codec_store_buffer to match the device-side START_CODE_ANNEX_B
# set by 0002. Without this, kernel sees a raw NAL stream with
# no 0x00 0x00 0x01 markers, fails to parse slice boundaries,
# and emits a zeroed CAPTURE buffer (flat green frames in mpv).
patch -p1 < "${srcdir}/0007-context-h264-start-code-annex-b.patch"
# Patch 8: fill DECODE_PARAMS frame_num + FIELD_PIC/BOTTOM_FIELD
# flag bits from VAAPI. fourier left these zero-init; under
# FRAME_BASED on hantro the kernel uses them to drive bitstream
# parsing. Empirical question: does hantro tolerate the bit_size
# fields (idr_pic_id, pic_order_cnt_lsb, delta_pic_order_cnt_*,
# dec_ref_pic_marking_bit_size, pic_order_cnt_bit_size,
# slice_group_change_cycle) being zero, or do we need a
# slice_header() bit-level parser?
patch -p1 < "${srcdir}/0008-h264-fill-decode-params-from-vaapi.patch"
# Patch 9: drop VIDIOC_S_FMT on CAPTURE queue. Hantro derives
# CAPTURE format from per-request SPS; explicit S_FMT here can
# leave the driver in a state where DQBUF returns zeroed
# buffers despite no errors. GStreamer's reference path only
# G_FMTs the CAPTURE side.
patch -p1 < "${srcdir}/0009-surface-no-capture-sfmt.patch"
# Patch 10: DEBUG-only instrumentation. Hex-dumps OUTPUT and
# CAPTURE buffer first 32 bytes per frame via request_log().
# Removed before upstream submission.
patch -p1 < "${srcdir}/0010-DEBUG-hex-dump-output-capture.patch"
# Patch 11: DEBUG-only sentinel write before CAPTURE QBUF.
# Tells us whether kernel wrote to the buffer (sentinel gone)
# or didn't (sentinel survives).
patch -p1 < "${srcdir}/0011-DEBUG-sentinel-capture-buffer.patch"
# Patch 12 (REVISED 2026-05-02): gate SCALING_MATRIX submission
# on a per-surface matrix_set flag mirroring fourier's existing
# mpeg2.iqmatrix_set / h265.iqmatrix_set pattern. The earlier
# draft of this patch unconditionally omitted SCALING_MATRIX in
# FRAME_BASED, which was corpus-correct (bbb has no explicit
# scaling lists) but the wrong predicate — kernel-side gating
# is by "matrix-supplied vs. not," not by decode mode. Streams
# with explicit scaling lists must still submit in either mode.
# Three coordinated changes: surface.h adds bool matrix_set;
# picture.c sets it on VAIQMatrixBuffer arrival and resets it
# in RequestBeginPicture; h264.c builds controls[] incrementally.
# The pre-existing FRAME_BASED-omits-SLICE_PARAMS rule is
# preserved (kernel doc is explicit on it).
patch -p1 < "${srcdir}/0012-h264-omit-scaling-matrix-frame-based.patch"
# Patch 13 (REVISED 2026-05-02): hardcode SPS level_idc = 51 as
# an INTENTIONALLY OVER-ALLOCATING known-incomplete intermediate.
# VAAPI's decode-side picture-parameter buffer structurally lacks
# level_idc (only present in encode path). The H.264 SPS NAL is
# not in VASliceDataBuffer either (ffmpeg-vaapi parses it
# client-side and forwards only slice data — verified via the
# 0010 hex dump showing OUTPUT first bytes are "00 00 01 65 ...",
# i.e. start code + IDR slice NAL, no SPS). So a SPS-NAL byte
# extractor is not viable. TODO captured inline for level-from-
# resolution derivation per H.264 Annex A.3.
patch -p1 < "${srcdir}/0013-h264-sps-level-idc.patch"
# Patch 14: DEBUG-only — dump VAPictureH264 raw bytes + decoded
# fields. Used to disambiguate the TopFieldOrderCnt=65536 anomaly
# on ohm in 2026-04-30..2026-05-02 investigation. The dump output
# cross-referenced against meitner ground-truth (i965 backend)
# confirmed +0x10000 is ffmpeg-vaapi convention, not an ohm bug.
# Resolution: patch 0015. This patch stays in the series until
# the 65536 sentinel handling has been validated on ohm; remove
# before upstream submission.
patch -p1 < "${srcdir}/0014-DEBUG-vapic-bytes-dump.patch"
# Patch 15: strip ffmpeg-vaapi's POC sentinel before passing to
# V4L2. Root-cause fix for the "kernel decodes successfully but
# produces zeroed CAPTURE buffers" symptom. ffmpeg's
# H264POCContext initialises prev_poc_msb to (1 << 16) and the
# value leaks through field_poc[] to VAPictureH264. Working
# backends (i965, intel-iHD) tolerate the high word; V4L2
# stateless drivers cannot. Adds h264_strip_ffmpeg_poc_sentinel()
# static inline and applies it at all 4 POC sites (DPB top/bot,
# CurrPic top/bot). Detection by bit-16-set so a future ffmpeg
# version that fixes the leak degrades gracefully.
patch -p1 < "${srcdir}/0015-h264-strip-ffmpeg-poc-sentinel.patch"
# Patch 16: derive PFRAME / BFRAME flags from VAAPI slice_type.
# Upstreamability fix — tegra-vde consumes these flags to choose
# the inter-frame decode kernel; hantro/rkvdec/cedrus/mediatek/
# qcom don't read them but should still see spec-correct values.
patch -p1 < "${srcdir}/0016-h264-derive-pframe-bframe-flags.patch"
# Patch 17: fill dpb[].pic_num as PicNum/LongTermPicNum per H.264
# spec equations 8-28/8-29 instead of fourier's wrong VAAPI
# surface-id assignment. Adds VAPicture parameter to h264_fill_dpb
# so it can compute FrameNumWrap from log2_max_frame_num_minus4 +
# current frame_num. Mediatek consumes pic_num for short-term
# field-coded ref disambiguation; hantro doesn't read it (uses
# reference_ts), which is why fourier's wrong value never
# surfaced on RK3568.
patch -p1 < "${srcdir}/0017-h264-dpb-picnum-correctness.patch"
# Patch 18: derive sps.level_idc from encoded frame size per
# H.264 Annex A.3 (Table A-1) MaxFS thresholds. Replaces patch
# 0013's intermediate hardcode of 51. For typical content:
# 1080p → Level 4.1 (level_idc=41), 4K → 5.1, 8K → 6.0. Hantro
# uses level_idc to size DPB / MV buffers; correct sizing means
# less wasted memory than 0013's blanket over-allocation.
patch -p1 < "${srcdir}/0018-h264-level-idc-from-annex-a3.patch"
}
build() {
cd "${srcdir}/${_upstreampkg}-${_commit}"
# meson_options.txt only exposes 'kernel_headers' — leave it empty to
# use system /usr/include kernel UAPI headers. No per-codec toggles.
arch-meson build --buildtype=release
meson compile -C build
}
package() {
cd "${srcdir}/${_upstreampkg}-${_commit}"
meson install -C build --destdir "${pkgdir}"
install -Dm644 COPYING "${pkgdir}/usr/share/licenses/${pkgname}/COPYING"
install -Dm644 COPYING.LGPL "${pkgdir}/usr/share/licenses/${pkgname}/COPYING.LGPL"
install -Dm644 COPYING.MIT "${pkgdir}/usr/share/licenses/${pkgname}/COPYING.MIT"
}