radeonsi/vcn: Don't reinitialize encode session on bitrate/fps change
When bitrate or fps change is detected, only update rate control parameters instead of completely reinitializing encode session. This fixes an issue where if application changed bitrate or fps often, the output bitrate would significantly overshoot the target bitrate in some cases. In other cases, the output bitrate would be extremely low instead. Cc: mesa-stable Reviewed-by: Ruijing Dong <ruijing.dong@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27548>
This commit is contained in:
@@ -1042,23 +1042,23 @@ 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;
|
||||
bool need_rate_control = false;
|
||||
enc->need_rate_control = 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;
|
||||
need_rate_control =
|
||||
enc->need_rate_control =
|
||||
(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);
|
||||
} 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;
|
||||
need_rate_control =
|
||||
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);
|
||||
} 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;
|
||||
need_rate_control =
|
||||
enc->need_rate_control =
|
||||
(enc->enc_pic.rc_layer_init[0].target_bit_rate != pic->rc[0].target_bitrate) ||
|
||||
(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);
|
||||
@@ -1113,23 +1113,22 @@ static void radeon_enc_begin_frame(struct pipe_video_codec *encoder,
|
||||
|
||||
enc->need_feedback = false;
|
||||
|
||||
if (!enc->stream_handle || need_rate_control) {
|
||||
if (!enc->stream_handle) {
|
||||
struct rvid_buffer fb;
|
||||
if (!enc->stream_handle) {
|
||||
enc->stream_handle = si_vid_alloc_stream_handle();
|
||||
enc->si = CALLOC_STRUCT(rvid_buffer);
|
||||
if (!enc->si ||
|
||||
!enc->stream_handle ||
|
||||
!si_vid_create_buffer(enc->screen, enc->si, 128 * 1024, PIPE_USAGE_STAGING)) {
|
||||
RVID_ERR("Can't create session buffer.\n");
|
||||
goto error;
|
||||
}
|
||||
enc->stream_handle = si_vid_alloc_stream_handle();
|
||||
enc->si = CALLOC_STRUCT(rvid_buffer);
|
||||
if (!enc->si ||
|
||||
!enc->stream_handle ||
|
||||
!si_vid_create_buffer(enc->screen, enc->si, 128 * 1024, PIPE_USAGE_STAGING)) {
|
||||
RVID_ERR("Can't create session buffer.\n");
|
||||
goto error;
|
||||
}
|
||||
si_vid_create_buffer(enc->screen, &fb, 4096, PIPE_USAGE_STAGING);
|
||||
enc->fb = &fb;
|
||||
enc->begin(enc);
|
||||
flush(enc);
|
||||
si_vid_destroy_buffer(&fb);
|
||||
enc->need_rate_control = false;
|
||||
}
|
||||
|
||||
return;
|
||||
|
@@ -262,6 +262,7 @@ struct radeon_encoder {
|
||||
|
||||
bool emulation_prevention;
|
||||
bool need_feedback;
|
||||
bool need_rate_control;
|
||||
unsigned dpb_size;
|
||||
unsigned roi_size;
|
||||
rvcn_enc_picture_info_t dpb_info[RENCODE_MAX_NUM_RECONSTRUCTED_PICTURES];
|
||||
|
@@ -1392,11 +1392,22 @@ static void radeon_enc_headers_hevc(struct radeon_encoder *enc)
|
||||
|
||||
static void encode(struct radeon_encoder *enc)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
enc->before_encode(enc);
|
||||
enc->session_info(enc);
|
||||
enc->total_task_size = 0;
|
||||
enc->task_info(enc, enc->need_feedback);
|
||||
|
||||
if (enc->need_rate_control) {
|
||||
i = 0;
|
||||
do {
|
||||
enc->enc_pic.temporal_id = i;
|
||||
enc->layer_select(enc);
|
||||
enc->rc_layer_init(enc);
|
||||
} while (++i < enc->enc_pic.num_temporal_layers);
|
||||
}
|
||||
|
||||
enc->encode_headers(enc);
|
||||
enc->ctx(enc);
|
||||
enc->bitstream(enc);
|
||||
|
@@ -505,11 +505,22 @@ static void radeon_enc_ctx(struct radeon_encoder *enc)
|
||||
}
|
||||
static void encode(struct radeon_encoder *enc)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
enc->before_encode(enc);
|
||||
enc->session_info(enc);
|
||||
enc->total_task_size = 0;
|
||||
enc->task_info(enc, enc->need_feedback);
|
||||
|
||||
if (enc->need_rate_control) {
|
||||
i = 0;
|
||||
do {
|
||||
enc->enc_pic.temporal_id = i;
|
||||
enc->layer_select(enc);
|
||||
enc->rc_layer_init(enc);
|
||||
} while (++i < enc->enc_pic.num_temporal_layers);
|
||||
}
|
||||
|
||||
enc->encode_headers(enc);
|
||||
enc->ctx(enc);
|
||||
enc->bitstream(enc);
|
||||
|
Reference in New Issue
Block a user