Files
marfrit-packages/arch/libva-v4l2-request-ohm-gl-fix/0008-h264-fill-decode-params-from-vaapi.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

88 lines
3.8 KiB
Diff

From: Markus Fritsche <fritsche.markus@gmail.com>
Date: 2026-05-01
Subject: [PATCH] h264: fill DECODE_PARAMS frame_num + field flags from VAAPI
Fourier's h264_va_picture_to_v4l2 only populated four fields of the
struct v4l2_ctrl_h264_decode_params: dpb (via h264_fill_dpb),
nal_ref_idc, top_field_order_cnt, bottom_field_order_cnt, and the
IDR_PIC flag. Many other required-by-spec fields were left at zero-
init (frame_num, 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, FIELD_PIC and BOTTOM_FIELD flags).
For an IDR (first frame) on hantro-vpu RK3568, the kernel parses
the bitstream from the OUTPUT buffer and uses these fields to drive
its bitstream-element offset tracking. Empirically the kernel
returned a successfully-decoded but ZEROED CAPTURE buffer — flat
dark-green frames in mpv output, no errors logged.
This patch fills every field VAAPI exposes:
- frame_num: from VAPicture->frame_num.
- FIELD_PIC flag: from VAPicture->pic_fields.bits.field_pic_flag.
- BOTTOM_FIELD flag: from
VAPicture->CurrPic.flags & VA_PICTURE_H264_BOTTOM_FIELD.
Also corrects the IDR_PIC flag to use |= instead of = so the new
field flags don't clobber it.
Fields NOT derivable from VAAPI's pre-parsed structures —
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 — require a slice_header() bit-level
parse. libva-v4l2-request does not currently do this. They remain
at zero-init.
Empirical question this patch answers: does hantro tolerate the
bit_size fields being zero for IDR frames, or does it strictly
require them? If post-patch CAPTURE is still zeroed, a slice-header
parser is required. If CAPTURE shows real picture data, hantro
fills in the bit-positions itself when no hint is supplied.
Cross-reference: gstv4l2codech264dec.c::
gst_v4l2_codec_h264_dec_fill_decoder_params (commit 9e3e775,
lines 632-678).
Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
---
--- a/src/h264.c 2026-05-01 20:59:41.710154198 +0000
+++ b/src/h264.c 2026-05-01 21:16:35.712995986 +0000
@@ -243,13 +243,34 @@
h264_fill_dpb(driver_data, context, decode);
- //decode->num_slices = surface->slices_count;
+ /*
+ * Populate every V4L2_CID_STATELESS_H264_DECODE_PARAMS field
+ * we can derive from VAAPI's pre-parsed VAPictureParameterBuffer
+ * + bitstream byte. Cross-reference: GStreamer
+ * gstv4l2codech264dec.c::gst_v4l2_codec_h264_dec_fill_decoder_params
+ * (lines 632-678).
+ *
+ * Fields not derivable from VAAPI (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) require a
+ * full slice_header() bit-level parse, which libva-v4l2-request
+ * does not currently do. They are left at zero-init and the
+ * kernel-side hantro-vpu may compute them itself when scanning
+ * the OUTPUT bitstream — a hypothesis verified empirically by
+ * running this patch and inspecting the CAPTURE buffer.
+ */
decode->nal_ref_idc = nal_ref_idc;
- if (nal_unit_type == 5)
- decode->flags = V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC;
+ decode->frame_num = VAPicture->frame_num;
decode->top_field_order_cnt = VAPicture->CurrPic.TopFieldOrderCnt;
decode->bottom_field_order_cnt = VAPicture->CurrPic.BottomFieldOrderCnt;
+ if (nal_unit_type == 5)
+ decode->flags |= V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC;
+ if (VAPicture->pic_fields.bits.field_pic_flag)
+ decode->flags |= V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC;
+ if (VAPicture->CurrPic.flags & VA_PICTURE_H264_BOTTOM_FIELD)
+ decode->flags |= V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD;
+
pps->weighted_bipred_idc =
VAPicture->pic_fields.bits.weighted_bipred_idc;
pps->pic_init_qs_minus26 = VAPicture->pic_init_qs_minus26;