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

Reply via email to