convertframe: Fix video crop meta handling

Cropping parameters were being miscalculated - getting
the output width/height wrong when an x/y crop offset
was given.

Cropping was also incorrectly being applied twice (because at
some point after the convertframe code was written,
`videocrop` also started paying attention to the
GstVideoCropMeta, but not in useful ways for this purpose). Add
a buffer probe to strip the crop meta from the input buffer
so videocrop can do its job correctly.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8526>
This commit is contained in:
Jan Schmidt 2025-02-20 19:57:48 +11:00 committed by GStreamer Marge Bot
parent 8d42a7e233
commit ae33acda5d

View file

@ -218,6 +218,25 @@ failed:
return NULL;
}
static GstPadProbeReturn
strip_video_crop_meta (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
{
GstBuffer *buf = gst_pad_probe_info_get_buffer (info);
GstVideoCropMeta *cmeta = gst_buffer_get_video_crop_meta (buf);
if (cmeta != NULL) {
/* Make the buffer writable before stripping the meta and
* putting the possibly-replaced buffer back into
* the pad probe data */
GST_DEBUG ("Removing video crop meta from input buffer");
buf = gst_buffer_make_writable (buf);
gst_buffer_remove_meta (buf, GST_META_CAST (cmeta));
GST_PAD_PROBE_INFO_DATA (info) = buf;
}
return GST_PAD_PROBE_OK;
}
static GstElement *
build_convert_frame_pipeline (GstElement ** src_element,
GstElement ** sink_element, GstCaps * from_caps,
@ -291,16 +310,25 @@ build_convert_frame_pipeline (GstElement ** src_element,
gst_video_info_from_caps (&info, from_caps);
g_object_set (vcrop, "left", cmeta->x, NULL);
g_object_set (vcrop, "top", cmeta->y, NULL);
g_object_set (vcrop, "right", GST_VIDEO_INFO_WIDTH (&info) - cmeta->width,
NULL);
g_object_set (vcrop, "right",
GST_VIDEO_INFO_WIDTH (&info) - (cmeta->x + cmeta->width), NULL);
g_object_set (vcrop, "bottom",
GST_VIDEO_INFO_HEIGHT (&info) - cmeta->height, NULL);
GST_VIDEO_INFO_HEIGHT (&info) - (cmeta->y + cmeta->height), NULL);
/* Because we are asking videocrop to apply the cropping explicitly,
* we need to give it a buffer without crop meta, or the crop amounts end up
* getting applied twice. Add a probe to strip the meta and use videocrop's
* properties */
GstPad *sink = gst_element_get_static_pad (vcrop, "sink");
g_assert (sink != NULL);
gst_pad_add_probe (sink, GST_PAD_PROBE_TYPE_BUFFER,
strip_video_crop_meta, NULL, NULL);
gst_object_unref (sink);
GST_DEBUG ("crop meta [x,y,width,height]: %d %d %d %d", cmeta->x, cmeta->y,
cmeta->width, cmeta->height);
}
/* FIXME: linking is still way too expensive, profile this properly */
if (vcrop) {
/* FIXME: linking is still way too expensive, profile this properly */
if (!dl) {
GST_DEBUG ("linking src->csp2");
if (!gst_element_link_pads (src, "src", csp2, "sink"))