parsebin: Implement ACCEPT_CAPS handling
authorEdward Hervey <edward@centricular.com>
Fri, 21 Jan 2022 13:52:07 +0000 (14:52 +0100)
committerEdward Hervey <bilboed@bilboed.com>
Fri, 11 Mar 2022 14:02:02 +0000 (15:02 +0100)
The default query handler would go through typefind, which by default accepts
any CAPS. But once configured, parsebin can't reconfigure itself, it should
therefore pass through the ACCEPT_CAPS query to the first element after
typefind (if any).

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

subprojects/gst-plugins-base/gst/playback/gstparsebin.c

index 02eb82a..a17cc6b 100644 (file)
@@ -411,6 +411,8 @@ struct _GstParseChain
   GList *old_groups;            /* Groups that should be freed later */
 };
 
+static gboolean gst_parse_chain_accept_caps (GstParseChain * chain,
+    GstCaps * caps);
 static void gst_parse_chain_free (GstParseChain * chain);
 static GstParseChain *gst_parse_chain_new (GstParseBin * parsebin,
     GstParseGroup * group, GstPad * pad, GstCaps * start_caps);
@@ -855,6 +857,24 @@ gst_parse_bin_update_factories_list (GstParseBin * parsebin)
   }
 }
 
+static gboolean
+sink_query_function (GstPad * sinkpad, GstParseBin * parsebin, GstQuery * query)
+{
+  GST_DEBUG_OBJECT (parsebin, "query %" GST_PTR_FORMAT, query);
+
+  if (parsebin->parse_chain && GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS) {
+    GstCaps *querycaps = NULL;
+    gst_query_parse_accept_caps (query, &querycaps);
+    if (querycaps) {
+      gboolean ret =
+          gst_parse_chain_accept_caps (parsebin->parse_chain, querycaps);
+      gst_query_set_accept_caps_result (query, ret);
+    }
+    return TRUE;
+  }
+  return gst_pad_query_default (sinkpad, GST_OBJECT (parsebin), query);
+}
+
 static void
 gst_parse_bin_init (GstParseBin * parse_bin)
 {
@@ -885,6 +905,8 @@ gst_parse_bin_init (GstParseBin * parse_bin)
 
     /* ghost the sink pad to ourself */
     gpad = gst_ghost_pad_new_from_template ("sink", pad, pad_tmpl);
+    gst_pad_set_query_function (gpad,
+        (GstPadQueryFunction) sink_query_function);
     gst_pad_set_active (gpad, TRUE);
     gst_element_add_pad (GST_ELEMENT (parse_bin), gpad);
 
@@ -3084,6 +3106,33 @@ chain_remove_old_groups (GstParseChain * chain)
 }
 
 static gboolean
+gst_parse_chain_accept_caps (GstParseChain * chain, GstCaps * caps)
+{
+  GstParseElement *initial_element;
+  GList *lastlist;
+  GstPad *sink;
+  gboolean ret;
+
+  if (!chain->elements)
+    return TRUE;
+
+  lastlist = g_list_last (chain->elements);
+  initial_element = lastlist->data;
+
+  GST_DEBUG_OBJECT (chain->parsebin, "element %s caps %" GST_PTR_FORMAT,
+      GST_ELEMENT_NAME (initial_element->element), caps);
+
+  sink = gst_element_get_static_pad (initial_element->element, "sink");
+  ret = gst_pad_query_accept_caps (sink, caps);
+  gst_object_unref (sink);
+
+  GST_DEBUG_OBJECT (chain->parsebin, "Chain can%s handle caps",
+      ret ? "" : " NOT");
+
+  return ret;
+}
+
+static gboolean
 drain_and_switch_chains (GstParseChain * chain, GstParsePad * drainpad,
     gboolean * last_group, gboolean * drained, gboolean * switched);
 /* drain_and_switch_chains/groups: