forked from marfrit/libva-v4l2-request-fourier
iter25 α-25: inject synthetic SPS before cap_pool_init to seed image_fmt
Root cause for Bug 5 (HEVC libva = all-zero CAPTURE) and Bug 4 (H.264 libva = keyframe partial), localized via iter17→iter24 kernel-printk chain: rkvdec_s_ctrl() for HEVC_SPS / H264_SPS calls get_image_fmt() and, if the resolved image_fmt differs from cached ctx->image_fmt (default RKVDEC_IMG_FMT_ANY at open), tries to reset the CAPTURE format. Format reset returns -EBUSY when vb2_is_busy(CAPTURE_queue) — any CAPTURE buffer allocated blocks the change. libva (iter5b-β) pre-allocates 24 CAPTURE buffers at CreateContext via cap_pool_init, BEFORE any per-frame S_EXT_CTRLS. First per-frame HEVC_SPS therefore fails with -EBUSY in try_or_set_cluster, breaks v4l2_ctrl_request_setup's outer loop, leaves all 5 staged HEVC compound controls at zero in ctx->ctrl_hdl. rkvdec_hevc_run reads zero (iter20 dmesg: sps[0..16]=00..00), hardware sees w=0 h=0, CAPTURE comes out all-zero (Bug 5). Fix: BEFORE cap_pool_init, inject one S_EXT_CTRLS (no request, no which) with a synthetic SPS containing the profile's known chroma + bit_depth. CAPTURE queue is still empty at this point → vb2_is_busy returns false → rkvdec_s_ctrl succeeds, ctx->image_fmt is updated to the profile's image_fmt. From then on, per-frame SPS submissions with matching chroma + bit_depth see image_fmt_changed=false → skip reset → commit succeeds. VP9 / MPEG-2 / VP8 paths are not affected: VP9's rkvdec coded_fmt_desc has no get_image_fmt op; MPEG-2 + VP8 route to hantro. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -195,6 +195,94 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* iter25 α-25: synthetic-SPS injection to pre-seed ctx->image_fmt
|
||||||
|
* before CAPTURE buffer allocation.
|
||||||
|
*
|
||||||
|
* Root cause (iter17→iter24 kernel-printk chain): rkvdec_s_ctrl for
|
||||||
|
* HEVC_SPS / H264_SPS calls get_image_fmt() and, if the resolved
|
||||||
|
* image_fmt differs from the cached ctx->image_fmt (default
|
||||||
|
* RKVDEC_IMG_FMT_ANY), tries to reset the CAPTURE format. The reset
|
||||||
|
* returns -EBUSY when vb2_is_busy(CAPTURE_queue) — i.e. any CAPTURE
|
||||||
|
* buffer is allocated.
|
||||||
|
*
|
||||||
|
* libva (iter5b-β CAPTURE pool) pre-allocates 24 CAPTURE buffers
|
||||||
|
* via cap_pool_init below — before any per-frame S_EXT_CTRLS
|
||||||
|
* arrives. So the first real HEVC_SPS at decode time fails with
|
||||||
|
* -EBUSY in try_or_set_cluster, breaks v4l2_ctrl_request_setup's
|
||||||
|
* outer loop, and leaves ctx->ctrl_hdl[SPS..DECODE_PARAMS] at all-
|
||||||
|
* zero contents. rkvdec_hevc_run reads zero, hardware sees w=0
|
||||||
|
* h=0, decoded CAPTURE is all-zero (Bug 5 + Bug 4).
|
||||||
|
*
|
||||||
|
* Fix: while CAPTURE is still empty (before cap_pool_init), inject
|
||||||
|
* a synthetic SPS containing the profile's chroma + bit_depth so
|
||||||
|
* rkvdec_s_ctrl resolves image_fmt and updates ctx->image_fmt
|
||||||
|
* before vb2_is_busy can return true. From then on, per-frame
|
||||||
|
* SPS submissions with matching profile parameters see
|
||||||
|
* image_fmt_changed=false → skip reset → commit succeeds.
|
||||||
|
*
|
||||||
|
* Gated by config->profile: only HEVC and H.264 paths set
|
||||||
|
* get_image_fmt in their rkvdec coded_fmt_desc->ops; VP9 / MPEG-2 /
|
||||||
|
* VP8 are unaffected (rkvdec_s_ctrl returns 0 immediately when
|
||||||
|
* get_image_fmt is NULL, or those codecs are routed to hantro).
|
||||||
|
*
|
||||||
|
* Failure is best-effort: if the kernel returns -EBUSY/-EINVAL here
|
||||||
|
* (e.g. driver doesn't expose the control on this DT path), we fall
|
||||||
|
* through and may still hit the original bug for that codec — but
|
||||||
|
* the device-init DECODE_MODE + START_CODE block below ALSO uses
|
||||||
|
* void-cast best-effort, so this is consistent with prior pattern.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
switch (config_object->profile) {
|
||||||
|
case VAProfileHEVCMain: {
|
||||||
|
struct v4l2_ctrl_hevc_sps dummy_sps;
|
||||||
|
struct v4l2_ext_control dummy_ctrl;
|
||||||
|
|
||||||
|
memset(&dummy_sps, 0, sizeof(dummy_sps));
|
||||||
|
dummy_sps.chroma_format_idc = 1; /* 4:2:0 */
|
||||||
|
dummy_sps.bit_depth_luma_minus8 = 0; /* 8-bit */
|
||||||
|
dummy_sps.bit_depth_chroma_minus8 = 0;
|
||||||
|
dummy_sps.pic_width_in_luma_samples = picture_width;
|
||||||
|
dummy_sps.pic_height_in_luma_samples = picture_height;
|
||||||
|
|
||||||
|
dummy_ctrl.id = V4L2_CID_STATELESS_HEVC_SPS;
|
||||||
|
dummy_ctrl.ptr = &dummy_sps;
|
||||||
|
dummy_ctrl.size = sizeof(dummy_sps);
|
||||||
|
(void)v4l2_set_controls(driver_data->video_fd, -1,
|
||||||
|
&dummy_ctrl, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case VAProfileH264Main:
|
||||||
|
case VAProfileH264High:
|
||||||
|
case VAProfileH264ConstrainedBaseline:
|
||||||
|
case VAProfileH264MultiviewHigh:
|
||||||
|
case VAProfileH264StereoHigh: {
|
||||||
|
struct v4l2_ctrl_h264_sps dummy_sps;
|
||||||
|
struct v4l2_ext_control dummy_ctrl;
|
||||||
|
|
||||||
|
memset(&dummy_sps, 0, sizeof(dummy_sps));
|
||||||
|
dummy_sps.chroma_format_idc = 1; /* 4:2:0 */
|
||||||
|
dummy_sps.bit_depth_luma_minus8 = 0;
|
||||||
|
dummy_sps.bit_depth_chroma_minus8 = 0;
|
||||||
|
dummy_sps.pic_width_in_mbs_minus1 =
|
||||||
|
(picture_width + 15) / 16 - 1;
|
||||||
|
dummy_sps.pic_height_in_map_units_minus1 =
|
||||||
|
(picture_height + 15) / 16 - 1;
|
||||||
|
dummy_sps.profile_idc = 100; /* High */
|
||||||
|
dummy_sps.level_idc = 41;
|
||||||
|
|
||||||
|
dummy_ctrl.id = V4L2_CID_STATELESS_H264_SPS;
|
||||||
|
dummy_ctrl.ptr = &dummy_sps;
|
||||||
|
dummy_ctrl.size = sizeof(dummy_sps);
|
||||||
|
(void)v4l2_set_controls(driver_data->video_fd, -1,
|
||||||
|
&dummy_ctrl, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
destination_planes_count = video_format->planes_count;
|
destination_planes_count = video_format->planes_count;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user