From d61e5393f110ed482815d77807245d78b52eff46 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Thu, 18 Jun 2015 09:26:13 +1000 Subject: [PATCH] splitmuxsink: Mask async-start/done while switching files. Sometimes, extra async-start/done from the internal sink while the element is still starting up can cause splitmuxsink to stall in PAUSED state when it has been set to PLAYING by the app. Drop the child's async-start/done messages while switching, so they don't cause state changes at the splitmuxsink level. https://bugzilla.gnome.org/show_bug.cgi?id=750747 --- gst/multifile/gstsplitmuxsink.c | 49 +++++++++++++++++++++++++++++++++++++---- gst/multifile/gstsplitmuxsink.h | 3 +++ 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/gst/multifile/gstsplitmuxsink.c b/gst/multifile/gstsplitmuxsink.c index 91d7fc4..2c7d15f 100644 --- a/gst/multifile/gstsplitmuxsink.c +++ b/gst/multifile/gstsplitmuxsink.c @@ -63,6 +63,9 @@ GST_DEBUG_CATEGORY_STATIC (splitmux_debug); #define GST_SPLITMUX_WAIT(s) g_cond_wait (&(s)->data_cond, &(s)->lock) #define GST_SPLITMUX_BROADCAST(s) g_cond_broadcast (&(s)->data_cond) +#define GST_SPLITMUX_WAIT_ASYNC_DONE(s) g_cond_wait (&(s)->async_cond, &(s)->lock) +#define GST_SPLITMUX_BROADCAST_ASYNC_DONE(s) g_cond_broadcast (&(s)->async_cond) + enum { PROP_0, @@ -209,6 +212,7 @@ gst_splitmux_sink_init (GstSplitMuxSink * splitmux) { g_mutex_init (&splitmux->lock); g_cond_init (&splitmux->data_cond); + g_cond_init (&splitmux->async_cond); splitmux->mux_overhead = DEFAULT_MUXER_OVERHEAD; splitmux->threshold_time = DEFAULT_MAX_SIZE_TIME; @@ -248,6 +252,7 @@ gst_splitmux_sink_finalize (GObject * object) { GstSplitMuxSink *splitmux = GST_SPLITMUX_SINK (object); g_cond_clear (&splitmux->data_cond); + g_cond_clear (&splitmux->async_cond); g_mutex_clear (&splitmux->lock); if (splitmux->provided_sink) gst_object_unref (splitmux->provided_sink); @@ -667,7 +672,17 @@ restart_context (MqStreamCtx * ctx, GstSplitMuxSink * splitmux) static void start_next_fragment (GstSplitMuxSink * splitmux) { + if (splitmux->is_async) { + /* Wait for async done on the sink */ + GST_SPLITMUX_WAIT_ASYNC_DONE (splitmux); + } + /* 1 change to new file */ + splitmux->restarting = TRUE; + + GST_SPLITMUX_UNLOCK (splitmux); + GST_STATE_LOCK (splitmux); + gst_element_set_state (splitmux->muxer, GST_STATE_NULL); gst_element_set_state (splitmux->active_sink, GST_STATE_NULL); @@ -676,6 +691,12 @@ start_next_fragment (GstSplitMuxSink * splitmux) gst_element_sync_state_with_parent (splitmux->active_sink); gst_element_sync_state_with_parent (splitmux->muxer); + GST_STATE_UNLOCK (splitmux); + GST_SPLITMUX_LOCK (splitmux); + + splitmux->restarting = FALSE; + + GST_LOG_OBJECT (splitmux, "Restarting contexts to push more data"); g_list_foreach (splitmux->contexts, (GFunc) restart_context, splitmux); /* Switch state and go back to processing */ @@ -715,11 +736,26 @@ bus_handler (GstBin * bin, GstMessage * message) GST_DEBUG_OBJECT (splitmux, "Caught EOS at end of fragment, dropping"); splitmux->state = SPLITMUX_STATE_START_NEXT_FRAGMENT; GST_SPLITMUX_BROADCAST (splitmux); - - gst_message_unref (message); - GST_SPLITMUX_UNLOCK (splitmux); - return; + goto drop; + } + GST_SPLITMUX_UNLOCK (splitmux); + GST_INFO_OBJECT (splitmux, "Passing EOS message"); + break; + case GST_MESSAGE_ASYNC_START: + GST_SPLITMUX_LOCK (splitmux); + if (splitmux->restarting) + goto drop; + splitmux->is_async = TRUE; + GST_SPLITMUX_UNLOCK (splitmux); + break; + case GST_MESSAGE_ASYNC_DONE: + GST_SPLITMUX_LOCK (splitmux); + if (splitmux->is_async) { + GST_SPLITMUX_BROADCAST_ASYNC_DONE (splitmux); + splitmux->is_async = FALSE; } + if (splitmux->restarting) + goto drop; GST_SPLITMUX_UNLOCK (splitmux); break; default: @@ -727,6 +763,11 @@ bus_handler (GstBin * bin, GstMessage * message) } GST_BIN_CLASS (parent_class)->handle_message (bin, message); + return; + +drop: + gst_message_unref (message); + GST_SPLITMUX_UNLOCK (splitmux); } /* Called with splitmux lock held */ diff --git a/gst/multifile/gstsplitmuxsink.h b/gst/multifile/gstsplitmuxsink.h index a305ed4..a78dbd0 100644 --- a/gst/multifile/gstsplitmuxsink.h +++ b/gst/multifile/gstsplitmuxsink.h @@ -88,6 +88,9 @@ struct _GstSplitMuxSink { GMutex lock; GCond data_cond; + GCond async_cond; + gboolean is_async; + gboolean restarting; SplitMuxState state; gdouble mux_overhead; -- 2.7.4