From 0efd7381c4bdd97388e2e35e90638dad396d1a44 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Sun, 18 Dec 2005 15:04:21 +0000 Subject: [PATCH] ext/ogg/gstoggdemux.c: Extra debug output when activating/deactivating chains. Original commit message from CVS: * ext/ogg/gstoggdemux.c: (gst_ogg_demux_deactivate_current_chain), (gst_ogg_demux_activate_chain): Extra debug output when activating/deactivating chains. * gst/playback/gstdecodebin.c: (gst_decode_bin_factory_filter), (is_demuxer_element), (try_to_link_1), (remove_element_chain), (unlinked): Remove a queue from our list when it becomes unlinked. Don't add queues to elements in class 'Demux' if they can only produce one pad --- ChangeLog | 13 ++++ ext/ogg/gstoggdemux.c | 8 ++- gst/playback/gstdecodebin.c | 146 +++++++++++++++++++++++++++++++------------- 3 files changed, 123 insertions(+), 44 deletions(-) diff --git a/ChangeLog b/ChangeLog index a7f0103..6454309 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2005-12-18 Jan Schmidt + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_deactivate_current_chain), + (gst_ogg_demux_activate_chain): + Extra debug output when activating/deactivating chains. + + * gst/playback/gstdecodebin.c: (gst_decode_bin_factory_filter), + (is_demuxer_element), (try_to_link_1), (remove_element_chain), + (unlinked): + Remove a queue from our list when it becomes unlinked. + Don't add queues to elements in class 'Demux' if they + can only produce one pad + 2005-12-18 Julien MOUTTE * gst-libs/gst/video/gstvideosink.c: (gst_video_sink_base_init), diff --git a/ext/ogg/gstoggdemux.c b/ext/ogg/gstoggdemux.c index bdd6cbe..75baf9e 100644 --- a/ext/ogg/gstoggdemux.c +++ b/ext/ogg/gstoggdemux.c @@ -1378,11 +1378,15 @@ gst_ogg_demux_deactivate_current_chain (GstOggDemux * ogg) if (chain == NULL) return TRUE; + GST_DEBUG ("deactivating chain %p", chain); + /* send EOS on all the pads */ for (i = 0; i < chain->streams->len; i++) { GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i); gst_pad_push_event (GST_PAD (pad), gst_event_new_eos ()); + + GST_DEBUG_OBJECT (ogg, "removing pad %" GST_PTR_FORMAT, pad); gst_element_remove_pad (GST_ELEMENT (ogg), GST_PAD (pad)); } /* if we cannot seek back to the chain, we can destroy the chain @@ -1409,13 +1413,15 @@ gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain, gst_ogg_demux_deactivate_current_chain (ogg); - GST_DEBUG ("activating chain"); + GST_DEBUG ("activating chain %p", chain); /* first add the pads */ for (i = 0; i < chain->streams->len; i++) { GstOggPad *pad; pad = g_array_index (chain->streams, GstOggPad *, i); + GST_DEBUG_OBJECT (ogg, "adding pad %" GST_PTR_FORMAT, pad); + gst_element_add_pad (GST_ELEMENT (ogg), GST_PAD (pad)); } diff --git a/gst/playback/gstdecodebin.c b/gst/playback/gstdecodebin.c index d651e09..fbbdac9 100644 --- a/gst/playback/gstdecodebin.c +++ b/gst/playback/gstdecodebin.c @@ -69,6 +69,8 @@ struct _GstDecodeBin guint have_type_id; /* signal id for the typefind element */ gboolean shutting_down; /* stop pluggin if we're shutting down */ + + GType queue_type; /* store the GType of queues, to aid in recognising them */ }; struct _GstDecodeBinClass @@ -233,7 +235,7 @@ gst_decode_bin_factory_filter (GstPluginFeature * feature, return FALSE; klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature)); - /* only demuxers and decoders can play */ + /* only demuxers, decoders and parsers can play */ if (strstr (klass, "Demux") == NULL && strstr (klass, "Decoder") == NULL && strstr (klass, "Parse") == NULL) { return FALSE; @@ -603,6 +605,56 @@ many_types: } } +/* Decide whether an element is a demuxer based on the + * klass and number/type of src pad templates it has */ +static gboolean +is_demuxer_element (GstElement * srcelement) +{ + GstElementFactory *srcfactory; + GstElementClass *elemclass; + GList *templates, *walk; + const gchar *klass; + gint potential_src_pads = 0; + + srcfactory = gst_element_get_factory (srcelement); + klass = gst_element_factory_get_klass (srcfactory); + + /* Can't be a demuxer unless it has Demux in the klass name */ + if (!strstr (klass, "Demux")) + return FALSE; + + /* Walk the src pad templates and count how many the element + * might produce */ + elemclass = GST_ELEMENT_GET_CLASS (srcelement); + + walk = templates = gst_element_class_get_pad_template_list (elemclass); + while (walk != NULL) { + GstPadTemplate *templ; + + templ = (GstPadTemplate *) walk->data; + if (GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC) { + switch (GST_PAD_TEMPLATE_PRESENCE (templ)) { + case GST_PAD_ALWAYS: + case GST_PAD_SOMETIMES: + if (strstr (GST_PAD_TEMPLATE_NAME_TEMPLATE (templ), "%")) + potential_src_pads += 2; /* Might make multiple pads */ + else + potential_src_pads += 1; + break; + case GST_PAD_REQUEST: + potential_src_pads += 2; + break; + } + } + walk = g_list_next (walk); + } + + if (potential_src_pads < 2) + return FALSE; + + return TRUE; +} + /* * given a list of element factories, try to link one of the factories * to the given pad. @@ -615,25 +667,41 @@ try_to_link_1 (GstDecodeBin * decode_bin, GstElement * srcelement, GstPad * pad, GList * factories) { GList *walk; - GstElementFactory *srcfactory = NULL; GstElement *result = NULL; gboolean isdemux = FALSE; - const gchar *klass; + GstPad *queuesinkpad = NULL, *queuesrcpad = NULL; + GstElement *queue = NULL; + GstPad *usedsrcpad = pad; /* Check if the parent of the src pad is a demuxer */ - srcfactory = gst_element_get_factory (srcelement); - klass = gst_element_factory_get_klass (srcfactory); - isdemux = !!(strstr (klass, "Demux")); + isdemux = is_demuxer_element (srcelement); + + if (isdemux && factories != NULL) { + /* Insert a queue between demuxer and decoder */ + GST_DEBUG_OBJECT (decode_bin, + "Element %s is a demuxer, inserting a queue", + GST_OBJECT_NAME (srcelement)); + queue = gst_element_factory_make ("queue", NULL); + decode_bin->queue_type = G_OBJECT_TYPE (queue); + + g_object_set (G_OBJECT (queue), "max-size-buffers", 0, NULL); + g_object_set (G_OBJECT (queue), "max-size-time", 0LL, NULL); + g_object_set (G_OBJECT (queue), "max-size-bytes", 8192, NULL); + gst_bin_add (GST_BIN (decode_bin), queue); + gst_element_set_state (queue, GST_STATE_READY); + queuesinkpad = gst_element_get_pad (queue, "sink"); + usedsrcpad = queuesrcpad = gst_element_get_pad (queue, "src"); + + g_return_val_if_fail (gst_pad_link (pad, queuesinkpad) == GST_PAD_LINK_OK, + NULL); + } /* loop over the factories */ for (walk = factories; walk; walk = g_list_next (walk)) { GstElementFactory *factory = GST_ELEMENT_FACTORY (walk->data); GstElement *element; - GstElement *queue = NULL; GstPadLinkReturn ret; GstPad *sinkpad; - GstPad *usedsrcpad = pad; - GstPad *queuesinkpad = NULL, *queuesrcpad = NULL; GST_DEBUG_OBJECT (decode_bin, "trying to link %s", gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory))); @@ -662,24 +730,6 @@ try_to_link_1 (GstDecodeBin * decode_bin, GstElement * srcelement, GstPad * pad, /* set to ready first so it is ready */ gst_element_set_state (element, GST_STATE_READY); - if (isdemux) { - /* Insert a queue between demuxer and decoder */ - GST_DEBUG_OBJECT (decode_bin, - "Element %s is a demuxer, inserting a queue", - GST_OBJECT_NAME (srcelement)); - - queue = gst_element_factory_make ("queue", NULL); - g_object_set (G_OBJECT (queue), "max-size-buffers", 0, NULL); - g_object_set (G_OBJECT (queue), "max-size-time", 0LL, NULL); - g_object_set (G_OBJECT (queue), "max-size-bytes", 8192, NULL); - gst_bin_add (GST_BIN (decode_bin), queue); - gst_element_set_state (queue, GST_STATE_READY); - queuesinkpad = gst_element_get_pad (queue, "sink"); - usedsrcpad = queuesrcpad = gst_element_get_pad (queue, "src"); - - gst_pad_link (pad, queuesinkpad); - } - if ((ret = gst_pad_link (usedsrcpad, sinkpad)) != GST_PAD_LINK_OK) { GST_DEBUG_OBJECT (decode_bin, "link failed on pad %s:%s, reason %d", GST_DEBUG_PAD_NAME (pad), ret); @@ -687,15 +737,7 @@ try_to_link_1 (GstDecodeBin * decode_bin, GstElement * srcelement, GstPad * pad, gst_object_unref (sinkpad); /* this element did not work, remove it again and continue trying * other elements, the element will be disposed. */ - if (isdemux) - gst_element_set_state (queue, GST_STATE_NULL); gst_element_set_state (element, GST_STATE_NULL); - if (isdemux) { - gst_pad_unlink (pad, queuesrcpad); - gst_object_unref (queuesrcpad); - gst_object_unref (queuesinkpad); - gst_bin_remove (GST_BIN (decode_bin), queue); - } gst_bin_remove (GST_BIN (decode_bin), element); } else { @@ -704,7 +746,7 @@ try_to_link_1 (GstDecodeBin * decode_bin, GstElement * srcelement, GstPad * pad, GST_DEBUG_OBJECT (decode_bin, "linked on pad %s:%s", GST_DEBUG_PAD_NAME (usedsrcpad)); - if (isdemux) { + if (queue != NULL) { decode_bin->queues = g_list_append (decode_bin->queues, queue); g_signal_connect (G_OBJECT (queue), "overrun", G_CALLBACK (queue_filled_cb), decode_bin); @@ -713,12 +755,9 @@ try_to_link_1 (GstDecodeBin * decode_bin, GstElement * srcelement, GstPad * pad, /* The link worked, now figure out what it was that we connected */ /* make sure we catch unlink signals */ - sig = g_signal_connect (G_OBJECT (usedsrcpad), "unlinked", + sig = g_signal_connect (G_OBJECT (pad), "unlinked", G_CALLBACK (unlinked), decode_bin); - /* keep a ref to the signal id so that we can disconnect the signal callback */ - g_object_set_data (G_OBJECT (pad), "unlinked_id", GINT_TO_POINTER (sig)); - /* now that we added the element we can try to continue autoplugging * on it until we have a raw type */ close_link (element, decode_bin); @@ -729,8 +768,12 @@ try_to_link_1 (GstDecodeBin * decode_bin, GstElement * srcelement, GstPad * pad, /* get rid of the sinkpad now */ gst_object_unref (sinkpad); - if (isdemux) { + + /* Set the queue to paused and set the pointer to NULL so we don't + * remove it below */ + if (queue != NULL) { gst_element_set_state (queue, GST_STATE_PAUSED); + queue = NULL; gst_object_unref (queuesrcpad); gst_object_unref (queuesinkpad); } @@ -740,6 +783,14 @@ try_to_link_1 (GstDecodeBin * decode_bin, GstElement * srcelement, GstPad * pad, } } done: + if (queue != NULL) { + /* We didn't successfully connect to the queue */ + gst_pad_unlink (pad, queuesrcpad); + gst_element_set_state (queue, GST_STATE_NULL); + gst_object_unref (queuesrcpad); + gst_object_unref (queuesinkpad); + gst_bin_remove (GST_BIN (decode_bin), queue); + } return result; } @@ -801,6 +852,12 @@ remove_element_chain (GstDecodeBin * decode_bin, GstPad * pad) GST_OBJECT_PARENT (elem) != GST_OBJECT (decode_bin)) elem = GST_ELEMENT (GST_OBJECT_PARENT (elem)); + if (G_OBJECT_TYPE (elem) == decode_bin->queue_type) { + GST_DEBUG_OBJECT (decode_bin, + "Encountered demuxer output queue while removing element chain"); + decode_bin->queues = g_list_remove (decode_bin->queues, elem); + } + GST_DEBUG_OBJECT (decode_bin, "%s:%s", GST_DEBUG_PAD_NAME (pad)); int_links = gst_pad_get_internal_links (pad); @@ -1010,15 +1067,18 @@ unlinked (GstPad * pad, GstPad * peerpad, GstDecodeBin * decode_bin) if (!is_our_kid (peer, decode_bin)) goto exit; + GST_DEBUG_OBJECT (decode_bin, "pad %s:%s removal while alive - chained?", + GST_DEBUG_PAD_NAME (pad)); + /* remove all elements linked to the peerpad */ remove_element_chain (decode_bin, peerpad); /* if an element removes two pads, then we don't want this twice */ + /* FIXME: decode_bin->dynamics doesn't contain a list of GstElements, it + * has GstDynamic structures */ if (g_list_find (decode_bin->dynamics, element) != NULL) goto exit; - GST_DEBUG_OBJECT (decode_bin, "pad removal while alive - chained?"); - dyn = dynamic_create (element, decode_bin); /* and add this element to the dynamic elements */ decode_bin->dynamics = g_list_prepend (decode_bin->dynamics, dyn); -- 2.7.4