From f735a86ebbb57b33dad2edfe4adb949ccb7f32ec Mon Sep 17 00:00:00 2001 From: olly Date: Wed, 4 Jan 2017 08:13:05 -0800 Subject: [PATCH] Better handle inconsistent HLS timeline updates Issue: #2249 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=143555467 --- .../source/hls/playlist/HlsMediaPlaylist.java | 45 +++++++++++++++-- .../hls/playlist/HlsPlaylistTracker.java | 48 ++++++++++--------- 2 files changed, 67 insertions(+), 26 deletions(-) diff --git a/library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java b/library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java index fc70ec6de1..4f30e018ae 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java @@ -96,19 +96,58 @@ public final class HlsMediaPlaylist extends HlsPlaylist { } } + /** + * Returns whether this playlist is newer than {@code other}. + * + * @param other The playlist to compare. + * @return Whether this playlist is newer than {@code other}. + */ public boolean isNewerThan(HlsMediaPlaylist other) { - return other == null || mediaSequence > other.mediaSequence - || (mediaSequence == other.mediaSequence && segments.size() > other.segments.size()) - || (hasEndTag && !other.hasEndTag); + if (other == null || mediaSequence > other.mediaSequence) { + return true; + } + if (mediaSequence < other.mediaSequence) { + return false; + } + // The media sequences are equal. + int segmentCount = segments.size(); + int otherSegmentCount = other.segments.size(); + return segmentCount > otherSegmentCount + || (segmentCount == otherSegmentCount && hasEndTag && !other.hasEndTag); } public long getEndTimeUs() { return startTimeUs + durationUs; } + /** + * Returns a playlist identical to this one except for the start time, which is set to the + * specified value. If the start time already equals the specified value then the playlist will + * return itself. + * + * @param startTimeUs The start time for the returned playlist. + * @return The playlist. + */ public HlsMediaPlaylist copyWithStartTimeUs(long startTimeUs) { + if (this.startTimeUs == startTimeUs) { + return this; + } return new HlsMediaPlaylist(baseUri, startTimeUs, mediaSequence, version, targetDurationUs, hasEndTag, hasProgramDateTime, initializationSegment, segments); } + /** + * Returns a playlist identical to this one except that an end tag is added. If an end tag is + * already present then the playlist will return itself. + * + * @return The playlist. + */ + public HlsMediaPlaylist copyWithEndTag() { + if (this.hasEndTag) { + return this; + } + return new HlsMediaPlaylist(baseUri, startTimeUs, mediaSequence, version, targetDurationUs, + true, hasProgramDateTime, initializationSegment, segments); + } + } diff --git a/library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java b/library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java index d25e5b1d9c..711854b277 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java @@ -334,16 +334,18 @@ public final class HlsPlaylistTracker implements Loader.Callback oldSegments = oldPlaylist.segments; int oldPlaylistSize = oldSegments.size(); - if (!newPlaylist.isNewerThan(oldPlaylist)) { - // Playlist has not changed. - return oldPlaylist; - } - int mediaSequenceOffset = newPlaylist.mediaSequence - oldPlaylist.mediaSequence; + int mediaSequenceOffset = loadedPlaylist.mediaSequence - oldPlaylist.mediaSequence; if (mediaSequenceOffset <= oldPlaylistSize) { long adjustedNewPlaylistStartTimeUs = mediaSequenceOffset == oldPlaylistSize ? oldPlaylist.getEndTimeUs() : oldPlaylist.startTimeUs + oldSegments.get(mediaSequenceOffset).relativeStartTimeUs; - return newPlaylist.copyWithStartTimeUs(adjustedNewPlaylistStartTimeUs); + return loadedPlaylist.copyWithStartTimeUs(adjustedNewPlaylistStartTimeUs); } // No segments overlap, we assume the new playlist start coincides with the primary playlist. - return newPlaylist.copyWithStartTimeUs(primarySnapshotStartTimeUs); + return loadedPlaylist.copyWithStartTimeUs(primarySnapshotStartTimeUs); } /** @@ -460,15 +462,15 @@ public final class HlsPlaylistTracker implements Loader.Callback