Fix missing error handling durations in HLS

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=208023954
This commit is contained in:
aquilescanta 2018-08-09 03:39:33 -07:00 committed by Oliver Woodman
parent d5c7bff643
commit c1998da44e
5 changed files with 33 additions and 28 deletions

View file

@ -32,7 +32,6 @@ import com.google.android.exoplayer2.trackselection.BaseTrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.TimestampAdjuster;
import com.google.android.exoplayer2.util.UriUtil;
@ -414,10 +413,11 @@ import java.util.List;
* Called when a playlist load encounters an error.
*
* @param url The url of the playlist whose load encountered an error.
* @param shouldBlacklist Whether the playlist should be blacklisted.
* @param blacklistDurationMs The duration for which the playlist should be blacklisted. Or {@link
* C#TIME_UNSET} if the playlist should not be blacklisted.
* @return True if blacklisting did not encounter errors. False otherwise.
*/
public boolean onPlaylistError(HlsUrl url, boolean shouldBlacklist) {
public boolean onPlaylistError(HlsUrl url, long blacklistDurationMs) {
int trackGroupIndex = trackGroup.indexOf(url.format);
if (trackGroupIndex == C.INDEX_UNSET) {
return true;
@ -427,9 +427,8 @@ import java.util.List;
return true;
}
seenExpectedPlaylistError |= expectedPlaylistUrl == url;
return !shouldBlacklist
|| trackSelection.blacklist(
trackSelectionIndex, DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_BLACKLIST_MS);
return blacklistDurationMs == C.TIME_UNSET
|| trackSelection.blacklist(trackSelectionIndex, blacklistDurationMs);
}
// Private methods.

View file

@ -330,10 +330,10 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
}
@Override
public boolean onPlaylistError(HlsUrl url, boolean shouldBlacklist) {
public boolean onPlaylistError(HlsUrl url, long blacklistDurationMs) {
boolean noBlacklistingFailure = true;
for (HlsSampleStreamWrapper streamWrapper : sampleStreamWrappers) {
noBlacklistingFailure &= streamWrapper.onPlaylistError(url, shouldBlacklist);
noBlacklistingFailure &= streamWrapper.onPlaylistError(url, blacklistDurationMs);
}
callback.onContinueLoadingRequested(this);
return noBlacklistingFailure;

View file

@ -416,8 +416,8 @@ import java.util.List;
chunkSource.setIsTimestampMaster(isTimestampMaster);
}
public boolean onPlaylistError(HlsUrl url, boolean shouldBlacklist) {
return chunkSource.onPlaylistError(url, shouldBlacklist);
public boolean onPlaylistError(HlsUrl url, long blacklistDurationMs) {
return chunkSource.onPlaylistError(url, blacklistDurationMs);
}
// SampleStream implementation.

View file

@ -25,7 +25,6 @@ import com.google.android.exoplayer2.source.hls.HlsDataSourceFactory;
import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.HlsUrl;
import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Segment;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy;
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
import com.google.android.exoplayer2.upstream.Loader;
import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction;
@ -208,7 +207,7 @@ public final class DefaultHlsPlaylistTracker
MediaPlaylistBundle primaryBundle = playlistBundles.get(primaryHlsUrl);
if (isMediaPlaylist) {
// We don't need to load the playlist again. We can use the same result.
primaryBundle.processLoadedPlaylist((HlsMediaPlaylist) result);
primaryBundle.processLoadedPlaylist((HlsMediaPlaylist) result, loadDurationMs);
} else {
primaryBundle.loadPlaylist();
}
@ -321,11 +320,11 @@ public final class DefaultHlsPlaylistTracker
}
}
private boolean notifyPlaylistError(HlsUrl playlistUrl, boolean shouldBlacklist) {
private boolean notifyPlaylistError(HlsUrl playlistUrl, long blacklistDurationMs) {
int listenersSize = listeners.size();
boolean anyBlacklistingFailed = false;
for (int i = 0; i < listenersSize; i++) {
anyBlacklistingFailed |= !listeners.get(i).onPlaylistError(playlistUrl, shouldBlacklist);
anyBlacklistingFailed |= !listeners.get(i).onPlaylistError(playlistUrl, blacklistDurationMs);
}
return anyBlacklistingFailed;
}
@ -473,7 +472,7 @@ public final class DefaultHlsPlaylistTracker
ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs, long loadDurationMs) {
HlsPlaylist result = loadable.getResult();
if (result instanceof HlsMediaPlaylist) {
processLoadedPlaylist((HlsMediaPlaylist) result);
processLoadedPlaylist((HlsMediaPlaylist) result, loadDurationMs);
eventDispatcher.loadCompleted(
loadable.dataSpec,
loadable.getUri(),
@ -516,9 +515,9 @@ public final class DefaultHlsPlaylistTracker
boolean shouldBlacklist = blacklistDurationMs != C.TIME_UNSET;
boolean blacklistingFailed =
notifyPlaylistError(playlistUrl, shouldBlacklist) || !shouldBlacklist;
notifyPlaylistError(playlistUrl, blacklistDurationMs) || !shouldBlacklist;
if (shouldBlacklist) {
blacklistingFailed |= blacklistPlaylist();
blacklistingFailed |= blacklistPlaylist(blacklistDurationMs);
}
if (blacklistingFailed) {
@ -569,7 +568,7 @@ public final class DefaultHlsPlaylistTracker
elapsedRealtime);
}
private void processLoadedPlaylist(HlsMediaPlaylist loadedPlaylist) {
private void processLoadedPlaylist(HlsMediaPlaylist loadedPlaylist, long loadDurationMs) {
// Update the loaded playlist with any inheritable information from the master playlist.
loadedPlaylist = loadedPlaylist.copyWithMasterPlaylistInfo(masterPlaylist);
@ -585,17 +584,22 @@ public final class DefaultHlsPlaylistTracker
if (loadedPlaylist.mediaSequence + loadedPlaylist.segments.size()
< playlistSnapshot.mediaSequence) {
// TODO: Allow customization of playlist resets handling.
// The media sequence jumped backwards. The server has probably reset.
// The media sequence jumped backwards. The server has probably reset. We do not try
// blacklisting in this case.
playlistError = new PlaylistResetException(playlistUrl.url);
notifyPlaylistError(playlistUrl, false);
notifyPlaylistError(playlistUrl, C.TIME_UNSET);
} else if (currentTimeMs - lastSnapshotChangeMs
> C.usToMs(playlistSnapshot.targetDurationUs)
* PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT) {
// TODO: Allow customization of stuck playlists handling.
// The playlist seems to be stuck. Blacklist it.
playlistError = new PlaylistStuckException(playlistUrl.url);
notifyPlaylistError(playlistUrl, true);
blacklistPlaylist();
long blacklistDurationMs =
loadErrorHandlingPolicy.getBlacklistDurationMsFor(
C.DATA_TYPE_MANIFEST, loadDurationMs, playlistError, /* errorCount= */ 1);
notifyPlaylistError(playlistUrl, blacklistDurationMs);
if (blacklistDurationMs != C.TIME_UNSET) {
blacklistPlaylist(blacklistDurationMs);
}
}
}
// Do not allow the playlist to load again within the target duration if we obtained a new
@ -617,11 +621,12 @@ public final class DefaultHlsPlaylistTracker
/**
* Blacklists the playlist.
*
* @param blacklistDurationMs The number of milliseconds for which the playlist should be
* blacklisted.
* @return Whether the playlist is the primary, despite being blacklisted.
*/
private boolean blacklistPlaylist() {
blacklistUntilMs =
SystemClock.elapsedRealtime() + DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_BLACKLIST_MS;
private boolean blacklistPlaylist(long blacklistDurationMs) {
blacklistUntilMs = SystemClock.elapsedRealtime() + blacklistDurationMs;
return primaryHlsUrl == playlistUrl && !maybeSelectNewPrimaryUrl();
}
}

View file

@ -59,10 +59,11 @@ public interface HlsPlaylistTracker {
* Called if an error is encountered while loading a playlist.
*
* @param url The loaded url that caused the error.
* @param shouldBlacklist Whether the playlist should be blacklisted.
* @param blacklistDurationMs The duration for which the playlist should be blacklisted. Or
* {@link C#TIME_UNSET} if the playlist should not be blacklisted.
* @return True if blacklisting did not encounter errors. False otherwise.
*/
boolean onPlaylistError(HlsUrl url, boolean shouldBlacklist);
boolean onPlaylistError(HlsUrl url, long blacklistDurationMs);
}
/** Thrown when a playlist is considered to be stuck due to a server side error. */