summaryrefslogtreecommitdiff
path: root/gst/playback/gstdecodebin2.c
diff options
context:
space:
mode:
authorThiago Santos <ts.santos@sisa.samsung.com>2014-07-14 12:29:50 -0300
committerSebastian Dröge <sebastian@centricular.com>2014-08-13 18:51:37 +0300
commit14d79a3a47bc11e9a9f79a816387aa2599412434 (patch)
treece59f8cfe9257f2f0f2153e2fc4f06d833d0412b /gst/playback/gstdecodebin2.c
parent9c09c8ae17bc0d39c1b02d3ed83e64a5c80f807e (diff)
decodebin: handle group switching for deadend group
Gracefully handle switching groups that all pads are deadend. This can happen when quickly switching programs on mpegts as the output is unaligned it can happen that not enough data was accumulated at parsers to generate any buffers, causing the stream to receive EOS before any data can be decoded. To handle this scenario, the _expose function now also gets if there is any next group to be exposed along with the list of endpads. If there are no endpads and there is another group to expose it will switch to this next group and then retry exposing the streams. Also, the requirement to only switch from the chain that has the endpad had to be modified to care for when the drainpad is NULL https://bugzilla.gnome.org/show_bug.cgi?id=733169
Diffstat (limited to 'gst/playback/gstdecodebin2.c')
-rw-r--r--gst/playback/gstdecodebin2.c45
1 files changed, 31 insertions, 14 deletions
diff --git a/gst/playback/gstdecodebin2.c b/gst/playback/gstdecodebin2.c
index 7b1e0f3a4..bc3d18d7e 100644
--- a/gst/playback/gstdecodebin2.c
+++ b/gst/playback/gstdecodebin2.c
@@ -462,7 +462,7 @@ static GstDecodeGroup *gst_decode_group_new (GstDecodeBin * dbin,
GstDecodeChain * chain);
static gboolean gst_decode_chain_is_complete (GstDecodeChain * chain);
static gboolean gst_decode_chain_expose (GstDecodeChain * chain,
- GList ** endpads, gboolean * missing_plugin);
+ GList ** endpads, gboolean * missing_plugin, gboolean * last_group);
static gboolean gst_decode_chain_is_drained (GstDecodeChain * chain);
static gboolean gst_decode_chain_reset_buffering (GstDecodeChain * chain);
static gboolean gst_decode_group_is_complete (GstDecodeGroup * group);
@@ -2657,9 +2657,6 @@ pad_event_cb (GstPad * pad, GstPadProbeInfo * info, gpointer data)
gst_object_replace ((GstObject **) & chain->current_pad, NULL);
/* we don't set the endcaps because NULL endcaps means early EOS */
- /* TODO check if this makes the next_group complete, but drained/deadend,
- * meaning that it should be skipped and not exposed */
-
EXPOSE_LOCK (dbin);
if (gst_decode_chain_is_complete (dbin->decode_chain))
gst_decode_bin_expose (dbin);
@@ -3579,8 +3576,8 @@ drain_and_switch_chains (GstDecodeChain * chain, GstDecodePad * drainpad,
gboolean handled = FALSE;
GstDecodeBin *dbin = chain->dbin;
- GST_DEBUG ("Checking chain %p (target pad %s:%s)",
- chain, GST_DEBUG_PAD_NAME (drainpad));
+ GST_DEBUG ("Checking chain %p %s:%s (target pad %s:%s)",
+ chain, GST_DEBUG_PAD_NAME (chain->pad), GST_DEBUG_PAD_NAME (drainpad));
CHAIN_MUTEX_LOCK (chain);
@@ -3591,7 +3588,7 @@ drain_and_switch_chains (GstDecodeChain * chain, GstDecodePad * drainpad,
if (chain->endpad) {
/* Check if we're reached the target endchain */
- if (chain == drainpad->chain) {
+ if (drainpad != NULL && chain == drainpad->chain) {
GST_DEBUG ("Found the target chain");
drainpad->drained = TRUE;
handled = TRUE;
@@ -3612,7 +3609,7 @@ drain_and_switch_chains (GstDecodeChain * chain, GstDecodePad * drainpad,
last_group, &subdrained, switched);
/* The group is drained, see if we can switch to another */
- if (handled && subdrained && !*switched) {
+ if ((handled || drainpad == NULL) && subdrained && !*switched) {
if (chain->next_groups) {
/* Switch to next group */
GST_DEBUG_OBJECT (dbin, "Hiding current group %p", chain->active_group);
@@ -4037,7 +4034,9 @@ gst_decode_bin_expose (GstDecodeBin * dbin)
GList *tmp, *endpads = NULL;
gboolean missing_plugin = FALSE;
gboolean already_exposed = TRUE;
+ gboolean last_group = TRUE;
+retry:
GST_DEBUG_OBJECT (dbin, "Exposing currently active chains/groups");
/* Don't expose if we're currently shutting down */
@@ -4050,7 +4049,8 @@ gst_decode_bin_expose (GstDecodeBin * dbin)
DYN_UNLOCK (dbin);
/* Get the pads that we're going to expose and mark things as exposed */
- if (!gst_decode_chain_expose (dbin->decode_chain, &endpads, &missing_plugin)) {
+ if (!gst_decode_chain_expose (dbin->decode_chain, &endpads, &missing_plugin,
+ &last_group)) {
g_list_foreach (endpads, (GFunc) gst_object_unref, NULL);
g_list_free (endpads);
GST_ERROR_OBJECT (dbin, "Broken chain/group tree");
@@ -4065,9 +4065,22 @@ gst_decode_bin_expose (GstDecodeBin * dbin)
} else {
/* in this case, the stream ended without buffers,
* just post a warning */
- GST_WARNING_OBJECT (dbin, "All streams finished without buffers");
- GST_ELEMENT_ERROR (dbin, STREAM, FAILED, (NULL),
- ("all streams without buffers"));
+ GST_WARNING_OBJECT (dbin, "All streams finished without buffers. "
+ "Last group: %d", last_group);
+ if (last_group) {
+ GST_ELEMENT_ERROR (dbin, STREAM, FAILED, (NULL),
+ ("all streams without buffers"));
+ } else {
+ gboolean switched = FALSE;
+ gboolean drained = FALSE;
+
+ drain_and_switch_chains (dbin->decode_chain, NULL, &last_group,
+ &drained, &switched);
+ GST_ELEMENT_WARNING (dbin, STREAM, FAILED, (NULL),
+ ("all streams without buffers"));
+ if (switched)
+ goto retry;
+ }
}
do_async_done (dbin);
@@ -4174,7 +4187,7 @@ gst_decode_bin_expose (GstDecodeBin * dbin)
*/
static gboolean
gst_decode_chain_expose (GstDecodeChain * chain, GList ** endpads,
- gboolean * missing_plugin)
+ gboolean * missing_plugin, gboolean * last_group)
{
GstDecodeGroup *group;
GList *l;
@@ -4193,6 +4206,9 @@ gst_decode_chain_expose (GstDecodeChain * chain, GList ** endpads,
return TRUE;
}
+ if (chain->next_groups)
+ *last_group = FALSE;
+
group = chain->active_group;
if (!group)
return FALSE;
@@ -4212,7 +4228,8 @@ gst_decode_chain_expose (GstDecodeChain * chain, GList ** endpads,
for (l = group->children; l; l = l->next) {
GstDecodeChain *childchain = l->data;
- if (!gst_decode_chain_expose (childchain, endpads, missing_plugin))
+ if (!gst_decode_chain_expose (childchain, endpads, missing_plugin,
+ last_group))
return FALSE;
}