From 57bbd18471c7a9f82cf33e2b270e95c73d27910c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 11 Mar 2016 14:17:13 +0200 Subject: [PATCH] typefind: Store caps on the pad before emitting have-type but send it downstream only in the default signal handler https://bugzilla.gnome.org/show_bug.cgi?id=763491 --- plugins/elements/gsttypefindelement.c | 55 +++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/plugins/elements/gsttypefindelement.c b/plugins/elements/gsttypefindelement.c index 230cbed000..d4d2e8127e 100644 --- a/plugins/elements/gsttypefindelement.c +++ b/plugins/elements/gsttypefindelement.c @@ -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) {