From 05ffd02ff28f8c213794cb3c3bda9ffc3adc4be6 Mon Sep 17 00:00:00 2001 From: Markus Fritsche Date: Sat, 2 May 2026 12:00:00 +0000 Subject: [PATCH] h264: derive PFRAME / BFRAME flags from VASlice slice_type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v4l2_ctrl_h264_decode_params.flags has PFRAME and BFRAME bits per ext-ctrls-codec-stateless.rst. fourier never set them; libva-v4l2- request relied on each backing driver tolerating frame-class ambiguity. Kernel survey (linux 6.19.x): - tegra-vde/h264.c (lines 783-799) consumes both flags to select the inter-frame decode kernel. Without them the I-frame kernel runs on P/B content. - visl-trace-h264.h uses them for decode tracing. - hantro / rkvdec / cedrus / mediatek / qcom-iris-stateless do not consume the flags. Hantro on ohm decoded bbb cleanly without these flags set (see phase6/step1/ohm_smoke_2026-05-02T060255Z_post_0015/), so this is an upstreamability fix for cross-driver portability rather than a correctness fix for hantro. VAAPI's VASliceParameterBufferH264.slice_type maps directly to the H.264 slice_header() slice_type field. Per spec 7.4.3: 0=P 1=B 2=I 3=SP 4=SI; 5..9 = "all slices in the picture have this slice_type." `slice_type % 5` recovers the underlying type in either encoding form. In FRAME_BASED mode we only see surface->params.h264.slice from the most-recent VASliceParameterBuffer — that's fine: a single coded picture has a uniform slice_type for the purposes of the PFRAME / BFRAME flag (multi-slice frames may mix slice types in some streams, but the flag's semantic is "this is an inter-coded frame," which holds if any slice is P or B; using the last-seen slice's type is a reasonable approximation). Cross-reference: ext-ctrls-codec-stateless.rst Decode Parameters Flags table. Signed-off-by: Markus Fritsche --- src/h264.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/h264.c b/src/h264.c index 7d20a98..6efacb2 100644 --- a/src/h264.c +++ b/src/h264.c @@ -632,6 +632,38 @@ int h264_set_controls(struct request_data *driver_data, &surface->params.h264.slice, &surface->params.h264.picture, &slice, &weights); + /* + * Derive PFRAME / BFRAME flags in v4l2_ctrl_h264_decode_params.flags + * from VASliceParameterBufferH264.slice_type. VAAPI's slice_type + * matches the H.264 spec slice_type semantic: 0=P, 1=B, 2=I, 3=SP, + * 4=SI; values 5..9 mean "all slices in the picture have this + * slice_type" (mod 5 yields the underlying type). VAAPI consumers + * (ffmpeg, mpv) populate this for every slice; in FRAME_BASED mode + * we only see the most-recent slice's params, but slice_type is + * uniform across a single coded picture for our purposes. + * + * Kernel consumers that read these flags: tegra-vde + * (drivers/media/platform/nvidia/tegra-vde/h264.c lines 783-799 of + * 6.19.x) selects the inter-frame decode kernel. Hantro / rkvdec / + * cedrus / mediatek / qcom-iris-stateless do not consume them. + * Setting them keeps the libva-v4l2-request fork upstreamable + * across drivers without affecting hantro behaviour. + * + * Cross-reference: ext-ctrls-codec-stateless.rst Decode Parameters + * Flags — V4L2_H264_DECODE_PARAM_FLAG_PFRAME / _BFRAME. + */ + switch (surface->params.h264.slice.slice_type % 5) { + case H264_SLICE_P: + decode.flags |= V4L2_H264_DECODE_PARAM_FLAG_PFRAME; + break; + case H264_SLICE_B: + decode.flags |= V4L2_H264_DECODE_PARAM_FLAG_BFRAME; + break; + default: + /* I / SP / SI: no extra flag. */ + break; + } + sps.profile_idc = h264_profile_to_idc(profile); /*