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
This commit is contained in:
Víctor Manuel Jáquez Leal 2018-02-22 14:20:42 -06:00 committed by Nicolas Dufresne
parent d3110713b8
commit c49a17ed15
6 changed files with 131 additions and 48 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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;
/**

View file

@ -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;

View file

@ -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;

View file

@ -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,