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
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)
88 lines
3.8 KiB
Diff
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;
|