From ff2a75a2dd084cf2ff02a6b4a20ad3aaa7d89949 Mon Sep 17 00:00:00 2001 From: He Junyan Date: Tue, 20 Jun 2023 21:45:56 +0800 Subject: [PATCH] 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: --- .../sys/va/gstvabasetransform.c | 69 ++++++++++++++++++- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/va/gstvabasetransform.c b/subprojects/gst-plugins-bad/sys/va/gstvabasetransform.c index 5bfaaab25e..731a2bbefd 100644 --- a/subprojects/gst-plugins-bad/sys/va/gstvabasetransform.c +++ b/subprojects/gst-plugins-bad/sys/va/gstvabasetransform.c @@ -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);