From 61a04cf51f4d1298ca66c205dd759b472494371c Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Thu, 29 Apr 2021 17:14:43 -0400 Subject: [PATCH] testbinsrc: Handle setting URI on the fly Reusing existing streams when possible Part-of: --- gst/debugutils/gsttestsrcbin.c | 106 +++++++++++++++++++++++++++++++++-------- 1 file changed, 86 insertions(+), 20 deletions(-) diff --git a/gst/debugutils/gsttestsrcbin.c b/gst/debugutils/gsttestsrcbin.c index e97556f..35a5cab 100644 --- a/gst/debugutils/gsttestsrcbin.c +++ b/gst/debugutils/gsttestsrcbin.c @@ -76,6 +76,7 @@ struct _GstTestSrcBin GstStreamCollection *collection; gint group_id; GstFlowCombiner *flow_combiner; + GstCaps *streams_def; }; enum @@ -125,7 +126,7 @@ _probe_data_new (GstEvent * stream_start, GstStreamCollection * collection) { ProbeData *data = g_malloc0 (sizeof (ProbeData)); - data->stream_start = gst_event_ref (stream_start); + data->stream_start = stream_start; data->collection = gst_object_ref (collection); return data; @@ -196,6 +197,9 @@ static gboolean gst_test_src_bin_set_element_property (GQuark property_id, const GValue * value, GObject * element) { + if (property_id == g_quark_from_static_string ("__streamobj__")) + return TRUE; + if (G_VALUE_HOLDS_STRING (value)) gst_util_set_object_arg (element, g_quark_to_string (property_id), g_value_get_string (value)); @@ -266,11 +270,13 @@ gst_test_src_bin_setup_src (GstTestSrcBin * self, const gchar * srcfactory, gst_event_set_stream (stream_start, stream); gst_event_set_group_id (stream_start, self->group_id); + gst_structure_set (props, "__streamobj__", GST_TYPE_STREAM, stream, NULL); + gst_stream_collection_add_stream (collection, stream); + gst_pad_add_probe (pad, (GstPadProbeType) GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, (GstPadProbeCallback) src_pad_probe_cb, _probe_data_new (stream_start, collection), (GDestroyNotify) _probe_data_free); - gst_stream_collection_add_stream (collection, stream); g_free (stream_id); gst_bin_add (GST_BIN (self), src); @@ -289,14 +295,58 @@ gst_test_src_bin_setup_src (GstTestSrcBin * self, const gchar * srcfactory, gst_object_unref (pad); gst_element_sync_state_with_parent (src); *n_stream += 1; + + gst_structure_set (props, "__src__", GST_TYPE_OBJECT, src, NULL); } static void -gst_test_src_bin_remove_child (GValue * val, GstBin * self) +gst_test_src_bin_remove_child (GstElement * self, GstElement * child) { - GstElement *child = g_value_get_object (val); + GstPad *pad = gst_element_get_static_pad (child, "src"); + GstPad *ghost = + GST_PAD (gst_proxy_pad_get_internal (GST_PROXY_PAD (gst_pad_get_peer + (pad)))); + - gst_bin_remove (self, child); + gst_element_set_locked_state (child, FALSE); + gst_element_set_state (child, GST_STATE_NULL); + gst_bin_remove (GST_BIN (self), child); + gst_element_remove_pad (self, ghost); +} + +static GstStream * +gst_test_check_prev_stream_def (GstTestSrcBin * self, GstCaps * prev_streams, + GstStructure * stream_def) +{ + gint i; + + if (!prev_streams) + return NULL; + + for (i = 0; i < gst_caps_get_size (prev_streams); i++) { + GstStructure *prev_stream = gst_caps_get_structure (prev_streams, i); + GstElement *e = NULL; + GstStream *stream = NULL; + + gst_structure_get (prev_stream, "__src__", GST_TYPE_OBJECT, &e, + "__streamobj__", GST_TYPE_STREAM, &stream, NULL); + gst_structure_remove_fields (prev_stream, "__src__", "__streamobj__", NULL); + if (gst_structure_is_equal (prev_stream, stream_def)) { + g_assert (stream); + + gst_caps_remove_structure (prev_streams, i); + gst_structure_set (stream_def, "__src__", GST_TYPE_OBJECT, e, + "__streamobj__", GST_TYPE_STREAM, stream, NULL); + + g_assert (stream); + return stream; + } + + gst_structure_set (stream_def, "__src__", GST_TYPE_OBJECT, e, + "__streamobj__", GST_TYPE_STREAM, stream, NULL); + } + + return NULL; } static gboolean @@ -307,31 +357,34 @@ gst_test_src_bin_uri_handler_set_uri (GstURIHandler * handler, gchar *tmp, *location = gst_uri_get_location (uri); gint i, n_audio = 0, n_video = 0; GstStreamCollection *collection = gst_stream_collection_new (NULL); - GstIterator *it; - GstCaps *streams_defs; + GstCaps *streams_def, *prev_streams = self->streams_def; for (tmp = location; *tmp != '\0'; tmp++) if (*tmp == '+') *tmp = ';'; - streams_defs = gst_caps_from_string (location); + streams_def = gst_caps_from_string (location); g_free (location); - if (!streams_defs) + if (!streams_def) goto failed; - /* Clear us up */ - it = gst_bin_iterate_elements (GST_BIN (self)); - while (gst_iterator_foreach (it, - (GstIteratorForeachFunction) gst_test_src_bin_remove_child, - self) == GST_ITERATOR_RESYNC) - gst_iterator_resync (it); - - gst_iterator_free (it); - self->group_id = gst_util_group_id_next (); - for (i = 0; i < gst_caps_get_size (streams_defs); i++) { - GstStructure *stream_def = gst_caps_get_structure (streams_defs, i); + for (i = 0; i < gst_caps_get_size (streams_def); i++) { + GstStream *stream; + GstStructure *stream_def = gst_caps_get_structure (streams_def, i); + + if ((stream = + gst_test_check_prev_stream_def (self, prev_streams, stream_def))) { + GST_INFO_OBJECT (self, + "Reusing already existing stream: %" GST_PTR_FORMAT, stream_def); + gst_stream_collection_add_stream (collection, stream); + if (gst_structure_has_name (stream_def, "video")) + n_video++; + else + n_audio++; + continue; + } if (gst_structure_has_name (stream_def, "video")) gst_test_src_bin_setup_src (self, "videotestsrc", &video_src_template, @@ -343,6 +396,18 @@ gst_test_src_bin_uri_handler_set_uri (GstURIHandler * handler, GST_ERROR_OBJECT (self, "Unknown type %s", gst_structure_get_name (stream_def)); } + self->streams_def = streams_def; + + if (prev_streams) { + for (i = 0; i < gst_caps_get_size (prev_streams); i++) { + GstStructure *prev_stream = gst_caps_get_structure (prev_streams, i); + GstElement *child; + + gst_structure_get (prev_stream, "__src__", GST_TYPE_OBJECT, &child, NULL); + gst_test_src_bin_remove_child (GST_ELEMENT (self), child); + } + gst_clear_caps (&prev_streams); + } if (!n_video && !n_audio) goto failed; @@ -454,6 +519,7 @@ gst_test_src_bin_finalize (GObject * object) GstTestSrcBin *self = GST_TEST_SRC_BIN (object); g_free (self->uri); + gst_clear_caps (&self->streams_def); gst_flow_combiner_free (self->flow_combiner); } -- 2.7.4