From cf5b659bc646c78d2833888f95419b511923315c Mon Sep 17 00:00:00 2001 From: Vivia Nikolaidou Date: Thu, 2 Mar 2023 15:51:08 +0200 Subject: [PATCH] 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: --- .../plugins/elements/gstinputselector.c | 18 ++++++++++++++++++ .../plugins/elements/gstinputselector.h | 1 + 2 files changed, 19 insertions(+) diff --git a/subprojects/gstreamer/plugins/elements/gstinputselector.c b/subprojects/gstreamer/plugins/elements/gstinputselector.c index 6982be3271..b55b42bc0a 100644 --- a/subprojects/gstreamer/plugins/elements/gstinputselector.c +++ b/subprojects/gstreamer/plugins/elements/gstinputselector.c @@ -853,6 +853,13 @@ gst_input_selector_wait_running_time (GstInputSelector * sel, 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 */ clock_id = gst_clock_new_single_shot_id (clock, @@ -1432,6 +1439,7 @@ gst_input_selector_init (GstInputSelector * sel) g_mutex_init (&sel->lock); g_cond_init (&sel->cond); sel->eos = FALSE; + sel->playing = FALSE; sel->upstream_latency = 0; 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_UNLOCK (self); 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:{ GList *walk; @@ -2051,6 +2065,10 @@ gst_input_selector_change_state (GstElement * element, case GST_STATE_CHANGE_PAUSED_TO_READY: gst_input_selector_reset (self); break; + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + GST_INPUT_SELECTOR_LOCK (self); + self->playing = FALSE; + GST_INPUT_SELECTOR_UNLOCK (self); default: break; } diff --git a/subprojects/gstreamer/plugins/elements/gstinputselector.h b/subprojects/gstreamer/plugins/elements/gstinputselector.h index 039f6285b0..35e008ba28 100644 --- a/subprojects/gstreamer/plugins/elements/gstinputselector.h +++ b/subprojects/gstreamer/plugins/elements/gstinputselector.h @@ -81,6 +81,7 @@ struct _GstInputSelector { gboolean eos; gboolean eos_sent; gboolean flushing; + gboolean playing; GstClockTime upstream_latency; GstClockTime last_output_ts;