uridecodebin: Ensure that pads caps are set before exposing them
authorThibault Saunier <tsaunier@igalia.com>
Wed, 7 Sep 2022 14:39:21 +0000 (10:39 -0400)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Thu, 15 Sep 2022 19:25:01 +0000 (19:25 +0000)
We are supposed to guarantee that pads that are exposed have the caps
set, but for sources that have pad with "all raw caps" templates, we end
up exposing pads that don't have caps set yet, which can break code (in
GES for example).

To avoid that we let uridecodebin plug a `decodebin` after such pads and
let decodebin to handle that for us. In the end the only thing that
decodebin does in those cases is to wait for pads to be ready and expose
them, after that `uridecodebin` will expose those pads.

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

subprojects/gst-plugins-base/gst/playback/gsturidecodebin.c
subprojects/gst-plugins-base/tests/validate/meson.build
subprojects/gst-plugins-base/tests/validate/uridecodebin/expose_raw_pad_caps.validatetest [new file with mode: 0644]

index b27c2fc..00fc502 100644 (file)
@@ -1478,23 +1478,23 @@ no_source:
 }
 
 /**
- * has_all_raw_caps:
+ * has_raw_caps:
  * @pad: a #GstPad
  * @all_raw: pointer to hold the result
  *
  * check if the caps of the pad are all raw. The caps are all raw if
  * all of its structures contain audio/x-raw or video/x-raw.
  *
- * Returns: %FALSE @pad has no caps. Else TRUE and @all_raw set t the result.
+ * Returns: %FALSE @pad caps are not set and raw
  */
 static gboolean
-has_all_raw_caps (GstPad * pad, GstCaps * rawcaps, gboolean * all_raw)
+has_raw_caps (GstPad * pad, GstCaps * rawcaps)
 {
   GstCaps *caps, *intersection;
   gint capssize;
   gboolean res = FALSE;
 
-  caps = gst_pad_query_caps (pad, NULL);
+  caps = gst_pad_get_current_caps (pad);
   if (caps == NULL)
     return FALSE;
 
@@ -1506,12 +1506,9 @@ has_all_raw_caps (GstPad * pad, GstCaps * rawcaps, gboolean * all_raw)
     goto done;
 
   intersection = gst_caps_intersect (caps, rawcaps);
-  *all_raw = !gst_caps_is_empty (intersection)
-      && (gst_caps_get_size (intersection) == capssize);
+  res = !gst_caps_is_empty (intersection);
   gst_caps_unref (intersection);
 
-  res = TRUE;
-
 done:
   gst_caps_unref (caps);
   return res;
@@ -1593,16 +1590,15 @@ analyse_source (GstURIDecodeBin * decoder, gboolean * is_raw,
         *have_out = TRUE;
 
         /* if FALSE, this pad has no caps and we continue with the next pad. */
-        if (!has_all_raw_caps (pad, rawcaps, is_raw)) {
+        if (!has_raw_caps (pad, rawcaps)) {
           gst_object_unref (pad);
           g_value_reset (&item);
           break;
-        }
-
-        /* caps on source pad are all raw, we can add the pad */
-        if (*is_raw) {
+        } else {
+          /* caps on source pad are all raw, we can add the pad */
           GstElement *outelem;
 
+          *is_raw = TRUE;
           if (use_queue) {
             GstPad *sinkpad;
 
@@ -2169,7 +2165,6 @@ static void
 source_new_pad (GstElement * element, GstPad * pad, GstURIDecodeBin * bin)
 {
   GstElement *decoder;
-  gboolean is_raw;
   GstCaps *rawcaps;
   GstPad *sinkpad;
 
@@ -2182,7 +2177,7 @@ source_new_pad (GstElement * element, GstPad * pad, GstURIDecodeBin * bin)
     rawcaps = DEFAULT_CAPS;
 
   /* if this is a pad with all raw caps, we can expose it */
-  if (has_all_raw_caps (pad, rawcaps, &is_raw) && is_raw) {
+  if (has_raw_caps (pad, rawcaps)) {
     /* it's all raw, create output pads. */
     GST_URI_DECODE_BIN_UNLOCK (bin);
     gst_caps_unref (rawcaps);
index 82d22a4..f055ffd 100644 (file)
@@ -20,6 +20,7 @@ tests = [
     'compositor/renogotiate_failing_unsupported_src_format',
     'giosrc/read-growing-file',
     'encodebin/set-encoder-properties',
+    'uridecodebin/expose_raw_pad_caps',
 ]
 
 env = environment()
diff --git a/subprojects/gst-plugins-base/tests/validate/uridecodebin/expose_raw_pad_caps.validatetest b/subprojects/gst-plugins-base/tests/validate/uridecodebin/expose_raw_pad_caps.validatetest
new file mode 100644 (file)
index 0000000..a8e367c
--- /dev/null
@@ -0,0 +1,15 @@
+meta,
+    args = {
+        "uridecodebin uri=testbin://video,num-buffers=1 ! fakesink",
+    },
+    handles-states=true,
+    ignore-eos=true
+
+wait, signal-name="pad-added", target-element-factory-name="uridecodebin", non-blocking=true,
+    check=[
+        check-current-pad-caps, expected-caps=[video/x-raw], target-element-factory-name="uridecodebin", pad="src_0", comparison-mode="intersect",
+    ]
+
+pause
+
+stop