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
This commit is contained in:
Jan Schmidt 2015-06-18 09:26:13 +10:00
parent e5db2673bd
commit d61e5393f1
2 changed files with 48 additions and 4 deletions

View File

@ -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,18 +736,38 @@ 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:
break;
}
GST_BIN_CLASS (parent_class)->handle_message (bin, message);
return;
drop:
gst_message_unref (message);
GST_SPLITMUX_UNLOCK (splitmux);
}
/* Called with splitmux lock held */

View File

@ -88,6 +88,9 @@ struct _GstSplitMuxSink {
GMutex lock;
GCond data_cond;
GCond async_cond;
gboolean is_async;
gboolean restarting;
SplitMuxState state;
gdouble mux_overhead;