discoverer: Fix discovering source that expose raw audio/video
authorThibault Saunier <tsaunier@igalia.com>
Wed, 7 Sep 2022 14:36:09 +0000 (10:36 -0400)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Thu, 15 Sep 2022 19:25:01 +0000 (19:25 +0000)
Exposes a "uridecodebin:post-stream-topology" property as the discoverer
needs to have topology information about all streams so we need
`uridecodebin` to always plug decodebins for that case.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3009>

subprojects/gst-plugins-base/docs/plugins/gst_plugins_cache.json
subprojects/gst-plugins-base/gst-libs/gst/pbutils/gstdiscoverer.c
subprojects/gst-plugins-base/gst/playback/gsturidecodebin.c

index 5014d23..8828ace 100644 (file)
                         "type": "gboolean",
                         "writable": true
                     },
+                    "post-stream-topology": {
+                        "blurb": "Post stream-topology messages",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
                     "ring-buffer-max-size": {
                         "blurb": "Max. amount of data in the ring buffer (bytes, 0 = ring buffer disabled)",
                         "conditionally-available": false,
index 5075fe3..bd5feee 100644 (file)
@@ -127,8 +127,6 @@ struct _GstDiscovererPrivate
   GstElement *uridecodebin;
   GstBus *bus;
 
-  GType decodebin_type;
-
   /* Custom main context variables */
   GMainContext *ctx;
   GSource *bus_source;
@@ -142,7 +140,6 @@ struct _GstDiscovererPrivate
   gulong pad_remove_id;
   gulong no_more_pads_id;
   gulong source_chg_id;
-  gulong element_added_id;
   gulong bus_cb_id;
 
   gboolean use_cache;
@@ -329,21 +326,8 @@ gst_discoverer_class_init (GstDiscovererClass * klass)
 }
 
 static void
-uridecodebin_element_added_cb (GstElement * uridecodebin,
-    GstElement * child, GstDiscoverer * dc)
-{
-  GST_DEBUG ("New element added to uridecodebin : %s",
-      GST_ELEMENT_NAME (child));
-
-  if (G_OBJECT_TYPE (child) == dc->priv->decodebin_type) {
-    g_object_set (child, "post-stream-topology", TRUE, NULL);
-  }
-}
-
-static void
 gst_discoverer_init (GstDiscoverer * dc)
 {
-  GstElement *tmp;
   GstFormat format = GST_FORMAT_TIME;
 
   dc->priv = gst_discoverer_get_instance_private (dc);
@@ -372,6 +356,9 @@ gst_discoverer_init (GstDiscoverer * dc)
     GST_ERROR ("Can't create uridecodebin");
     return;
   }
+
+  g_object_set (dc->priv->uridecodebin, "post-stream-topology", TRUE, NULL);
+
   GST_LOG_OBJECT (dc, "Adding uridecodebin to pipeline");
   gst_bin_add (dc->priv->pipeline, dc->priv->uridecodebin);
 
@@ -397,16 +384,6 @@ gst_discoverer_init (GstDiscoverer * dc)
 
   GST_DEBUG_OBJECT (dc, "Done initializing Discoverer");
 
-  /* This is ugly. We get the GType of decodebin so we can quickly detect
-   * when a decodebin is added to uridecodebin so we can set the
-   * post-stream-topology setting to TRUE */
-  dc->priv->element_added_id =
-      g_signal_connect_object (dc->priv->uridecodebin, "element-added",
-      G_CALLBACK (uridecodebin_element_added_cb), dc, 0);
-  tmp = gst_element_factory_make ("decodebin", NULL);
-  dc->priv->decodebin_type = G_OBJECT_TYPE (tmp);
-  gst_object_unref (tmp);
-
   /* create queries */
   dc->priv->seeking_query = gst_query_new_seeking (format);
 }
@@ -447,7 +424,6 @@ gst_discoverer_dispose (GObject * obj)
     DISCONNECT_SIGNAL (dc->priv->uridecodebin, dc->priv->pad_remove_id);
     DISCONNECT_SIGNAL (dc->priv->uridecodebin, dc->priv->no_more_pads_id);
     DISCONNECT_SIGNAL (dc->priv->uridecodebin, dc->priv->source_chg_id);
-    DISCONNECT_SIGNAL (dc->priv->uridecodebin, dc->priv->element_added_id);
     DISCONNECT_SIGNAL (dc->priv->bus, dc->priv->bus_cb_id);
 
     /* pipeline was set to NULL in _reset */
