From 324339b88f18da30817e69218bc93be8dea51661 Mon Sep 17 00:00:00 2001 From: hoangtc Date: Tue, 7 Mar 2017 05:42:33 +0000 Subject: [PATCH] Tweak live-streaming track selection logic. Follow-up on the update to ABR logic in AdaptiveTrackSelection for live streaming case: - Do not reset liveEdgeTimeUs when user seek to a different position. - For HlsChunkSource, for non-independent segments, currently the bufferedDuration calculate will subtract previousChunk's duration. So to make it work with live-streaming ABR logic, we subtract timeToLiveEdgeUs a similar amount to compensate for that operation. - Minor update to DefaultSSChunkSource, only perform TrackSelection when needed (after checking necessary conditions). ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=169531275 --- .../source/dash/DefaultDashChunkSource.java | 7 +++-- .../exoplayer2/source/hls/HlsChunkSource.java | 27 ++++++++++++------- .../smoothstreaming/DefaultSsChunkSource.java | 12 +++------ 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java index eba36e9057..732934515b 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java @@ -181,7 +181,7 @@ public class DefaultDashChunkSource implements DashChunkSource { } long bufferedDurationUs = previous != null ? (previous.endTimeUs - playbackPositionUs) : 0; - long timeToLiveEdgeUs = resolveTimeToLiveEdgeUs(playbackPositionUs, previous == null); + long timeToLiveEdgeUs = resolveTimeToLiveEdgeUs(playbackPositionUs); trackSelection.updateSelectedTrack(bufferedDurationUs, timeToLiveEdgeUs); RepresentationHolder representationHolder = @@ -385,9 +385,8 @@ public class DefaultDashChunkSource implements DashChunkSource { } } - private long resolveTimeToLiveEdgeUs(long playbackPositionUs, boolean isAfterPositionReset) { - boolean resolveTimeToLiveEdgePossible = manifest.dynamic - && !isAfterPositionReset && liveEdgeTimeUs != C.TIME_UNSET; + private long resolveTimeToLiveEdgeUs(long playbackPositionUs) { + boolean resolveTimeToLiveEdgePossible = manifest.dynamic && liveEdgeTimeUs != C.TIME_UNSET; return resolveTimeToLiveEdgePossible ? liveEdgeTimeUs - playbackPositionUs : C.TIME_UNSET; } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java index a5688e8bc5..8aa4e057a2 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java @@ -209,14 +209,24 @@ import java.util.List; int oldVariantIndex = previous == null ? C.INDEX_UNSET : trackGroup.indexOf(previous.trackFormat); expectedPlaylistUrl = null; - // Unless segments are known to be independent, switching variant will require downloading - // overlapping segments. Hence we use the start time of the previous chunk rather than its end - // time for this case. - long bufferedDurationUs = previous == null ? 0 : Math.max(0, - (independentSegments ? previous.endTimeUs : previous.startTimeUs) - playbackPositionUs); + long bufferedDurationUs = previous == null ? 0 : previous.endTimeUs - playbackPositionUs; + + long timeToLiveEdgeUs = resolveTimeToLiveEdgeUs(playbackPositionUs); + if (previous != null && !independentSegments) { + // Unless segments are known to be independent, switching variant will require downloading + // overlapping segments. Hence we will subtract previous chunk's duration from buffered + // duration. + // This may affect the live-streaming adaptive track selection logic, when we are comparing + // buffered duration to time to live edge to decide whether to switch. Therefore, + // we will subtract this same amount from timeToLiveEdgeUs as well. + long subtractedDurationUs = previous.getDurationUs(); + bufferedDurationUs = Math.max(0, bufferedDurationUs - subtractedDurationUs); + if (timeToLiveEdgeUs != C.TIME_UNSET) { + timeToLiveEdgeUs = Math.max(0, timeToLiveEdgeUs - subtractedDurationUs); + } + } // Select the variant. - long timeToLiveEdgeUs = resolveTimeToLiveEdgeUs(playbackPositionUs, previous == null); trackSelection.updateSelectedTrack(bufferedDurationUs, timeToLiveEdgeUs); int selectedVariantIndex = trackSelection.getSelectedIndexInTrackGroup(); @@ -365,9 +375,8 @@ import java.util.List; // Private methods. - private long resolveTimeToLiveEdgeUs(long playbackPositionUs, boolean isAfterPositionReset) { - final boolean resolveTimeToLiveEdgePossible = !isAfterPositionReset - && liveEdgeTimeUs != C.TIME_UNSET; + private long resolveTimeToLiveEdgeUs(long playbackPositionUs) { + final boolean resolveTimeToLiveEdgePossible = liveEdgeTimeUs != C.TIME_UNSET; return resolveTimeToLiveEdgePossible ? liveEdgeTimeUs - playbackPositionUs : C.TIME_UNSET; } diff --git a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java index cbd6db04af..d9743649c5 100644 --- a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java +++ b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java @@ -154,10 +154,6 @@ public class DefaultSsChunkSource implements SsChunkSource { return; } - long bufferedDurationUs = previous != null ? (previous.endTimeUs - playbackPositionUs) : 0; - long timeToLiveEdgeUs = resolveTimeToLiveEdgeUs(playbackPositionUs); - trackSelection.updateSelectedTrack(bufferedDurationUs, timeToLiveEdgeUs); - StreamElement streamElement = manifest.streamElements[elementIndex]; if (streamElement.chunkCount == 0) { // There aren't any chunks for us to load. @@ -183,6 +179,10 @@ public class DefaultSsChunkSource implements SsChunkSource { return; } + long bufferedDurationUs = previous != null ? (previous.endTimeUs - playbackPositionUs) : 0; + long timeToLiveEdgeUs = resolveTimeToLiveEdgeUs(playbackPositionUs); + trackSelection.updateSelectedTrack(bufferedDurationUs, timeToLiveEdgeUs); + long chunkStartTimeUs = streamElement.getStartTimeUs(chunkIndex); long chunkEndTimeUs = chunkStartTimeUs + streamElement.getChunkDurationUs(chunkIndex); int currentAbsoluteChunkIndex = chunkIndex + currentManifestChunkOffset; @@ -229,10 +229,6 @@ public class DefaultSsChunkSource implements SsChunkSource { } StreamElement currentElement = manifest.streamElements[elementIndex]; - if (currentElement.chunkCount == 0) { - return C.TIME_UNSET; - } - int lastChunkIndex = currentElement.chunkCount - 1; long lastChunkEndTimeUs = currentElement.getStartTimeUs(lastChunkIndex) + currentElement.getChunkDurationUs(lastChunkIndex);