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