va: postproc: enable cropping by crop meta

If incoming buffers have crop meta it's done by vapostproc, iif
vapostproc is not in passthrough mode and downstream doesn't handle
it.

This patch announces the crop meta API in proposed bufferpool, while
it stops filtering meta APIs, since it was only filter crop api.

Also if downstream supports crop and video metas, vapostporoc
announces both meta APIs in upstream bufferpool.

Finally, the meta is removed from the buffer if the crop is enabled.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2058>
This commit is contained in:
Víctor Manuel Jáquez Leal 2021-02-23 09:01:10 +01:00
parent c88abb9291
commit f4862f8298

View file

@ -39,6 +39,15 @@
* gst-launch-1.0 videotestsrc ! "video/x-raw,format=(string)NV12" ! vapostproc ! autovideosink
* ```
*
* Cropping is supported via buffers' crop meta. It's only done if the
* postproccessor is not in passthrough mode or if downstream doesn't
* support the crop meta API.
*
* ### Cropping example
* ```
* gst-launch-1.0 videotestsrc ! "video/x-raw,format=(string)NV12" ! videocrop bottom=50 left=100 ! vapostproc ! autovideosink
* ```
*
* If the VA driver support color balance filter, with controls such
* as hue, brightness, contrast, etc., those controls are exposed both
* as element properties and through the #GstColorBalance interface.
@ -114,6 +123,7 @@ struct _GstVaVpp
GstVideoInfo srcpad_info;
gboolean rebuild_filters;
gboolean forward_crop;
guint op_flags;
/* filters */
@ -150,6 +160,7 @@ enum
VPP_CONVERT_FILTERS = 1 << 2,
VPP_CONVERT_DIRECTION = 1 << 3,
VPP_CONVERT_FEATURE = 1 << 4,
VPP_CONVERT_CROP = 1 << 5,
};
extern GRecMutex GST_VA_SHARED_LOCK;
@ -509,8 +520,15 @@ gst_va_vpp_propose_allocation (GstBaseTransform * trans,
gst_clear_caps (&self->alloccaps);
if (!GST_BASE_TRANSFORM_CLASS (parent_class)->propose_allocation (trans,
decide_query, query))
decide_query, query)) {
self->forward_crop = FALSE;
return FALSE;
}
self->forward_crop =
(gst_query_find_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE,
NULL)
&& gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL));
gst_query_parse_allocation (query, &caps, NULL);
if (caps == NULL)
@ -569,6 +587,7 @@ gst_va_vpp_propose_allocation (GstBaseTransform * trans,
gst_object_unref (pool);
gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
gst_query_add_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE, NULL);
}
return TRUE;
@ -612,9 +631,9 @@ gst_va_vpp_decide_allocation (GstBaseTransform * trans, GstQuery * query)
GstBufferPool *pool = NULL, *other_pool = NULL;
GstCaps *outcaps = NULL;
GstStructure *config;
GstVideoInfo alloc_info;
guint min, max, size = 0, usage_hint = VA_SURFACE_ATTRIB_USAGE_HINT_VPP_WRITE;
gboolean update_pool, update_allocator, has_videometa, copy_frames;
GstVideoInfo alloc_info;
gst_query_parse_allocation (query, &outcaps, NULL);
@ -658,9 +677,6 @@ gst_va_vpp_decide_allocation (GstBaseTransform * trans, GstQuery * query)
update_pool = FALSE;
}
has_videometa = gst_query_find_allocation_meta (query,
GST_VIDEO_META_API_TYPE, NULL);
if (!allocator) {
if (!(allocator = _create_allocator (self, outcaps, usage_hint)))
return FALSE;
@ -694,6 +710,9 @@ gst_va_vpp_decide_allocation (GstBaseTransform * trans, GstQuery * query)
else
gst_query_add_allocation_pool (query, pool, size, min, max);
has_videometa = gst_query_find_allocation_meta (query,
GST_VIDEO_META_API_TYPE, NULL);
copy_frames = (!has_videometa && gst_va_pool_requires_video_meta (pool)
&& gst_caps_is_raw (outcaps));
if (copy_frames) {
@ -719,6 +738,7 @@ gst_va_vpp_decide_allocation (GstBaseTransform * trans, GstQuery * query)
gst_clear_object (&other_allocator);
gst_clear_object (&other_pool);
/* removes allocation metas */
return GST_BASE_TRANSFORM_CLASS (parent_class)->decide_allocation (trans,
query);
}
@ -1019,6 +1039,22 @@ gst_va_vpp_before_transform (GstBaseTransform * trans, GstBuffer * inbuf)
if (GST_CLOCK_TIME_IS_VALID (stream_time))
gst_object_sync_values (GST_OBJECT (self), stream_time);
GST_OBJECT_LOCK (self);
if (gst_buffer_get_video_crop_meta (inbuf)) {
/* enable cropping if either already do operations on frame or
* downstream doesn't support cropping */
if (self->op_flags == 0 && self->forward_crop) {
self->op_flags &= ~VPP_CONVERT_CROP;
} else {
self->op_flags |= VPP_CONVERT_CROP;
}
} else {
self->op_flags &= ~VPP_CONVERT_CROP;
}
gst_va_filter_enable_cropping (self->filter,
(self->op_flags & VPP_CONVERT_CROP));
GST_OBJECT_UNLOCK (self);
gst_va_vpp_rebuild_filters (self);
gst_va_vpp_update_passthrough (self, TRUE);
}
@ -1270,21 +1306,6 @@ unknown_format:
}
}
static gboolean
gst_va_vpp_filter_meta (GstBaseTransform * trans, GstQuery * query,
GType api, const GstStructure * params)
{
/* FIXME: This element cannot passthrough the crop meta, because it
* would convert the wrong sub-region of the image, and worst, our
* output image may not be large enough for the crop to be applied
* later */
if (api == GST_VIDEO_CROP_META_API_TYPE)
return FALSE;
/* propose all other metadata upstream */
return TRUE;
}
static gboolean
gst_va_vpp_transform_meta (GstBaseTransform * trans, GstBuffer * inbuf,
GstMeta * meta, GstBuffer * outbuf)
@ -1302,7 +1323,7 @@ gst_va_vpp_transform_meta (GstBaseTransform * trans, GstBuffer * inbuf,
if ((self->op_flags & VPP_CONVERT_FORMAT)
&& gst_meta_api_type_has_tag (info->api, META_TAG_COLORSPACE))
return FALSE;
else if ((self->op_flags & VPP_CONVERT_SIZE)
else if ((self->op_flags & (VPP_CONVERT_SIZE | VPP_CONVERT_CROP))
&& gst_meta_api_type_has_tag (info->api, META_TAG_SIZE))
return FALSE;
else if ((self->op_flags & VPP_CONVERT_DIRECTION)
@ -2464,7 +2485,6 @@ gst_va_vpp_class_init (gpointer g_class, gpointer class_data)
GST_DEBUG_FUNCPTR (gst_va_vpp_before_transform);
trans_class->transform = GST_DEBUG_FUNCPTR (gst_va_vpp_transform);
trans_class->transform_meta = GST_DEBUG_FUNCPTR (gst_va_vpp_transform_meta);
trans_class->filter_meta = GST_DEBUG_FUNCPTR (gst_va_vpp_filter_meta);
trans_class->src_event = GST_DEBUG_FUNCPTR (gst_va_vpp_src_event);
trans_class->sink_event = GST_DEBUG_FUNCPTR (gst_va_vpp_sink_event);
trans_class->generate_output = GST_DEBUG_FUNCPTR (gst_va_vpp_generate_output);