radeonsi/vcn: Add support for QVBR rate control mode
This rate control mode needs pre-encode enabled and currently is supported for VCN3 and VCN4. AV1 needs quality level scaled down from 255 to 51 range. Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/4024 Reviewed-by: Ruijing Dong <ruijing.dong@amd.com> Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30221>
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user