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

Author: Ruijing Dong <ruijing.d...@amd.com>
Date:   Fri Dec  8 18:18:01 2023 -0500

frontends/va: add ROI feature

ROI (region of interest) feature implementation
in va.

It does not support ROI priority, and supports
qp delta, and the maximum number of supported
region is defined as 32, the region sequence implies
the priority, the lower the sequence number, the higher
the region priority, when region overlapping happened,
the higher priority region overwrites the lower
priority one.

And specifically for AV1, the adjust step will be
rounded by 5 when rate control is used, for example,
if qp_delta (q index) is 6, it will use 5, if
qp_delta is 8, it will use 10.

For AVC/HEVC (RC/CQP) and AV1 CQP mode, the
qp_delta granularity is 1.

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

---

 src/gallium/frontends/va/config.c        | 11 ++++++
 src/gallium/frontends/va/picture.c       | 54 ++++++++++++++++++++++++++
 src/gallium/include/pipe/p_video_enums.h |  4 ++
 src/gallium/include/pipe/p_video_state.h | 66 ++++++++++++++++++++++++++++++++
 4 files changed, 135 insertions(+)

diff --git a/src/gallium/frontends/va/config.c 
b/src/gallium/frontends/va/config.c
index 9abf9af832b..868e568a1a3 100644
--- a/src/gallium/frontends/va/config.c
+++ b/src/gallium/frontends/va/config.c
@@ -544,6 +544,17 @@ vlVaGetConfigAttributes(VADriverContextP ctx, VAProfile 
profile, VAEntrypoint en
                value = ir_support;
          } break;
 
+         case VAConfigAttribEncROI:
+         {
+            int roi_support = pscreen->get_video_param(pscreen, 
ProfileToPipe(profile),
+                                             PIPE_VIDEO_ENTRYPOINT_ENCODE,
+                                             PIPE_VIDEO_CAP_ENC_ROI);
+            if (roi_support <= 0)
+               value = VA_ATTRIB_NOT_SUPPORTED;
+            else
+               value = roi_support;
+         } 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 abcfec06233..9172980bc77 100644
--- a/src/gallium/frontends/va/picture.c
+++ b/src/gallium/frontends/va/picture.c
@@ -718,6 +718,56 @@ handleVAEncMiscParameterTypeRIR(vlVaContext *context, 
VAEncMiscParameterBuffer *
    return status;
 }
 
+static VAStatus
+handleVAEncMiscParameterTypeROI(vlVaContext *context, VAEncMiscParameterBuffer 
*misc)
+{
+   VAStatus status = VA_STATUS_SUCCESS;
+   struct pipe_enc_roi *proi= NULL;
+   switch (u_reduce_video_profile(context->templat.profile)) {
+      case PIPE_VIDEO_FORMAT_MPEG4_AVC:
+         proi = &context->desc.h264enc.roi;
+         break;
+      case PIPE_VIDEO_FORMAT_HEVC:
+         proi = &context->desc.h265enc.roi;
+         break;
+#if VA_CHECK_VERSION(1, 16, 0)
+      case PIPE_VIDEO_FORMAT_AV1:
+         proi = &context->desc.av1enc.roi;
+         break;
+#endif
+      default:
+         break;
+   };
+
+   if (proi) {
+      VAEncMiscParameterBufferROI *roi = (VAEncMiscParameterBufferROI 
*)misc->data;
+      /* do not support priority type, and the maximum region is 32  */
+      if ((roi->num_roi > 0 && roi->roi_flags.bits.roi_value_is_qp_delta == 0)
+           || roi->num_roi > PIPE_ENC_ROI_REGION_NUM_MAX)
+         status = VA_STATUS_ERROR_FLAG_NOT_SUPPORTED;
+      else {
+         uint32_t i;
+         VAEncROI *src = roi->roi;
+
+         proi->num = roi->num_roi;
+         for (i = 0; i < roi->num_roi; i++) {
+            proi->region[i].valid = true;
+            proi->region[i].x = src->roi_rectangle.x;
+            proi->region[i].y = src->roi_rectangle.y;
+            proi->region[i].width = src->roi_rectangle.width;
+            proi->region[i].height = src->roi_rectangle.height;
+            proi->region[i].qp_value = (int32_t)CLAMP(src->roi_value, 
roi->min_delta_qp, roi->max_delta_qp);
+            src++;
+         }
+
+         for (; i < PIPE_ENC_ROI_REGION_NUM_MAX; i++)
+            proi->region[i].valid = false;
+      }
+   }
+
+   return status;
+}
+
 static VAStatus
 handleVAEncMiscParameterBufferType(vlVaContext *context, vlVaBuffer *buf)
 {
@@ -758,6 +808,10 @@ handleVAEncMiscParameterBufferType(vlVaContext *context, 
vlVaBuffer *buf)
       vaStatus = handleVAEncMiscParameterTypeMaxSliceSize(context, misc);
       break;
 
+   case VAEncMiscParameterTypeROI:
+      vaStatus = handleVAEncMiscParameterTypeROI(context, misc);
+      break;
+
    default:
       break;
    }
diff --git a/src/gallium/include/pipe/p_video_enums.h 
b/src/gallium/include/pipe/p_video_enums.h
index cfc1f74e6f6..8c03fe74755 100644
--- a/src/gallium/include/pipe/p_video_enums.h
+++ b/src/gallium/include/pipe/p_video_enums.h
@@ -157,6 +157,10 @@ enum pipe_video_cap
       crop and partial decode support
    */
    PIPE_VIDEO_CAP_ROI_CROP_DEC = 48,
