va: basetransform: Check the crop meta when importing

When the input buffer has crop meta, and we need to do copy, we
should consider the uncropped video size and copy the full size
of video memory.
The video meta in this case should contain the full uncropped
resolution info. We can use it to create full size va buffers.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4887>
This commit is contained in:
He Junyan 2023-06-20 21:45:56 +08:00 committed by GStreamer Marge Bot
parent 703ab45334
commit ff2a75a2dd

View file

@ -49,6 +49,8 @@ struct _GstVaBaseTransformPrivate
GstCaps *sinkpad_caps;
GstVideoInfo sinkpad_info;
GstBufferPool *sinkpad_pool;
guint uncropped_width;
guint uncropped_height;
GstCaps *filter_caps;
};
@ -756,8 +758,54 @@ _try_import_dmabuf_unlocked (GstVaBaseTransform * self, GstBuffer * inbuf)
mems, fd, offset, VA_SURFACE_ATTRIB_USAGE_HINT_VPP_READ);
}
static gboolean
_check_uncropped_size (GstVaBaseTransform * self, GstBuffer * inbuf)
{
GstVideoCropMeta *crop_meta;
GstVideoMeta *video_meta;
crop_meta = gst_buffer_get_video_crop_meta (inbuf);
video_meta = gst_buffer_get_video_meta (inbuf);
if (!crop_meta) {
if (self->priv->uncropped_width > 0 || self->priv->uncropped_height > 0) {
self->priv->uncropped_width = 0;
self->priv->uncropped_height = 0;
return TRUE;
}
return FALSE;
}
if (!video_meta) {
GST_WARNING_OBJECT (self, "The buffer has video crop meta without "
"video meta, the cropped result may be wrong.");
self->priv->uncropped_width = 0;
self->priv->uncropped_height = 0;
return FALSE;
}
if (video_meta->width < crop_meta->x + crop_meta->width ||
video_meta->height < crop_meta->y + crop_meta->height) {
GST_WARNING_OBJECT (self, "Invalid video meta or crop meta, "
"the cropped result may be wrong.");
self->priv->uncropped_width = 0;
self->priv->uncropped_height = 0;
return FALSE;
}
if (self->priv->uncropped_width != video_meta->width ||
self->priv->uncropped_height != video_meta->height) {
self->priv->uncropped_width = video_meta->width;
self->priv->uncropped_height = video_meta->height;
return TRUE;
}
return FALSE;
}
static GstBufferPool *
_get_sinkpad_pool (GstVaBaseTransform * self)
_get_sinkpad_pool (GstVaBaseTransform * self, GstBuffer * inbuf)
{
GstAllocator *allocator;
GstAllocationParams params = { 0, };
@ -765,6 +813,13 @@ _get_sinkpad_pool (GstVaBaseTransform * self)
GstVideoInfo in_info;
guint size, usage_hint = VA_SURFACE_ATTRIB_USAGE_HINT_VPP_READ;
if (_check_uncropped_size (self, inbuf)) {
if (self->priv->sinkpad_pool)
gst_buffer_pool_set_active (self->priv->sinkpad_pool, FALSE);
gst_clear_object (&self->priv->sinkpad_pool);
}
if (self->priv->sinkpad_pool)
return self->priv->sinkpad_pool;
@ -776,6 +831,16 @@ _get_sinkpad_pool (GstVaBaseTransform * self)
gst_caps_set_features_simple (caps,
gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_VA));
/* When the input buffer contains video crop meta, the real video
resolution can be bigger than the caps. The video meta should
contain the real video resolution. */
if (self->priv->uncropped_width > 0)
gst_caps_set_simple (caps, "width", G_TYPE_INT,
self->priv->uncropped_width, NULL);
if (self->priv->uncropped_height > 0)
gst_caps_set_simple (caps, "height", G_TYPE_INT,
self->priv->uncropped_height, NULL);
if (!gst_video_info_from_caps (&in_info, caps)) {
GST_ERROR_OBJECT (self, "Cannot parse caps %" GST_PTR_FORMAT, caps);
gst_caps_unref (caps);
@ -849,7 +914,7 @@ gst_va_base_transform_import_buffer (GstVaBaseTransform * self,
/* input buffer doesn't come from a vapool, thus it is required to
* have a pool, grab from it a new buffer and copy the input
* buffer to the new one */
if (!(pool = _get_sinkpad_pool (self)))
if (!(pool = _get_sinkpad_pool (self, inbuf)))
return GST_FLOW_ERROR;
ret = gst_buffer_pool_acquire_buffer (pool, &buffer, NULL);