Mesa (main): radeon/vcn: implement encoder dpb management

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Dec 8 03:41:42 UTC 2021


Module: Mesa
Branch: main
Commit: 7ba0c68e3195aa127370bfce01166387e6903d39
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=7ba0c68e3195aa127370bfce01166387e6903d39

Author: Thong Thai <thong.thai at amd.com>
Date:   Sun Nov 21 19:51:16 2021 -0500

radeon/vcn: implement encoder dpb management

Previously, the number of previously encoded frames the encoder handled
was 1 - the encoder now supports many more encoded pictures, so the
encoder now has to keep track of multiple reconstructed pictures.

v2: Add a check to make sure an array index is not negative (Boyuan)

Signed-off-by: Thong Thai <thong.thai at amd.com>
Reviewed-by: Boyuan Zhang <boyuan.zhang at amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13915>

---

 src/gallium/drivers/radeon/radeon_vcn_enc.h     |  8 +++
 src/gallium/drivers/radeon/radeon_vcn_enc_1_2.c | 86 +++++++++++++++++++++----
 src/gallium/drivers/radeon/radeon_vcn_enc_2_0.c |  1 +
 3 files changed, 81 insertions(+), 14 deletions(-)

diff --git a/src/gallium/drivers/radeon/radeon_vcn_enc.h b/src/gallium/drivers/radeon/radeon_vcn_enc.h
index 877d54bfb78..889fd5cbc84 100644
--- a/src/gallium/drivers/radeon/radeon_vcn_enc.h
+++ b/src/gallium/drivers/radeon/radeon_vcn_enc.h
@@ -330,6 +330,12 @@ typedef struct rvcn_enc_reconstructed_picture_s {
    uint32_t chroma_offset;
 } rvcn_enc_reconstructed_picture_t;
 
