From c49a17ed153c662b30bb5d4e61654bfee8ce7df9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Thu, 22 Feb 2018 14:20:42 -0600 Subject: [PATCH] libs: encoder: reimplement ROI using meta Check input buffers for ROI metas and pass them to VA. Also added a new "default-roi-delta-qp" property in order to tell the encoder what delta QP should be applied to ROI by default. Enabled it for H264 and H265 encoders. https://bugzilla.gnome.org/show_bug.cgi?id=768248 --- gst-libs/gst/vaapi/gstvaapicontext.c | 2 +- gst-libs/gst/vaapi/gstvaapiencoder.c | 119 +++++++++++++++++++++- gst-libs/gst/vaapi/gstvaapiencoder.h | 3 +- gst-libs/gst/vaapi/gstvaapiencoder_h264.c | 46 +-------- gst-libs/gst/vaapi/gstvaapiencoder_h265.c | 2 + gst-libs/gst/vaapi/gstvaapiencoder_priv.h | 7 ++ 6 files changed, 131 insertions(+), 48 deletions(-) diff --git a/gst-libs/gst/vaapi/gstvaapicontext.c b/gst-libs/gst/vaapi/gstvaapicontext.c index 204e463308..afbf8b4b20 100644 --- a/gst-libs/gst/vaapi/gstvaapicontext.c +++ b/gst-libs/gst/vaapi/gstvaapicontext.c @@ -318,7 +318,7 @@ config_create (GstVaapiContext * context) roi_config = (VAConfigAttribValEncROI *) & value; if (roi_config->bits.num_roi_regions != config->roi_num_supported || VA_ROI_RC_QP_DELTA_SUPPORT (roi_config) == 0) { - GST_ERROR ("ROI unsupported - number of regions supported: %d" + GST_ERROR ("Mismatched ROI support: number of regions supported: %d" " ROI delta QP: %d", roi_config->bits.num_roi_regions, VA_ROI_RC_QP_DELTA_SUPPORT (roi_config)); goto cleanup; diff --git a/gst-libs/gst/vaapi/gstvaapiencoder.c b/gst-libs/gst/vaapi/gstvaapiencoder.c index 71a7c1a02f..caddb75478 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder.c +++ b/gst-libs/gst/vaapi/gstvaapiencoder.c @@ -193,6 +193,19 @@ gst_vaapi_encoder_properties_get_default (const GstVaapiEncoderClass * klass) " higher value means lower-quality/fast-encode)", 1, 7, 4, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstVapiEncoder:roi-default-delta-qp + * + * Default delta-qp to apply to each Region of Interest + */ + GST_VAAPI_ENCODER_PROPERTIES_APPEND (props, + GST_VAAPI_ENCODER_PROP_DEFAULT_ROI_VALUE, + g_param_spec_int ("default-roi-delta-qp", "Default ROI delta QP", + "The default delta-qp to apply to each Region of Interest" + "(lower value means higher-quality, " + "higher value means lower-quality)", + -10, 10, -10, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + return props; } @@ -260,6 +273,99 @@ gst_vaapi_encoder_ensure_param_control_rate (GstVaapiEncoder * encoder, return TRUE; } +gboolean +gst_vaapi_encoder_ensure_param_roi_regions (GstVaapiEncoder * encoder, + GstVaapiEncPicture * picture) +{ +#if VA_CHECK_VERSION(0,39,1) + GstVaapiContextInfo *const cip = &encoder->context_info; + const GstVaapiConfigInfoEncoder *const config = &cip->config.encoder; + VAEncMiscParameterBufferROI *roi_param; + GstVaapiEncMiscParam *misc; + VAEncROI *region_roi; + GstBuffer *input; + guint num_roi, i; + gpointer state = NULL; + + if (!config->roi_capability) + return TRUE; + + if (!picture->frame) + return FALSE; + + input = picture->frame->input_buffer; + if (!input) + return FALSE; + + num_roi = + gst_buffer_get_n_meta (input, GST_VIDEO_REGION_OF_INTEREST_META_API_TYPE); + if (num_roi == 0) + return TRUE; + num_roi = CLAMP (num_roi, 1, config->roi_num_supported); + + misc = + gst_vaapi_enc_misc_param_new (encoder, VAEncMiscParameterTypeROI, + sizeof (VAEncMiscParameterBufferROI) + num_roi * sizeof (VAEncROI)); + if (!misc) + return FALSE; + + region_roi = + (VAEncROI *) ((guint8 *) misc->param + sizeof (VAEncMiscParameterBuffer) + + sizeof (VAEncMiscParameterBufferROI)); + + roi_param = misc->data; + roi_param->num_roi = num_roi; + roi_param->roi = region_roi; + + /* roi_value in VAEncROI should be used as ROI delta QP */ + roi_param->roi_flags.bits.roi_value_is_qp_delta = 1; + roi_param->max_delta_qp = 10; + roi_param->min_delta_qp = -10; + + for (i = 0; i < num_roi; i++) { + GstVideoRegionOfInterestMeta *roi; + GstStructure *s; + + roi = (GstVideoRegionOfInterestMeta *) + gst_buffer_iterate_meta_filtered (input, &state, + GST_VIDEO_REGION_OF_INTEREST_META_API_TYPE); + + /* ignore roi if overflow */ + if ((roi->x > G_MAXINT16) || (roi->y > G_MAXINT16) + || (roi->w > G_MAXUINT16) || (roi->h > G_MAXUINT16)) + continue; + + GST_LOG ("Input buffer ROI: type=%s id=%d (%d, %d) %dx%d", + g_quark_to_string (roi->roi_type), roi->id, roi->x, roi->y, roi->w, + roi->h); + + region_roi[i].roi_rectangle.x = roi->x; + region_roi[i].roi_rectangle.y = roi->y; + region_roi[i].roi_rectangle.width = roi->w; + region_roi[i].roi_rectangle.height = roi->h; + + s = gst_video_region_of_interest_meta_get_param (roi, "roi/vaapi"); + if (s) { + int value = 0; + + if (!gst_structure_get_int (s, "delta-qp", &value)) + continue; + value = CLAMP (value, roi_param->min_delta_qp, roi_param->max_delta_qp); + region_roi[i].roi_value = value; + } else { + region_roi[i].roi_value = encoder->default_roi_value; + + GST_LOG ("No ROI value specified upstream, use default (%d)", + encoder->default_roi_value); + } + } + + gst_vaapi_enc_picture_add_misc_param (picture, misc); + gst_vaapi_codec_object_replace (&misc, NULL); +#endif + return TRUE; +} + /** * gst_vaapi_encoder_ref: * @encoder: a #GstVaapiEncoder @@ -656,8 +762,13 @@ get_roi_capability (GstVaapiEncoder * encoder, guint * num_roi_supported) roi_config = (VAConfigAttribValEncROI *) & value; - if (roi_config->bits.num_roi_regions == 0 || - VA_ROI_RC_QP_DELTA_SUPPORT (roi_config) == 0) + if (roi_config->bits.num_roi_regions == 0) + return FALSE; + + /* Only support QP delta, and it only makes sense when rate control + * is not CQP */ + if ((GST_VAAPI_ENCODER_RATE_CONTROL (encoder) != GST_VAAPI_RATECONTROL_CQP) + && (VA_ROI_RC_QP_DELTA_SUPPORT (roi_config) == 0)) return FALSE; GST_INFO ("Support for ROI - number of regions supported: %d", @@ -982,6 +1093,10 @@ set_property (GstVaapiEncoder * encoder, gint prop_id, const GValue * value) status = gst_vaapi_encoder_set_quality_level (encoder, g_value_get_uint (value)); break; + case GST_VAAPI_ENCODER_PROP_DEFAULT_ROI_VALUE: + encoder->default_roi_value = g_value_get_int (value); + status = GST_VAAPI_ENCODER_STATUS_SUCCESS; + break; } return status; diff --git a/gst-libs/gst/vaapi/gstvaapiencoder.h b/gst-libs/gst/vaapi/gstvaapiencoder.h index c610e8e1e4..974a70a9b2 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder.h +++ b/gst-libs/gst/vaapi/gstvaapiencoder.h @@ -125,7 +125,8 @@ typedef enum { GST_VAAPI_ENCODER_PROP_BITRATE, GST_VAAPI_ENCODER_PROP_KEYFRAME_PERIOD, GST_VAAPI_ENCODER_PROP_TUNE, - GST_VAAPI_ENCODER_PROP_QUALITY_LEVEL + GST_VAAPI_ENCODER_PROP_QUALITY_LEVEL, + GST_VAAPI_ENCODER_PROP_DEFAULT_ROI_VALUE } GstVaapiEncoderProp; /** diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_h264.c b/gst-libs/gst/vaapi/gstvaapiencoder_h264.c index 2355d912f3..a4e65b0067 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_h264.c +++ b/gst-libs/gst/vaapi/gstvaapiencoder_h264.c @@ -2514,10 +2514,6 @@ static gboolean ensure_misc_params (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture) { GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder); -#if VA_CHECK_VERSION(0,39,1) - GstVaapiEncMiscParam *misc; - guint num_roi; -#endif if (!gst_vaapi_encoder_ensure_param_control_rate (base_encoder, picture)) return FALSE; @@ -2540,47 +2536,9 @@ ensure_misc_params (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture) goto error_create_packed_sei_hdr; } } -#if VA_CHECK_VERSION(0,39,1) - /* region-of-interest params */ - num_roi = base_encoder->roi_regions ? - g_list_length (base_encoder->roi_regions) : 0; - if (num_roi > 0) { - /* ROI(Region of Interest) params */ - VAEncMiscParameterBufferROI *roi_param; - VAEncROI *region_roi; - gpointer ptr; - GList *tmp; - misc = - gst_vaapi_enc_misc_param_new (base_encoder, VAEncMiscParameterTypeROI, - sizeof (VAEncMiscParameterBufferROI) + num_roi * sizeof (VAEncROI)); - - roi_param = misc->data; - roi_param->roi_flags.bits.roi_value_is_qp_delta = 1; - roi_param->max_delta_qp = 10; - roi_param->min_delta_qp = 10; - - ptr = (guchar *) misc->param + sizeof (VAEncMiscParameterBuffer) + - sizeof (VAEncMiscParameterBufferROI); - region_roi = ptr; - - for (tmp = base_encoder->roi_regions; tmp; tmp = tmp->next) { - GstVaapiROI *item = tmp->data; - region_roi->roi_value = item->roi_value; - region_roi->roi_rectangle.x = item->rect.x; - region_roi->roi_rectangle.y = item->rect.y; - region_roi->roi_rectangle.width = item->rect.width; - region_roi->roi_rectangle.height = item->rect.height; - region_roi++; - } - - roi_param->roi = ptr; - roi_param->num_roi = num_roi; - - gst_vaapi_enc_picture_add_misc_param (picture, misc); - gst_vaapi_codec_object_replace (&misc, NULL); - } -#endif + if (!gst_vaapi_encoder_ensure_param_roi_regions (base_encoder, picture)) + return FALSE; if (!gst_vaapi_encoder_ensure_param_quality_level (base_encoder, picture)) return FALSE; diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_h265.c b/gst-libs/gst/vaapi/gstvaapiencoder_h265.c index 479294e926..87f3a6bc59 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_h265.c +++ b/gst-libs/gst/vaapi/gstvaapiencoder_h265.c @@ -1852,6 +1852,8 @@ ensure_misc_params (GstVaapiEncoderH265 * encoder, GstVaapiEncPicture * picture) if (!gst_vaapi_encoder_ensure_param_control_rate (base_encoder, picture)) return FALSE; + if (!gst_vaapi_encoder_ensure_param_roi_regions (base_encoder, picture)) + return FALSE; if (!gst_vaapi_encoder_ensure_param_quality_level (base_encoder, picture)) return FALSE; return TRUE; diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_priv.h b/gst-libs/gst/vaapi/gstvaapiencoder_priv.h index 2dccabce26..d3253a23cc 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_priv.h +++ b/gst-libs/gst/vaapi/gstvaapiencoder_priv.h @@ -287,6 +287,8 @@ struct _GstVaapiEncoder VAEncMiscParameterRateControl va_ratecontrol; VAEncMiscParameterFrameRate va_framerate; VAEncMiscParameterHRD va_hrd; + + gint8 default_roi_value; }; struct _GstVaapiEncoderClassData @@ -413,6 +415,11 @@ gboolean gst_vaapi_encoder_ensure_param_control_rate (GstVaapiEncoder * encoder, GstVaapiEncPicture * picture); +G_GNUC_INTERNAL +gboolean +gst_vaapi_encoder_ensure_param_roi_regions (GstVaapiEncoder * encoder, + GstVaapiEncPicture * picture); + G_GNUC_INTERNAL gboolean gst_vaapi_encoder_ensure_num_slices (GstVaapiEncoder * encoder,