urisourcebin: Allow more cases for posting stream-collection
authorEdward Hervey <edward@centricular.com>
Wed, 2 Oct 2024 08:34:57 +0000 (10:34 +0200)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Wed, 2 Oct 2024 23:04:42 +0000 (23:04 +0000)
Previously urisourcebin only allows stream-collections messages from adaptive
demuxers or sources to be posted.

This commit also allows the case where they come from a single parsebin. We
still want to prevent it in the case where they are multiple parsebins, since
that would require some form of aggregation to show a single/unified collection.

In order to avoid a regression with uridecodebin3 behavior, we also implement
support for GST_QUERY_SELECTABLE, so that uridecodebin3 can figure out whether
it should let GST_MESSAGE_STREAM_COLLECTION flow upwards (because app/user could
react on it) or whether it drops it in order for decodebin3 to do the collection
aggregation and posting.

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

subprojects/gst-plugins-base/gst/playback/gsturidecodebin3.c
subprojects/gst-plugins-base/gst/playback/gsturisourcebin.c

index 85474bbcdacff140fec00e2337758cbb19d34808..d785948288749cf571d9463c4ee7f2a564e5399d 100644 (file)
@@ -2213,6 +2213,35 @@ gst_uri_decode_bin3_handle_message (GstBin * bin, GstMessage * msg)
   GstURIDecodeBin3 *uridecodebin = (GstURIDecodeBin3 *) bin;
 
   switch (GST_MESSAGE_TYPE (msg)) {
+    case GST_MESSAGE_STREAM_COLLECTION:
+    {
+      GstSourceHandler *handler;
+      GST_DEBUG_OBJECT (uridecodebin, "Handle stream collection");
+      PLAY_ITEMS_LOCK (uridecodebin);
+      /* Find the matching handler (if any) */
+      if ((handler = find_source_handler_for_element (uridecodebin, msg->src))) {
+        gboolean selectable = FALSE;
+        GstQuery *query = gst_query_new_selectable ();
+        /* We only want to forward this message if the source is selectable,
+         * else we will let decodebin3 do its emission. */
+        if (gst_element_query ((GstElement *) msg->src, query)) {
+          gst_query_parse_selectable (query, &selectable);
+          GST_DEBUG_OBJECT (uridecodebin,
+              "%s is selectable : %d",
+              GST_ELEMENT_NAME (handler->urisourcebin), selectable);
+        }
+        gst_query_unref (query);
+        if (!selectable) {
+          GST_DEBUG_OBJECT (uridecodebin,
+              "%s doesn't handle selection, dropping stream-collection message",
+              GST_ELEMENT_NAME (handler->urisourcebin));
+          gst_message_unref (msg);
+          msg = NULL;
+        }
+      }
+      PLAY_ITEMS_UNLOCK (uridecodebin);
+      break;
+    }
     case GST_MESSAGE_STREAMS_SELECTED:
     {
       GstSourceHandler *handler;
index 3c9a71c9ce360011b81833dad6ee82ad68efec0b..90d4e03131891b4a293e8f135ebaaf1344193597 100644 (file)
@@ -2896,10 +2896,14 @@ handle_message (GstBin * bin, GstMessage * msg)
     case GST_MESSAGE_STREAM_COLLECTION:
     {
       ChildSrcPadInfo *info;
-      /* We only want to forward stream collection from the source element *OR*
-       * from adaptive demuxers. We do not want to forward them from the
-       * potential parsebins since there might be many and require aggregation
-       * to be useful/coherent. */
+      /* We only want to forward stream collections:
+       * * from the source element
+       * * OR from adaptive demuxers
+       * * OR from parsebin if there is only a single ChildSrcPadInfo
+       *
+       * We do not want to forward them if there are multiple parsebins since it
+       * requires them to be aggregated to be coherent to the outside world.
+       */
       GST_URI_SOURCE_BIN_LOCK (urisrc);
       info =
           find_adaptive_demuxer_cspi_for_msg (urisrc,
@@ -2909,14 +2913,17 @@ handle_message (GstBin * bin, GstMessage * msg)
         if (info->demuxer_is_parsebin) {
           GstStreamCollection *collection = NULL;
           gst_message_parse_stream_collection (msg, &collection);
-          GST_DEBUG_OBJECT (bin, "Dropping stream-collection from parsebin");
           /* Check if some output slots can/could be re-used with this new collection */
           if (collection) {
             handle_parsebin_collection (info, collection);
             gst_object_unref (collection);
           }
-          gst_message_unref (msg);
-          msg = NULL;
+          if (g_list_length (urisrc->src_infos) > 1) {
+            GST_DEBUG_OBJECT (bin,
+                "Dropping stream-collection, multiple parsebins present");
+            gst_message_unref (msg);
+            msg = NULL;
+          }
         }
       } else if (GST_MESSAGE_SRC (msg) != (GstObject *) urisrc->source) {
         GST_LOG_OBJECT (bin, "Collection %" GST_PTR_FORMAT, msg);
@@ -3176,6 +3183,26 @@ gst_uri_source_bin_query (GstElement * element, GstQuery * query)
       fold_init = uri_source_query_init;
       fold_done = uri_source_query_seeking_done;
       break;
+    case GST_QUERY_SELECTABLE:
+      /* This is a special case, we need to respond to it potentially before any
+       * pads are present, so we directly target childsrcpadinfos or the source */
+      if (urisrc->is_adaptive) {
+        /* Forward directly to adaptive demuxer */
+        if (urisrc->src_infos) {
+          ChildSrcPadInfo *child = urisrc->src_infos->data;
+          if (child->demuxer) {
+            return gst_element_query (child->demuxer, query);
+          }
+        }
+        GST_ERROR_OBJECT (urisrc,
+            "Source is adaptive ... but no adaptive demuxer present ?");
+        return FALSE;
+      }
+      /* FIXME: Theoretically we should fold/try on all chilsrcpadinfo, but they
+       * might not have exposed any pads yet and as of this implementation there
+       * are no known SELECTABLE support in other elements, so we fallback on the
+       * source element */
+      return gst_element_query (urisrc->source, query);
     default:
       fold_func = (GstIteratorFoldFunction) uri_source_query_generic_fold;
       break;