From e4aa8fcb19c75ebacc39315ad49ddfd60941186b Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Mon, 23 Jan 2006 15:05:24 +0000 Subject: [PATCH] gst/playback/gstdecodebin.c: Replace GstPadBlockCallback with pad probes that detect first buffer AND eos before remo... Original commit message from CVS: * gst/playback/gstdecodebin.c: (gst_decode_bin_init), (free_pad_probes), (remove_fakesink), (pad_probe), (close_pad_link), (gst_decode_bin_change_state): Replace GstPadBlockCallback with pad probes that detect first buffer AND eos before removing fakesink. Fixes hang with demuxers doing EOS while pre-rolling. Solves #328279 --- ChangeLog | 10 ++++++ gst/playback/gstdecodebin.c | 71 ++++++++++++++++++++++++++++++------- 2 files changed, 68 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9ae8000a1a..0b7535d41d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2006-01-23 Edward Hervey + + * gst/playback/gstdecodebin.c: (gst_decode_bin_init), + (free_pad_probes), (remove_fakesink), (pad_probe), + (close_pad_link), (gst_decode_bin_change_state): + Replace GstPadBlockCallback with pad probes that detect + first buffer AND eos before removing fakesink. + Fixes hang with demuxers doing EOS while pre-rolling. + Solves #328279 + 2006-01-23 Andy Wingo * ext/alsa/gstalsasink.c: diff --git a/gst/playback/gstdecodebin.c b/gst/playback/gstdecodebin.c index 2b431094b0..5329a61695 100644 --- a/gst/playback/gstdecodebin.c +++ b/gst/playback/gstdecodebin.c @@ -62,6 +62,8 @@ struct _GstDecodeBin GList *queues; /* list of demuxer-decoder queues */ + GList *probes; /* list of PadProbeData */ + GList *factories; /* factories we can use for selecting elements */ gint numpads; gint numwaiting; @@ -95,6 +97,14 @@ enum LAST_SIGNAL }; + +typedef struct +{ + GstPad *pad; + gulong sigid; + gboolean done; +} PadProbeData; + /* this structure is created for all dynamic pads that could get created * at runtime */ typedef struct @@ -336,6 +346,7 @@ gst_decode_bin_init (GstDecodeBin * decode_bin) decode_bin->dynamics = NULL; decode_bin->queues = NULL; + decode_bin->probes = NULL; } static void dynamic_free (GstDynamic * dyn); @@ -463,6 +474,22 @@ mimetype_is_raw (const gchar * mimetype) g_str_has_prefix (mimetype, "text/plain"); } +static void +free_pad_probes (GstDecodeBin * decode_bin) +{ + GList *tmp; + + /* Remove pad probes */ + for (tmp = decode_bin->probes; tmp; tmp = g_list_next (tmp)) { + PadProbeData *data = (PadProbeData *) tmp->data; + + gst_pad_remove_data_probe (data->pad, data->sigid); + g_free (data); + } + g_list_free (decode_bin->probes); + decode_bin->probes = NULL; +} + static void remove_fakesink (GstDecodeBin * decode_bin) { @@ -477,22 +504,33 @@ remove_fakesink (GstDecodeBin * decode_bin) gst_object_unref (decode_bin->fakesink); decode_bin->fakesink = NULL; + free_pad_probes (decode_bin); + gst_element_post_message (GST_ELEMENT_CAST (decode_bin), gst_message_new_state_dirty (GST_OBJECT_CAST (decode_bin))); } } -static void -pad_blocked (GstPad * pad, gboolean blocked, GstDecodeBin * decode_bin) +static gboolean +pad_probe (GstPad * pad, GstMiniObject * data, GstDecodeBin * decode_bin) { - if (blocked) { - decode_bin->numwaiting--; - if (decode_bin->numwaiting == 0) { - remove_fakesink (decode_bin); - } - gst_pad_set_blocked_async (pad, FALSE, (GstPadBlockCallback) pad_blocked, - NULL); + GList *tmp; + gboolean alldone = TRUE; + + for (tmp = decode_bin->probes; tmp; tmp = g_list_next (tmp)) { + PadProbeData *pdata = (PadProbeData *) tmp->data; + + if (pdata->pad == pad) { + if (GST_IS_BUFFER (data)) + pdata->done = TRUE; + else if (GST_IS_EVENT (data) && (GST_EVENT_TYPE (data) == GST_EVENT_EOS)) + pdata->done = TRUE; + } else if (!(pdata->done)) + alldone = FALSE; } + if (alldone) + remove_fakesink (decode_bin); + return TRUE; } /* given a pad and a caps from an element, find the list of elements @@ -544,6 +582,7 @@ close_pad_link (GstElement * element, GstPad * pad, GstCaps * caps, if (mimetype_is_raw (mimetype)) { gchar *padname; GstPad *ghost; + PadProbeData *data; /* make a unique name for this new pad */ padname = g_strdup_printf ("src%d", decode_bin->numpads); @@ -553,10 +592,15 @@ close_pad_link (GstElement * element, GstPad * pad, GstCaps * caps, ghost = gst_ghost_pad_new (padname, pad); gst_element_add_pad (GST_ELEMENT (decode_bin), ghost); - if (gst_pad_set_blocked_async (pad, TRUE, (GstPadBlockCallback) pad_blocked, - decode_bin)) { - decode_bin->numwaiting++; - } + data = g_new0 (PadProbeData, 1); + data->pad = pad; + data->done = FALSE; + + data->sigid = gst_pad_add_data_probe (pad, G_CALLBACK (pad_probe), + decode_bin); + decode_bin->numwaiting++; + + decode_bin->probes = g_list_append (decode_bin->probes, data); GST_LOG_OBJECT (element, "closed pad %s", padname); @@ -1279,6 +1323,7 @@ gst_decode_bin_change_state (GstElement * element, GstStateChange transition) break; case GST_STATE_CHANGE_READY_TO_NULL: free_dynamics (decode_bin); + free_pad_probes (decode_bin); break; default: break;