Commit c1998da4 by aquilescanta Committed by Oliver Woodman

Fix missing error handling durations in HLS

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=208023954
parent d5c7bff6
...@@ -32,7 +32,6 @@ import com.google.android.exoplayer2.trackselection.BaseTrackSelection; ...@@ -32,7 +32,6 @@ import com.google.android.exoplayer2.trackselection.BaseTrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec; 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.upstream.TransferListener;
import com.google.android.exoplayer2.util.TimestampAdjuster; import com.google.android.exoplayer2.util.TimestampAdjuster;
import com.google.android.exoplayer2.util.UriUtil; import com.google.android.exoplayer2.util.UriUtil;
...@@ -414,10 +413,11 @@ import java.util.List; ...@@ -414,10 +413,11 @@ import java.util.List;
* Called when a playlist load encounters an error. * Called when a playlist load encounters an error.
* *
* @param url The url of the playlist whose load encountered 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. * @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); int trackGroupIndex = trackGroup.indexOf(url.format);
if (trackGroupIndex == C.INDEX_UNSET) { if (trackGroupIndex == C.INDEX_UNSET) {
return true; return true;
...@@ -427,9 +427,8 @@ import java.util.List; ...@@ -427,9 +427,8 @@ import java.util.List;
return true; return true;
} }
seenExpectedPlaylistError |= expectedPlaylistUrl == url; seenExpectedPlaylistError |= expectedPlaylistUrl == url;
return !shouldBlacklist return blacklistDurationMs == C.TIME_UNSET
|| trackSelection.blacklist( || trackSelection.blacklist(trackSelectionIndex, blacklistDurationMs);
trackSelectionIndex, DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_BLACKLIST_MS);
} }
// Private methods. // Private methods.
......
...@@ -330,10 +330,10 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper ...@@ -330,10 +330,10 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
} }
@Override @Override
public boolean onPlaylistError(HlsUrl url, boolean shouldBlacklist) { public boolean onPlaylistError(HlsUrl url, long blacklistDurationMs) {
boolean noBlacklistingFailure = true; boolean noBlacklistingFailure = true;
for (HlsSampleStreamWrapper streamWrapper : sampleStreamWrappers) { for (HlsSampleStreamWrapper streamWrapper : sampleStreamWrappers) {
noBlacklistingFailure &= streamWrapper.onPlaylistError(url, shouldBlacklist); noBlacklistingFailure &= streamWrapper.onPlaylistError(url, blacklistDurationMs);
} }
callback.onContinueLoadingRequested(this); callback.onContinueLoadingRequested(this);
return noBlacklistingFailure; return noBlacklistingFailure;
......
...@@ -416,8 +416,8 @@ import java.util.List; ...@@ -416,8 +416,8 @@ import java.util.List;
chunkSource.setIsTimestampMaster(isTimestampMaster); chunkSource.setIsTimestampMaster(isTimestampMaster);
} }
public boolean onPlaylistError(HlsUrl url, boolean shouldBlacklist) { public boolean onPlaylistError(HlsUrl url, long blacklistDurationMs) {
return chunkSource.onPlaylistError(url, shouldBlacklist); return chunkSource.onPlaylistError(url, blacklistDurationMs);
} }
// SampleStream implementation. // SampleStream implementation.
......
...@@ -25,7 +25,6 @@ import com.google.android.exoplayer2.source.hls.HlsDataSourceFactory; ...@@ -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.HlsMasterPlaylist.HlsUrl;
import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Segment; import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Segment;
import com.google.android.exoplayer2.upstream.DataSource; 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.LoadErrorHandlingPolicy;
import com.google.android.exoplayer2.upstream.Loader; import com.google.android.exoplayer2.upstream.Loader;
import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction; import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction;
...@@ -208,7 +207,7 @@ public final class DefaultHlsPlaylistTracker ...@@ -208,7 +207,7 @@ public final class DefaultHlsPlaylistTracker
MediaPlaylistBundle primaryBundle = playlistBundles.get(primaryHlsUrl); MediaPlaylistBundle primaryBundle = playlistBundles.get(primaryHlsUrl);
if (isMediaPlaylist) { if (isMediaPlaylist) {
// We don't need to load the playlist again. We can use the same result. // 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 { } else {
primaryBundle.loadPlaylist(); primaryBundle.loadPlaylist();
} }
...@@ -321,11 +320,11 @@ public final class DefaultHlsPlaylistTracker ...@@ -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(); int listenersSize = listeners.size();
boolean anyBlacklistingFailed = false; boolean anyBlacklistingFailed = false;
for (int i = 0; i < listenersSize; i++) { for (int i = 0; i < listenersSize; i++) {
anyBlacklistingFailed |= !listeners.get(i).onPlaylistError(playlistUrl, shouldBlacklist); anyBlacklistingFailed |= !listeners.get(i).onPlaylistError(playlistUrl, blacklistDurationMs);
} }
return anyBlacklistingFailed; return anyBlacklistingFailed;
} }
...@@ -473,7 +472,7 @@ public final class DefaultHlsPlaylistTracker ...@@ -473,7 +472,7 @@ public final class DefaultHlsPlaylistTracker
ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs, long loadDurationMs) { ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs, long loadDurationMs) {
HlsPlaylist result = loadable.getResult(); HlsPlaylist result = loadable.getResult();
if (result instanceof HlsMediaPlaylist) { if (result instanceof HlsMediaPlaylist) {
processLoadedPlaylist((HlsMediaPlaylist) result); processLoadedPlaylist((HlsMediaPlaylist) result, loadDurationMs);
eventDispatcher.loadCompleted( eventDispatcher.loadCompleted(
loadable.dataSpec, loadable.dataSpec,
loadable.getUri(), loadable.getUri(),
...@@ -516,9 +515,9 @@ public final class DefaultHlsPlaylistTracker ...@@ -516,9 +515,9 @@ public final class DefaultHlsPlaylistTracker
boolean shouldBlacklist = blacklistDurationMs != C.TIME_UNSET; boolean shouldBlacklist = blacklistDurationMs != C.TIME_UNSET;
boolean blacklistingFailed = boolean blacklistingFailed =
notifyPlaylistError(playlistUrl, shouldBlacklist) || !shouldBlacklist; notifyPlaylistError(playlistUrl, blacklistDurationMs) || !shouldBlacklist;
if (shouldBlacklist) { if (shouldBlacklist) {
blacklistingFailed |= blacklistPlaylist(); blacklistingFailed |= blacklistPlaylist(blacklistDurationMs);
} }
if (blacklistingFailed) { if (blacklistingFailed) {
...@@ -569,7 +568,7 @@ public final class DefaultHlsPlaylistTracker ...@@ -569,7 +568,7 @@ public final class DefaultHlsPlaylistTracker
elapsedRealtime); 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. // Update the loaded playlist with any inheritable information from the master playlist.
loadedPlaylist = loadedPlaylist.copyWithMasterPlaylistInfo(masterPlaylist); loadedPlaylist = loadedPlaylist.copyWithMasterPlaylistInfo(masterPlaylist);
...@@ -585,17 +584,22 @@ public final class DefaultHlsPlaylistTracker ...@@ -585,17 +584,22 @@ public final class DefaultHlsPlaylistTracker
if (loadedPlaylist.mediaSequence + loadedPlaylist.segments.size() if (loadedPlaylist.mediaSequence + loadedPlaylist.segments.size()
< playlistSnapshot.mediaSequence) { < playlistSnapshot.mediaSequence) {
// TODO: Allow customization of playlist resets handling. // 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); playlistError = new PlaylistResetException(playlistUrl.url);
notifyPlaylistError(playlistUrl, false); notifyPlaylistError(playlistUrl, C.TIME_UNSET);
} else if (currentTimeMs - lastSnapshotChangeMs } else if (currentTimeMs - lastSnapshotChangeMs
> C.usToMs(playlistSnapshot.targetDurationUs) > C.usToMs(playlistSnapshot.targetDurationUs)
* PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT) { * PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT) {
// TODO: Allow customization of stuck playlists handling. // TODO: Allow customization of stuck playlists handling.
// The playlist seems to be stuck. Blacklist it.
playlistError = new PlaylistStuckException(playlistUrl.url); playlistError = new PlaylistStuckException(playlistUrl.url);
notifyPlaylistError(playlistUrl, true); long blacklistDurationMs =
blacklistPlaylist(); 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 // 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 ...@@ -617,11 +621,12 @@ public final class DefaultHlsPlaylistTracker
/** /**
* Blacklists the playlist. * 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. * @return Whether the playlist is the primary, despite being blacklisted.
*/ */
private boolean blacklistPlaylist() { private boolean blacklistPlaylist(long blacklistDurationMs) {
blacklistUntilMs = blacklistUntilMs = SystemClock.elapsedRealtime() + blacklistDurationMs;
SystemClock.elapsedRealtime() + DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_BLACKLIST_MS;
return primaryHlsUrl == playlistUrl && !maybeSelectNewPrimaryUrl(); return primaryHlsUrl == playlistUrl && !maybeSelectNewPrimaryUrl();
} }
} }
......
...@@ -59,10 +59,11 @@ public interface HlsPlaylistTracker { ...@@ -59,10 +59,11 @@ public interface HlsPlaylistTracker {
* Called if an error is encountered while loading a playlist. * Called if an error is encountered while loading a playlist.
* *
* @param url The loaded url that caused the error. * @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. * @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. */ /** Thrown when a playlist is considered to be stuck due to a server side error. */
......
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