radeonsi/vcn: Ensure at least one reference for H264 P/B frames

The original fix from

0f3370eede ("raseonsi/vcn: fix a h264 decoding issue")

would in some cases also trigger for I frames with interlaced streams.
Instead of checking used_for_reference_flags, use slice type and
only add one reference for P/B frames if needed.
This change still fixes playback of the sample from the original issue,
avoids the issue with interlaced streams and also fixes the case where
application provides no references at all.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/11060
Cc: mesa-stable
Reviewed-by: Leo Liu <leo.liu@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29055>
(cherry picked from commit 5f4a6b5b00)
This commit is contained in:
David Rosca 2024-05-03 16:20:44 +02:00 committed by Eric Engestrom
parent c3f11a4011
commit 0fd4f15601
2 changed files with 7 additions and 9 deletions

View file

@ -554,7 +554,7 @@
"description": "radeonsi/vcn: Ensure at least one reference for H264 P/B frames",
"nominated": true,
"nomination_type": 0,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": null,
"notes": null

View file

@ -239,15 +239,13 @@ static rvcn_dec_message_avc_t get_h264_msg(struct radeon_decoder *dec,
}
}
/* if reference picture exists, however no reference picture found at the end
curr_pic_ref_frame_num == 0, which is not reasonable, should be corrected. */
if (result.used_for_reference_flags && (result.curr_pic_ref_frame_num == 0)) {
for (i = 0; i < ARRAY_SIZE(result.ref_frame_list); i++) {
result.ref_frame_list[i] = pic->ref[i] ?
(uintptr_t)vl_video_buffer_get_associated_data(pic->ref[i], &dec->base) : 0xff;
if (result.ref_frame_list[i] != 0xff) {
/* need at least one reference for P/B frames */
if (result.curr_pic_ref_frame_num == 0 && pic->slice_parameter.slice_info_present) {
for (i = 0; i < pic->slice_count; i++) {
if (pic->slice_parameter.slice_type[i] % 5 != 2) {
result.curr_pic_ref_frame_num++;
result.non_existing_frame_flags &= ~(1 << i);
result.ref_frame_list[0] = 0;
result.non_existing_frame_flags &= ~1;
break;
}
}