iter11 Phase 6 α-13 + α-14: HEVC SPS hygiene + IRAP/IDR flags fix Bug 5
Two fixes in one commit: α-13 (h265_fill_sps): sps_max_num_reorder_pics now derived from sps_max_dec_pic_buffering_minus1 (safe upper bound per H.265 §A.4.2) instead of hardcoded 0. Phase 5b empirically showed rkvdec ignores this field on RK3399, so this is wire-correctness hygiene only — matches kdirect's payload pattern without behavior change. α-14 (h265_set_controls): derive IRAP_PIC / IDR_PIC flags from the first slice's nal_unit_type (parsed by h265_fill_slice_params into slice_params_array[0].nal_unit_type). Without these flags rkvdec doesn't recognise the keyframe boundary, treats IDR as inter without references, and produces all-zero CAPTURE output — observed as Bug 5 on libva HEVC (06b2c5a0...). kdirect sets these from the bitstream parse and decodes correctly (9340b832...). Mapping: nal_unit_type 16..23 -> IRAP_PIC nal_unit_type 19 (IDR_W_RADL) or 20 (IDR_N_LP) -> IDR_PIC HEVC-only (no risk to other codecs). h265_set_controls already profile-gated via picture.c::codec_set_controls VAProfileHEVCMain dispatch. Per feedback_unconditional_codec_state.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+53
-5
@@ -107,8 +107,20 @@ static void h265_fill_sps(VAPictureParameterBufferHEVC *picture,
|
||||
picture->log2_max_pic_order_cnt_lsb_minus4;
|
||||
sps->sps_max_dec_pic_buffering_minus1 =
|
||||
picture->sps_max_dec_pic_buffering_minus1;
|
||||
sps->sps_max_num_reorder_pics = 0; /* not exposed */
|
||||
sps->sps_max_latency_increase_plus1 = 0; /* not exposed */
|
||||
/*
|
||||
* iter11 α-13: VAAPI doesn't forward sps_max_num_reorder_pics or
|
||||
* sps_max_latency_increase_plus1. kdirect parses the SPS NAL and
|
||||
* submits the bitstream's true values; libva used to hardcode 0
|
||||
* (a structurally wrong "no reordering" hint, even though Phase 5b
|
||||
* empirically confirmed rkvdec ignores both fields on RK3399, so
|
||||
* this is wire-hygiene only — matches kdirect's payload more
|
||||
* closely without behavior change). sps_max_dec_pic_buffering_minus1
|
||||
* is a safe upper bound per H.265 §A.4.2 (sps_max_num_reorder_pics ≤
|
||||
* sps_max_dec_pic_buffering_minus1 always holds). latency_increase_plus1
|
||||
* stays at 0 = spec "unconstrained".
|
||||
*/
|
||||
sps->sps_max_num_reorder_pics = picture->sps_max_dec_pic_buffering_minus1;
|
||||
sps->sps_max_latency_increase_plus1 = 0;
|
||||
sps->log2_min_luma_coding_block_size_minus3 =
|
||||
picture->log2_min_luma_coding_block_size_minus3;
|
||||
sps->log2_diff_max_min_luma_coding_block_size =
|
||||
@@ -304,9 +316,20 @@ static void h265_fill_decode_params(struct request_data *driver_data,
|
||||
* num_delta_pocs_of_ref_rps_idx left zero (VAAPI doesn't expose;
|
||||
* matches FFmpeg's behavior for non-bitstream-driven population). */
|
||||
|
||||
/* IRAP/IDR/NO_OUTPUT_OF_PRIOR flags — VAAPI doesn't expose; computing
|
||||
* from CurrPic flags + nal_unit_type would require parsing. Leave
|
||||
* zero for iter2 binding cell (BBB B/P-frames don't need these set). */
|
||||
/*
|
||||
* iter11 α-14: IRAP/IDR/NO_OUTPUT_OF_PRIOR flags. VAAPI doesn't
|
||||
* expose these in VAPictureParameterBufferHEVC. The iter2 binding
|
||||
* cell hardcoded them to 0 with the comment "BBB B/P-frames don't
|
||||
* need these set" — but IDR keyframes DO need IDR_PIC|IRAP_PIC.
|
||||
* Without them rkvdec doesn't recognise the keyframe boundary,
|
||||
* treats the IDR as inter without references, and produces all-zero
|
||||
* CAPTURE output (Bug 5).
|
||||
*
|
||||
* The flags are derived at h265_set_controls level after slice_params
|
||||
* have been parsed (slice_params[0].nal_unit_type carries the NAL
|
||||
* type extracted from the bitstream). Initialise to 0 here; the caller
|
||||
* patches the IRAP/IDR bits.
|
||||
*/
|
||||
decode_params->flags = 0;
|
||||
}
|
||||
|
||||
@@ -549,6 +572,31 @@ int h265_set_controls(struct request_data *driver_data,
|
||||
h265_fill_decode_params(driver_data, picture, &decode_params);
|
||||
h265_fill_scaling_matrix(iqmatrix, iqmatrix_set, &scaling_matrix);
|
||||
|
||||
/*
|
||||
* iter11 α-14: derive IRAP_PIC / IDR_PIC flags from the first
|
||||
* slice's nal_unit_type (already parsed by h265_fill_slice_params
|
||||
* from the bitstream into slice_params_array[0].nal_unit_type).
|
||||
*
|
||||
* H.265 §7.4.2.2:
|
||||
* nal_unit_type 16..23 are IRAP (random access).
|
||||
* nal_unit_type 19 (IDR_W_RADL) and 20 (IDR_N_LP) are IDR.
|
||||
*
|
||||
* Without setting these, rkvdec doesn't recognise the keyframe
|
||||
* boundary, treats the IDR as inter without references, and
|
||||
* produces all-zero CAPTURE output. Phase 3 confirmed kdirect
|
||||
* (ffmpeg-v4l2request) sets flags=0x03 (IRAP|IDR) on frame 1
|
||||
* and decodes correctly through the same kernel.
|
||||
*/
|
||||
if (num_slices > 0) {
|
||||
uint8_t nut = slice_params_array[0].nal_unit_type;
|
||||
if (nut >= 16 && nut <= 23)
|
||||
decode_params.flags |=
|
||||
V4L2_HEVC_DECODE_PARAM_FLAG_IRAP_PIC;
|
||||
if (nut == 19 || nut == 20)
|
||||
decode_params.flags |=
|
||||
V4L2_HEVC_DECODE_PARAM_FLAG_IDR_PIC;
|
||||
}
|
||||
|
||||
controls[n++] = (struct v4l2_ext_control){
|
||||
.id = V4L2_CID_STATELESS_HEVC_SPS,
|
||||
.ptr = &sps,
|
||||
|
||||
Reference in New Issue
Block a user