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