radeonsi/vcn: Implement separate QP for I/P/B frames

This also fixes max_au_size as a side effect of using new IB.

Reviewed-by: Ruijing Dong <ruijing.dong@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27558>
This commit is contained in:
David Rosca
2024-02-22 16:39:13 +01:00
committed by Marge Bot
parent 252ba4bbdd
commit cbbed6ca3e
5 changed files with 114 additions and 33 deletions

View File

@@ -312,13 +312,22 @@ typedef struct rvcn_enc_rate_ctl_layer_init_s {
} rvcn_enc_rate_ctl_layer_init_t;
typedef struct rvcn_enc_rate_ctl_per_picture_s {
uint32_t qp;
uint32_t min_qp_app;
uint32_t max_qp_app;
uint32_t max_au_size;
uint32_t qp_i;
uint32_t qp_p;
uint32_t qp_b;
uint32_t min_qp_i;
uint32_t max_qp_i;
uint32_t min_qp_p;
uint32_t max_qp_p;
uint32_t min_qp_b;
uint32_t max_qp_b;
uint32_t max_au_size_i;
uint32_t max_au_size_p;
uint32_t max_au_size_b;
uint32_t enabled_filler_data;
uint32_t skip_frame_enable;
uint32_t enforce_hrd;
uint32_t reserved_0xff;
} rvcn_enc_rate_ctl_per_picture_t;
typedef struct rvcn_enc_quality_params_s {

View File

@@ -235,7 +235,7 @@ static void radeon_vcn_enc_h264_get_spec_misc_param(struct radeon_encoder *enc,
static void radeon_vcn_enc_h264_get_rc_param(struct radeon_encoder *enc,
struct pipe_h264_enc_picture_desc *pic)
{
uint32_t frame_rate_den, frame_rate_num;
uint32_t frame_rate_den, frame_rate_num, max_qp;
enc->enc_pic.num_temporal_layers = pic->seq.num_temporal_layers ? pic->seq.num_temporal_layers : 1;
for (int i = 0; i < enc->enc_pic.num_temporal_layers; i++) {
@@ -261,10 +261,16 @@ static void radeon_vcn_enc_h264_get_rc_param(struct radeon_encoder *enc,
frame_rate_num);
}
enc->enc_pic.rc_session_init.vbv_buffer_level = pic->rate_ctrl[0].vbv_buf_lv;
enc->enc_pic.rc_per_pic.qp = pic->quant_i_frames;
enc->enc_pic.rc_per_pic.min_qp_app = pic->rate_ctrl[0].min_qp;
enc->enc_pic.rc_per_pic.max_qp_app = pic->rate_ctrl[0].max_qp ?
pic->rate_ctrl[0].max_qp : 51;
enc->enc_pic.rc_per_pic.qp_i = pic->quant_i_frames;
enc->enc_pic.rc_per_pic.qp_p = pic->quant_p_frames;
enc->enc_pic.rc_per_pic.qp_b = pic->quant_b_frames;
enc->enc_pic.rc_per_pic.min_qp_i = pic->rate_ctrl[0].min_qp;
enc->enc_pic.rc_per_pic.min_qp_p = pic->rate_ctrl[0].min_qp;
enc->enc_pic.rc_per_pic.min_qp_b = pic->rate_ctrl[0].min_qp;
max_qp = pic->rate_ctrl[0].max_qp ? pic->rate_ctrl[0].max_qp : 51;
enc->enc_pic.rc_per_pic.max_qp_i = max_qp;
enc->enc_pic.rc_per_pic.max_qp_p = max_qp;
enc->enc_pic.rc_per_pic.max_qp_b = max_qp;
enc->enc_pic.rc_per_pic.enabled_filler_data = pic->rate_ctrl[0].fill_data_enable;
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;
@@ -285,7 +291,9 @@ static void radeon_vcn_enc_h264_get_rc_param(struct radeon_encoder *enc,
default:
enc->enc_pic.rc_session_init.rate_control_method = RENCODE_RATE_CONTROL_METHOD_NONE;
}
enc->enc_pic.rc_per_pic.max_au_size = pic->rate_ctrl[0].max_au_size;
enc->enc_pic.rc_per_pic.max_au_size_i = pic->rate_ctrl[0].max_au_size;
enc->enc_pic.rc_per_pic.max_au_size_p = pic->rate_ctrl[0].max_au_size;
enc->enc_pic.rc_per_pic.max_au_size_b = pic->rate_ctrl[0].max_au_size;
}
static void radeon_vcn_enc_h264_get_vui_param(struct radeon_encoder *enc,
@@ -482,7 +490,7 @@ static void radeon_vcn_enc_hevc_get_spec_misc_param(struct radeon_encoder *enc,
static void radeon_vcn_enc_hevc_get_rc_param(struct radeon_encoder *enc,
struct pipe_h265_enc_picture_desc *pic)
{
uint32_t frame_rate_den, frame_rate_num;
uint32_t frame_rate_den, frame_rate_num, max_qp;
enc->enc_pic.rc_layer_init[0].target_bit_rate = pic->rc.target_bitrate;
enc->enc_pic.rc_layer_init[0].peak_bit_rate = pic->rc.peak_bitrate;
@@ -505,9 +513,13 @@ static void radeon_vcn_enc_hevc_get_rc_param(struct radeon_encoder *enc,
frame_rate_den,
frame_rate_num);
enc->enc_pic.rc_session_init.vbv_buffer_level = pic->rc.vbv_buf_lv;
enc->enc_pic.rc_per_pic.qp = pic->rc.quant_i_frames;
enc->enc_pic.rc_per_pic.min_qp_app = pic->rc.min_qp;
enc->enc_pic.rc_per_pic.max_qp_app = pic->rc.max_qp ? pic->rc.max_qp : 51;
enc->enc_pic.rc_per_pic.qp_i = pic->rc.quant_i_frames;
enc->enc_pic.rc_per_pic.qp_p = pic->rc.quant_p_frames;
enc->enc_pic.rc_per_pic.min_qp_i = pic->rc.min_qp;
enc->enc_pic.rc_per_pic.min_qp_p = pic->rc.min_qp;
max_qp = pic->rc.max_qp ? pic->rc.max_qp : 51;
enc->enc_pic.rc_per_pic.max_qp_i = max_qp;
enc->enc_pic.rc_per_pic.max_qp_p = max_qp;
enc->enc_pic.rc_per_pic.enabled_filler_data = pic->rc.fill_data_enable;
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;
@@ -527,7 +539,8 @@ static void radeon_vcn_enc_hevc_get_rc_param(struct radeon_encoder *enc,
default:
enc->enc_pic.rc_session_init.rate_control_method = RENCODE_RATE_CONTROL_METHOD_NONE;
}
enc->enc_pic.rc_per_pic.max_au_size = pic->rc.max_au_size;
enc->enc_pic.rc_per_pic.max_au_size_i = pic->rc.max_au_size;
enc->enc_pic.rc_per_pic.max_au_size_p = pic->rc.max_au_size;
}
static void radeon_vcn_enc_hevc_get_vui_param(struct radeon_encoder *enc,
@@ -699,7 +712,7 @@ static void radeon_vcn_enc_av1_color_description(struct radeon_encoder *enc,
static void radeon_vcn_enc_av1_get_rc_param(struct radeon_encoder *enc,
struct pipe_av1_enc_picture_desc *pic)
{
uint32_t frame_rate_den, frame_rate_num;
uint32_t frame_rate_den, frame_rate_num, min_qp, max_qp;
for (int i = 0; i < ARRAY_SIZE(enc->enc_pic.rc_layer_init); i++) {
enc->enc_pic.rc_layer_init[i].target_bit_rate = pic->rc[i].target_bitrate;
@@ -724,9 +737,14 @@ static void radeon_vcn_enc_av1_get_rc_param(struct radeon_encoder *enc,
frame_rate_num);
}
enc->enc_pic.rc_session_init.vbv_buffer_level = pic->rc[0].vbv_buf_lv;
enc->enc_pic.rc_per_pic.qp = pic->rc[0].qp;
enc->enc_pic.rc_per_pic.min_qp_app = pic->rc[0].min_qp ? pic->rc[0].min_qp : 1;
enc->enc_pic.rc_per_pic.max_qp_app = pic->rc[0].max_qp ? pic->rc[0].max_qp : 255;
enc->enc_pic.rc_per_pic.qp_i = pic->rc[0].qp;
enc->enc_pic.rc_per_pic.qp_p = pic->rc[0].qp_inter;
min_qp = pic->rc[0].min_qp ? pic->rc[0].min_qp : 1;
enc->enc_pic.rc_per_pic.min_qp_i = min_qp;
enc->enc_pic.rc_per_pic.min_qp_p = min_qp;
max_qp = pic->rc[0].max_qp ? pic->rc[0].max_qp : 255;
enc->enc_pic.rc_per_pic.max_qp_i = max_qp;
enc->enc_pic.rc_per_pic.max_qp_p = max_qp;
enc->enc_pic.rc_per_pic.enabled_filler_data = pic->rc[0].fill_data_enable;
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;
@@ -746,7 +764,8 @@ static void radeon_vcn_enc_av1_get_rc_param(struct radeon_encoder *enc,
default:
enc->enc_pic.rc_session_init.rate_control_method = RENCODE_RATE_CONTROL_METHOD_NONE;
}
enc->enc_pic.rc_per_pic.max_au_size = pic->rc[0].max_au_size;
enc->enc_pic.rc_per_pic.max_au_size_i = pic->rc[0].max_au_size;
enc->enc_pic.rc_per_pic.max_au_size_p = pic->rc[0].max_au_size;
}
static void radeon_vcn_enc_av1_get_param(struct radeon_encoder *enc,
@@ -1053,6 +1072,7 @@ static void radeon_enc_begin_frame(struct pipe_video_codec *encoder,
struct radeon_encoder *enc = (struct radeon_encoder *)encoder;
struct vl_video_buffer *vid_buf = (struct vl_video_buffer *)source;
enc->need_rate_control = false;
enc->need_rc_per_pic = false;
if (u_reduce_video_profile(enc->base.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) {
struct pipe_h264_enc_picture_desc *pic = (struct pipe_h264_enc_picture_desc *)picture;
@@ -1060,12 +1080,32 @@ static void radeon_enc_begin_frame(struct pipe_video_codec *encoder,
(enc->enc_pic.rc_layer_init[0].target_bit_rate != pic->rate_ctrl[0].target_bitrate) ||
(enc->enc_pic.rc_layer_init[0].frame_rate_num != pic->rate_ctrl[0].frame_rate_num) ||
(enc->enc_pic.rc_layer_init[0].frame_rate_den != pic->rate_ctrl[0].frame_rate_den);
if (enc->need_rate_control) {
enc->enc_pic.rc_per_pic.qp_i = 0;
enc->enc_pic.rc_per_pic.qp_p = 0;
enc->enc_pic.rc_per_pic.qp_b = 0;
}
enc->need_rc_per_pic =
(!enc->enc_pic.rc_per_pic.qp_i && enc->enc_pic.rc_per_pic.qp_i != pic->quant_i_frames) ||
(!enc->enc_pic.rc_per_pic.qp_p && enc->enc_pic.rc_per_pic.qp_p != pic->quant_p_frames) ||
(!enc->enc_pic.rc_per_pic.qp_b && enc->enc_pic.rc_per_pic.qp_b != pic->quant_b_frames);
} else if (u_reduce_video_profile(picture->profile) == PIPE_VIDEO_FORMAT_HEVC) {
struct pipe_h265_enc_picture_desc *pic = (struct pipe_h265_enc_picture_desc *)picture;
enc->need_rate_control =
(enc->enc_pic.rc_layer_init[0].target_bit_rate != pic->rc.target_bitrate) ||
(enc->enc_pic.rc_layer_init[0].frame_rate_num != pic->rc.frame_rate_num) ||
(enc->enc_pic.rc_layer_init[0].frame_rate_den != pic->rc.frame_rate_den);
if (enc->need_rate_control) {
enc->enc_pic.rc_per_pic.qp_i = 0;
enc->enc_pic.rc_per_pic.qp_p = 0;
}
enc->need_rc_per_pic =
(!enc->enc_pic.rc_per_pic.qp_i && enc->enc_pic.rc_per_pic.qp_i != pic->rc.quant_i_frames) ||
(!enc->enc_pic.rc_per_pic.qp_p && enc->enc_pic.rc_per_pic.qp_p != pic->rc.quant_p_frames);
} else if (u_reduce_video_profile(picture->profile) == PIPE_VIDEO_FORMAT_AV1) {
struct pipe_av1_enc_picture_desc *pic = (struct pipe_av1_enc_picture_desc *)picture;
enc->need_rate_control =
@@ -1073,6 +1113,15 @@ static void radeon_enc_begin_frame(struct pipe_video_codec *encoder,
(enc->enc_pic.rc_layer_init[0].frame_rate_num != pic->rc[0].frame_rate_num) ||
(enc->enc_pic.rc_layer_init[0].frame_rate_den != pic->rc[0].frame_rate_den);
if (enc->need_rate_control) {
enc->enc_pic.rc_per_pic.qp_i = 0;
enc->enc_pic.rc_per_pic.qp_p = 0;
}
enc->need_rc_per_pic =
(!enc->enc_pic.rc_per_pic.qp_i && enc->enc_pic.rc_per_pic.qp_i != pic->rc[0].qp) ||
(!enc->enc_pic.rc_per_pic.qp_p && enc->enc_pic.rc_per_pic.qp_p != pic->rc[0].qp_inter);
if (!enc->cdf) {
enc->cdf = CALLOC_STRUCT(rvid_buffer);
if (setup_cdf(enc)) {
@@ -1139,6 +1188,7 @@ static void radeon_enc_begin_frame(struct pipe_video_codec *encoder,
flush(enc);
si_vid_destroy_buffer(&fb);
enc->need_rate_control = false;
enc->need_rc_per_pic = false;
}
return;

View File

@@ -271,6 +271,7 @@ struct radeon_encoder {
bool emulation_prevention;
bool need_feedback;
bool need_rate_control;
bool need_rc_per_pic;
unsigned dpb_size;
unsigned roi_size;
rvcn_enc_picture_info_t dpb_info[RENCODE_MAX_NUM_RECONSTRUCTED_PICTURES];

View File

@@ -25,7 +25,7 @@
#define RENCODE_IB_PARAM_LAYER_SELECT 0x00000005
#define RENCODE_IB_PARAM_RATE_CONTROL_SESSION_INIT 0x00000006
#define RENCODE_IB_PARAM_RATE_CONTROL_LAYER_INIT 0x00000007
#define RENCODE_IB_PARAM_RATE_CONTROL_PER_PICTURE 0x00000008
#define RENCODE_IB_PARAM_RATE_CONTROL_PER_PICTURE 0x0000001d
#define RENCODE_IB_PARAM_QUALITY_PARAMS 0x00000009
#define RENCODE_IB_PARAM_SLICE_HEADER 0x0000000a
#define RENCODE_IB_PARAM_ENCODE_PARAMS 0x0000000b
@@ -1187,14 +1187,25 @@ static void radeon_enc_intra_refresh(struct radeon_encoder *enc)
static void radeon_enc_rc_per_pic(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);
RADEON_ENC_CS(enc->enc_pic.rc_per_pic.min_qp_app);
RADEON_ENC_CS(enc->enc_pic.rc_per_pic.max_qp_app);
RADEON_ENC_CS(enc->enc_pic.rc_per_pic.max_au_size);
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.reserved_0xff);
RADEON_ENC_END();
}
@@ -1397,12 +1408,18 @@ static void encode(struct radeon_encoder *enc)
enc->total_task_size = 0;
enc->task_info(enc, enc->need_feedback);
if (enc->need_rate_control) {
if (enc->need_rate_control || enc->need_rc_per_pic) {
i = 0;
do {
enc->enc_pic.layer_sel.temporal_layer_index = i;
enc->layer_select(enc);
enc->rc_layer_init(enc);
if (enc->need_rate_control) {
enc->layer_select(enc);
enc->rc_layer_init(enc);
}
if (enc->need_rc_per_pic) {
enc->layer_select(enc);
enc->rc_per_pic(enc);
}
} while (++i < enc->enc_pic.num_temporal_layers);
}

View File

@@ -24,7 +24,6 @@
#define RENCODE_IB_PARAM_LAYER_SELECT 0x00000005
#define RENCODE_IB_PARAM_RATE_CONTROL_SESSION_INIT 0x00000006
#define RENCODE_IB_PARAM_RATE_CONTROL_LAYER_INIT 0x00000007
#define RENCODE_IB_PARAM_RATE_CONTROL_PER_PICTURE 0x00000008
#define RENCODE_IB_PARAM_QUALITY_PARAMS 0x00000009
#define RENCODE_IB_PARAM_DIRECT_OUTPUT_NALU 0x0000000a
#define RENCODE_IB_PARAM_SLICE_HEADER 0x0000000b
@@ -512,12 +511,18 @@ static void encode(struct radeon_encoder *enc)
enc->total_task_size = 0;
enc->task_info(enc, enc->need_feedback);
if (enc->need_rate_control) {
if (enc->need_rate_control || enc->need_rc_per_pic) {
i = 0;
do {
enc->enc_pic.layer_sel.temporal_layer_index = i;
enc->layer_select(enc);
enc->rc_layer_init(enc);
if (enc->need_rate_control) {
enc->layer_select(enc);
enc->rc_layer_init(enc);
}
if (enc->need_rc_per_pic) {
enc->layer_select(enc);
enc->rc_per_pic(enc);
}
} while (++i < enc->enc_pic.num_temporal_layers);
}
@@ -560,7 +565,6 @@ void radeon_enc_2_0_init(struct radeon_encoder *enc)
enc->cmd.layer_select = RENCODE_IB_PARAM_LAYER_SELECT;
enc->cmd.rc_session_init = RENCODE_IB_PARAM_RATE_CONTROL_SESSION_INIT;
enc->cmd.rc_layer_init = RENCODE_IB_PARAM_RATE_CONTROL_LAYER_INIT;
enc->cmd.rc_per_pic = RENCODE_IB_PARAM_RATE_CONTROL_PER_PICTURE;
enc->cmd.quality_params = RENCODE_IB_PARAM_QUALITY_PARAMS;
enc->cmd.nalu = RENCODE_IB_PARAM_DIRECT_OUTPUT_NALU;
enc->cmd.slice_header = RENCODE_IB_PARAM_SLICE_HEADER;