From cd7a91cef1c6a2e24d440126b7f2ab543fb205c5 Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Thu, 14 Apr 2022 09:48:14 -0400 Subject: [PATCH] videoconvertscale: Add properties to disable scaling/converting in videoconvert/videoscale Part-of: --- .../validate/launcher/testsuites/check.py | 4 +- .../docs/plugins/gst_plugins_cache.json | 26 +++++++ .../gst/videoconvertscale/gstvideoconvert.c | 55 ++++++++++++++ .../videoconvertscale/gstvideoconvertscale.c | 72 ++++++++++++++++--- .../videoconvertscale/gstvideoconvertscale.h | 5 ++ .../gst/videoconvertscale/gstvideoscale.c | 24 ++++++- .../convert_disable_scale.validatetest | 37 ++++++++++ .../log-converter-src-expected | 7 ++ .../scale_disable_convert.validatetest | 36 ++++++++++ .../flow-expectations/log-scaler-src-expected | 7 ++ .../tests/validate/meson.build | 2 + 11 files changed, 262 insertions(+), 13 deletions(-) create mode 100644 subprojects/gst-plugins-base/tests/validate/convertscale/convert_disable_scale.validatetest create mode 100644 subprojects/gst-plugins-base/tests/validate/convertscale/convert_disable_scale/flow-expectations/log-converter-src-expected create mode 100644 subprojects/gst-plugins-base/tests/validate/convertscale/scale_disable_convert.validatetest create mode 100644 subprojects/gst-plugins-base/tests/validate/convertscale/scale_disable_convert/flow-expectations/log-scaler-src-expected diff --git a/subprojects/gst-devtools/validate/launcher/testsuites/check.py b/subprojects/gst-devtools/validate/launcher/testsuites/check.py index e4c884d676..551e697c12 100644 --- a/subprojects/gst-devtools/validate/launcher/testsuites/check.py +++ b/subprojects/gst-devtools/validate/launcher/testsuites/check.py @@ -112,7 +112,9 @@ VALGRIND_BLACKLIST = [ (r'check.gst-editing-services.pythontests', 'Need to figure out how to introduce python suppressions'), (r'check.gst-editing-services.check_keyframes_in_compositor_two_sources', 'Valgrind exit with an exitcode 20 but shows no issue: https://gitlab.freedesktop.org/thiblahute/gst-editing-services/-/jobs/4079972'), (r'check.gst-plugins-good.elements_splitmuxsrc.test_splitmuxsrc_sparse_streams', 'https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/739'), - (r'check.gst-plugins-good.elements_udpsrc.test_udpsrc_empty_packet', 'https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/740') + (r'check.gst-plugins-good.elements_udpsrc.test_udpsrc_empty_packet', 'https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/740'), + (r'check.gst-plugins-base.validate.convertscale.scale_disable_convert', 'Use of uninitialised value of size 8 in digest_to_string that needs investigating'), + (r'check.gst-plugins-base.validate.convertscale.convert_disable_scale', 'Use of uninitialised value of size 8 in digest_to_string that needs investigating'), ] diff --git a/subprojects/gst-plugins-base/docs/plugins/gst_plugins_cache.json b/subprojects/gst-plugins-base/docs/plugins/gst_plugins_cache.json index 6827f94171..a466734894 100644 --- a/subprojects/gst-plugins-base/docs/plugins/gst_plugins_cache.json +++ b/subprojects/gst-plugins-base/docs/plugins/gst_plugins_cache.json @@ -13639,6 +13639,20 @@ "presence": "always" } }, + "properties": { + "disable-scaling": { + "blurb": "Disables frame scaling", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "false", + "mutable": "ready", + "readable": true, + "type": "gboolean", + "writable": true + } + }, "rank": "marginal" }, "videoconvertscale": { @@ -13891,6 +13905,18 @@ } }, "properties": { + "disable-conversion": { + "blurb": "Disables colorspace conversions", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "false", + "mutable": "ready", + "readable": true, + "type": "gboolean", + "writable": true + }, "gamma-decode": { "blurb": "Decode gamma before scaling", "conditionally-available": false, diff --git a/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvert.c b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvert.c index ff8b4f10de..5aae71deb7 100644 --- a/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvert.c +++ b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvert.c @@ -46,10 +46,65 @@ G_DEFINE_TYPE (GstVideoConvert, gst_video_convert, GST_ELEMENT_REGISTER_DEFINE (videoconvert, "videoconvert", GST_RANK_MARGINAL, gst_video_convert_get_type ()); +enum +{ + PROP_0, + PROP_DISABLE_SCALING, +}; + +#define DEFAULT_PROP_DISABLE_SCALING FALSE + +static void +gst_video_convert_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + switch (prop_id) { + case PROP_DISABLE_SCALING: + g_value_set_boolean (value, + !gst_video_convert_scale_get_scales (GST_VIDEO_CONVERT_SCALE + (object))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_video_convert_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + switch (prop_id) { + case PROP_DISABLE_SCALING: + gst_video_convert_scale_set_scales (GST_VIDEO_CONVERT_SCALE (object), + !g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + static void gst_video_convert_class_init (GstVideoConvertClass * klass) { + GObjectClass *gobject_class = (GObjectClass *) klass; + + gobject_class->set_property = gst_video_convert_set_property; + gobject_class->get_property = gst_video_convert_get_property; + ((GstVideoConvertScaleClass *) klass)->any_memory = TRUE; + + /** + * videoconvert::disable-scaling: + * + * Since: 1.22 + */ + g_object_class_install_property (gobject_class, PROP_DISABLE_SCALING, + g_param_spec_boolean ("disable-scaling", "Disable Scaling", + "Disables frame scaling", DEFAULT_PROP_DISABLE_SCALING, + G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY)); } static void diff --git a/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvertscale.c b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvertscale.c index a5d9b52de4..c4181251e1 100644 --- a/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvertscale.c +++ b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvertscale.c @@ -107,6 +107,9 @@ typedef struct gint borders_h; gint borders_w; + + gboolean scales; + gboolean converts; } GstVideoConvertScalePrivate; #define gst_video_convert_scale_parent_class parent_class @@ -115,7 +118,7 @@ G_DEFINE_TYPE_WITH_PRIVATE (GstVideoConvertScale, gst_video_convert_scale, GST_ELEMENT_REGISTER_DEFINE (videoconvertscale, "videoconvertscale", GST_RANK_SECONDARY, GST_TYPE_VIDEO_CONVERT_SCALE); -#define PRIV(self) gst_video_convert_scale_get_instance_private(((GstVideoConvertScale*) self)) +#define PRIV(self) ((GstVideoConvertScalePrivate*)gst_video_convert_scale_get_instance_private(((GstVideoConvertScale*) self))) #define GST_CAT_DEFAULT video_convertscale_debug GST_DEBUG_CATEGORY_STATIC (video_convertscale_debug); @@ -426,6 +429,8 @@ gst_video_convert_scale_init (GstVideoConvertScale * self) priv->matrix_mode = DEFAULT_PROP_MATRIX_MODE; priv->gamma_mode = DEFAULT_PROP_GAMMA_MODE; priv->primaries_mode = DEFAULT_PROP_PRIMARIES_MODE; + priv->scales = TRUE; + priv->converts = TRUE; } static void @@ -569,12 +574,14 @@ gst_video_convert_scale_get_property (GObject * object, guint prop_id, } static GstCaps * -gst_video_convert_caps_remove_format_and_rangify_size_info (GstCaps * caps) +gst_video_convert_caps_remove_format_and_rangify_size_info (GstVideoConvertScale + * self, GstCaps * caps) { GstCaps *ret; GstStructure *structure; GstCapsFeatures *features; gint i, n; + GstVideoConvertScalePrivate *priv = PRIV (self); ret = gst_caps_new_empty (); @@ -596,15 +603,21 @@ gst_video_convert_caps_remove_format_and_rangify_size_info (GstCaps * caps) || gst_caps_features_is_equal (features, features_format_interlaced) || gst_caps_features_is_equal (features, features_format_interlaced_sysmem))) { - gst_structure_set (structure, "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); - /* if pixel aspect ratio, make a range of it */ - if (gst_structure_has_field (structure, "pixel-aspect-ratio")) { - gst_structure_set (structure, "pixel-aspect-ratio", - GST_TYPE_FRACTION_RANGE, 1, G_MAXINT, G_MAXINT, 1, NULL); + + if (priv->scales) { + gst_structure_set (structure, "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); + /* if pixel aspect ratio, make a range of it */ + if (gst_structure_has_field (structure, "pixel-aspect-ratio")) { + gst_structure_set (structure, "pixel-aspect-ratio", + GST_TYPE_FRACTION_RANGE, 1, G_MAXINT, G_MAXINT, 1, NULL); + } + } + + if (priv->converts) { + gst_structure_remove_fields (structure, "format", "colorimetry", + "chroma-site", NULL); } - gst_structure_remove_fields (structure, "format", "colorimetry", - "chroma-site", NULL); } gst_caps_append_structure_full (ret, structure, gst_caps_features_copy (features)); @@ -619,12 +632,13 @@ gst_video_convert_scale_transform_caps (GstBaseTransform * trans, { gint i; GstCaps *ret; + GstVideoConvertScale *self = GST_VIDEO_CONVERT_SCALE (trans); GST_DEBUG_OBJECT (trans, "Transforming caps %" GST_PTR_FORMAT " in direction %s", caps, (direction == GST_PAD_SINK) ? "sink" : "src"); - ret = gst_video_convert_caps_remove_format_and_rangify_size_info (caps); + ret = gst_video_convert_caps_remove_format_and_rangify_size_info (self, caps); if (filter) { GstCaps *intersection; @@ -1769,3 +1783,39 @@ gst_video_convert_scale_src_event (GstBaseTransform * trans, GstEvent * event) return ret; } + +void +gst_video_convert_scale_set_scales (GstVideoConvertScale * self, + gboolean scales) +{ + GstVideoConvertScalePrivate *priv = PRIV (self); + + if (!scales) + g_assert (priv->converts); + + priv->scales = scales; +} + +void +gst_video_convert_scale_set_converts (GstVideoConvertScale * self, + gboolean converts) +{ + GstVideoConvertScalePrivate *priv = PRIV (self); + + if (!converts) + g_assert (priv->scales); + + priv->converts = converts; +} + +gboolean +gst_video_convert_scale_get_scales (GstVideoConvertScale * self) +{ + return PRIV (self)->scales; +} + +gboolean +gst_video_convert_scale_get_converts (GstVideoConvertScale * self) +{ + return PRIV (self)->converts; +} diff --git a/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvertscale.h b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvertscale.h index 64be8b1eaa..4cac22b8b3 100644 --- a/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvertscale.h +++ b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvertscale.h @@ -69,6 +69,11 @@ typedef enum { GST_VIDEO_SCALE_MITCHELL } GstVideoScaleMethod; +void gst_video_convert_scale_set_scales (GstVideoConvertScale *self, gboolean scales); +void gst_video_convert_scale_set_converts (GstVideoConvertScale *self, gboolean converts); +gboolean gst_video_convert_scale_get_scales (GstVideoConvertScale *self); +gboolean gst_video_convert_scale_get_converts (GstVideoConvertScale *self); + GST_ELEMENT_REGISTER_DECLARE (videoconvertscale); G_END_DECLS diff --git a/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoscale.c b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoscale.c index e8e41f152c..94f25d99c1 100644 --- a/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoscale.c +++ b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoscale.c @@ -51,6 +51,7 @@ #endif #define DEFAULT_PROP_GAMMA_DECODE FALSE +#define DEFAULT_PROP_DISABLE_CONVERSION FALSE #include "gstvideoscale.h" @@ -61,7 +62,8 @@ GST_ELEMENT_REGISTER_DEFINE (videoscale, "videoscale", enum { PROP_0, - PROP_GAMMA_DECODE + PROP_GAMMA_DECODE, + PROP_DISABLE_CONVERSION, }; static void @@ -78,6 +80,11 @@ gst_video_scale_get_property (GObject * object, guint prop_id, break; } + case PROP_DISABLE_CONVERSION: + g_value_set_boolean (value, + !gst_video_convert_scale_get_converts (GST_VIDEO_CONVERT_SCALE + (object))); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -98,6 +105,10 @@ gst_video_scale_set_property (GObject * object, guint prop_id, break; } + case PROP_DISABLE_CONVERSION: + gst_video_convert_scale_set_converts (GST_VIDEO_CONVERT_SCALE (object), + !g_value_get_boolean (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -118,6 +129,17 @@ gst_video_scale_class_init (GstVideoScaleClass * klass) g_param_spec_boolean ("gamma-decode", "Gamma Decode", "Decode gamma before scaling", DEFAULT_PROP_GAMMA_DECODE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * videoscale::disable-conversion: + * + * Since: 1.22 + */ + g_object_class_install_property (gobject_class, PROP_DISABLE_CONVERSION, + g_param_spec_boolean ("disable-conversion", "Disable Conversion", + "Disables colorspace conversions", DEFAULT_PROP_DISABLE_CONVERSION, + G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY)); } static void diff --git a/subprojects/gst-plugins-base/tests/validate/convertscale/convert_disable_scale.validatetest b/subprojects/gst-plugins-base/tests/validate/convertscale/convert_disable_scale.validatetest new file mode 100644 index 0000000000..8570000665 --- /dev/null +++ b/subprojects/gst-plugins-base/tests/validate/convertscale/convert_disable_scale.validatetest @@ -0,0 +1,37 @@ +meta, + handles-states=true, + ignore-eos=true, + allow-errors=true, + args = { + "videotestsrc num-buffers=1 ! video/x-raw,format=ARGB,width=20,height=20 ! videoconvert name=converter ! video/x-raw,format=I420,width=100,height=100 ! fakevideosink", + }, + configs = { + "$(validateflow), pad=converter:src, buffers-checksum=as-id, ignored-event-types={ tag }", + }, + expected-issues = { + [ + expected-issue, + level=critical, + issue-id=runtime::not-negotiated, + details="\ +.*Caps negotiation failed starting from pad 'capsfilter1:sink' as the QUERY_CAPS returned EMPTY caps for the following possible reasons:.*\\n\ +.*-> Field 'width' downstream value from structure 0 '.*100' can't intersect with filter value from structure number 0 '.*20'.*\\n\ +.*-> Field 'height' downstream value from structure 0 '.*100' can't intersect with filter value from structure number 0 '.*20'.*\ +", + ], + [ + expected-issue, + level=critical, + issue-id=scenario::execution-error, + details="Error message happened while executing action", + ], + } + + +play +set-state, state=ready, on-message=eos + +set-properties, converter::disable-scaling=true +play + +stop, on-message=error diff --git a/subprojects/gst-plugins-base/tests/validate/convertscale/convert_disable_scale/flow-expectations/log-converter-src-expected b/subprojects/gst-plugins-base/tests/validate/convertscale/convert_disable_scale/flow-expectations/log-converter-src-expected new file mode 100644 index 0000000000..0db91d16ba --- /dev/null +++ b/subprojects/gst-plugins-base/tests/validate/convertscale/convert_disable_scale/flow-expectations/log-converter-src-expected @@ -0,0 +1,7 @@ +event stream-start: GstEventStreamStart, flags=(GstStreamFlags)GST_STREAM_FLAG_NONE, group-id=(uint)1; +event caps: video/x-raw, format=(string)I420, framerate=(fraction)30/1, height=(int)100, interlace-mode=(string)progressive, multiview-mode=(string)mono, pixel-aspect-ratio=(fraction)1/1, width=(int)100; +event segment: format=TIME, start=0:00:00.000000000, offset=0:00:00.000000000, stop=none, time=0:00:00.000000000, base=0:00:00.000000000, position=0:00:00.000000000 +buffer: content-id=0, pts=0:00:00.000000000, dur=0:00:00.033333333, flags=discont, meta=GstVideoMeta +event eos: (no structure) +event stream-start: GstEventStreamStart, flags=(GstStreamFlags)GST_STREAM_FLAG_NONE, group-id=(uint)2; +event eos: (no structure) diff --git a/subprojects/gst-plugins-base/tests/validate/convertscale/scale_disable_convert.validatetest b/subprojects/gst-plugins-base/tests/validate/convertscale/scale_disable_convert.validatetest new file mode 100644 index 0000000000..3088b624d8 --- /dev/null +++ b/subprojects/gst-plugins-base/tests/validate/convertscale/scale_disable_convert.validatetest @@ -0,0 +1,36 @@ +meta, + handles-states=true, + ignore-eos=true, + allow-errors=true, + args = { + "videotestsrc num-buffers=1 ! video/x-raw,format=ARGB,width=20,height=20 ! videoscale name=scaler ! video/x-raw,format=I420,width=100,height=100 ! fakevideosink", + }, + configs = { + "$(validateflow), pad=scaler:src, buffers-checksum=as-id, ignored-event-types={ tag }", + }, + expected-issues = { + [ + expected-issue, + level=critical, + issue-id=runtime::not-negotiated, + details="\ +.*Caps negotiation failed starting from pad 'capsfilter.*:sink' as the QUERY_CAPS returned EMPTY caps for the following possible reasons:.*\\n\ + -> Field 'format' downstream value from structure 0 '\\(gchararray\\)I420' can't intersect with filter value from structure number 0 '\\(gchararray\\)ARGB'\ +", + ], + [ + expected-issue, + level=critical, + issue-id=scenario::execution-error, + details="Error message happened while executing action", + ], + } + + +play +set-state, state=ready, on-message=eos + +set-properties, scaler::disable-conversion=true +play + +stop, on-message=error diff --git a/subprojects/gst-plugins-base/tests/validate/convertscale/scale_disable_convert/flow-expectations/log-scaler-src-expected b/subprojects/gst-plugins-base/tests/validate/convertscale/scale_disable_convert/flow-expectations/log-scaler-src-expected new file mode 100644 index 0000000000..0db91d16ba --- /dev/null +++ b/subprojects/gst-plugins-base/tests/validate/convertscale/scale_disable_convert/flow-expectations/log-scaler-src-expected @@ -0,0 +1,7 @@ +event stream-start: GstEventStreamStart, flags=(GstStreamFlags)GST_STREAM_FLAG_NONE, group-id=(uint)1; +event caps: video/x-raw, format=(string)I420, framerate=(fraction)30/1, height=(int)100, interlace-mode=(string)progressive, multiview-mode=(string)mono, pixel-aspect-ratio=(fraction)1/1, width=(int)100; +event segment: format=TIME, start=0:00:00.000000000, offset=0:00:00.000000000, stop=none, time=0:00:00.000000000, base=0:00:00.000000000, position=0:00:00.000000000 +buffer: content-id=0, pts=0:00:00.000000000, dur=0:00:00.033333333, flags=discont, meta=GstVideoMeta +event eos: (no structure) +event stream-start: GstEventStreamStart, flags=(GstStreamFlags)GST_STREAM_FLAG_NONE, group-id=(uint)2; +event eos: (no structure) diff --git a/subprojects/gst-plugins-base/tests/validate/meson.build b/subprojects/gst-plugins-base/tests/validate/meson.build index 82d22a4b0b..326ac8a7f6 100644 --- a/subprojects/gst-plugins-base/tests/validate/meson.build +++ b/subprojects/gst-plugins-base/tests/validate/meson.build @@ -20,6 +20,8 @@ tests = [ 'compositor/renogotiate_failing_unsupported_src_format', 'giosrc/read-growing-file', 'encodebin/set-encoder-properties', + 'convertscale/convert_disable_scale', + 'convertscale/scale_disable_convert', ] env = environment()