index 87f0268..a128d92 100644 (file)
@@ -119,6 +119,7 @@ struct _GstURIDecodeBin
   gboolean expose_allstreams;   /* Whether to expose unknown type streams or not */
 
   guint64 ring_buffer_max_size; /* 0 means disabled */
+  gboolean post_stream_topology;
 };
 
 struct _GstURIDecodeBinClass
@@ -186,6 +187,7 @@ enum
 #define DEFAULT_FORCE_SW_DECODERS   FALSE
 #define DEFAULT_EXPOSE_ALL_STREAMS  TRUE
 #define DEFAULT_RING_BUFFER_MAX_SIZE 0
+#define DEFAULT_POST_STREAM_TOPOLOGY FALSE
 
 enum
 {
@@ -201,7 +203,8 @@ enum
   PROP_USE_BUFFERING,
   PROP_FORCE_SW_DECODERS,
   PROP_EXPOSE_ALL_STREAMS,
-  PROP_RING_BUFFER_MAX_SIZE
+  PROP_RING_BUFFER_MAX_SIZE,
+  PROP_POST_STREAM_TOPOLOGY
 };
 
 static guint gst_uri_decode_bin_signals[LAST_SIGNAL] = { 0 };
@@ -530,6 +533,19 @@ gst_uri_decode_bin_class_init (GstURIDecodeBinClass * klass)
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
+   * GstURIDecodeBin:post-stream-topology
+   *
+   * Post stream-topology messages on the bus every time the topology changes.
+   *
+   * Since: 1.22
+   */
+  g_object_class_install_property (gobject_class, PROP_POST_STREAM_TOPOLOGY,
+      g_param_spec_boolean ("post-stream-topology", "Post Stream Topology",
+          "Post stream-topology messages",
+          DEFAULT_POST_STREAM_TOPOLOGY,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
    * GstURIDecodeBin::unknown-type:
    * @bin: The uridecodebin.
    * @pad: the new pad containing caps that cannot be resolved to a 'final'.
@@ -850,6 +866,9 @@ gst_uri_decode_bin_set_property (GObject * object, guint prop_id,
     case PROP_RING_BUFFER_MAX_SIZE:
       dec->ring_buffer_max_size = g_value_get_uint64 (value);
       break;
+    case PROP_POST_STREAM_TOPOLOGY:
+      dec->post_stream_topology = g_value_get_boolean (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -913,6 +932,9 @@ gst_uri_decode_bin_get_property (GObject * object, guint prop_id,
     case PROP_RING_BUFFER_MAX_SIZE:
       g_value_set_uint64 (value, dec->ring_buffer_max_size);
       break;
+    case PROP_POST_STREAM_TOPOLOGY:
+      g_value_set_boolean (value, dec->post_stream_topology);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1879,9 +1901,11 @@ make_decoder (GstURIDecodeBin * decoder)
   if (decoder->caps)
     g_object_set (decodebin, "caps", decoder->caps, NULL);
 
-  /* Propagate expose-all-streams and connection-speed properties */
+  /* Propagate expose-all-streams, connection-speed properties
+   * and post_stream_topology */
   g_object_set (decodebin, "expose-all-streams", decoder->expose_allstreams,
-      "connection-speed", decoder->connection_speed / 1000, NULL);
+      "connection-speed", decoder->connection_speed / 1000,
+      "post-stream-topology", decoder->post_stream_topology, NULL);
 
   if (!decoder->is_stream || decoder->is_adaptive) {
     /* propagate the use-buffering property but only when we are not already
@@ -2176,8 +2200,10 @@ source_new_pad (GstElement * element, GstPad * pad, GstURIDecodeBin * bin)
   if (!rawcaps)
     rawcaps = DEFAULT_CAPS;
 
-  /* if this is a pad with all raw caps, we can expose it */
-  if (has_raw_caps (pad, rawcaps)) {
+  /* if this is a pad with all raw caps, we can expose it.
+   * But if stream-topology needs to be posted, we need to
+   * plug a decodebin so it can build the topology for us to forward. */
+  if (!bin->post_stream_topology && has_raw_caps (pad, rawcaps)) {
     /* it's all raw, create output pads. */
     GST_URI_DECODE_BIN_UNLOCK (bin);
     gst_caps_unref (rawcaps);