splitmux: Handle a hang draining out at EOS

Make sure that all data is drained out when the reference pad
goes EOS. Fixes a problem where data that arrives on other
pads after the reference pad finishes can stall forever and
never pass EOS.

https://bugzilla.gnome.org/show_bug.cgi?id=763711
This commit is contained in:
Jan Schmidt 2016-03-31 02:15:04 +11:00
parent fb835c100a
commit 41d2b6f19e

View file

@ -718,8 +718,8 @@ restart_context (MqStreamCtx * ctx, GstSplitMuxSink * splitmux)
gst_pad_sticky_events_foreach (ctx->srcpad,
(GstPadStickyEventsForeachFunction) (resend_sticky), peer);
/* Clear EOS flag */
ctx->out_eos = FALSE;
/* Clear EOS flag if not actually EOS */
ctx->out_eos = GST_PAD_IS_EOS (ctx->srcpad);
gst_object_unref (peer);
}
@ -743,11 +743,11 @@ start_next_fragment (GstSplitMuxSink * splitmux)
g_list_foreach (splitmux->contexts, (GFunc) restart_context, splitmux);
/* Switch state and go back to processing */
splitmux->state = SPLITMUX_STATE_COLLECTING_GOP_START;
if (!splitmux->reference_ctx->in_eos) {
splitmux->state = SPLITMUX_STATE_COLLECTING_GOP_START;
splitmux->max_out_running_time = splitmux->reference_ctx->in_running_time;
} else {
splitmux->state = SPLITMUX_STATE_WAITING_GOP_COMPLETE;
splitmux->max_out_running_time = GST_CLOCK_TIME_NONE;
splitmux->have_muxed_something = FALSE;
}
@ -811,6 +811,7 @@ handle_gathered_gop (GstSplitMuxSink * splitmux)
GList *cur;
gsize queued_bytes = 0;
GstClockTime queued_time = 0;
gboolean at_eos = TRUE;
/* Assess if the multiqueue contents overflowed the current file */
for (cur = g_list_first (splitmux->contexts);
@ -819,6 +820,7 @@ handle_gathered_gop (GstSplitMuxSink * splitmux)
if (tmpctx->in_running_time > queued_time)
queued_time = tmpctx->in_running_time;
queued_bytes += tmpctx->in_bytes;
at_eos &= tmpctx->in_eos;
}
g_assert (queued_bytes >= splitmux->mux_start_bytes);
@ -835,11 +837,11 @@ handle_gathered_gop (GstSplitMuxSink * splitmux)
/* Check for overrun - have we output at least one byte and overrun
* either threshold? */
if (splitmux->have_muxed_something &&
((splitmux->threshold_bytes > 0 &&
queued_bytes >= splitmux->threshold_bytes) ||
(splitmux->threshold_time > 0 &&
queued_time >= splitmux->threshold_time))) {
if ((splitmux->have_muxed_something &&
((splitmux->threshold_bytes > 0 &&
queued_bytes >= splitmux->threshold_bytes) ||
(splitmux->threshold_time > 0 &&
queued_time >= splitmux->threshold_time))) || at_eos) {
splitmux->state = SPLITMUX_STATE_ENDING_FILE;
@ -857,13 +859,15 @@ handle_gathered_gop (GstSplitMuxSink * splitmux)
queued_bytes, GST_TIME_ARGS (queued_time));
/* Wake everyone up to push this one GOP, then sleep */
splitmux->state = SPLITMUX_STATE_COLLECTING_GOP_START;
splitmux->have_muxed_something = TRUE;
if (!splitmux->reference_ctx->in_eos)
if (!splitmux->reference_ctx->in_eos) {
splitmux->state = SPLITMUX_STATE_COLLECTING_GOP_START;
splitmux->max_out_running_time = splitmux->reference_ctx->in_running_time;
else
} else {
splitmux->state = SPLITMUX_STATE_WAITING_GOP_COMPLETE;
splitmux->max_out_running_time = GST_CLOCK_TIME_NONE;
}
GST_LOG_OBJECT (splitmux, "Waking output for complete GOP, TS %"
GST_TIME_FORMAT, GST_TIME_ARGS (splitmux->max_out_running_time));
@ -887,9 +891,11 @@ check_completed_gop (GstSplitMuxSink * splitmux, MqStreamCtx * ctx)
if (splitmux->state == SPLITMUX_STATE_WAITING_GOP_COMPLETE) {
/* Iterate each pad, and check that the input running time is at least
* up to the reference running time, and if so handle the collected GOP */
GST_LOG_OBJECT (splitmux, "Checking GOP collected, ctx %p", ctx);
for (cur = g_list_first (splitmux->contexts);
cur != NULL; cur = g_list_next (cur)) {
GST_LOG_OBJECT (splitmux, "Checking GOP collected, Max in running time %"
GST_TIME_FORMAT " ctx %p",
GST_TIME_ARGS (splitmux->max_in_running_time), ctx);
for (cur = g_list_first (splitmux->contexts); cur != NULL;
cur = g_list_next (cur)) {
MqStreamCtx *tmpctx = (MqStreamCtx *) (cur->data);
GST_LOG_OBJECT (splitmux,
@ -897,7 +903,8 @@ check_completed_gop (GstSplitMuxSink * splitmux, MqStreamCtx * ctx)
" EOS %d", tmpctx, tmpctx->srcpad,
GST_TIME_ARGS (tmpctx->in_running_time), tmpctx->in_eos);
if (tmpctx->in_running_time < splitmux->max_in_running_time &&
if (splitmux->max_in_running_time != GST_CLOCK_TIME_NONE &&
tmpctx->in_running_time < splitmux->max_in_running_time &&
!tmpctx->in_eos) {
GST_LOG_OBJECT (splitmux,
"Context %p (src pad %" GST_PTR_FORMAT ") not ready. We'll sleep",