typefind: Store caps on the pad before emitting have-type but send it downstream...
authorSebastian Dröge <sebastian@centricular.com>
Fri, 11 Mar 2016 12:17:13 +0000 (14:17 +0200)
committerSebastian Dröge <sebastian@centricular.com>
Mon, 14 Mar 2016 11:07:49 +0000 (13:07 +0200)
https://bugzilla.gnome.org/show_bug.cgi?id=763491

plugins/elements/gsttypefindelement.c

index 230cbed000ddb6350faf53346a53d0afb504418a..d4d2e8127e52f96fe53c7fe6059bef79afc662ab 100644 (file)
@@ -172,18 +172,62 @@ static void
 gst_type_find_element_have_type (GstTypeFindElement * typefind,
     guint probability, GstCaps * caps)
 {
+  GstEvent *event;
+
   g_assert (caps != NULL);
 
   GST_INFO_OBJECT (typefind, "found caps %" GST_PTR_FORMAT ", probability=%u",
       caps, probability);
 
   GST_OBJECT_LOCK (typefind);
+
+  /* Now actually send the CAPS event downstream.
+   *
+   * Try to directly send the CAPS event downstream that we created in
+   * gst_type_find_element_emit_have_type() if it is still there, instead
+   * of creating a new one. No need to create an equivalent one, replacing
+   * it in the sticky event list and possibly causing renegotiation
+   */
+  event = gst_pad_get_sticky_event (typefind->src, GST_EVENT_CAPS, 0);
+  if (event) {
+    GstCaps *event_caps;
+
+    gst_event_parse_caps (event, &event_caps);
+    if (caps == event_caps) {
+      event = event;
+    } else {
+      gst_event_unref (event);
+      event = gst_event_new_caps (caps);
+    }
+  } else {
+    event = gst_event_new_caps (caps);
+  }
+
   if (typefind->caps)
     gst_caps_unref (typefind->caps);
   typefind->caps = gst_caps_ref (caps);
   GST_OBJECT_UNLOCK (typefind);
 
-  gst_pad_set_caps (typefind->src, caps);
+  gst_pad_push_event (typefind->src, event);
+}
+
+static void
+gst_type_find_element_emit_have_type (GstTypeFindElement * typefind,
+    guint probability, GstCaps * caps)
+{
+  GstEvent *event;
+
+  /* Only store the caps event at this point. We give signal handlers
+   * the chance to look at the caps before they are sent downstream.
+   * They are only forwarded downstream later in the default signal
+   * handler after all application signal handlers
+   */
+  event = gst_event_new_caps (caps);
+  gst_pad_store_sticky_event (typefind->src, event);
+  gst_event_unref (event);
+
+  g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
+      probability, caps);
 }
 
 static void
@@ -729,8 +773,7 @@ gst_type_find_element_setcaps (GstTypeFindElement * typefind, GstCaps * caps)
   if (gst_caps_is_any (caps))
     return TRUE;
 
-  g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
-      GST_TYPE_FIND_MAXIMUM, caps);
+  gst_type_find_element_emit_have_type (typefind, GST_TYPE_FIND_MAXIMUM, caps);
 
   /* Shortcircuit typefinding if we get caps */
   GST_DEBUG_OBJECT (typefind, "Skipping typefinding, using caps from "
@@ -914,8 +957,7 @@ gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind,
 
   /* probability is good enough too, so let's make it known ... emiting this
    * signal calls our object handler which sets the caps. */
-  g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
-      probability, caps);
+  gst_type_find_element_emit_have_type (typefind, probability, caps);
 
   /* .. and send out the accumulated data */
   stop_typefinding (typefind);
@@ -1106,8 +1148,7 @@ gst_type_find_element_loop (GstPad * pad)
     }
 
     GST_DEBUG ("Emiting found caps %" GST_PTR_FORMAT, found_caps);
-    g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
-        0, probability, found_caps);
+    gst_type_find_element_emit_have_type (typefind, probability, found_caps);
     typefind->mode = MODE_NORMAL;
     gst_caps_unref (found_caps);
   } else if (typefind->mode == MODE_NORMAL) {