radeonsi/vcn: enable 2 pass search center map
authorRuijing Dong <ruijing.dong@amd.com>
Tue, 18 Apr 2023 20:04:26 +0000 (16:04 -0400)
committerMarge Bot <emma+marge@anholt.net>
Thu, 27 Apr 2023 15:11:35 +0000 (15:11 +0000)
2 pass search map is a feature supported by VCN,
the main purpose is to enlarge motion search
range that in pre-encoding path the center global
motion vectors could be obtained and used in the
final path as a block center base. When 2pass is
used, this feature will be automatically enabled.

2 pass feature can be enabled by ffmpeg command
line "-compression_level 1"

and also correct some typos and move quality
package from vcn3.0 to vcn2.0 since it is availabe
in vcn2.0 and vcn3.0 can use it directly. Correct
vcn3.0 hevc spec misc IB package.

Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com>
Signed-off-by: Ruijing Dong <ruijing.dong@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22585>

src/gallium/drivers/radeonsi/radeon_vcn_enc.c
src/gallium/drivers/radeonsi/radeon_vcn_enc.h
src/gallium/drivers/radeonsi/radeon_vcn_enc_1_2.c
src/gallium/drivers/radeonsi/radeon_vcn_enc_2_0.c
src/gallium/drivers/radeonsi/radeon_vcn_enc_3_0.c

index 7a42948..15073b7 100644 (file)
@@ -535,8 +535,9 @@ static void radeon_enc_rec_offset(rvcn_enc_reconstructed_picture_t *recon,
 
 static int setup_dpb(struct radeon_encoder *enc)
 {
-   uint32_t rec_alignment = (u_reduce_video_profile(enc->base.profile)
-                             == PIPE_VIDEO_FORMAT_MPEG4_AVC) ? 16 : 64;
+   bool is_h264 = u_reduce_video_profile(enc->base.profile)
+                             == PIPE_VIDEO_FORMAT_MPEG4_AVC;
+   uint32_t rec_alignment = is_h264 ? 16 : 64;
    uint32_t aligned_width = align(enc->base.width, rec_alignment);
    uint32_t aligned_height = align(enc->base.height, rec_alignment);
    uint32_t aligned_chroma_height = align(aligned_height / 2, rec_alignment);
@@ -561,6 +562,22 @@ static int setup_dpb(struct radeon_encoder *enc)
    enc_pic->ctx_buf.pre_encode_picture_chroma_pitch = pitch;
 
    offset = 0;
+   if (enc_pic->quality_modes.pre_encode_mode) {
+      uint32_t pre_size  = ALIGN_TO((aligned_width >> 2), rec_alignment) *
+                           ALIGN_TO((aligned_height >> 2), rec_alignment);
+      uint32_t full_size = ALIGN_TO(aligned_width, rec_alignment) *
+                           ALIGN_TO(aligned_height, rec_alignment);
+      pre_size  = align(pre_size, 4);
+      full_size = align(full_size, 4);
+
+      enc_pic->ctx_buf.two_pass_search_center_map_offset = offset;
+      if (is_h264)
+         offset += align((pre_size * 4 + full_size) * sizeof(uint32_t), enc->alignment);
+      else
+         offset += align((pre_size * 52 + full_size) * sizeof(uint32_t), enc->alignment);
+   } else
+      enc_pic->ctx_buf.two_pass_search_center_map_offset = 0;
+
    for (i = 0; i < num_reconstructed_pictures; i++) {
       radeon_enc_rec_offset(&enc_pic->ctx_buf.reconstructed_pictures[i],
                             &offset, luma_size, chroma_size);
index 0971fd5..5b0646d 100644 (file)
@@ -309,6 +309,8 @@ typedef struct rvcn_enc_hevc_spec_misc_s {
    uint32_t cabac_init_flag;
    uint32_t half_pel_enabled;
    uint32_t quarter_pel_enabled;
+   uint32_t transform_skip_discarded;
+   uint32_t cu_qp_delta_enabled_flag;
 } rvcn_enc_hevc_spec_misc_t;
 
 typedef struct rvcn_enc_rate_ctl_session_init_s {
@@ -342,6 +344,7 @@ typedef struct rvcn_enc_quality_params_s {
    uint32_t scene_change_sensitivity;
    uint32_t scene_change_min_idr_interval;
    uint32_t two_pass_search_center_map_mode;
+   uint32_t vbaq_strength;
 } rvcn_enc_quality_params_t;
 
 typedef struct rvcn_enc_direct_output_nalu_s {
index 9ca28cc..2e690a5 100644 (file)
@@ -242,7 +242,8 @@ static void radeon_enc_quality_params(struct radeon_encoder *enc)
    enc->enc_pic.quality_params.vbaq_mode = enc->enc_pic.quality_modes.vbaq_mode;
    enc->enc_pic.quality_params.scene_change_sensitivity = 0;
    enc->enc_pic.quality_params.scene_change_min_idr_interval = 0;
-   enc->enc_pic.quality_params.two_pass_search_center_map_mode = 0;
+   enc->enc_pic.quality_params.two_pass_search_center_map_mode =
+                    (enc->enc_pic.quality_modes.pre_encode_mode) ? 1 : 0;
 
    RADEON_ENC_BEGIN(enc->cmd.quality_params);
    RADEON_ENC_CS(enc->enc_pic.quality_params.vbaq_mode);
@@ -1504,7 +1505,6 @@ void radeon_enc_1_2_init(struct radeon_encoder *enc)
    enc->op_init_rc = radeon_enc_op_init_rc;
    enc->op_init_rc_vbv = radeon_enc_op_init_rc_vbv;
    enc->op_preset = radeon_enc_op_preset;
-   enc->encode_params = radeon_enc_encode_params;
    enc->session_init = radeon_enc_session_init;
    enc->encode_statistics = radeon_enc_encode_statistics;
    enc->nalu_aud = radeon_enc_nalu_aud;
index 0ca223f..3d285fd 100644 (file)
@@ -84,6 +84,24 @@ static void radeon_enc_op_preset(struct radeon_encoder *enc)
    RADEON_ENC_END();
 }
 
+static void radeon_enc_quality_params(struct radeon_encoder *enc)
+{
+   enc->enc_pic.quality_params.vbaq_mode = enc->enc_pic.quality_modes.vbaq_mode;
+   enc->enc_pic.quality_params.scene_change_sensitivity = 0;
+   enc->enc_pic.quality_params.scene_change_min_idr_interval = 0;
+   enc->enc_pic.quality_params.two_pass_search_center_map_mode =
+                    (enc->enc_pic.quality_modes.pre_encode_mode) ? 1 : 0;
+   enc->enc_pic.quality_params.vbaq_strength = 0;
+
+   RADEON_ENC_BEGIN(enc->cmd.quality_params);
+   RADEON_ENC_CS(enc->enc_pic.quality_params.vbaq_mode);
+   RADEON_ENC_CS(enc->enc_pic.quality_params.scene_change_sensitivity);
+   RADEON_ENC_CS(enc->enc_pic.quality_params.scene_change_min_idr_interval);
+   RADEON_ENC_CS(enc->enc_pic.quality_params.two_pass_search_center_map_mode);
+   RADEON_ENC_CS(enc->enc_pic.quality_params.vbaq_strength);
+   RADEON_ENC_END();
+}
+
 static void radeon_enc_slice_header_hevc(struct radeon_encoder *enc)
 {
    uint32_t instruction[RENCODE_SLICE_HEADER_TEMPLATE_MAX_NUM_INSTRUCTIONS] = {0};
@@ -506,6 +524,7 @@ void radeon_enc_2_0_init(struct radeon_encoder *enc)
    enc->output_format = radeon_enc_output_format;
    enc->ctx = radeon_enc_ctx;
    enc->op_preset = radeon_enc_op_preset;
+   enc->quality_params = radeon_enc_quality_params;
 
    if (u_reduce_video_profile(enc->base.profile) == PIPE_VIDEO_FORMAT_HEVC) {
       enc->deblocking_filter = radeon_enc_loop_filter_hevc;
index 763c5df..cd78079 100644 (file)
@@ -60,19 +60,21 @@ static void radeon_enc_spec_misc(struct radeon_encoder *enc)
    RADEON_ENC_END();
 }
 
-static void radeon_enc_quality_params(struct radeon_encoder *enc)
+static void radeon_enc_spec_misc_hevc(struct radeon_encoder *enc)
 {
-   enc->enc_pic.quality_params.vbaq_mode = enc->enc_pic.quality_modes.vbaq_mode;
-   enc->enc_pic.quality_params.scene_change_sensitivity = 0;
-   enc->enc_pic.quality_params.scene_change_min_idr_interval = 0;
-   enc->enc_pic.quality_params.two_pass_search_center_map_mode = 0;
-
-   RADEON_ENC_BEGIN(enc->cmd.quality_params);
-   RADEON_ENC_CS(enc->enc_pic.quality_params.vbaq_mode);
-   RADEON_ENC_CS(enc->enc_pic.quality_params.scene_change_sensitivity);
-   RADEON_ENC_CS(enc->enc_pic.quality_params.scene_change_min_idr_interval);
-   RADEON_ENC_CS(enc->enc_pic.quality_params.two_pass_search_center_map_mode);
-   RADEON_ENC_CS(0);
+   enc->enc_pic.hevc_spec_misc.transform_skip_discarded = 0;
+   enc->enc_pic.hevc_spec_misc.cu_qp_delta_enabled_flag = 0;
+
+   RADEON_ENC_BEGIN(enc->cmd.spec_misc_hevc);
+   RADEON_ENC_CS(enc->enc_pic.hevc_spec_misc.log2_min_luma_coding_block_size_minus3);
+   RADEON_ENC_CS(enc->enc_pic.hevc_spec_misc.amp_disabled);
+   RADEON_ENC_CS(enc->enc_pic.hevc_spec_misc.strong_intra_smoothing_enabled);
+   RADEON_ENC_CS(enc->enc_pic.hevc_spec_misc.constrained_intra_pred_flag);
+   RADEON_ENC_CS(enc->enc_pic.hevc_spec_misc.cabac_init_flag);
+   RADEON_ENC_CS(enc->enc_pic.hevc_spec_misc.half_pel_enabled);
+   RADEON_ENC_CS(enc->enc_pic.hevc_spec_misc.quarter_pel_enabled);
+   RADEON_ENC_CS(enc->enc_pic.hevc_spec_misc.transform_skip_discarded);
+   RADEON_ENC_CS(enc->enc_pic.hevc_spec_misc.cu_qp_delta_enabled_flag);
    RADEON_ENC_END();
 }
 
@@ -240,7 +242,6 @@ void radeon_enc_3_0_init(struct radeon_encoder *enc)
    radeon_enc_2_0_init(enc);
 
    enc->session_init = radeon_enc_session_init;
-   enc->quality_params = radeon_enc_quality_params;
    enc->ctx = radeon_enc_ctx;
 
    if (u_reduce_video_profile(enc->base.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) {
@@ -248,8 +249,10 @@ void radeon_enc_3_0_init(struct radeon_encoder *enc)
       enc->encode_params_codec_spec = radeon_enc_encode_params_h264;
    }
 
-   if (u_reduce_video_profile(enc->base.profile) == PIPE_VIDEO_FORMAT_HEVC)
+   if (u_reduce_video_profile(enc->base.profile) == PIPE_VIDEO_FORMAT_HEVC) {
+      enc->spec_misc = radeon_enc_spec_misc_hevc;
       enc->nalu_pps = radeon_enc_nalu_pps_hevc;
+   }
 
    enc->enc_pic.session_info.interface_version =
       ((RENCODE_FW_INTERFACE_MAJOR_VERSION << RENCODE_IF_MAJOR_VERSION_SHIFT) |