diff --git a/src/amd/common/ac_vcn_enc.h b/src/amd/common/ac_vcn_enc.h index 80bac3f124c..7ced87fe143 100644 --- a/src/amd/common/ac_vcn_enc.h +++ b/src/amd/common/ac_vcn_enc.h @@ -72,6 +72,7 @@ #define RENCODE_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR 0x00000001 #define RENCODE_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR 0x00000002 #define RENCODE_RATE_CONTROL_METHOD_CBR 0x00000003 +#define RENCODE_RATE_CONTROL_METHOD_QUALITY_VBR 0x00000004 #define RENCODE_DIRECT_OUTPUT_NALU_TYPE_AUD 0x00000000 #define RENCODE_DIRECT_OUTPUT_NALU_TYPE_VPS 0x00000001 @@ -391,7 +392,7 @@ typedef struct rvcn_enc_rate_ctl_per_picture_s { uint32_t enabled_filler_data; uint32_t skip_frame_enable; uint32_t enforce_hrd; - uint32_t reserved_0xff; + uint32_t qvbr_quality_level; } rvcn_enc_rate_ctl_per_picture_t; typedef struct rvcn_enc_quality_params_s { diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc.c b/src/gallium/drivers/radeonsi/radeon_vcn_enc.c index c703fe93a10..fcf6edab9bc 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc.c @@ -295,6 +295,7 @@ static void radeon_vcn_enc_h264_get_rc_param(struct radeon_encoder *enc, enc->enc_pic.rc_per_pic.enabled_filler_data = 0; enc->enc_pic.rc_per_pic.skip_frame_enable = pic->rate_ctrl[0].skip_frame_enable; enc->enc_pic.rc_per_pic.enforce_hrd = pic->rate_ctrl[0].enforce_hrd; + enc->enc_pic.rc_per_pic.qvbr_quality_level = pic->rate_ctrl[0].vbr_quality_factor; switch (pic->rate_ctrl[0].rate_ctrl_method) { case PIPE_H2645_ENC_RATE_CONTROL_METHOD_DISABLE: @@ -310,6 +311,12 @@ static void radeon_vcn_enc_h264_get_rc_param(struct radeon_encoder *enc, enc->enc_pic.rc_session_init.rate_control_method = RENCODE_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR; break; + case PIPE_H2645_ENC_RATE_CONTROL_METHOD_QUALITY_VARIABLE: + enc->enc_pic.rc_session_init.rate_control_method = + RENCODE_RATE_CONTROL_METHOD_QUALITY_VBR; + /* QVBR requires pre-encode enabled. */ + enc->enc_pic.quality_modes.pre_encode_mode = RENCODE_PREENCODE_MODE_4X; + break; default: enc->enc_pic.rc_session_init.rate_control_method = RENCODE_RATE_CONTROL_METHOD_NONE; } @@ -564,6 +571,7 @@ static void radeon_vcn_enc_hevc_get_rc_param(struct radeon_encoder *enc, enc->enc_pic.rc_per_pic.enabled_filler_data = 0; enc->enc_pic.rc_per_pic.skip_frame_enable = pic->rc.skip_frame_enable; enc->enc_pic.rc_per_pic.enforce_hrd = pic->rc.enforce_hrd; + enc->enc_pic.rc_per_pic.qvbr_quality_level = pic->rc.vbr_quality_factor; switch (pic->rc.rate_ctrl_method) { case PIPE_H2645_ENC_RATE_CONTROL_METHOD_DISABLE: enc->enc_pic.rc_session_init.rate_control_method = RENCODE_RATE_CONTROL_METHOD_NONE; @@ -578,6 +586,12 @@ static void radeon_vcn_enc_hevc_get_rc_param(struct radeon_encoder *enc, enc->enc_pic.rc_session_init.rate_control_method = RENCODE_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR; break; + case PIPE_H2645_ENC_RATE_CONTROL_METHOD_QUALITY_VARIABLE: + enc->enc_pic.rc_session_init.rate_control_method = + RENCODE_RATE_CONTROL_METHOD_QUALITY_VBR; + /* QVBR requires pre-encode enabled. */ + enc->enc_pic.quality_modes.pre_encode_mode = RENCODE_PREENCODE_MODE_4X; + break; default: enc->enc_pic.rc_session_init.rate_control_method = RENCODE_RATE_CONTROL_METHOD_NONE; } @@ -813,6 +827,7 @@ static void radeon_vcn_enc_av1_get_rc_param(struct radeon_encoder *enc, enc->enc_pic.rc_per_pic.enabled_filler_data = 0; enc->enc_pic.rc_per_pic.skip_frame_enable = pic->rc[0].skip_frame_enable; enc->enc_pic.rc_per_pic.enforce_hrd = pic->rc[0].enforce_hrd; + enc->enc_pic.rc_per_pic.qvbr_quality_level = (pic->rc[0].vbr_quality_factor + 2) / 5; switch (pic->rc[0].rate_ctrl_method) { case PIPE_H2645_ENC_RATE_CONTROL_METHOD_DISABLE: enc->enc_pic.rc_session_init.rate_control_method = RENCODE_RATE_CONTROL_METHOD_NONE; @@ -827,6 +842,12 @@ static void radeon_vcn_enc_av1_get_rc_param(struct radeon_encoder *enc, enc->enc_pic.rc_session_init.rate_control_method = RENCODE_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR; break; + case PIPE_H2645_ENC_RATE_CONTROL_METHOD_QUALITY_VARIABLE: + enc->enc_pic.rc_session_init.rate_control_method = + RENCODE_RATE_CONTROL_METHOD_QUALITY_VBR; + /* QVBR requires pre-encode enabled. */ + enc->enc_pic.quality_modes.pre_encode_mode = RENCODE_PREENCODE_MODE_4X; + break; default: enc->enc_pic.rc_session_init.rate_control_method = RENCODE_RATE_CONTROL_METHOD_NONE; } diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc_1_2.c b/src/gallium/drivers/radeonsi/radeon_vcn_enc_1_2.c index d533246ec34..a1f864b1c75 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc_1_2.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc_1_2.c @@ -1213,8 +1213,6 @@ static void radeon_enc_rc_per_pic(struct radeon_encoder *enc) static void radeon_enc_rc_per_pic_ex(struct radeon_encoder *enc) { - enc->enc_pic.rc_per_pic.reserved_0xff = 0xFFFFFFFF; - RADEON_ENC_BEGIN(enc->cmd.rc_per_pic); RADEON_ENC_CS(enc->enc_pic.rc_per_pic.qp_i); RADEON_ENC_CS(enc->enc_pic.rc_per_pic.qp_p); @@ -1231,7 +1229,6 @@ static void radeon_enc_rc_per_pic_ex(struct radeon_encoder *enc) RADEON_ENC_CS(enc->enc_pic.rc_per_pic.enabled_filler_data); RADEON_ENC_CS(enc->enc_pic.rc_per_pic.skip_frame_enable); RADEON_ENC_CS(enc->enc_pic.rc_per_pic.enforce_hrd); - RADEON_ENC_CS(enc->enc_pic.rc_per_pic.reserved_0xff); RADEON_ENC_END(); } diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc_3_0.c b/src/gallium/drivers/radeonsi/radeon_vcn_enc_3_0.c index 7c02ffcd5c2..6d684aa54c9 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc_3_0.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc_3_0.c @@ -117,6 +117,28 @@ static void radeon_enc_quality_params(struct radeon_encoder *enc) RADEON_ENC_END(); } +static void radeon_enc_rc_per_pic_ex(struct radeon_encoder *enc) +{ + RADEON_ENC_BEGIN(enc->cmd.rc_per_pic); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.qp_i); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.qp_p); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.qp_b); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.min_qp_i); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.max_qp_i); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.min_qp_p); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.max_qp_p); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.min_qp_b); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.max_qp_b); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.max_au_size_i); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.max_au_size_p); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.max_au_size_b); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.enabled_filler_data); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.skip_frame_enable); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.enforce_hrd); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.qvbr_quality_level); + RADEON_ENC_END(); +} + static void radeon_enc_nalu_sps(struct radeon_encoder *enc) { struct radeon_enc_pic *pic = &enc->enc_pic; @@ -540,6 +562,8 @@ void radeon_enc_3_0_init(struct radeon_encoder *enc) enc->session_init = radeon_enc_session_init; enc->ctx = radeon_enc_ctx; enc->quality_params = radeon_enc_quality_params; + if (enc->enc_pic.use_rc_per_pic_ex) + enc->rc_per_pic = radeon_enc_rc_per_pic_ex; if (u_reduce_video_profile(enc->base.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) { enc->spec_misc = radeon_enc_spec_misc; diff --git a/src/gallium/drivers/radeonsi/si_get.c b/src/gallium/drivers/radeonsi/si_get.c index fa7613319b4..93399b5b44e 100644 --- a/src/gallium/drivers/radeonsi/si_get.c +++ b/src/gallium/drivers/radeonsi/si_get.c @@ -876,6 +876,17 @@ static int si_get_video_param(struct pipe_screen *screen, enum pipe_video_profil else return 0; + case PIPE_VIDEO_CAP_ENC_RATE_CONTROL_QVBR: + if (sscreen->info.vcn_ip_version >= VCN_3_0_0 && + sscreen->info.vcn_ip_version < VCN_4_0_0) + return sscreen->info.vcn_enc_minor_version >= 30; + + if (sscreen->info.vcn_ip_version >= VCN_4_0_0 && + sscreen->info.vcn_ip_version < VCN_5_0_0) + return sscreen->info.vcn_enc_minor_version >= 15; + + return 0; + default: return 0; }