From 9befb810360f871de486a30458500aec6bc5b008 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Tue, 31 Jan 2023 16:12:17 +0100 Subject: [PATCH] urisourcebin: Set source element to READY before querying it Generating the source element is done when urisourcebin is doing the READY to PAUSED state change, so it is reasonable to set the new source element to that state. This also allows detecting early failures with backing libraries or hardware (checks done in NULL->READY). Finally it makes more sense to have an element in READY when attempting to query information from it (such as SCHEDULING queries or probing live-ness). Part-of: --- .../gst/playback/gsturisourcebin.c | 70 ++++++++++++------- 1 file changed, 44 insertions(+), 26 deletions(-) diff --git a/subprojects/gst-plugins-base/gst/playback/gsturisourcebin.c b/subprojects/gst-plugins-base/gst/playback/gsturisourcebin.c index a37653030d..55aaee36dc 100644 --- a/subprojects/gst-plugins-base/gst/playback/gsturisourcebin.c +++ b/subprojects/gst-plugins-base/gst/playback/gsturisourcebin.c @@ -1465,8 +1465,6 @@ gen_source_element (GstURISourceBin * urisrc) GObjectClass *source_class; GstElement *source; GParamSpec *pspec; - GstQuery *query; - GstSchedulingFlags flags; GError *err = NULL; if (!urisrc->uri) @@ -1486,31 +1484,9 @@ gen_source_element (GstURISourceBin * urisrc) GST_LOG_OBJECT (urisrc, "found source type %s", G_OBJECT_TYPE_NAME (source)); - urisrc->is_stream = IS_STREAM_URI (urisrc->uri); - - query = gst_query_new_scheduling (); - if (gst_element_query (source, query)) { - gst_query_parse_scheduling (query, &flags, NULL, NULL, NULL); - if ((flags & GST_SCHEDULING_FLAG_BANDWIDTH_LIMITED)) - urisrc->is_stream = TRUE; - } - gst_query_unref (query); - source_class = G_OBJECT_GET_CLASS (source); - if (urisrc->is_stream) { - /* Live sources are not streamable */ - pspec = g_object_class_find_property (source_class, "is-live"); - if (pspec && G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_BOOLEAN) { - gboolean is_live; - g_object_get (G_OBJECT (source), "is-live", &is_live, NULL); - if (is_live) - urisrc->is_stream = FALSE; - } - } - - GST_LOG_OBJECT (urisrc, "source is stream: %d", urisrc->is_stream); - + /* Propagate connection speed */ pspec = g_object_class_find_property (source_class, "connection-speed"); if (pspec != NULL) { guint64 speed = urisrc->connection_speed / 1000; @@ -1750,6 +1726,38 @@ analyse_source_and_expose_raw_pads (GstURISourceBin * urisrc, GstIterator *pads_iter; gboolean res = TRUE; + /* Collect generic information about the source */ + + urisrc->is_stream = IS_STREAM_URI (urisrc->uri); + + if (!urisrc->is_stream) { + GstQuery *query; + GstSchedulingFlags flags; + /* do a final check to see if the source element is streamable */ + query = gst_query_new_scheduling (); + if (gst_element_query (urisrc->source, query)) { + gst_query_parse_scheduling (query, &flags, NULL, NULL, NULL); + if ((flags & GST_SCHEDULING_FLAG_BANDWIDTH_LIMITED)) + urisrc->is_stream = TRUE; + } + gst_query_unref (query); + } + + if (urisrc->is_stream) { + GObjectClass *source_class = G_OBJECT_GET_CLASS (urisrc->source); + GParamSpec *pspec = g_object_class_find_property (source_class, "is-live"); + /* Live sources are not streamable */ + if (pspec && G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_BOOLEAN) { + gboolean is_live; + g_object_get (G_OBJECT (urisrc->source), "is-live", &is_live, NULL); + if (is_live) + urisrc->is_stream = FALSE; + } + } + + GST_LOG_OBJECT (urisrc, "source is stream: %d", urisrc->is_stream); + + /* Handle the existing source pads */ pads_iter = gst_element_iterate_src_pads (urisrc->source); restart: @@ -2285,12 +2293,16 @@ setup_source (GstURISourceBin * urisrc) * handled by the application right after. */ gst_bin_add (GST_BIN_CAST (urisrc), urisrc->source); - /* notify of the new source used */ + /* notify of the new source used and allow external users to do final + * modifications before activating the element */ g_object_notify (G_OBJECT (urisrc), "source"); g_signal_emit (urisrc, gst_uri_source_bin_signals[SIGNAL_SOURCE_SETUP], 0, urisrc->source); + if (gst_element_set_state (urisrc->source, + GST_STATE_READY) != GST_STATE_CHANGE_SUCCESS) + goto state_fail; /* see if the source element emits raw audio/video all by itself, * if so, we can create streams for the pads and be done with it. * Also check that is has source pads, if not, we assume it will @@ -2323,6 +2335,12 @@ invalid_source: (_("Source element is invalid.")), (NULL)); return FALSE; } +state_fail: + { + GST_ELEMENT_ERROR (urisrc, CORE, FAILED, + (_("Source element can't be prepared")), (NULL)); + return FALSE; + } no_pads: { GST_ELEMENT_ERROR (urisrc, CORE, FAILED,