From e359b3c525f3d11ca1a836a91db0071cc120bc42 Mon Sep 17 00:00:00 2001 From: "David (Ming Qiang) Wu" Date: Fri, 2 Aug 2024 17:22:54 -0400 Subject: [PATCH] radeonsi/vcn: support 12bit YUV420 AV1 decoding Add 12bit AV1 decoding support for PIPE_VIDEO_PROFILE_AV1_PROFILE2. This feature is tested on VCN5 and VCN4. Signed-off-by: David (Ming Qiang) Wu Reviewed-by: David Rosca Part-of: --- src/gallium/drivers/radeonsi/radeon_vcn_dec.c | 25 +++++++++++++++---- src/gallium/drivers/radeonsi/radeon_vcn_dec.h | 3 ++- src/gallium/drivers/radeonsi/si_get.c | 7 ++++++ 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_dec.c b/src/gallium/drivers/radeonsi/radeon_vcn_dec.c index 771969fc94d..32f033d3757 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_dec.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_dec.c @@ -35,6 +35,7 @@ #define NUM_AV1_REFS 8 #define NUM_AV1_REFS_PER_FRAME 7 +static enum pipe_format get_buffer_format(struct radeon_decoder *dec); static unsigned calc_dpb_size(struct radeon_decoder *dec); static unsigned calc_ctx_size_h264_perf(struct radeon_decoder *dec); static unsigned calc_ctx_size_h265_main(struct radeon_decoder *dec); @@ -999,7 +1000,9 @@ static rvcn_dec_message_av1_t get_av1_msg(struct radeon_decoder *dec, } if (pic->picture_parameter.bit_depth_idx) { - if (target->buffer_format == PIPE_FORMAT_P010 || target->buffer_format == PIPE_FORMAT_P016) { + if (target->buffer_format == PIPE_FORMAT_P010 || + target->buffer_format == PIPE_FORMAT_P012 || + target->buffer_format == PIPE_FORMAT_P016) { result.p010_mode = 1; result.msb_mode = 1; } else { @@ -1106,7 +1109,7 @@ static rvcn_dec_message_av1_t get_av1_msg(struct radeon_decoder *dec, } if (dec->dpb_type == DPB_DYNAMIC_TIER_2) { - dec->ref_codec.bts = pic->picture_parameter.bit_depth_idx ? CODEC_10_BITS : CODEC_8_BITS; + dec->ref_codec.bts = pic->picture_parameter.bit_depth_idx; dec->ref_codec.index = result.curr_pic_idx; dec->ref_codec.ref_size = 8; dec->ref_codec.num_refs = num_refs; @@ -1371,7 +1374,7 @@ static unsigned rvcn_dec_dynamic_dpb_t2_message(struct radeon_decoder *dec, rvcn width = align(decode->width_in_samples, dec->db_alignment); height = align(decode->height_in_samples, dec->db_alignment); size = align((width * height * 3) / 2, 256); - if (dec->ref_codec.bts == CODEC_10_BITS) + if (dec->ref_codec.bts == CODEC_10_BITS || dec->ref_codec.bts == CODEC_12_BITS) size = (((struct si_screen *)dec->screen)->info.vcn_ip_version == VCN_5_0_0) ? size * 2 : size * 3 / 2; list_for_each_entry_safe(struct rvcn_dec_dynamic_dpb_t2, d, &dec->dpb_ref_list, list) { @@ -1448,7 +1451,7 @@ static unsigned rvcn_dec_dynamic_dpb_t2_message(struct radeon_decoder *dec, rvcn if (dec->dpb_use_surf) { struct pipe_video_buffer templat; memset(&templat, 0, sizeof(templat)); - templat.buffer_format = (dec->ref_codec.bts != CODEC_10_BITS) ? PIPE_FORMAT_NV12 : PIPE_FORMAT_P010; + templat.buffer_format = get_buffer_format(dec); templat.width = width; templat.height = height; if (encrypted) @@ -1529,7 +1532,7 @@ static unsigned rvcn_dec_dynamic_dpb_t2_message(struct radeon_decoder *dec, rvcn dynamic_dpb_t2->dpbChromaAlignedSize = dynamic_dpb_t2->dpbChromaPitch * dynamic_dpb_t2->dpbChromaAlignedHeight * 2; - if (dec->ref_codec.bts == CODEC_10_BITS) { + if (dec->ref_codec.bts == CODEC_10_BITS || dec->ref_codec.bts == CODEC_12_BITS) { if (((struct si_screen *)dec->screen)->info.vcn_ip_version == VCN_5_0_0) { dynamic_dpb_t2->dpbLumaAlignedSize = dynamic_dpb_t2->dpbLumaAlignedSize * 2; dynamic_dpb_t2->dpbChromaAlignedSize = dynamic_dpb_t2->dpbChromaAlignedSize * 2; @@ -3071,3 +3074,15 @@ err: return NULL; } + +static enum pipe_format get_buffer_format(struct radeon_decoder *dec) +{ + switch (dec->ref_codec.bts) { + case CODEC_10_BITS: + return PIPE_FORMAT_P010; + case CODEC_12_BITS: + return PIPE_FORMAT_P012; + default: + return PIPE_FORMAT_NV12; + } +} diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_dec.h b/src/gallium/drivers/radeonsi/radeon_vcn_dec.h index 769039ed952..98904e38792 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_dec.h +++ b/src/gallium/drivers/radeonsi/radeon_vcn_dec.h @@ -118,7 +118,8 @@ struct radeon_decoder { struct { enum { CODEC_8_BITS = 0, - CODEC_10_BITS + CODEC_10_BITS, + CODEC_12_BITS } bts; uint8_t index; unsigned ref_size; diff --git a/src/gallium/drivers/radeonsi/si_get.c b/src/gallium/drivers/radeonsi/si_get.c index be66f4775c5..bd66aef9821 100644 --- a/src/gallium/drivers/radeonsi/si_get.c +++ b/src/gallium/drivers/radeonsi/si_get.c @@ -1103,6 +1103,13 @@ static bool si_vid_is_format_supported(struct pipe_screen *screen, enum pipe_for return (format == PIPE_FORMAT_P010) || (format == PIPE_FORMAT_P016) || (format == PIPE_FORMAT_NV12); + if (profile == PIPE_VIDEO_PROFILE_AV1_PROFILE2 && entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) { + if (sscreen->info.vcn_ip_version < VCN_5_0_0 && sscreen->info.vcn_ip_version != VCN_4_0_0) + return false; + return (format == PIPE_FORMAT_P010) || (format == PIPE_FORMAT_P016) || + (format == PIPE_FORMAT_P012) || (format == PIPE_FORMAT_NV12); + } + /* JPEG supports YUV400 and YUV444 */ if (profile == PIPE_VIDEO_PROFILE_JPEG_BASELINE) { switch (format) {