Commit a3be9376 by olly Committed by Oliver Woodman

Prevent unnecessary consecutive playlist loads

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=170078933
parent 792f046c
...@@ -363,9 +363,8 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable ...@@ -363,9 +363,8 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
* *
* @param url The url of the playlist. * @param url The url of the playlist.
* @param newSnapshot The new snapshot. * @param newSnapshot The new snapshot.
* @return True if a refresh should be scheduled.
*/ */
private boolean onPlaylistUpdated(HlsUrl url, HlsMediaPlaylist newSnapshot) { private void onPlaylistUpdated(HlsUrl url, HlsMediaPlaylist newSnapshot) {
if (url == primaryHlsUrl) { if (url == primaryHlsUrl) {
if (primaryUrlSnapshot == null) { if (primaryUrlSnapshot == null) {
// This is the first primary url snapshot. // This is the first primary url snapshot.
...@@ -378,8 +377,6 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable ...@@ -378,8 +377,6 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
for (int i = 0; i < listenersSize; i++) { for (int i = 0; i < listenersSize; i++) {
listeners.get(i).onPlaylistChanged(); listeners.get(i).onPlaylistChanged();
} }
// If the primary playlist is not the final one, we should schedule a refresh.
return url == primaryHlsUrl && !newSnapshot.hasEndTag;
} }
private void notifyPlaylistBlacklisting(HlsUrl url, long blacklistMs) { private void notifyPlaylistBlacklisting(HlsUrl url, long blacklistMs) {
...@@ -469,8 +466,9 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable ...@@ -469,8 +466,9 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
private HlsMediaPlaylist playlistSnapshot; private HlsMediaPlaylist playlistSnapshot;
private long lastSnapshotLoadMs; private long lastSnapshotLoadMs;
private long lastSnapshotChangeMs; private long lastSnapshotChangeMs;
private long earliestNextLoadTimeMs;
private long blacklistUntilMs; private long blacklistUntilMs;
private boolean pendingRefresh; private boolean loadPending;
private IOException playlistError; private IOException playlistError;
public MediaPlaylistBundle(HlsUrl playlistUrl) { public MediaPlaylistBundle(HlsUrl playlistUrl) {
...@@ -504,8 +502,16 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable ...@@ -504,8 +502,16 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
public void loadPlaylist() { public void loadPlaylist() {
blacklistUntilMs = 0; blacklistUntilMs = 0;
if (!pendingRefresh && !mediaPlaylistLoader.isLoading()) { if (loadPending || mediaPlaylistLoader.isLoading()) {
mediaPlaylistLoader.startLoading(mediaPlaylistLoadable, this, minRetryCount); // Load already pending or in progress. Do nothing.
return;
}
long currentTimeMs = SystemClock.elapsedRealtime();
if (currentTimeMs < earliestNextLoadTimeMs) {
loadPending = true;
playlistRefreshHandler.postDelayed(this, earliestNextLoadTimeMs - currentTimeMs);
} else {
loadPlaylistImmediately();
} }
} }
...@@ -549,8 +555,7 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable ...@@ -549,8 +555,7 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
} }
boolean shouldRetry = true; boolean shouldRetry = true;
if (ChunkedTrackBlacklistUtil.shouldBlacklist(error)) { if (ChunkedTrackBlacklistUtil.shouldBlacklist(error)) {
blacklistPlaylist(); shouldRetry = blacklistPlaylist();
shouldRetry = primaryHlsUrl == playlistUrl && !maybeSelectNewPrimaryUrl();
} }
return shouldRetry ? Loader.RETRY : Loader.DONT_RETRY; return shouldRetry ? Loader.RETRY : Loader.DONT_RETRY;
} }
...@@ -559,48 +564,60 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable ...@@ -559,48 +564,60 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
@Override @Override
public void run() { public void run() {
pendingRefresh = false; loadPending = false;
loadPlaylist(); loadPlaylistImmediately();
} }
// Internal methods. // Internal methods.
private void loadPlaylistImmediately() {
mediaPlaylistLoader.startLoading(mediaPlaylistLoadable, this, minRetryCount);
}
private void processLoadedPlaylist(HlsMediaPlaylist loadedPlaylist) { private void processLoadedPlaylist(HlsMediaPlaylist loadedPlaylist) {
HlsMediaPlaylist oldPlaylist = playlistSnapshot; HlsMediaPlaylist oldPlaylist = playlistSnapshot;
long currentTimeMs = SystemClock.elapsedRealtime(); long currentTimeMs = SystemClock.elapsedRealtime();
lastSnapshotLoadMs = currentTimeMs; lastSnapshotLoadMs = currentTimeMs;
playlistSnapshot = getLatestPlaylistSnapshot(oldPlaylist, loadedPlaylist); playlistSnapshot = getLatestPlaylistSnapshot(oldPlaylist, loadedPlaylist);
long refreshDelayUs = C.TIME_UNSET;
if (playlistSnapshot != oldPlaylist) { if (playlistSnapshot != oldPlaylist) {
playlistError = null; playlistError = null;
lastSnapshotChangeMs = currentTimeMs; lastSnapshotChangeMs = currentTimeMs;
if (onPlaylistUpdated(playlistUrl, playlistSnapshot)) { onPlaylistUpdated(playlistUrl, playlistSnapshot);
refreshDelayUs = playlistSnapshot.targetDurationUs;
}
} else if (!playlistSnapshot.hasEndTag) { } else if (!playlistSnapshot.hasEndTag) {
if (currentTimeMs - lastSnapshotChangeMs if (loadedPlaylist.mediaSequence + loadedPlaylist.segments.size()
< playlistSnapshot.mediaSequence) {
// The media sequence jumped backwards. The server has probably reset.
playlistError = new PlaylistResetException(playlistUrl.url);
} else if (currentTimeMs - lastSnapshotChangeMs
> C.usToMs(playlistSnapshot.targetDurationUs) > C.usToMs(playlistSnapshot.targetDurationUs)
* PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT) { * PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT) {
// The playlist seems to be stuck, we blacklist it. // The playlist seems to be stuck. Blacklist it.
playlistError = new PlaylistStuckException(playlistUrl.url); playlistError = new PlaylistStuckException(playlistUrl.url);
blacklistPlaylist(); blacklistPlaylist();
} else if (loadedPlaylist.mediaSequence + loadedPlaylist.segments.size()
< playlistSnapshot.mediaSequence) {
// The media sequence has jumped backwards. The server has likely reset.
playlistError = new PlaylistResetException(playlistUrl.url);
} }
refreshDelayUs = playlistSnapshot.targetDurationUs / 2;
} }
if (refreshDelayUs != C.TIME_UNSET) { // Do not allow the playlist to load again within the target duration if we obtained a new
// See HLS spec v20, section 6.3.4 for more information on media playlist refreshing. // snapshot, or half the target duration otherwise.
pendingRefresh = playlistRefreshHandler.postDelayed(this, C.usToMs(refreshDelayUs)); earliestNextLoadTimeMs = currentTimeMs + C.usToMs(playlistSnapshot != oldPlaylist
? playlistSnapshot.targetDurationUs : (playlistSnapshot.targetDurationUs / 2));
// Schedule a load if this is the primary playlist and it doesn't have an end tag. Else the
// next load will be scheduled when refreshPlaylist is called, or when this playlist becomes
// the primary.
if (playlistUrl == primaryHlsUrl && !playlistSnapshot.hasEndTag) {
loadPlaylist();
} }
} }
private void blacklistPlaylist() { /**
* Blacklists the playlist.
*
* @return Whether the playlist is the primary, despite being blacklisted.
*/
private boolean blacklistPlaylist() {
blacklistUntilMs = SystemClock.elapsedRealtime() blacklistUntilMs = SystemClock.elapsedRealtime()
+ ChunkedTrackBlacklistUtil.DEFAULT_TRACK_BLACKLIST_MS; + ChunkedTrackBlacklistUtil.DEFAULT_TRACK_BLACKLIST_MS;
notifyPlaylistBlacklisting(playlistUrl, ChunkedTrackBlacklistUtil.DEFAULT_TRACK_BLACKLIST_MS); notifyPlaylistBlacklisting(playlistUrl, ChunkedTrackBlacklistUtil.DEFAULT_TRACK_BLACKLIST_MS);
return primaryHlsUrl == playlistUrl && !maybeSelectNewPrimaryUrl();
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment