kernel: register H.264 DECODE_MODE + START_CODE menu controls

libva-v4l2-request sets V4L2_CID_STATELESS_H264_DECODE_MODE and
V4L2_CID_STATELESS_H264_START_CODE on the device fd at context init
(see libva-v4l2-request-fourier src/context.c:577 — best-effort call,
result is (void)cast).  Our ctrl_handler did not advertise either
control, so v4l2-core returned EINVAL on validate; userspace logged
the noisy

    v4l2-request: Unable to set control(s): Invalid argument
                  (error_idx=2/2 ioctl-level)

at every Firefox/ffmpeg context creation, despite decode itself
succeeding (the daemon already operates as FRAME_BASED + ANNEX_B and
the per-request SPS/PPS/SCALING_MATRIX/DECODE_PARAMS batch lands
fine).

Register the two as v4l2_ctrl_new_std_menu with the only value each
the daemon actually supports — FRAME_BASED for DECODE_MODE,
ANNEX_B for START_CODE — and mask out the unsupported alternates
(SLICE_BASED, NONE).  Pattern matches rkvdec / hantro.  Update the
handler-init capacity hint to ARRAY_SIZE(daedalus_stateless_ctrls)
+ 2 to cover the additions.

Verified: builds clean on 6.18.29+rpt-rpi-2712 (Pi CM5) DKMS source
tree.
This commit is contained in:
2026-05-21 11:01:41 +02:00
parent f0d41867f6
commit 69a62a922f
+42 -1
View File
@@ -287,6 +287,44 @@ static int daedalus_register_stateless_ctrls(struct v4l2_ctrl_handler *hdl)
}
(void) ctrl;
}
/*
* Device-wide H.264 mode controls. libva-v4l2-request sets these
* on the device fd (request_fd=-1) at context init via
* VIDIOC_S_EXT_CTRLS before any per-request controls are bound;
* without entries on our ctrl_handler v4l2-core returns EINVAL
* and userspace logs a noisy "Unable to set control(s)" warning
* (cosmetic — libva already treats this as best-effort). Expose
* the single value each that the daemon actually accepts:
*
* DECODE_MODE: FRAME_BASED only — the daemon receives a full
* frame's worth of slice data per REQ_DECODE and calls
* avcodec_send_packet / avcodec_receive_frame once per
* submission; partial-slice (SLICE_BASED) decode is not
* wired into the daemon pipeline.
* START_CODE: ANNEX_B only — the daemon's H.264 SPS/PPS
* synthesiser prepends 0x00000001-delimited NAL units
* (Annex B); a NONE start-code variant would need a
* separate emit path.
*
* Pattern matches rkvdec / hantro (skip_mask = BIT(unsupported)).
*/
v4l2_ctrl_new_std_menu(hdl, &daedalus_ctrl_ops,
V4L2_CID_STATELESS_H264_DECODE_MODE,
V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED,
BIT(V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED),
V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED);
v4l2_ctrl_new_std_menu(hdl, &daedalus_ctrl_ops,
V4L2_CID_STATELESS_H264_START_CODE,
V4L2_STATELESS_H264_START_CODE_ANNEX_B,
BIT(V4L2_STATELESS_H264_START_CODE_NONE),
V4L2_STATELESS_H264_START_CODE_ANNEX_B);
if (hdl->error) {
pr_debug("daedalus_v4l2: H.264 menu ctrls registration err=%d\n",
hdl->error);
hdl->error = 0;
}
return 0;
}
@@ -1130,7 +1168,10 @@ static int daedalus_open(struct file *file)
v4l2_fh_init(&ctx->fh, &dev->vdev);
file->private_data = &ctx->fh;
v4l2_ctrl_handler_init(&ctx->hdl, ARRAY_SIZE(daedalus_stateless_ctrls));
/* +2 covers the H.264 DECODE_MODE + START_CODE menu controls
* registered alongside daedalus_stateless_ctrls[]. */
v4l2_ctrl_handler_init(&ctx->hdl,
ARRAY_SIZE(daedalus_stateless_ctrls) + 2);
daedalus_register_stateless_ctrls(&ctx->hdl);
/*
* v4l2_ctrl_handler_setup runs s_ctrl for every registered