basesrc: fix race in PLAYING->PAUSED->PLAYING

When we quickly switch from PLAYING to PAUSED and back to PLAYING it's possible
in some cases that the task refuses to start, This is because when we go to
PAUSED, we unschedule the clock timeout, which could return UNSCHEDULED when
we're back to PLAYING, causing the task to PAUSE again with a wrong-state.

This patch checks if we are running when we return with an UNSCHEDULED return
value and if we are, try to create a new buffer.

Fixes #597550
This commit is contained in:
Wim Taymans 2009-10-15 16:30:36 +02:00
parent bad284be7a
commit e9f2714ff9

View file

@ -1934,6 +1934,7 @@ gst_base_src_get_range (GstBaseSrc * src, guint64 offset, guint length,
bclass = GST_BASE_SRC_GET_CLASS (src);
again:
if (src->is_live) {
while (G_UNLIKELY (!src->live_running)) {
ret = gst_base_src_wait_playing (src);
@ -2011,14 +2012,23 @@ gst_base_src_get_range (GstBaseSrc * src, guint64 offset, guint length,
break;
case GST_CLOCK_UNSCHEDULED:
/* this case is triggered when we were waiting for the clock and
* it got unlocked because we did a state change. We return
* WRONG_STATE in this case to stop the dataflow also get rid of the
* produced buffer. */
GST_DEBUG_OBJECT (src,
"clock was unscheduled (%d), returning WRONG_STATE", status);
* it got unlocked because we did a state change. In any case, get rid of
* the buffer. */
gst_buffer_unref (*buf);
*buf = NULL;
ret = GST_FLOW_WRONG_STATE;
if (!src->live_running) {
/* We return WRONG_STATE when we are not running to stop the dataflow also
* get rid of the produced buffer. */
GST_DEBUG_OBJECT (src,
"clock was unscheduled (%d), returning WRONG_STATE", status);
ret = GST_FLOW_WRONG_STATE;
} else {
/* If we are running when this happens, we quickly switched between
* pause and playing. We try to produce a new buffer */
GST_DEBUG_OBJECT (src,
"clock was unscheduled (%d), but we are running", status);
goto again;
}
break;
default:
/* all other result values are unexpected and errors */