mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-28 03:00:35 +00:00
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
This commit is contained in:
parent
9c09c8ae17
commit
14d79a3a47
1 changed files with 31 additions and 14 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue