Add @FallbackType to LoadErrorHandlingPolicy
No-op change that adds the @FallbackType IntDef and changes the signature of getBlacklistDurationMsFor(LoadErrorInfo) to getExclusionDurationMsFor(@FallbackType, LoadErrorInfo). PiperOrigin-RevId: 381075496
This commit is contained in:
parent
75c06cc4e7
commit
ed471fae96
@ -19,6 +19,8 @@
|
||||
`ExoPlaybackException.rendererIndex`).
|
||||
* `PlaybackException` introduces an `errorCode` which identifies the
|
||||
cause of the failure in order to simplify error handling.
|
||||
* Add `@FallbackType` to `LoadErrorHandlingPolicy` to support
|
||||
customization of the exclusion duration for locations and tracks.
|
||||
* Remove deprecated symbols:
|
||||
* Remove `Player.getPlaybackError`. Use `Player.getPlayerError` instead.
|
||||
* Remove `Player.getCurrentTag`. Use `Player.getCurrentMediaItem` and
|
||||
|
@ -518,7 +518,8 @@ public class ChunkSampleStream<T extends ChunkSource>
|
||||
|
||||
long exclusionDurationMs =
|
||||
cancelable
|
||||
? loadErrorHandlingPolicy.getBlacklistDurationMsFor(loadErrorInfo)
|
||||
? loadErrorHandlingPolicy.getExclusionDurationMsFor(
|
||||
LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK, loadErrorInfo)
|
||||
: C.TIME_UNSET;
|
||||
@Nullable LoadErrorAction loadErrorAction = null;
|
||||
if (chunkSource.onChunkLoadError(loadable, cancelable, error, exclusionDurationMs)) {
|
||||
|
@ -36,7 +36,11 @@ public class DefaultLoadErrorHandlingPolicy implements LoadErrorHandlingPolicy {
|
||||
*/
|
||||
public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT_PROGRESSIVE_LIVE = 6;
|
||||
/** The default duration for which a track is excluded in milliseconds. */
|
||||
public static final long DEFAULT_TRACK_BLACKLIST_MS = 60_000;
|
||||
public static final long DEFAULT_TRACK_EXCLUSION_MS = 60_000;
|
||||
/** @deprecated Use {@link #DEFAULT_TRACK_EXCLUSION_MS} instead. */
|
||||
@Deprecated public static final long DEFAULT_TRACK_BLACKLIST_MS = DEFAULT_TRACK_EXCLUSION_MS;
|
||||
/** The default duration for which a location is excluded in milliseconds. */
|
||||
public static final long DEFAULT_LOCATION_EXCLUSION_MS = 5 * 60_000;
|
||||
|
||||
private static final int DEFAULT_BEHAVIOR_MIN_LOADABLE_RETRY_COUNT = -1;
|
||||
|
||||
@ -64,12 +68,14 @@ public class DefaultLoadErrorHandlingPolicy implements LoadErrorHandlingPolicy {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exclusion duration, given by {@link #DEFAULT_TRACK_BLACKLIST_MS}, if the load error
|
||||
* was an {@link InvalidResponseCodeException} with response code HTTP 404, 410 or 416, or {@link
|
||||
* C#TIME_UNSET} otherwise.
|
||||
* Returns the exclusion duration, given by {@link #DEFAULT_TRACK_EXCLUSION_MS} or {@link
|
||||
* #DEFAULT_LOCATION_EXCLUSION_MS}, if the load error was an {@link InvalidResponseCodeException}
|
||||
* with an HTTP response code indicating an unrecoverable error, or {@link C#TIME_UNSET}
|
||||
* otherwise.
|
||||
*/
|
||||
@Override
|
||||
public long getBlacklistDurationMsFor(LoadErrorInfo loadErrorInfo) {
|
||||
public long getExclusionDurationMsFor(
|
||||
@FallbackType int fallbackType, LoadErrorInfo loadErrorInfo) {
|
||||
IOException exception = loadErrorInfo.exception;
|
||||
if (exception instanceof InvalidResponseCodeException) {
|
||||
int responseCode = ((InvalidResponseCodeException) exception).responseCode;
|
||||
@ -79,7 +85,9 @@ public class DefaultLoadErrorHandlingPolicy implements LoadErrorHandlingPolicy {
|
||||
|| responseCode == 416 // HTTP 416 Range Not Satisfiable.
|
||||
|| responseCode == 500 // HTTP 500 Internal Server Error.
|
||||
|| responseCode == 503 // HTTP 503 Service Unavailable.
|
||||
? DEFAULT_TRACK_BLACKLIST_MS
|
||||
? (fallbackType == FALLBACK_TYPE_TRACK
|
||||
? DEFAULT_TRACK_EXCLUSION_MS
|
||||
: DEFAULT_LOCATION_EXCLUSION_MS)
|
||||
: C.TIME_UNSET;
|
||||
}
|
||||
return C.TIME_UNSET;
|
||||
|
@ -15,29 +15,53 @@
|
||||
*/
|
||||
package com.google.android.exoplayer2.upstream;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.source.LoadEventInfo;
|
||||
import com.google.android.exoplayer2.source.MediaLoadData;
|
||||
import com.google.android.exoplayer2.upstream.Loader.Callback;
|
||||
import com.google.android.exoplayer2.upstream.Loader.Loadable;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Defines how errors encountered by loaders are handled.
|
||||
*
|
||||
* <p>A loader that can choose between one of a number of resources can exclude a resource when a
|
||||
* load error occurs. In this case, {@link #getBlacklistDurationMsFor(int, long, IOException, int)}
|
||||
* defines whether the resource should be excluded. Exclusion will succeed unless all of the
|
||||
* alternatives are already excluded.
|
||||
* load error occurs. In this case, {@link #getExclusionDurationMsFor(int, LoadErrorInfo)} defines
|
||||
* whether the resource should be excluded for a given {@link FallbackType fallback type}, and if so
|
||||
* for how long. If the policy indicates that a resource should be excluded, the loader will exclude
|
||||
* it for the specified amount of time unless all of the alternatives for the given fallback type
|
||||
* are already excluded.
|
||||
*
|
||||
* <p>When exclusion does not take place, {@link #getRetryDelayMsFor(int, long, IOException, int)}
|
||||
* defines whether the load is retried. An error that's not retried will always be propagated. An
|
||||
* error that is retried will be propagated according to {@link #getMinimumLoadableRetryCount(int)}.
|
||||
* <p>When exclusion does not take place, {@link #getRetryDelayMsFor(LoadErrorInfo)} defines whether
|
||||
* the load is retried. An error that's not retried will always be propagated. An error that is
|
||||
* retried will be propagated according to {@link #getMinimumLoadableRetryCount(int)}.
|
||||
*
|
||||
* <p>Methods are invoked on the playback thread.
|
||||
*/
|
||||
public interface LoadErrorHandlingPolicy {
|
||||
|
||||
/** Fallback type. One of {@link #FALLBACK_TYPE_LOCATION} or {@link #FALLBACK_TYPE_TRACK}. */
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({FALLBACK_TYPE_LOCATION, FALLBACK_TYPE_TRACK})
|
||||
@interface FallbackType {}
|
||||
|
||||
/**
|
||||
* Fallback type that is using exclusion of locations (i.e., multiple URLs through which the same
|
||||
* data is accessible).
|
||||
*/
|
||||
int FALLBACK_TYPE_LOCATION = 1;
|
||||
/**
|
||||
* Fallback type that is using exclusion of tracks (i.e., multiple URLs through which different
|
||||
* representations of the same content are available; for example the same video encoded at
|
||||
* different bitrates or resolutions).
|
||||
*/
|
||||
int FALLBACK_TYPE_TRACK = 2;
|
||||
|
||||
/** Holds information about a load task error. */
|
||||
final class LoadErrorInfo {
|
||||
|
||||
@ -63,36 +87,17 @@ public interface LoadErrorHandlingPolicy {
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated Implement {@link #getBlacklistDurationMsFor(LoadErrorInfo)} instead. */
|
||||
@Deprecated
|
||||
default long getBlacklistDurationMsFor(
|
||||
int dataType, long loadDurationMs, IOException exception, int errorCount) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of milliseconds for which a resource associated to a provided load error
|
||||
* should be excluded, or {@link C#TIME_UNSET} if the resource should not be excluded.
|
||||
* should be excluded for a given {@link FallbackType fallback type}, or {@link C#TIME_UNSET} if
|
||||
* the resource should not be excluded.
|
||||
*
|
||||
* @param fallbackType The {@link FallbackType fallback type} used for exclusion.
|
||||
* @param loadErrorInfo A {@link LoadErrorInfo} holding information about the load error.
|
||||
* @return The exclusion duration in milliseconds, or {@link C#TIME_UNSET} if the resource should
|
||||
* not be excluded.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
default long getBlacklistDurationMsFor(LoadErrorInfo loadErrorInfo) {
|
||||
return getBlacklistDurationMsFor(
|
||||
loadErrorInfo.mediaLoadData.dataType,
|
||||
loadErrorInfo.loadEventInfo.loadDurationMs,
|
||||
loadErrorInfo.exception,
|
||||
loadErrorInfo.errorCount);
|
||||
}
|
||||
|
||||
/** @deprecated Implement {@link #getRetryDelayMsFor(LoadErrorInfo)} instead. */
|
||||
@Deprecated
|
||||
default long getRetryDelayMsFor(
|
||||
int dataType, long loadDurationMs, IOException exception, int errorCount) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
long getExclusionDurationMsFor(@FallbackType int fallbackType, LoadErrorInfo loadErrorInfo);
|
||||
|
||||
/**
|
||||
* Returns the number of milliseconds to wait before attempting the load again, or {@link
|
||||
@ -106,14 +111,7 @@ public interface LoadErrorHandlingPolicy {
|
||||
* @return The number of milliseconds to wait before attempting the load again, or {@link
|
||||
* C#TIME_UNSET} if the error is fatal and should not be retried.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
default long getRetryDelayMsFor(LoadErrorInfo loadErrorInfo) {
|
||||
return getRetryDelayMsFor(
|
||||
loadErrorInfo.mediaLoadData.dataType,
|
||||
loadErrorInfo.loadEventInfo.loadDurationMs,
|
||||
loadErrorInfo.exception,
|
||||
loadErrorInfo.errorCount);
|
||||
}
|
||||
long getRetryDelayMsFor(LoadErrorInfo loadErrorInfo);
|
||||
|
||||
/**
|
||||
* Called once {@code loadTaskId} will not be associated with any more load errors.
|
||||
|
@ -50,50 +50,50 @@ public final class DefaultLoadErrorHandlingPolicyTest {
|
||||
@Test
|
||||
public void getExclusionDurationMsFor_responseCode403() {
|
||||
InvalidResponseCodeException exception = buildInvalidResponseCodeException(403, "Forbidden");
|
||||
assertThat(getDefaultPolicyExclusionDurationMsFor(exception))
|
||||
.isEqualTo(DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_BLACKLIST_MS);
|
||||
assertThat(getDefaultPolicyTrackExclusionDurationMsFor(exception))
|
||||
.isEqualTo(DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_EXCLUSION_MS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getExclusionDurationMsFor_responseCode404() {
|
||||
InvalidResponseCodeException exception = buildInvalidResponseCodeException(404, "Not found");
|
||||
assertThat(getDefaultPolicyExclusionDurationMsFor(exception))
|
||||
.isEqualTo(DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_BLACKLIST_MS);
|
||||
assertThat(getDefaultPolicyTrackExclusionDurationMsFor(exception))
|
||||
.isEqualTo(DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_EXCLUSION_MS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getExclusionDurationMsFor_responseCode410() {
|
||||
InvalidResponseCodeException exception = buildInvalidResponseCodeException(410, "Gone");
|
||||
assertThat(getDefaultPolicyExclusionDurationMsFor(exception))
|
||||
.isEqualTo(DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_BLACKLIST_MS);
|
||||
assertThat(getDefaultPolicyTrackExclusionDurationMsFor(exception))
|
||||
.isEqualTo(DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_EXCLUSION_MS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getExclusionDurationMsFor_responseCode500() {
|
||||
InvalidResponseCodeException exception =
|
||||
buildInvalidResponseCodeException(500, "Internal server error");
|
||||
assertThat(getDefaultPolicyExclusionDurationMsFor(exception))
|
||||
.isEqualTo(DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_BLACKLIST_MS);
|
||||
assertThat(getDefaultPolicyTrackExclusionDurationMsFor(exception))
|
||||
.isEqualTo(DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_EXCLUSION_MS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getExclusionDurationMsFor_responseCode503() {
|
||||
InvalidResponseCodeException exception =
|
||||
buildInvalidResponseCodeException(503, "Service unavailable");
|
||||
assertThat(getDefaultPolicyExclusionDurationMsFor(exception))
|
||||
.isEqualTo(DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_BLACKLIST_MS);
|
||||
assertThat(getDefaultPolicyTrackExclusionDurationMsFor(exception))
|
||||
.isEqualTo(DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_EXCLUSION_MS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getExclusionDurationMsFor_dontExcludeUnexpectedHttpCodes() {
|
||||
InvalidResponseCodeException exception = buildInvalidResponseCodeException(418, "I'm a teapot");
|
||||
assertThat(getDefaultPolicyExclusionDurationMsFor(exception)).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(getDefaultPolicyTrackExclusionDurationMsFor(exception)).isEqualTo(C.TIME_UNSET);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getExclusionDurationMsFor_dontExcludeUnexpectedExceptions() {
|
||||
IOException exception = new IOException();
|
||||
assertThat(getDefaultPolicyExclusionDurationMsFor(exception)).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(getDefaultPolicyTrackExclusionDurationMsFor(exception)).isEqualTo(C.TIME_UNSET);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -112,14 +112,15 @@ public final class DefaultLoadErrorHandlingPolicyTest {
|
||||
assertThat(getDefaultPolicyRetryDelayOutputFor(new IOException(), 9)).isEqualTo(5000);
|
||||
}
|
||||
|
||||
private static long getDefaultPolicyExclusionDurationMsFor(IOException exception) {
|
||||
private static long getDefaultPolicyTrackExclusionDurationMsFor(IOException exception) {
|
||||
LoadErrorInfo loadErrorInfo =
|
||||
new LoadErrorInfo(
|
||||
PLACEHOLDER_LOAD_EVENT_INFO,
|
||||
PLACEHOLDER_MEDIA_LOAD_DATA,
|
||||
exception,
|
||||
/* errorCount= */ 1);
|
||||
return new DefaultLoadErrorHandlingPolicy().getBlacklistDurationMsFor(loadErrorInfo);
|
||||
return new DefaultLoadErrorHandlingPolicy()
|
||||
.getExclusionDurationMsFor(LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK, loadErrorInfo);
|
||||
}
|
||||
|
||||
private static long getDefaultPolicyRetryDelayOutputFor(IOException exception, int errorCount) {
|
||||
|
@ -893,7 +893,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
LoadErrorInfo loadErrorInfo =
|
||||
new LoadErrorInfo(loadEventInfo, mediaLoadData, error, errorCount);
|
||||
LoadErrorAction loadErrorAction;
|
||||
long exclusionDurationMs = loadErrorHandlingPolicy.getBlacklistDurationMsFor(loadErrorInfo);
|
||||
long exclusionDurationMs =
|
||||
loadErrorHandlingPolicy.getExclusionDurationMsFor(
|
||||
LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK, loadErrorInfo);
|
||||
if (exclusionDurationMs != C.TIME_UNSET) {
|
||||
exclusionSucceeded = chunkSource.maybeExcludeTrack(loadable, exclusionDurationMs);
|
||||
}
|
||||
|
@ -631,7 +631,9 @@ public final class DefaultHlsPlaylistTracker
|
||||
LoadErrorInfo loadErrorInfo =
|
||||
new LoadErrorInfo(loadEventInfo, mediaLoadData, error, errorCount);
|
||||
LoadErrorAction loadErrorAction;
|
||||
long exclusionDurationMs = loadErrorHandlingPolicy.getBlacklistDurationMsFor(loadErrorInfo);
|
||||
long exclusionDurationMs =
|
||||
loadErrorHandlingPolicy.getExclusionDurationMsFor(
|
||||
LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK, loadErrorInfo);
|
||||
boolean shouldExclude = exclusionDurationMs != C.TIME_UNSET;
|
||||
|
||||
boolean exclusionFailed =
|
||||
@ -730,7 +732,8 @@ public final class DefaultHlsPlaylistTracker
|
||||
playlistError,
|
||||
/* errorCount= */ 1);
|
||||
long exclusionDurationMs =
|
||||
loadErrorHandlingPolicy.getBlacklistDurationMsFor(loadErrorInfo);
|
||||
loadErrorHandlingPolicy.getExclusionDurationMsFor(
|
||||
LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK, loadErrorInfo);
|
||||
notifyPlaylistError(playlistUrl, exclusionDurationMs);
|
||||
if (exclusionDurationMs != C.TIME_UNSET) {
|
||||
excludePlaylist(exclusionDurationMs);
|
||||
|
Loading…
x
Reference in New Issue
Block a user