playbin: ignore new pads if it is shutting down

If a new pad is added after playbin has been put to READY/NULL it
should ignore new pads as it is shutting down.

This can happen when the pipeline fails to preroll (is still in READY)
and the user gives up on waiting or an error that doesn't reach
the demuxer occurs (on some event handling) and it will continue to
work and exposing pads while playbin has been put to NULL.

Without this check an input-selector is created and set to PAUSED
state, preventing playbin from properly shutting down in case it
has data blocked inside it.
This commit is contained in:
Thiago Santos 2015-03-25 08:20:03 -03:00
parent 6ba8d385e3
commit d54d51d0d2

View file

@ -3148,6 +3148,8 @@ pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
playbin = group->playbin;
GST_PLAY_BIN_SHUTDOWN_LOCK (playbin, shutdown);
caps = gst_pad_get_current_caps (pad);
if (!caps)
caps = gst_pad_query_caps (pad, NULL);
@ -3189,8 +3191,10 @@ pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
}
/* no combiner found for the media type, don't bother linking it to a
* combiner. This will leave the pad unlinked and thus ignored. */
if (combine == NULL)
if (combine == NULL) {
GST_PLAY_BIN_SHUTDOWN_UNLOCK (playbin);
goto unknown_type;
}
GST_SOURCE_GROUP_LOCK (group);
if (combine->combiner == NULL && playbin->have_selector) {
@ -3236,6 +3240,8 @@ pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
}
}
GST_PLAY_BIN_SHUTDOWN_UNLOCK (playbin);
if (combine->srcpad == NULL) {
if (combine->combiner) {
/* save source pad of the combiner */
@ -3385,6 +3391,12 @@ request_pad_failed:
("Failed to get request pad from combiner %p.", combine->combiner));
GST_SOURCE_GROUP_UNLOCK (group);
goto done;
shutdown:
{
GST_DEBUG ("ignoring, we are shutting down. Pad will be left unlinked");
/* not going to done as we didn't request the caps */
return;
}
}
/* called when a pad is removed from the uridecodebin. We unlink the pad from
@ -5596,7 +5608,7 @@ gst_play_bin_change_state (GstElement * element, GstStateChange transition)
break;
case GST_STATE_CHANGE_READY_TO_NULL:
/* we go async to PAUSED, so if that fails, we never make it to PAUSED
* an no state change PAUSED to READY passes here,
* and no state change PAUSED to READY passes here,
* though it is a nice-to-have ... */
if (!g_atomic_int_get (&playbin->shutdown)) {
do_save = TRUE;