From 47b6ca47d0be9e218a7ca3f47f90de2ed6c174f7 Mon Sep 17 00:00:00 2001 From: David Rosca Date: Sat, 4 May 2024 14:28:51 +0200 Subject: [PATCH] radeonsi/vcn: Ensure DPB has as many buffers as references In case of corrupted streams (or application bugs) the number of references may not be equal to DPB size. This needs to be fixed by filling the missing slots with dummy buffers. Cc: mesa-stable Reviewed-by: Leo Liu Part-of: --- src/gallium/drivers/radeonsi/radeon_vcn_dec.c | 56 ++++++++++++++----- src/gallium/drivers/radeonsi/radeon_vcn_dec.h | 1 + 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_dec.c b/src/gallium/drivers/radeonsi/radeon_vcn_dec.c index 26baec00e4b..aa0abded43a 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_dec.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_dec.c @@ -282,7 +282,8 @@ static rvcn_dec_message_avc_t get_h264_msg(struct radeon_decoder *dec, dec->ref_codec.bts = CODEC_8_BITS; dec->ref_codec.index = result.decoded_pic_idx; dec->ref_codec.ref_size = 16; - memset(dec->ref_codec.ref_list, 0xff, sizeof(dec->ref_codec.ref_list)); + dec->ref_codec.num_refs = result.curr_pic_ref_frame_num; + STATIC_ASSERT(sizeof(dec->ref_codec.ref_list) == sizeof(result.ref_frame_list)); memcpy(dec->ref_codec.ref_list, result.ref_frame_list, sizeof(result.ref_frame_list)); } @@ -295,7 +296,7 @@ static rvcn_dec_message_hevc_t get_h265_msg(struct radeon_decoder *dec, struct pipe_h265_picture_desc *pic) { rvcn_dec_message_hevc_t result; - unsigned i, j; + unsigned i, j, num_refs = 0; memset(&result, 0, sizeof(result)); result.sps_info_flags = 0; @@ -416,9 +417,10 @@ static rvcn_dec_message_hevc_t get_h265_msg(struct radeon_decoder *dec, result.poc_list[i] = pic->PicOrderCntVal[i]; - if (ref) + if (ref) { ref_pic = (uintptr_t)vl_video_buffer_get_associated_data(ref, &dec->base); - else + num_refs++; + } else ref_pic = 0x7F; result.ref_pic_list[i] = ref_pic; } @@ -472,7 +474,8 @@ static rvcn_dec_message_hevc_t get_h265_msg(struct radeon_decoder *dec, CODEC_10_BITS : CODEC_8_BITS; dec->ref_codec.index = result.curr_idx; dec->ref_codec.ref_size = 15; - memset(dec->ref_codec.ref_list, 0x7f, sizeof(dec->ref_codec.ref_list)); + dec->ref_codec.num_refs = num_refs; + STATIC_ASSERT(sizeof(dec->ref_codec.ref_list) == sizeof(result.ref_pic_list)); memcpy(dec->ref_codec.ref_list, result.ref_pic_list, sizeof(result.ref_pic_list)); } return result; @@ -510,7 +513,7 @@ static rvcn_dec_message_vp9_t get_vp9_msg(struct radeon_decoder *dec, struct pipe_vp9_picture_desc *pic) { rvcn_dec_message_vp9_t result; - unsigned i ,j; + unsigned i, j, num_refs = 0; memset(&result, 0, sizeof(result)); @@ -644,9 +647,13 @@ static rvcn_dec_message_vp9_t get_vp9_msg(struct radeon_decoder *dec, get_current_pic_index(dec, target, &result.curr_pic_idx); for (i = 0; i < 8; i++) { - result.ref_frame_map[i] = - (pic->ref[i]) ? (uintptr_t)vl_video_buffer_get_associated_data(pic->ref[i], &dec->base) - : 0x7f; + uintptr_t ref_frame; + if (pic->ref[i]) { + ref_frame = (uintptr_t)vl_video_buffer_get_associated_data(pic->ref[i], &dec->base); + num_refs++; + } else + ref_frame = 0x7f; + result.ref_frame_map[i] = ref_frame; } result.frame_refs[0] = result.ref_frame_map[pic->picture_parameter.pic_fields.last_ref_frame]; @@ -672,6 +679,7 @@ static rvcn_dec_message_vp9_t get_vp9_msg(struct radeon_decoder *dec, CODEC_10_BITS : CODEC_8_BITS; dec->ref_codec.index = result.curr_pic_idx; dec->ref_codec.ref_size = 8; + dec->ref_codec.num_refs = num_refs; memset(dec->ref_codec.ref_list, 0x7f, sizeof(dec->ref_codec.ref_list)); memcpy(dec->ref_codec.ref_list, result.ref_frame_map, sizeof(result.ref_frame_map)); } @@ -962,7 +970,7 @@ static rvcn_dec_message_av1_t get_av1_msg(struct radeon_decoder *dec, struct pipe_av1_picture_desc *pic) { rvcn_dec_message_av1_t result; - unsigned i, j; + unsigned i, j, num_refs = 0; uint16_t tile_count = pic->picture_parameter.tile_cols * pic->picture_parameter.tile_rows; memset(&result, 0, sizeof(result)); @@ -1154,9 +1162,13 @@ static rvcn_dec_message_av1_t get_av1_msg(struct radeon_decoder *dec, result.order_hint_bits = pic->picture_parameter.order_hint_bits_minus_1 + 1; for (i = 0; i < NUM_AV1_REFS; ++i) { - result.ref_frame_map[i] = - (pic->ref[i]) ? (uintptr_t)vl_video_buffer_get_associated_data(pic->ref[i], &dec->base) - : 0x7f; + uintptr_t ref_frame; + if (pic->ref[i]) { + ref_frame = (uintptr_t)vl_video_buffer_get_associated_data(pic->ref[i], &dec->base); + num_refs++; + } else + ref_frame = 0x7f; + result.ref_frame_map[i] = ref_frame; } for (i = 0; i < NUM_AV1_REFS_PER_FRAME; ++i) result.frame_refs[i] = result.ref_frame_map[pic->picture_parameter.ref_frame_idx[i]]; @@ -1303,6 +1315,7 @@ static rvcn_dec_message_av1_t get_av1_msg(struct radeon_decoder *dec, dec->ref_codec.bts = pic->picture_parameter.bit_depth_idx ? CODEC_10_BITS : CODEC_8_BITS; dec->ref_codec.index = result.curr_pic_idx; dec->ref_codec.ref_size = 8; + dec->ref_codec.num_refs = num_refs; memset(dec->ref_codec.ref_list, 0x7f, sizeof(dec->ref_codec.ref_list)); memcpy(dec->ref_codec.ref_list, result.ref_frame_map, sizeof(result.ref_frame_map)); } @@ -1890,6 +1903,23 @@ static unsigned rvcn_dec_dynamic_dpb_t2_message(struct radeon_decoder *dec, rvcn list_addtail(&dpb->list, &dec->dpb_ref_list); } + if (dynamic_dpb_t2->dpbArraySize < dec->ref_codec.num_refs) { + struct rvcn_dec_dynamic_dpb_t2 *d = + list_first_entry(&dec->dpb_ref_list, struct rvcn_dec_dynamic_dpb_t2, list); + addr = dec->ws->buffer_get_virtual_address(d->dpb.res->buf); + if (!addr && dummy) + addr = dec->ws->buffer_get_virtual_address(dummy->dpb.res->buf); + assert(addr); + for (i = 0; i < dec->ref_codec.num_refs; ++i) { + if (dynamic_dpb_t2->dpbAddrLo[i] || dynamic_dpb_t2->dpbAddrHi[i]) + continue; + dynamic_dpb_t2->dpbAddrLo[i] = addr; + dynamic_dpb_t2->dpbAddrHi[i] = addr >> 32; + ++dynamic_dpb_t2->dpbArraySize; + } + assert(dynamic_dpb_t2->dpbArraySize == dec->ref_codec.num_refs); + } + dec->ws->cs_add_buffer(&dec->cs, dpb->dpb.res->buf, RADEON_USAGE_READWRITE | RADEON_USAGE_SYNCHRONIZED, RADEON_DOMAIN_VRAM); addr = dec->ws->buffer_get_virtual_address(dpb->dpb.res->buf); diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_dec.h b/src/gallium/drivers/radeonsi/radeon_vcn_dec.h index 91ee4a4e4d4..5eecea168b9 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_dec.h +++ b/src/gallium/drivers/radeonsi/radeon_vcn_dec.h @@ -125,6 +125,7 @@ struct radeon_decoder { } bts; uint8_t index; unsigned ref_size; + unsigned num_refs; uint8_t ref_list[16]; } ref_codec;