+   /*
+    * Encoding Region Of Interest feature
+    */
+   PIPE_VIDEO_CAP_ENC_ROI = 49,
 };
 
 enum pipe_video_h264_enc_dbk_filter_mode_flags
diff --git a/src/gallium/include/pipe/p_video_state.h 
b/src/gallium/include/pipe/p_video_state.h
index 67f41c0a3df..0945db18e8f 100644
--- a/src/gallium/include/pipe/p_video_state.h
+++ b/src/gallium/include/pipe/p_video_state.h
@@ -48,6 +48,7 @@ extern "C" {
 #define PIPE_DEFAULT_FRAME_RATE_NUM   30
 #define PIPE_DEFAULT_INTRA_IDR_PERIOD 30
 #define PIPE_H2645_EXTENDED_SAR       255
+#define PIPE_ENC_ROI_REGION_NUM_MAX   32
 #define PIPE_DEFAULT_DECODER_FEEDBACK_TIMEOUT_NS 1000000000
 
 /*
@@ -449,6 +450,32 @@ enum
    INTRA_REFRESH_MODE_UNIT_COLUMNS,
 };
 
+/* All the values are in pixels, driver converts it into
+ * different units for different codecs, for example: h264
+ * is in 16x16 block, hevc/av1 is in 64x64 block.
+ * x, y means the location of region start, width/height defines
+ * the region size; the qp value carries the qp_delta.
+ */
+struct pipe_enc_region_in_roi
+{
+   bool    valid;
+   int32_t qp_value;
+   unsigned int x, y;
+   unsigned int width, height;
+};
+/* It does not support prioirty only qp_delta.
+ * The priority is implied by the region sequence number.
+ * Region 0 is most significant one, and region 1 is less
+ * significant, and lesser significant when region number
+ * grows. It allows region overlapping, and lower
+ * priority region would be overwritten by the higher one.
+ */
+struct pipe_enc_roi
+{
+   unsigned int num;
+   struct pipe_enc_region_in_roi region[PIPE_ENC_ROI_REGION_NUM_MAX];
+};
+
 struct pipe_h264_enc_rate_control
 {
    enum pipe_h2645_enc_rate_control_method rate_ctrl_method;
@@ -625,6 +652,7 @@ struct pipe_h264_enc_picture_desc
    unsigned gop_size;
    struct pipe_enc_quality_modes quality_modes;
    struct pipe_enc_intra_refresh intra_refresh;
+   struct pipe_enc_roi roi;
 
    bool not_referenced;
    bool is_ltr;
@@ -819,6 +847,7 @@ struct pipe_h265_enc_picture_desc
    unsigned pic_order_cnt_type;
    struct pipe_enc_quality_modes quality_modes;
    struct pipe_enc_intra_refresh intra_refresh;
+   struct pipe_enc_roi roi;
    unsigned num_ref_idx_l0_active_minus1;
    unsigned num_ref_idx_l1_active_minus1;
    unsigned ref_idx_l0_list[PIPE_H265_MAX_REFERENCES];
@@ -964,6 +993,7 @@ struct pipe_av1_enc_picture_desc
    };
    struct pipe_enc_quality_modes quality_modes;
    struct pipe_enc_intra_refresh intra_refresh;
+   struct pipe_enc_roi roi;
    uint32_t num_tiles_in_pic; /* [1, 32], */
    uint32_t tile_rows;
    uint32_t tile_cols;
@@ -1936,6 +1966,42 @@ struct pipe_enc_feedback_metadata
    unsigned int average_frame_qp;
 };
 
+union pipe_enc_cap_roi {
+   struct {
+      /**
+       * The number of ROI regions supported, 0 if ROI is not supported
+       */
+      uint32_t num_roi_regions                 : 8;
+      /**
+       * A flag indicates whether ROI priority is supported
+       *
+       * roi_rc_priority_support equal to 1 specifies the underlying driver 
supports
+       * ROI priority when VAConfigAttribRateControl != VA_RC_CQP, user can 
use roi_value
+       * in #VAEncROI to set ROI priority. roi_rc_priority_support equal to 0 
specifies
+       * the underlying driver doesn't support ROI priority.
+       *
+       * User should ignore roi_rc_priority_support when 
VAConfigAttribRateControl == VA_RC_CQP
+       * because ROI delta QP is always required when 
VAConfigAttribRateControl == VA_RC_CQP.
+       */
+      uint32_t roi_rc_priority_support         : 1;
+      /**
+       * A flag indicates whether ROI delta QP is supported
+       *
+       * roi_rc_qp_delta_support equal to 1 specifies the underlying driver 
supports
+       * ROI delta QP when VAConfigAttribRateControl != VA_RC_CQP, user can 
use roi_value
+       * in #VAEncROI to set ROI delta QP. roi_rc_qp_delta_support equal to 0 
specifies
+       * the underlying driver doesn't support ROI delta QP.
+       *
+       * User should ignore roi_rc_qp_delta_support when 
VAConfigAttribRateControl == VA_RC_CQP
+       * because ROI delta QP is always required when 
VAConfigAttribRateControl == VA_RC_CQP.
+       */
+      uint32_t roi_rc_qp_delta_support         : 1;
+      uint32_t reserved                        : 22;
+
+   } bits;
+   uint32_t value;
+};
+
 #ifdef __cplusplus
 }
 #endif

Reply via email to