summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian@centricular.com>2017-04-03 15:48:13 +0300
committerEdward Hervey <bilboed@bilboed.com>2017-05-15 18:12:35 +0200
commit979d6719d39c2eaf6f1e08c598b928e64cd31a30 (patch)
treee9d6afed95878fdf4594b67c8a706d5ecc847066
parentcae7340ab1bb9b0dd39f388ca9093d8a3eb942ca (diff)
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.
-rw-r--r--ext/dash/gstdashdemux.c79
1 files changed, 67 insertions, 12 deletions
diff --git a/ext/dash/gstdashdemux.c b/ext/dash/gstdashdemux.c
index 4626bf30b..44214185b 100644
--- a/ext/dash/gstdashdemux.c
+++ b/ext/dash/gstdashdemux.c
@@ -1588,6 +1588,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 +
@@ -1606,6 +1610,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--;
+ }
}
}
@@ -1838,6 +1853,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");
@@ -1871,6 +1887,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;
@@ -1947,19 +1965,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,
- target_time, &actual_ts);
- else
- ret = gst_dash_demux_stream_seek (stream, FALSE, 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);
- 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,