Module: Mesa Branch: main Commit: 3c8937d3633d7327b5d6a0e1d65ea78b1557bc76 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=3c8937d3633d7327b5d6a0e1d65ea78b1557bc76
Author: Ruijing Dong <[email protected]> Date: Sat Sep 10 16:42:40 2022 -0400 frontends/va: add max_frame_size into rate control why: max au size and per picture rate control data structure need to follow the input how: have max_frame_size as the input to rate control also re-calculate other rate control related params Signed-off-by: Ruijing Dong <[email protected]> Reviewed-by: Sil Vilerino <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18534> --- src/gallium/drivers/radeonsi/radeon_vcn_enc.c | 46 ++++++++++++++++++++++----- src/gallium/drivers/radeonsi/si_get.c | 2 ++ src/gallium/frontends/va/config.c | 10 ++++++ src/gallium/frontends/va/picture.c | 24 ++++++++++++++ src/gallium/frontends/va/picture_h264_enc.c | 8 +++++ src/gallium/frontends/va/picture_hevc_enc.c | 8 +++++ src/gallium/frontends/va/va_private.h | 2 ++ src/gallium/include/pipe/p_video_enums.h | 1 + src/gallium/include/pipe/p_video_state.h | 2 ++ 9 files changed, 95 insertions(+), 8 deletions(-) diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc.c b/src/gallium/drivers/radeonsi/radeon_vcn_enc.c index 12ff106bfd5..6f1ce274e14 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc.c @@ -52,6 +52,20 @@ static void radeon_vcn_enc_quality_modes(struct radeon_encoder *enc, p->vbaq_mode = in->vbaq_mode ? RENCODE_VBAQ_AUTO : RENCODE_VBAQ_NONE; } +static uint32_t radeon_vcn_per_frame_integer(uint32_t bitrate, uint32_t den, uint32_t num) +{ + uint64_t rate_den = (uint64_t)bitrate * (uint64_t)den; + + return (uint32_t)(rate_den/num); +} + +static uint32_t radeon_vcn_per_frame_frac(uint32_t bitrate, uint32_t den, uint32_t num) +{ + uint64_t rate_den = (uint64_t)bitrate * (uint64_t)den; + uint64_t remainder = rate_den % num; + + return (uint32_t)((remainder << 32) / num); +} static void radeon_vcn_enc_get_param(struct radeon_encoder *enc, struct pipe_picture_desc *picture) { if (u_reduce_video_profile(picture->profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) { @@ -80,18 +94,24 @@ static void radeon_vcn_enc_get_param(struct radeon_encoder *enc, struct pipe_pic } enc->enc_pic.num_temporal_layers = pic->num_temporal_layers ? pic->num_temporal_layers : 1; enc->enc_pic.temporal_id = 0; - for (int i = 0; i < enc->enc_pic.num_temporal_layers; i++) - { + for (int i = 0; i < enc->enc_pic.num_temporal_layers; i++) { enc->enc_pic.rc_layer_init[i].target_bit_rate = pic->rate_ctrl[i].target_bitrate; enc->enc_pic.rc_layer_init[i].peak_bit_rate = pic->rate_ctrl[i].peak_bitrate; enc->enc_pic.rc_layer_init[i].frame_rate_num = pic->rate_ctrl[i].frame_rate_num; enc->enc_pic.rc_layer_init[i].frame_rate_den = pic->rate_ctrl[i].frame_rate_den; enc->enc_pic.rc_layer_init[i].vbv_buffer_size = pic->rate_ctrl[i].vbv_buffer_size; - enc->enc_pic.rc_layer_init[i].avg_target_bits_per_picture = pic->rate_ctrl[i].target_bits_picture; + enc->enc_pic.rc_layer_init[i].avg_target_bits_per_picture = + radeon_vcn_per_frame_integer(pic->rate_ctrl[i].target_bitrate, + pic->rate_ctrl[i].frame_rate_den, + pic->rate_ctrl[i].frame_rate_num); enc->enc_pic.rc_layer_init[i].peak_bits_per_picture_integer = - pic->rate_ctrl[i].peak_bits_picture_integer; + radeon_vcn_per_frame_integer(pic->rate_ctrl[i].peak_bitrate, + pic->rate_ctrl[i].frame_rate_den, + pic->rate_ctrl[i].frame_rate_num); enc->enc_pic.rc_layer_init[i].peak_bits_per_picture_fractional = - pic->rate_ctrl[i].peak_bits_picture_fraction; + radeon_vcn_per_frame_frac(pic->rate_ctrl[i].peak_bitrate, + pic->rate_ctrl[i].frame_rate_den, + pic->rate_ctrl[i].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; @@ -125,6 +145,7 @@ static void radeon_vcn_enc_get_param(struct radeon_encoder *enc, struct pipe_pic else enc->enc_pic.spec_misc.cabac_enable = false; + enc->enc_pic.rc_per_pic.max_au_size = pic->rate_ctrl[0].max_au_size; enc->enc_pic.spec_misc.cabac_init_idc = enc->enc_pic.spec_misc.cabac_enable ? pic->pic_ctrl.enc_cabac_init_idc : 0; } else if (u_reduce_video_profile(picture->profile) == PIPE_VIDEO_FORMAT_HEVC) { @@ -212,10 +233,18 @@ static void radeon_vcn_enc_get_param(struct radeon_encoder *enc, struct pipe_pic 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; enc->enc_pic.rc_layer_init[0].vbv_buffer_size = pic->rc.vbv_buffer_size; - enc->enc_pic.rc_layer_init[0].avg_target_bits_per_picture = pic->rc.target_bits_picture; - enc->enc_pic.rc_layer_init[0].peak_bits_per_picture_integer = pic->rc.peak_bits_picture_integer; + enc->enc_pic.rc_layer_init[0].avg_target_bits_per_picture = + radeon_vcn_per_frame_integer(pic->rc.target_bitrate, + pic->rc.frame_rate_den, + pic->rc.frame_rate_num); + enc->enc_pic.rc_layer_init[0].peak_bits_per_picture_integer = + radeon_vcn_per_frame_integer(pic->rc.peak_bitrate, + pic->rc.frame_rate_den, + pic->rc.frame_rate_num); enc->enc_pic.rc_layer_init[0].peak_bits_per_picture_fractional = - pic->rc.peak_bits_picture_fraction; + radeon_vcn_per_frame_frac(pic->rc.peak_bitrate, + pic->rc.frame_rate_den, + pic->rc.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 = 0; @@ -240,6 +269,7 @@ static void radeon_vcn_enc_get_param(struct radeon_encoder *enc, struct pipe_pic 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; } } diff --git a/src/gallium/drivers/radeonsi/si_get.c b/src/gallium/drivers/radeonsi/si_get.c index 46b74f8f068..2559cfdb940 100644 --- a/src/gallium/drivers/radeonsi/si_get.c +++ b/src/gallium/drivers/radeonsi/si_get.c @@ -623,6 +623,8 @@ static int si_get_video_param(struct pipe_screen *screen, enum pipe_video_profil return 32; else return 0; + case PIPE_VIDEO_CAP_ENC_SUPPORTS_MAX_FRAME_SIZE: + return (sscreen->info.family >= CHIP_RAVEN) ? 1 : 0; default: return 0; } diff --git a/src/gallium/frontends/va/config.c b/src/gallium/frontends/va/config.c index ae13e624861..445fc190e36 100644 --- a/src/gallium/frontends/va/config.c +++ b/src/gallium/frontends/va/config.c @@ -219,6 +219,16 @@ vlVaGetConfigAttributes(VADriverContextP ctx, VAProfile profile, VAEntrypoint en PIPE_VIDEO_CAP_ENC_QUALITY_LEVEL); value = quality_range ? quality_range : VA_ATTRIB_NOT_SUPPORTED; } break; + case VAConfigAttribMaxFrameSize: + { + /* Max Frame Size can be used to control picture level frame size. + * This frame size is in bits. + */ + value = pscreen->get_video_param(pscreen, ProfileToPipe(profile), + PIPE_VIDEO_ENTRYPOINT_ENCODE, + PIPE_VIDEO_CAP_ENC_SUPPORTS_MAX_FRAME_SIZE); + value = value ? value : VA_ATTRIB_NOT_SUPPORTED; + } break; default: value = VA_ATTRIB_NOT_SUPPORTED; break; diff --git a/src/gallium/frontends/va/picture.c b/src/gallium/frontends/va/picture.c index 7b34a0494e2..a8e86b2b4c4 100644 --- a/src/gallium/frontends/va/picture.c +++ b/src/gallium/frontends/va/picture.c @@ -523,6 +523,26 @@ handleVAEncMiscParameterTypeQualityLevel(vlVaContext *context, VAEncMiscParamete return status; } +static VAStatus +handleVAEncMiscParameterTypeMaxFrameSize(vlVaContext *context, VAEncMiscParameterBuffer *misc) +{ + VAStatus status = VA_STATUS_SUCCESS; + + switch (u_reduce_video_profile(context->templat.profile)) { + case PIPE_VIDEO_FORMAT_MPEG4_AVC: + status = vlVaHandleVAEncMiscParameterTypeMaxFrameSizeH264(context, misc); + break; + + case PIPE_VIDEO_FORMAT_HEVC: + status = vlVaHandleVAEncMiscParameterTypeMaxFrameSizeHEVC(context, misc); + break; + + default: + break; + } + + return status; +} static VAStatus handleVAEncMiscParameterBufferType(vlVaContext *context, vlVaBuffer *buf) { @@ -547,6 +567,10 @@ handleVAEncMiscParameterBufferType(vlVaContext *context, vlVaBuffer *buf) vaStatus = handleVAEncMiscParameterTypeQualityLevel(context, misc); break; + case VAEncMiscParameterTypeMaxFrameSize: + vaStatus = handleVAEncMiscParameterTypeMaxFrameSize(context, misc); + break; + default: break; } diff --git a/src/gallium/frontends/va/picture_h264_enc.c b/src/gallium/frontends/va/picture_h264_enc.c index 3ebfcfa7b31..b9848b9b1db 100644 --- a/src/gallium/frontends/va/picture_h264_enc.c +++ b/src/gallium/frontends/va/picture_h264_enc.c @@ -259,6 +259,14 @@ vlVaHandleVAEncMiscParameterTypeQualityLevelH264(vlVaContext *context, VAEncMisc return VA_STATUS_SUCCESS; } +VAStatus +vlVaHandleVAEncMiscParameterTypeMaxFrameSizeH264(vlVaContext *context, VAEncMiscParameterBuffer *misc) +{ + VAEncMiscParameterBufferMaxFrameSize *ms = (VAEncMiscParameterBufferMaxFrameSize *)misc->data; + context->desc.h264enc.rate_ctrl[0].max_au_size = ms->max_frame_size; + return VA_STATUS_SUCCESS; +} + void getEncParamPresetH264(vlVaContext *context) { //rate control diff --git a/src/gallium/frontends/va/picture_hevc_enc.c b/src/gallium/frontends/va/picture_hevc_enc.c index 1c6b37baf4b..910ecf60836 100644 --- a/src/gallium/frontends/va/picture_hevc_enc.c +++ b/src/gallium/frontends/va/picture_hevc_enc.c @@ -331,6 +331,14 @@ vlVaHandleVAEncPackedHeaderDataBufferTypeHEVC(vlVaContext *context, vlVaBuffer * return VA_STATUS_SUCCESS; } +VAStatus +vlVaHandleVAEncMiscParameterTypeMaxFrameSizeHEVC(vlVaContext *context, VAEncMiscParameterBuffer *misc) +{ + VAEncMiscParameterBufferMaxFrameSize *ms = (VAEncMiscParameterBufferMaxFrameSize *)misc->data; + context->desc.h265enc.rc.max_au_size = ms->max_frame_size; + return VA_STATUS_SUCCESS; +} + void getEncParamPresetH265(vlVaContext *context) { //rate control diff --git a/src/gallium/frontends/va/va_private.h b/src/gallium/frontends/va/va_private.h index 42f61c9b8a4..4ec79b55dce 100644 --- a/src/gallium/frontends/va/va_private.h +++ b/src/gallium/frontends/va/va_private.h @@ -498,6 +498,7 @@ VAStatus vlVaHandleVAEncMiscParameterTypeRateControlH264(vlVaContext *context, V VAStatus vlVaHandleVAEncMiscParameterTypeFrameRateH264(vlVaContext *context, VAEncMiscParameterBuffer *buf); VAStatus vlVaHandleVAEncMiscParameterTypeTemporalLayerH264(vlVaContext *context, VAEncMiscParameterBuffer *buf); VAStatus vlVaHandleVAEncMiscParameterTypeQualityLevelH264(vlVaContext *context, VAEncMiscParameterBuffer *buf); +VAStatus vlVaHandleVAEncMiscParameterTypeMaxFrameSizeH264(vlVaContext *context, VAEncMiscParameterBuffer *buf); VAStatus vlVaHandleVAEncPictureParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); VAStatus vlVaHandleVAEncSliceParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); VAStatus vlVaHandleVAEncSequenceParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); @@ -505,4 +506,5 @@ VAStatus vlVaHandleVAEncMiscParameterTypeRateControlHEVC(vlVaContext *context, V VAStatus vlVaHandleVAEncMiscParameterTypeFrameRateHEVC(vlVaContext *context, VAEncMiscParameterBuffer *buf); VAStatus vlVaHandleVAEncPackedHeaderDataBufferTypeHEVC(vlVaContext *context, vlVaBuffer *buf); VAStatus vlVaHandleVAEncMiscParameterTypeQualityLevelHEVC(vlVaContext *context, VAEncMiscParameterBuffer *buf); +VAStatus vlVaHandleVAEncMiscParameterTypeMaxFrameSizeHEVC(vlVaContext *context, VAEncMiscParameterBuffer *buf); #endif //VA_PRIVATE_H diff --git a/src/gallium/include/pipe/p_video_enums.h b/src/gallium/include/pipe/p_video_enums.h index b7b29b7af51..5a53808e79c 100644 --- a/src/gallium/include/pipe/p_video_enums.h +++ b/src/gallium/include/pipe/p_video_enums.h @@ -110,6 +110,7 @@ enum pipe_video_cap all the planes contiguously. This allows for use with some frontends functions that require this like vaDeriveImage */ PIPE_VIDEO_SUPPORTS_CONTIGUOUS_PLANES_MAP = 27, + PIPE_VIDEO_CAP_ENC_SUPPORTS_MAX_FRAME_SIZE = 28, }; /* To be used with PIPE_VIDEO_CAP_VPP_ORIENTATION_MODES and for VPP state*/ diff --git a/src/gallium/include/pipe/p_video_state.h b/src/gallium/include/pipe/p_video_state.h index a503081048b..918c9e22b7b 100644 --- a/src/gallium/include/pipe/p_video_state.h +++ b/src/gallium/include/pipe/p_video_state.h @@ -384,6 +384,7 @@ struct pipe_h264_enc_rate_control unsigned peak_bits_picture_fraction; unsigned fill_data_enable; unsigned enforce_hrd; + unsigned max_au_size; }; struct pipe_h264_enc_motion_estimation @@ -520,6 +521,7 @@ struct pipe_h265_enc_rate_control unsigned peak_bits_picture_fraction; unsigned fill_data_enable; unsigned enforce_hrd; + unsigned max_au_size; }; struct pipe_h265_enc_picture_desc