+typedef struct rvcn_enc_picture_info_s
+{
+   bool in_use;
+   uint32_t frame_num;
+} rvcn_enc_picture_info_t;
+
 typedef struct rvcn_enc_pre_encode_input_picture_s {
    union {
       struct {
@@ -481,6 +487,7 @@ struct radeon_encoder {
    struct pipe_video_codec base;
 
    void (*begin)(struct radeon_encoder *enc);
+   void (*before_encode)(struct radeon_encoder *enc);
    void (*encode)(struct radeon_encoder *enc);
    void (*destroy)(struct radeon_encoder *enc);
    void (*session_info)(struct radeon_encoder *enc);
@@ -554,6 +561,7 @@ struct radeon_encoder {
    bool emulation_prevention;
    bool need_feedback;
    unsigned dpb_size;
+   rvcn_enc_picture_info_t dpb[RENCODE_MAX_NUM_RECONSTRUCTED_PICTURES];
 };
 
 void radeon_enc_add_buffer(struct radeon_encoder *enc, struct pb_buffer *buf,
diff --git a/src/gallium/drivers/radeon/radeon_vcn_enc_1_2.c b/src/gallium/drivers/radeon/radeon_vcn_enc_1_2.c
index b6ac75dd034..772ba878a65 100644
--- a/src/gallium/drivers/radeon/radeon_vcn_enc_1_2.c
+++ b/src/gallium/drivers/radeon/radeon_vcn_enc_1_2.c
@@ -299,7 +299,7 @@ static void radeon_enc_nalu_sps(struct radeon_encoder *enc)
    if (enc->enc_pic.pic_order_cnt_type == 0)
       radeon_enc_code_ue(enc, 1);
 
-   radeon_enc_code_ue(enc, (enc->base.max_references + 1));
+   radeon_enc_code_ue(enc, enc->base.max_references);
    radeon_enc_code_fixed_bits(enc, enc->enc_pic.layer_ctrl.max_num_temporal_layers > 1 ? 0x1 : 0x0,
                               1);
    radeon_enc_code_ue(enc, (enc->enc_pic.session_init.aligned_picture_width / 16 - 1));
@@ -331,14 +331,14 @@ static void radeon_enc_nalu_sps(struct radeon_encoder *enc)
    radeon_enc_code_fixed_bits(enc, 0x0, 1);
    radeon_enc_code_fixed_bits(enc, 0x0, 1);
    radeon_enc_code_fixed_bits(enc, 0x0, 1);
-   radeon_enc_code_fixed_bits(enc, 0x1, 1);
-   radeon_enc_code_fixed_bits(enc, 0x1, 1);
+   radeon_enc_code_fixed_bits(enc, 0x1, 1);  /* bitstream_restriction_flag */
+   radeon_enc_code_fixed_bits(enc, 0x1, 1);  /* motion_vectors_over_pic_boundaries_flag */
    radeon_enc_code_ue(enc, 0x0);
    radeon_enc_code_ue(enc, 0x0);
    radeon_enc_code_ue(enc, 16);
    radeon_enc_code_ue(enc, 16);
    radeon_enc_code_ue(enc, 0x0);
-   radeon_enc_code_ue(enc, (enc->base.max_references + 1));
+   radeon_enc_code_ue(enc, enc->base.max_references); /* max_dec_frame_buffering */
 
    radeon_enc_code_fixed_bits(enc, 0x1, 1);
 
@@ -859,12 +859,15 @@ static void radeon_enc_slice_header(struct radeon_encoder *enc)
    if (enc->enc_pic.pic_order_cnt_type == 0)
       radeon_enc_code_fixed_bits(enc, enc->enc_pic.pic_order_cnt % 32, 5);
 
+   /* ref_pic_list_modification() */
    if (enc->enc_pic.picture_type != PIPE_H2645_ENC_PICTURE_TYPE_IDR) {
       radeon_enc_code_fixed_bits(enc, 0x0, 1);
 
+      /* list_mod_diff_pic_minus1 != 0 */
       if (enc->enc_pic.frame_num - enc->enc_pic.ref_idx_l0 > 1) {
-         radeon_enc_code_fixed_bits(enc, 0x1, 1);
-         radeon_enc_code_ue(enc, 0x0);
+         radeon_enc_code_fixed_bits(enc, 0x1, 1);  /* ref_pic_list_modification_flag_l0 */
+         radeon_enc_code_ue(enc, 0x0);             /* modification_of_pic_nums_idc */
+         /* abs_diff_pic_num_minus1 */
          radeon_enc_code_ue(enc, (enc->enc_pic.frame_num - enc->enc_pic.ref_idx_l0 - 1));
          radeon_enc_code_ue(enc, 0x3);
       } else
@@ -874,7 +877,7 @@ static void radeon_enc_slice_header(struct radeon_encoder *enc)
    if (enc->enc_pic.is_idr) {
       radeon_enc_code_fixed_bits(enc, 0x0, 1);
       radeon_enc_code_fixed_bits(enc, 0x0, 1);
-   } else
+   } else if (!enc->enc_pic.not_referenced)
       radeon_enc_code_fixed_bits(enc, 0x0, 1);
 
    if ((enc->enc_pic.picture_type != PIPE_H2645_ENC_PICTURE_TYPE_IDR) &&
@@ -1164,13 +1167,6 @@ static void radeon_enc_encode_params(struct radeon_encoder *enc)
    enc->enc_pic.enc_params.input_pic_chroma_pitch = enc->chroma->u.gfx9.surf_pitch;
    enc->enc_pic.enc_params.input_pic_swizzle_mode = enc->luma->u.gfx9.swizzle_mode;
 
-   if (enc->enc_pic.picture_type == PIPE_H2645_ENC_PICTURE_TYPE_IDR)
-      enc->enc_pic.enc_params.reference_picture_index = 0xFFFFFFFF;
-   else
-      enc->enc_pic.enc_params.reference_picture_index = (enc->enc_pic.frame_num - 1) % 2;
-
-   enc->enc_pic.enc_params.reconstructed_picture_index = enc->enc_pic.frame_num % 2;
-
    RADEON_ENC_BEGIN(enc->cmd.enc_params);
    RADEON_ENC_CS(enc->enc_pic.enc_params.pic_type);
    RADEON_ENC_CS(enc->enc_pic.enc_params.allowed_max_bitstream_size);
@@ -1296,6 +1292,7 @@ static void radeon_enc_headers_hevc(struct radeon_encoder *enc)
 
 static void encode(struct radeon_encoder *enc)
 {
+   enc->before_encode(enc);
    enc->session_info(enc);
    enc->total_task_size = 0;
    enc->task_info(enc, enc->need_feedback);
@@ -1320,8 +1317,69 @@ static void destroy(struct radeon_encoder *enc)
    *enc->p_task_size = (enc->total_task_size);
 }
 
+static int find_short_ref_idx(struct radeon_encoder *enc, int frame_num)
+{
+   for (int i = 0; i < enc->base.max_references + 1; i++)
+      if (enc->dpb[i].frame_num == frame_num && enc->dpb[i].in_use)
+         return i;
+
+   return -1;
+}
+
+static int get_picture_storage(struct radeon_encoder *enc)
+{
+   for (int i = 0; i < enc->base.max_references + 1; i++) {
+      if (!enc->dpb[i].in_use) {
+         memset(&(enc->dpb[i]), 0, sizeof(rvcn_enc_picture_info_t));
+         return i;
+      }
+   }
+
+   /* look for the oldest short term ref pic */
+   unsigned int oldest_frame_num = 0xFFFFFFFF;
+   int oldest_idx = -1;
+   for (int i = 0; i < enc->base.max_references + 1; i++)
+      if (enc->dpb[i].frame_num < oldest_frame_num) {
+         oldest_frame_num = enc->dpb[i].frame_num;
+         oldest_idx = i;
+      }
+
+   if (oldest_idx > 0)
+      enc->dpb[oldest_idx].in_use = FALSE;
+
+   return oldest_idx;
+}
+
+static void manage_dpb_before_encode(struct radeon_encoder *enc)
+{
+   int current_pic_idx = 0;
+
+   if (enc->enc_pic.picture_type == PIPE_H2645_ENC_PICTURE_TYPE_IDR) {
+      /* clear reference frames */
+      for (int i = 0; i < enc->base.max_references + 1; i++)
+         memset(&(enc->dpb[i]), 0, sizeof(rvcn_enc_picture_info_t));
+   }
+
+   current_pic_idx = get_picture_storage(enc);
+   assert(current_pic_idx >= 0);
+
+   int ref0_idx = find_short_ref_idx(enc, enc->enc_pic.ref_idx_l0);
+
+   if (!enc->enc_pic.not_referenced)
+      enc->dpb[current_pic_idx].in_use = TRUE;
+
+   enc->dpb[current_pic_idx].frame_num = enc->enc_pic.frame_num;
+
+   if (enc->enc_pic.picture_type == PIPE_H2645_ENC_PICTURE_TYPE_IDR)
+      enc->enc_pic.enc_params.reference_picture_index = 0xFFFFFFFF;
+   else
+      enc->enc_pic.enc_params.reference_picture_index = ref0_idx;
+   enc->enc_pic.enc_params.reconstructed_picture_index = current_pic_idx;
+}
+
 void radeon_enc_1_2_init(struct radeon_encoder *enc)
 {
+   enc->before_encode = manage_dpb_before_encode;
    enc->begin = begin;
    enc->encode = encode;
    enc->destroy = destroy;
diff --git a/src/gallium/drivers/radeon/radeon_vcn_enc_2_0.c b/src/gallium/drivers/radeon/radeon_vcn_enc_2_0.c
index d6835506ba5..9c711c331e9 100644
--- a/src/gallium/drivers/radeon/radeon_vcn_enc_2_0.c
+++ b/src/gallium/drivers/radeon/radeon_vcn_enc_2_0.c
@@ -430,6 +430,7 @@ static void radeon_enc_output_format(struct radeon_encoder *enc)
 
 static void encode(struct radeon_encoder *enc)
 {
+   enc->before_encode(enc);
    enc->session_info(enc);
    enc->total_task_size = 0;
    enc->task_info(enc, enc->need_feedback);



More information about the mesa-commit mailing list