inputselector: Avoid deadlock when shutting down

Transition from PLAYING to PAUSED unschedules any pending clock wait,
but there was no guard that prevented another input buffer then waiting
again while in PAUSED before dataflow stops. Use a new `playing` flag to
avoid this, and exit the chain function if instead of playing we're now
flushing. Basically the same as the clocksync element.

Closes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1772

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4098>
This commit is contained in:
Vivia Nikolaidou 2023-03-02 15:51:08 +02:00
parent eab15c8659
commit cf5b659bc6
2 changed files with 19 additions and 0 deletions

View file

@ -853,6 +853,13 @@ gst_input_selector_wait_running_time (GstInputSelector * sel,
continue; continue;
} }
if (!sel->playing) {
GST_DEBUG_OBJECT (selpad, "Waiting for playing");
GST_INPUT_SELECTOR_WAIT (sel);
GST_DEBUG_OBJECT (selpad, "Done waiting");
continue;
}
/* FIXME: If no upstream latency was queried yet, do one now */ /* FIXME: If no upstream latency was queried yet, do one now */
clock_id = clock_id =
gst_clock_new_single_shot_id (clock, gst_clock_new_single_shot_id (clock,
@ -1432,6 +1439,7 @@ gst_input_selector_init (GstInputSelector * sel)
g_mutex_init (&sel->lock); g_mutex_init (&sel->lock);
g_cond_init (&sel->cond); g_cond_init (&sel->cond);
sel->eos = FALSE; sel->eos = FALSE;
sel->playing = FALSE;
sel->upstream_latency = 0; sel->upstream_latency = 0;
sel->last_output_ts = GST_CLOCK_TIME_NONE; sel->last_output_ts = GST_CLOCK_TIME_NONE;
@ -2028,6 +2036,12 @@ gst_input_selector_change_state (GstElement * element,
GST_INPUT_SELECTOR_BROADCAST (self); GST_INPUT_SELECTOR_BROADCAST (self);
GST_INPUT_SELECTOR_UNLOCK (self); GST_INPUT_SELECTOR_UNLOCK (self);
break; break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:{
GST_INPUT_SELECTOR_LOCK (self);
self->playing = TRUE;
GST_INPUT_SELECTOR_BROADCAST (self);
GST_INPUT_SELECTOR_UNLOCK (self);
}
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:{ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:{
GList *walk; GList *walk;
@ -2051,6 +2065,10 @@ gst_input_selector_change_state (GstElement * element,
case GST_STATE_CHANGE_PAUSED_TO_READY: case GST_STATE_CHANGE_PAUSED_TO_READY:
gst_input_selector_reset (self); gst_input_selector_reset (self);
break; break;
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
GST_INPUT_SELECTOR_LOCK (self);
self->playing = FALSE;
GST_INPUT_SELECTOR_UNLOCK (self);
default: default:
break; break;
} }

View file

@ -81,6 +81,7 @@ struct _GstInputSelector {
gboolean eos; gboolean eos;
gboolean eos_sent; gboolean eos_sent;
gboolean flushing; gboolean flushing;
gboolean playing;
GstClockTime upstream_latency; GstClockTime upstream_latency;
GstClockTime last_output_ts; GstClockTime last_output_ts;