# Maintainer: Markus Fritsche # 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 -/, 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 # - 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" }