decodebin2: Take STREAM_LOCK before sending sticky events.

There was a race where:

1) we would put the element to PAUSED
2) It would get data sent to it from upstream
3) It would thus send caps
3) caps_notify_cb would continue autoplugging
4) caps would flow downstream, the last pad would get exposed
5) we were still not done sending the sticky events

Taking the stream lock on the new element's sinkpad and only
releasing it when sticky events have all been sent prevents
the caps from reaching the source pad of the element before
we're all set.

https://bugzilla.gnome.org/show_bug.cgi?id=740694
This commit is contained in:
Mathieu Duponchelle 2014-11-25 16:46:50 +01:00
parent 76199fddb6
commit 68edf0ebd6

View file

@ -2367,6 +2367,12 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
} }
/* Bring the element to the state of the parent */ /* Bring the element to the state of the parent */
/* First lock element's sinkpad stream lock so no data reaches
* the possible new element added when caps are sent by element
* while we're still sending sticky events */
GST_PAD_STREAM_LOCK (sinkpad);
if ((gst_element_set_state (element, if ((gst_element_set_state (element,
GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE || GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE ||
!send_sticky_events (dbin, pad)) { !send_sticky_events (dbin, pad)) {
@ -2374,6 +2380,8 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
GstElement *tmp = NULL; GstElement *tmp = NULL;
GstMessage *error_msg; GstMessage *error_msg;
GST_PAD_STREAM_UNLOCK (sinkpad);
GST_WARNING_OBJECT (dbin, "Couldn't set %s to PAUSED", GST_WARNING_OBJECT (dbin, "Couldn't set %s to PAUSED",
GST_ELEMENT_NAME (element)); GST_ELEMENT_NAME (element));
@ -2447,6 +2455,9 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
CHAIN_MUTEX_UNLOCK (chain); CHAIN_MUTEX_UNLOCK (chain);
continue; continue;
} else {
/* Everything went well, the spice must flow now */
GST_PAD_STREAM_UNLOCK (sinkpad);
} }
/* Remove error filter now, from now on we can't gracefully /* Remove error filter now, from now on we can't gracefully