From 6a037a78de4ab96fa7fb255b1e73eda1b337a58e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 3 Apr 2017 15:48:13 +0300 Subject: [PATCH] dashdemux: Try harder to not run into a loop over the same fragment over and over While still making sure to not jump ahead one fragment further than needed. --- ext/dash/gstdashdemux.c | 79 ++++++++++++++++++++++++++++++++++------- 1 file changed, 67 insertions(+), 12 deletions(-) diff --git a/ext/dash/gstdashdemux.c b/ext/dash/gstdashdemux.c index fe7c8914a1..6e59f710cf 100644 --- a/ext/dash/gstdashdemux.c +++ b/ext/dash/gstdashdemux.c @@ -1589,6 +1589,10 @@ gst_dash_demux_stream_advance_sync_sample (GstAdaptiveDemuxStream * stream, (target_time - dashstream->current_fragment_timestamp) / dashstream->current_fragment_keyframe_distance; + + /* Prevent getting stuck in a loop due to rounding errors */ + if (idx == dashstream->current_sync_sample) + idx++; } else { GstClockTime end_time = dashstream->current_fragment_timestamp + @@ -1607,6 +1611,17 @@ gst_dash_demux_stream_advance_sync_sample (GstAdaptiveDemuxStream * stream, } idx = dashstream->moof_sync_samples->len - 1 - idx; } + + /* Prevent getting stuck in a loop due to rounding errors */ + if (idx == dashstream->current_sync_sample) { + if (idx == 0) { + dashstream->current_sync_sample = -1; + fragment_finished = TRUE; + goto beach; + } + + idx--; + } } } @@ -1839,6 +1854,7 @@ gst_dash_demux_stream_advance_fragment (GstAdaptiveDemuxStream * stream) GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (stream->demux); GstClockTime target_time = GST_CLOCK_TIME_NONE; GstClockTime actual_ts; + GstClockTime previous_position; GstFlowReturn ret; GST_DEBUG_OBJECT (stream->pad, "Advance fragment"); @@ -1872,6 +1888,8 @@ gst_dash_demux_stream_advance_fragment (GstAdaptiveDemuxStream * stream) GST_TIME_ARGS (dashstream->average_download_time)); } + previous_position = dashstream->actual_position; + /* Update internal position */ if (GST_CLOCK_TIME_IS_VALID (dashstream->actual_position)) { GstClockTime dur; @@ -1948,19 +1966,56 @@ gst_dash_demux_stream_advance_fragment (GstAdaptiveDemuxStream * stream) if (GST_CLOCK_TIME_IS_VALID (target_time) && GST_ADAPTIVE_DEMUX_IN_TRICKMODE_KEY_UNITS (stream->demux) && dashstream->active_stream->mimeType == GST_STREAM_VIDEO) { - /* Key-unit trick mode, seek to fragment containing target time */ - if (stream->segment.rate > 0) - ret = gst_dash_demux_stream_seek (stream, TRUE, GST_SEEK_FLAG_SNAP_AFTER, + GstClockTime actual_ts; + GstSeekFlags flags = 0; + + /* Key-unit trick mode, seek to fragment containing target time + * + * We first try seeking without snapping. As above code to skip keyframes + * in the current fragment was not successful, we should go at least one + * fragment ahead. Due to rounding errors we could end up at the same + * fragment again here, in which case we retry seeking with the SNAP_AFTER + * flag. + * + * We don't always set that flag as we would then end up one further + * fragment in the future in all good cases. + */ + while (TRUE) { + ret = + gst_dash_demux_stream_seek (stream, (stream->segment.rate > 0), flags, target_time, &actual_ts); - else - ret = gst_dash_demux_stream_seek (stream, FALSE, GST_SEEK_FLAG_SNAP_AFTER, - target_time, &actual_ts); - if (ret == GST_FLOW_OK) - GST_DEBUG_OBJECT (stream->pad, "Emergency seek to %" GST_TIME_FORMAT, - GST_TIME_ARGS (actual_ts)); - else - GST_WARNING_OBJECT (stream->pad, "Failed to seek to %" GST_TIME_FORMAT, - GST_TIME_ARGS (target_time)); + + if (ret != GST_FLOW_OK) { + GST_WARNING_OBJECT (stream->pad, "Failed to seek to %" GST_TIME_FORMAT, + GST_TIME_ARGS (target_time)); + /* Give up */ + if (flags != 0) + break; + + /* Retry with skipping ahead */ + flags |= GST_SEEK_FLAG_SNAP_AFTER; + continue; + } + + GST_DEBUG_OBJECT (stream->pad, + "Skipped to %" GST_TIME_FORMAT " (wanted %" GST_TIME_FORMAT ")", + GST_TIME_ARGS (actual_ts), GST_TIME_ARGS (target_time)); + + if ((stream->segment.rate > 0 && actual_ts < previous_position) || + (stream->segment.rate < 0 && actual_ts > previous_position)) { + /* Give up */ + if (flags != 0) + break; + + /* Retry with forcing skipping ahead */ + flags |= GST_SEEK_FLAG_SNAP_AFTER; + + continue; + } + + /* All good */ + break; + } } else { /* Normal mode, advance to the next fragment */ ret = gst_mpd_client_advance_segment (dashdemux->client,