mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Make getFallbackSelection nullable to indicate disabling of exclusion
PiperOrigin-RevId: 386442542
This commit is contained in:
parent
cae309123b
commit
2ee6d6d95d
@ -384,8 +384,7 @@ public class DefaultDrmSessionManager implements DrmSessionManager {
|
|||||||
multiSession,
|
multiSession,
|
||||||
/* useDrmSessionsForClearContentTrackTypes= */ new int[0],
|
/* useDrmSessionsForClearContentTrackTypes= */ new int[0],
|
||||||
/* playClearSamplesWithoutKeys= */ false,
|
/* playClearSamplesWithoutKeys= */ false,
|
||||||
new DefaultLoadErrorHandlingPolicy(
|
new DefaultLoadErrorHandlingPolicy(initialDrmRequestRetryCount),
|
||||||
initialDrmRequestRetryCount, /* locationExclusionEnabled= */ false),
|
|
||||||
DEFAULT_SESSION_KEEPALIVE_MS);
|
DEFAULT_SESSION_KEEPALIVE_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ package com.google.android.exoplayer2.upstream;
|
|||||||
|
|
||||||
import static java.lang.Math.min;
|
import static java.lang.Math.min;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.ParserException;
|
import com.google.android.exoplayer2.ParserException;
|
||||||
import com.google.android.exoplayer2.upstream.HttpDataSource.CleartextNotPermittedException;
|
import com.google.android.exoplayer2.upstream.HttpDataSource.CleartextNotPermittedException;
|
||||||
@ -45,7 +46,6 @@ public class DefaultLoadErrorHandlingPolicy implements LoadErrorHandlingPolicy {
|
|||||||
private static final int DEFAULT_BEHAVIOR_MIN_LOADABLE_RETRY_COUNT = -1;
|
private static final int DEFAULT_BEHAVIOR_MIN_LOADABLE_RETRY_COUNT = -1;
|
||||||
|
|
||||||
private final int minimumLoadableRetryCount;
|
private final int minimumLoadableRetryCount;
|
||||||
private final boolean locationExclusionEnabled;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance with default behavior.
|
* Creates an instance with default behavior.
|
||||||
@ -54,72 +54,48 @@ public class DefaultLoadErrorHandlingPolicy implements LoadErrorHandlingPolicy {
|
|||||||
* #DEFAULT_MIN_LOADABLE_RETRY_COUNT_PROGRESSIVE_LIVE} for {@code dataType} {@link
|
* #DEFAULT_MIN_LOADABLE_RETRY_COUNT_PROGRESSIVE_LIVE} for {@code dataType} {@link
|
||||||
* C#DATA_TYPE_MEDIA_PROGRESSIVE_LIVE}. For other {@code dataType} values, it will return {@link
|
* C#DATA_TYPE_MEDIA_PROGRESSIVE_LIVE}. For other {@code dataType} values, it will return {@link
|
||||||
* #DEFAULT_MIN_LOADABLE_RETRY_COUNT}.
|
* #DEFAULT_MIN_LOADABLE_RETRY_COUNT}.
|
||||||
*
|
|
||||||
* <p>Exclusion of both fallback types {@link #FALLBACK_TYPE_TRACK} and {@link
|
|
||||||
* #FALLBACK_TYPE_TRACK} is enabled by default.
|
|
||||||
*/
|
*/
|
||||||
public DefaultLoadErrorHandlingPolicy() {
|
public DefaultLoadErrorHandlingPolicy() {
|
||||||
this(DEFAULT_BEHAVIOR_MIN_LOADABLE_RETRY_COUNT, /* locationExclusionEnabled= */ true);
|
this(DEFAULT_BEHAVIOR_MIN_LOADABLE_RETRY_COUNT);
|
||||||
}
|
|
||||||
|
|
||||||
/** @deprecated Use {@link #DefaultLoadErrorHandlingPolicy(int, boolean)} instead. */
|
|
||||||
@Deprecated
|
|
||||||
public DefaultLoadErrorHandlingPolicy(int minimumLoadableRetryCount) {
|
|
||||||
this(minimumLoadableRetryCount, /* locationExclusionEnabled= */ true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance with the given value for {@link #getMinimumLoadableRetryCount(int)}.
|
* Creates an instance with the given value for {@link #getMinimumLoadableRetryCount(int)}.
|
||||||
*
|
*
|
||||||
* @param minimumLoadableRetryCount See {@link #getMinimumLoadableRetryCount}.
|
* @param minimumLoadableRetryCount See {@link #getMinimumLoadableRetryCount}.
|
||||||
* @param locationExclusionEnabled Whether location exclusion is enabled.
|
|
||||||
*/
|
*/
|
||||||
public DefaultLoadErrorHandlingPolicy(
|
public DefaultLoadErrorHandlingPolicy(int minimumLoadableRetryCount) {
|
||||||
int minimumLoadableRetryCount, boolean locationExclusionEnabled) {
|
|
||||||
this.minimumLoadableRetryCount = minimumLoadableRetryCount;
|
this.minimumLoadableRetryCount = minimumLoadableRetryCount;
|
||||||
this.locationExclusionEnabled = locationExclusionEnabled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the fallback selection.
|
* Returns the fallback selection.
|
||||||
*
|
*
|
||||||
* <p>The exclusion duration is given by {@link #DEFAULT_TRACK_EXCLUSION_MS} or {@link
|
* <p>The exclusion duration is given by {@link #DEFAULT_TRACK_EXCLUSION_MS} or {@link
|
||||||
* #DEFAULT_LOCATION_EXCLUSION_MS}, if the load error was an {@link InvalidResponseCodeException}
|
* #DEFAULT_LOCATION_EXCLUSION_MS} if the load error was not an {@link
|
||||||
* with an HTTP response code indicating an unrecoverable error, or {@link C#TIME_UNSET}
|
* #isRecoverableError(IOException) recoverable error}. In case of a recoverable error null is
|
||||||
* otherwise.
|
* returned to disable exclusion but retry the same load instead.
|
||||||
*
|
*
|
||||||
* <p>If alternative locations are advertised by the {@link
|
* <p>If alternative locations {@link
|
||||||
* LoadErrorHandlingPolicy.FallbackOptions}, {@link #FALLBACK_TYPE_LOCATION} is selected until all
|
* LoadErrorHandlingPolicy.FallbackOptions#isFallbackAvailable(int) are advertised}, {@link
|
||||||
* locations are excluded, {@link #FALLBACK_TYPE_TRACK} otherwise.
|
* #FALLBACK_TYPE_LOCATION} is selected until all locations are excluded, {@link
|
||||||
|
* #FALLBACK_TYPE_TRACK} otherwise.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@Nullable
|
||||||
public FallbackSelection getFallbackSelectionFor(
|
public FallbackSelection getFallbackSelectionFor(
|
||||||
FallbackOptions fallbackOptions, LoadErrorInfo loadErrorInfo) {
|
FallbackOptions fallbackOptions, LoadErrorInfo loadErrorInfo) {
|
||||||
@FallbackType int fallbackType = FALLBACK_TYPE_TRACK;
|
if (isRecoverableError(loadErrorInfo.exception)) {
|
||||||
boolean fallbackAvailable =
|
// Don't fallback. Retry the same load again.
|
||||||
fallbackOptions.numberOfTracks - fallbackOptions.numberOfExcludedTracks > 1;
|
return null;
|
||||||
if (locationExclusionEnabled
|
|
||||||
&& fallbackOptions.numberOfLocations - fallbackOptions.numberOfExcludedLocations > 1) {
|
|
||||||
fallbackType = FALLBACK_TYPE_LOCATION;
|
|
||||||
fallbackAvailable = true;
|
|
||||||
}
|
}
|
||||||
long exclusionDurationMs = C.TIME_UNSET;
|
// Prefer location fallbacks to track fallbacks, when both are available.
|
||||||
IOException exception = loadErrorInfo.exception;
|
if (fallbackOptions.isFallbackAvailable(FALLBACK_TYPE_LOCATION)) {
|
||||||
if (fallbackAvailable && exception instanceof InvalidResponseCodeException) {
|
return new FallbackSelection(FALLBACK_TYPE_LOCATION, DEFAULT_LOCATION_EXCLUSION_MS);
|
||||||
int responseCode = ((InvalidResponseCodeException) exception).responseCode;
|
} else if (fallbackOptions.isFallbackAvailable(FALLBACK_TYPE_TRACK)) {
|
||||||
exclusionDurationMs =
|
return new FallbackSelection(FALLBACK_TYPE_TRACK, DEFAULT_TRACK_EXCLUSION_MS);
|
||||||
responseCode == 403 // HTTP 403 Forbidden.
|
|
||||||
|| responseCode == 404 // HTTP 404 Not Found.
|
|
||||||
|| responseCode == 410 // HTTP 410 Gone.
|
|
||||||
|| responseCode == 416 // HTTP 416 Range Not Satisfiable.
|
|
||||||
|| responseCode == 500 // HTTP 500 Internal Server Error.
|
|
||||||
|| responseCode == 503 // HTTP 503 Service Unavailable.
|
|
||||||
? (fallbackType == FALLBACK_TYPE_TRACK
|
|
||||||
? DEFAULT_TRACK_EXCLUSION_MS
|
|
||||||
: DEFAULT_LOCATION_EXCLUSION_MS)
|
|
||||||
: C.TIME_UNSET;
|
|
||||||
}
|
}
|
||||||
return new FallbackSelection(fallbackType, exclusionDurationMs);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -153,4 +129,24 @@ public class DefaultLoadErrorHandlingPolicy implements LoadErrorHandlingPolicy {
|
|||||||
return minimumLoadableRetryCount;
|
return minimumLoadableRetryCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the error is considered recoverable.
|
||||||
|
*
|
||||||
|
* @param exception The exception.
|
||||||
|
* @return Whether the error is considered an recoverable error.
|
||||||
|
*/
|
||||||
|
protected boolean isRecoverableError(IOException exception) {
|
||||||
|
if (!(exception instanceof InvalidResponseCodeException)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
InvalidResponseCodeException invalidResponseCodeException =
|
||||||
|
(InvalidResponseCodeException) exception;
|
||||||
|
return invalidResponseCodeException.responseCode != 403 // HTTP 403 Forbidden.
|
||||||
|
&& invalidResponseCodeException.responseCode != 404 // HTTP 404 Not Found.
|
||||||
|
&& invalidResponseCodeException.responseCode != 410 // HTTP 410 Gone.
|
||||||
|
&& invalidResponseCodeException.responseCode != 416 // HTTP 416 Range Not Satisfiable.
|
||||||
|
&& invalidResponseCodeException.responseCode != 500 // HTTP 500 Internal Server Error.
|
||||||
|
&& invalidResponseCodeException.responseCode != 503; // HTTP 503 Service Unavailable.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.upstream;
|
package com.google.android.exoplayer2.upstream;
|
||||||
|
|
||||||
|
import static com.google.android.exoplayer2.util.Assertions.checkArgument;
|
||||||
|
|
||||||
import androidx.annotation.IntDef;
|
import androidx.annotation.IntDef;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.source.LoadEventInfo;
|
import com.google.android.exoplayer2.source.LoadEventInfo;
|
||||||
import com.google.android.exoplayer2.source.MediaLoadData;
|
import com.google.android.exoplayer2.source.MediaLoadData;
|
||||||
@ -109,20 +112,28 @@ public interface LoadErrorHandlingPolicy {
|
|||||||
this.numberOfTracks = numberOfTracks;
|
this.numberOfTracks = numberOfTracks;
|
||||||
this.numberOfExcludedTracks = numberOfExcludedTracks;
|
this.numberOfExcludedTracks = numberOfExcludedTracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns whether a fallback is available for the given {@link FallbackType fallback type}. */
|
||||||
|
public boolean isFallbackAvailable(@FallbackType int type) {
|
||||||
|
return type == FALLBACK_TYPE_LOCATION
|
||||||
|
? numberOfLocations - numberOfExcludedLocations > 1
|
||||||
|
: numberOfTracks - numberOfExcludedTracks > 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The selection of a fallback option determining the fallback behaviour on load error. */
|
/** The selection of a fallback option determining the fallback behaviour on load error. */
|
||||||
final class FallbackSelection {
|
final class FallbackSelection {
|
||||||
/** The {@link FallbackType fallback type} to use. */
|
/** The {@link FallbackType fallback type} to use. */
|
||||||
@FallbackType public final int type;
|
@FallbackType public final int type;
|
||||||
/**
|
/** The exclusion duration of the {@link #type}, in milliseconds. */
|
||||||
* The exclusion duration of the {@link #type} in milliseconds, or {@link C#TIME_UNSET} to
|
|
||||||
* disable exclusion of any fallback type.
|
|
||||||
*/
|
|
||||||
public final long exclusionDurationMs;
|
public final long exclusionDurationMs;
|
||||||
|
|
||||||
/** Creates an instance with the given values. */
|
/**
|
||||||
|
* Creates an instance with the given values. The exclusion duration, in milliseconds, needs to
|
||||||
|
* be a positive integer.
|
||||||
|
*/
|
||||||
public FallbackSelection(@FallbackType int type, long exclusionDurationMs) {
|
public FallbackSelection(@FallbackType int type, long exclusionDurationMs) {
|
||||||
|
checkArgument(exclusionDurationMs >= 0);
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.exclusionDurationMs = exclusionDurationMs;
|
this.exclusionDurationMs = exclusionDurationMs;
|
||||||
}
|
}
|
||||||
@ -130,20 +141,18 @@ public interface LoadErrorHandlingPolicy {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link FallbackSelection fallback selection} that determines the exclusion
|
* Returns the {@link FallbackSelection fallback selection} that determines the exclusion
|
||||||
* behaviour on load error.
|
* behaviour on load error. If null is returned the caller will disable exclusion.
|
||||||
*
|
*
|
||||||
* <p>If {@link FallbackSelection#exclusionDurationMs} is {@link C#TIME_UNSET}, exclusion is
|
* <p>If {@link FallbackSelection#type} is of a type that is not {@link
|
||||||
* disabled for any fallback type, regardless of the value of the {@link FallbackSelection#type
|
* FallbackOptions#isFallbackAvailable(int) advertised as available}, then the caller will disable
|
||||||
* selected fallback type}.
|
* exclusion as if null had been returned.
|
||||||
*
|
|
||||||
* <p>If {@link FallbackSelection#type} is of a type that is not advertised as available by the
|
|
||||||
* {@link FallbackOptions}, exclusion is disabled for any fallback type.
|
|
||||||
*
|
*
|
||||||
* @param fallbackOptions The available fallback options.
|
* @param fallbackOptions The available fallback options.
|
||||||
* @param loadErrorInfo A {@link LoadErrorInfo} holding information about the load error.
|
* @param loadErrorInfo A {@link LoadErrorInfo} holding information about the load error.
|
||||||
* @return The fallback selection indicating whether to apply exclusion, and if so for which type
|
* @return The fallback selection indicating which exclusion type to apply and for how long the
|
||||||
* and how long the resource should be excluded.
|
* resource should be excluded. Returning null indicates to disable exclusion.
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
FallbackSelection getFallbackSelectionFor(
|
FallbackSelection getFallbackSelectionFor(
|
||||||
FallbackOptions fallbackOptions, LoadErrorInfo loadErrorInfo);
|
FallbackOptions fallbackOptions, LoadErrorInfo loadErrorInfo);
|
||||||
|
|
||||||
|
@ -16,13 +16,13 @@
|
|||||||
package com.google.android.exoplayer2.upstream;
|
package com.google.android.exoplayer2.upstream;
|
||||||
|
|
||||||
import static com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy.DEFAULT_LOCATION_EXCLUSION_MS;
|
import static com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy.DEFAULT_LOCATION_EXCLUSION_MS;
|
||||||
import static com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy.DEFAULT_MIN_LOADABLE_RETRY_COUNT;
|
|
||||||
import static com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_EXCLUSION_MS;
|
import static com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_EXCLUSION_MS;
|
||||||
import static com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.FALLBACK_TYPE_LOCATION;
|
import static com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.FALLBACK_TYPE_LOCATION;
|
||||||
import static com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK;
|
import static com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.ParserException;
|
import com.google.android.exoplayer2.ParserException;
|
||||||
@ -56,6 +56,7 @@ public final class DefaultLoadErrorHandlingPolicyTest {
|
|||||||
public void getFallbackSelectionFor_responseCode403() {
|
public void getFallbackSelectionFor_responseCode403() {
|
||||||
InvalidResponseCodeException exception = buildInvalidResponseCodeException(403, "Forbidden");
|
InvalidResponseCodeException exception = buildInvalidResponseCodeException(403, "Forbidden");
|
||||||
|
|
||||||
|
@Nullable
|
||||||
LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection =
|
LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection =
|
||||||
getDefaultPolicyFallbackSelection(
|
getDefaultPolicyFallbackSelection(
|
||||||
exception,
|
exception,
|
||||||
@ -83,6 +84,7 @@ public final class DefaultLoadErrorHandlingPolicyTest {
|
|||||||
public void getFallbackSelectionFor_responseCode404() {
|
public void getFallbackSelectionFor_responseCode404() {
|
||||||
InvalidResponseCodeException exception = buildInvalidResponseCodeException(404, "Not found");
|
InvalidResponseCodeException exception = buildInvalidResponseCodeException(404, "Not found");
|
||||||
|
|
||||||
|
@Nullable
|
||||||
LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection =
|
LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection =
|
||||||
getDefaultPolicyFallbackSelection(
|
getDefaultPolicyFallbackSelection(
|
||||||
exception,
|
exception,
|
||||||
@ -111,6 +113,7 @@ public final class DefaultLoadErrorHandlingPolicyTest {
|
|||||||
public void getFallbackSelectionFor_responseCode410() {
|
public void getFallbackSelectionFor_responseCode410() {
|
||||||
InvalidResponseCodeException exception = buildInvalidResponseCodeException(410, "Gone");
|
InvalidResponseCodeException exception = buildInvalidResponseCodeException(410, "Gone");
|
||||||
|
|
||||||
|
@Nullable
|
||||||
LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection =
|
LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection =
|
||||||
getDefaultPolicyFallbackSelection(
|
getDefaultPolicyFallbackSelection(
|
||||||
exception,
|
exception,
|
||||||
@ -140,6 +143,7 @@ public final class DefaultLoadErrorHandlingPolicyTest {
|
|||||||
InvalidResponseCodeException exception =
|
InvalidResponseCodeException exception =
|
||||||
buildInvalidResponseCodeException(500, "Internal server error");
|
buildInvalidResponseCodeException(500, "Internal server error");
|
||||||
|
|
||||||
|
@Nullable
|
||||||
LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection =
|
LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection =
|
||||||
getDefaultPolicyFallbackSelection(
|
getDefaultPolicyFallbackSelection(
|
||||||
exception,
|
exception,
|
||||||
@ -169,6 +173,7 @@ public final class DefaultLoadErrorHandlingPolicyTest {
|
|||||||
InvalidResponseCodeException exception =
|
InvalidResponseCodeException exception =
|
||||||
buildInvalidResponseCodeException(503, "Service unavailable");
|
buildInvalidResponseCodeException(503, "Service unavailable");
|
||||||
|
|
||||||
|
@Nullable
|
||||||
LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection =
|
LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection =
|
||||||
getDefaultPolicyFallbackSelection(
|
getDefaultPolicyFallbackSelection(
|
||||||
exception,
|
exception,
|
||||||
@ -197,6 +202,7 @@ public final class DefaultLoadErrorHandlingPolicyTest {
|
|||||||
public void getFallbackSelectionFor_dontExcludeUnexpectedHttpCodes() {
|
public void getFallbackSelectionFor_dontExcludeUnexpectedHttpCodes() {
|
||||||
InvalidResponseCodeException exception = buildInvalidResponseCodeException(418, "I'm a teapot");
|
InvalidResponseCodeException exception = buildInvalidResponseCodeException(418, "I'm a teapot");
|
||||||
|
|
||||||
|
@Nullable
|
||||||
LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection =
|
LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection =
|
||||||
getDefaultPolicyFallbackSelection(
|
getDefaultPolicyFallbackSelection(
|
||||||
exception,
|
exception,
|
||||||
@ -205,8 +211,7 @@ public final class DefaultLoadErrorHandlingPolicyTest {
|
|||||||
/* numberOfTracks= */ 10,
|
/* numberOfTracks= */ 10,
|
||||||
/* numberOfExcludedTracks= */ 0);
|
/* numberOfExcludedTracks= */ 0);
|
||||||
|
|
||||||
assertThat(defaultPolicyFallbackSelection.type).isEqualTo(FALLBACK_TYPE_TRACK);
|
assertThat(defaultPolicyFallbackSelection).isNull();
|
||||||
assertThat(defaultPolicyFallbackSelection.exclusionDurationMs).isEqualTo(C.TIME_UNSET);
|
|
||||||
|
|
||||||
defaultPolicyFallbackSelection =
|
defaultPolicyFallbackSelection =
|
||||||
getDefaultPolicyFallbackSelection(
|
getDefaultPolicyFallbackSelection(
|
||||||
@ -215,14 +220,14 @@ public final class DefaultLoadErrorHandlingPolicyTest {
|
|||||||
/* numberOfExcludedLocations= */ 0,
|
/* numberOfExcludedLocations= */ 0,
|
||||||
/* numberOfTracks= */ 4,
|
/* numberOfTracks= */ 4,
|
||||||
/* numberOfExcludedTracks= */ 1);
|
/* numberOfExcludedTracks= */ 1);
|
||||||
assertThat(defaultPolicyFallbackSelection.type).isEqualTo(FALLBACK_TYPE_LOCATION);
|
assertThat(defaultPolicyFallbackSelection).isNull();
|
||||||
assertThat(defaultPolicyFallbackSelection.exclusionDurationMs).isEqualTo(C.TIME_UNSET);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getFallbackSelectionFor_dontExcludeUnexpectedExceptions() {
|
public void getFallbackSelectionFor_dontExcludeUnexpectedExceptions() {
|
||||||
IOException exception = new IOException();
|
IOException exception = new IOException();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection =
|
LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection =
|
||||||
getDefaultPolicyFallbackSelection(
|
getDefaultPolicyFallbackSelection(
|
||||||
exception,
|
exception,
|
||||||
@ -231,8 +236,7 @@ public final class DefaultLoadErrorHandlingPolicyTest {
|
|||||||
/* numberOfTracks= */ 10,
|
/* numberOfTracks= */ 10,
|
||||||
/* numberOfExcludedTracks= */ 0);
|
/* numberOfExcludedTracks= */ 0);
|
||||||
|
|
||||||
assertThat(defaultPolicyFallbackSelection.type).isEqualTo(FALLBACK_TYPE_TRACK);
|
assertThat(defaultPolicyFallbackSelection).isNull();
|
||||||
assertThat(defaultPolicyFallbackSelection.exclusionDurationMs).isEqualTo(C.TIME_UNSET);
|
|
||||||
|
|
||||||
defaultPolicyFallbackSelection =
|
defaultPolicyFallbackSelection =
|
||||||
getDefaultPolicyFallbackSelection(
|
getDefaultPolicyFallbackSelection(
|
||||||
@ -241,26 +245,7 @@ public final class DefaultLoadErrorHandlingPolicyTest {
|
|||||||
/* numberOfExcludedLocations= */ 0,
|
/* numberOfExcludedLocations= */ 0,
|
||||||
/* numberOfTracks= */ 4,
|
/* numberOfTracks= */ 4,
|
||||||
/* numberOfExcludedTracks= */ 1);
|
/* numberOfExcludedTracks= */ 1);
|
||||||
assertThat(defaultPolicyFallbackSelection.type).isEqualTo(FALLBACK_TYPE_LOCATION);
|
assertThat(defaultPolicyFallbackSelection).isNull();
|
||||||
assertThat(defaultPolicyFallbackSelection.exclusionDurationMs).isEqualTo(C.TIME_UNSET);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getFallbackSelectionFor_disabledLocationExclusion_useTrackExclusion() {
|
|
||||||
InvalidResponseCodeException exception = buildInvalidResponseCodeException(404, "Not found");
|
|
||||||
|
|
||||||
LoadErrorHandlingPolicy.FallbackSelection defaultPolicyFallbackSelection =
|
|
||||||
getDefaultPolicyFallbackSelection(
|
|
||||||
exception,
|
|
||||||
/* numberOfLocations= */ 2,
|
|
||||||
/* numberOfExcludedLocations= */ 0,
|
|
||||||
/* numberOfTracks= */ 4,
|
|
||||||
/* numberOfExcludedTracks= */ 1,
|
|
||||||
new DefaultLoadErrorHandlingPolicy(
|
|
||||||
DEFAULT_MIN_LOADABLE_RETRY_COUNT, /* locationExclusionEnabled= */ false));
|
|
||||||
assertThat(defaultPolicyFallbackSelection.type).isEqualTo(FALLBACK_TYPE_TRACK);
|
|
||||||
assertThat(defaultPolicyFallbackSelection.exclusionDurationMs)
|
|
||||||
.isEqualTo(DEFAULT_TRACK_EXCLUSION_MS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -279,28 +264,13 @@ public final class DefaultLoadErrorHandlingPolicyTest {
|
|||||||
assertThat(getDefaultPolicyRetryDelayOutputFor(new IOException(), 9)).isEqualTo(5000);
|
assertThat(getDefaultPolicyRetryDelayOutputFor(new IOException(), 9)).isEqualTo(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private static LoadErrorHandlingPolicy.FallbackSelection getDefaultPolicyFallbackSelection(
|
private static LoadErrorHandlingPolicy.FallbackSelection getDefaultPolicyFallbackSelection(
|
||||||
IOException exception,
|
IOException exception,
|
||||||
int numberOfLocations,
|
int numberOfLocations,
|
||||||
int numberOfExcludedLocations,
|
int numberOfExcludedLocations,
|
||||||
int numberOfTracks,
|
int numberOfTracks,
|
||||||
int numberOfExcludedTracks) {
|
int numberOfExcludedTracks) {
|
||||||
return getDefaultPolicyFallbackSelection(
|
|
||||||
exception,
|
|
||||||
numberOfLocations,
|
|
||||||
numberOfExcludedLocations,
|
|
||||||
numberOfTracks,
|
|
||||||
numberOfExcludedTracks,
|
|
||||||
new DefaultLoadErrorHandlingPolicy());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static LoadErrorHandlingPolicy.FallbackSelection getDefaultPolicyFallbackSelection(
|
|
||||||
IOException exception,
|
|
||||||
int numberOfLocations,
|
|
||||||
int numberOfExcludedLocations,
|
|
||||||
int numberOfTracks,
|
|
||||||
int numberOfExcludedTracks,
|
|
||||||
DefaultLoadErrorHandlingPolicy defaultLoadErrorHandlingPolicy) {
|
|
||||||
LoadErrorInfo loadErrorInfo =
|
LoadErrorInfo loadErrorInfo =
|
||||||
new LoadErrorInfo(
|
new LoadErrorInfo(
|
||||||
PLACEHOLDER_LOAD_EVENT_INFO,
|
PLACEHOLDER_LOAD_EVENT_INFO,
|
||||||
@ -310,7 +280,8 @@ public final class DefaultLoadErrorHandlingPolicyTest {
|
|||||||
LoadErrorHandlingPolicy.FallbackOptions fallbackOptions =
|
LoadErrorHandlingPolicy.FallbackOptions fallbackOptions =
|
||||||
new LoadErrorHandlingPolicy.FallbackOptions(
|
new LoadErrorHandlingPolicy.FallbackOptions(
|
||||||
numberOfLocations, numberOfExcludedLocations, numberOfTracks, numberOfExcludedTracks);
|
numberOfLocations, numberOfExcludedLocations, numberOfTracks, numberOfExcludedTracks);
|
||||||
return defaultLoadErrorHandlingPolicy.getFallbackSelectionFor(fallbackOptions, loadErrorInfo);
|
return new DefaultLoadErrorHandlingPolicy()
|
||||||
|
.getFallbackSelectionFor(fallbackOptions, loadErrorInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long getDefaultPolicyRetryDelayOutputFor(IOException exception, int errorCount) {
|
private static long getDefaultPolicyRetryDelayOutputFor(IOException exception, int errorCount) {
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package com.google.android.exoplayer2.source.dash;
|
package com.google.android.exoplayer2.source.dash;
|
||||||
|
|
||||||
import static com.google.android.exoplayer2.trackselection.TrackSelectionUtil.createFallbackOptions;
|
import static com.google.android.exoplayer2.trackselection.TrackSelectionUtil.createFallbackOptions;
|
||||||
|
import static com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK;
|
||||||
import static java.lang.Math.max;
|
import static java.lang.Math.max;
|
||||||
import static java.lang.Math.min;
|
import static java.lang.Math.min;
|
||||||
|
|
||||||
@ -490,10 +491,11 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||||||
// No more alternative tracks remaining.
|
// No more alternative tracks remaining.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@Nullable
|
||||||
LoadErrorHandlingPolicy.FallbackSelection fallbackSelection =
|
LoadErrorHandlingPolicy.FallbackSelection fallbackSelection =
|
||||||
loadErrorHandlingPolicy.getFallbackSelectionFor(fallbackOptions, loadErrorInfo);
|
loadErrorHandlingPolicy.getFallbackSelectionFor(fallbackOptions, loadErrorInfo);
|
||||||
return fallbackSelection.type == LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK
|
return fallbackSelection != null
|
||||||
&& fallbackSelection.exclusionDurationMs != C.TIME_UNSET
|
&& fallbackSelection.type == FALLBACK_TYPE_TRACK
|
||||||
&& trackSelection.blacklist(
|
&& trackSelection.blacklist(
|
||||||
trackSelection.indexOf(chunk.trackFormat), fallbackSelection.exclusionDurationMs);
|
trackSelection.indexOf(chunk.trackFormat), fallbackSelection.exclusionDurationMs);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
@ -186,10 +187,11 @@ public class DefaultDashChunkSourceTest {
|
|||||||
DefaultLoadErrorHandlingPolicy loadErrorHandlingPolicy =
|
DefaultLoadErrorHandlingPolicy loadErrorHandlingPolicy =
|
||||||
new DefaultLoadErrorHandlingPolicy() {
|
new DefaultLoadErrorHandlingPolicy() {
|
||||||
@Override
|
@Override
|
||||||
|
@Nullable
|
||||||
public FallbackSelection getFallbackSelectionFor(
|
public FallbackSelection getFallbackSelectionFor(
|
||||||
FallbackOptions fallbackOptions, LoadErrorInfo loadErrorInfo) {
|
FallbackOptions fallbackOptions, LoadErrorInfo loadErrorInfo) {
|
||||||
// Never exclude, neither tracks nor locations.
|
// Never exclude, neither tracks nor locations.
|
||||||
return new FallbackSelection(FALLBACK_TYPE_TRACK, C.TIME_UNSET);
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
DashChunkSource chunkSource = createDashChunkSource(/* numberOfTracks= */ 2);
|
DashChunkSource chunkSource = createDashChunkSource(/* numberOfTracks= */ 2);
|
||||||
|
@ -562,13 +562,14 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
}
|
}
|
||||||
long exclusionDurationMs = C.TIME_UNSET;
|
long exclusionDurationMs = C.TIME_UNSET;
|
||||||
if (!forceRetry) {
|
if (!forceRetry) {
|
||||||
|
@Nullable
|
||||||
LoadErrorHandlingPolicy.FallbackSelection fallbackSelection =
|
LoadErrorHandlingPolicy.FallbackSelection fallbackSelection =
|
||||||
loadErrorHandlingPolicy.getFallbackSelectionFor(
|
loadErrorHandlingPolicy.getFallbackSelectionFor(
|
||||||
createFallbackOptions(chunkSource.getTrackSelection()), loadErrorInfo);
|
createFallbackOptions(chunkSource.getTrackSelection()), loadErrorInfo);
|
||||||
exclusionDurationMs =
|
if (fallbackSelection != null
|
||||||
fallbackSelection.type == LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK
|
&& fallbackSelection.type == LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK) {
|
||||||
? fallbackSelection.exclusionDurationMs
|
exclusionDurationMs = fallbackSelection.exclusionDurationMs;
|
||||||
: C.TIME_UNSET;
|
}
|
||||||
}
|
}
|
||||||
return chunkSource.onPlaylistError(playlistUrl, exclusionDurationMs);
|
return chunkSource.onPlaylistError(playlistUrl, exclusionDurationMs);
|
||||||
}
|
}
|
||||||
@ -909,11 +910,12 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
LoadErrorInfo loadErrorInfo =
|
LoadErrorInfo loadErrorInfo =
|
||||||
new LoadErrorInfo(loadEventInfo, mediaLoadData, error, errorCount);
|
new LoadErrorInfo(loadEventInfo, mediaLoadData, error, errorCount);
|
||||||
LoadErrorAction loadErrorAction;
|
LoadErrorAction loadErrorAction;
|
||||||
|
@Nullable
|
||||||
LoadErrorHandlingPolicy.FallbackSelection fallbackSelection =
|
LoadErrorHandlingPolicy.FallbackSelection fallbackSelection =
|
||||||
loadErrorHandlingPolicy.getFallbackSelectionFor(
|
loadErrorHandlingPolicy.getFallbackSelectionFor(
|
||||||
createFallbackOptions(chunkSource.getTrackSelection()), loadErrorInfo);
|
createFallbackOptions(chunkSource.getTrackSelection()), loadErrorInfo);
|
||||||
if (fallbackSelection.type == LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK
|
if (fallbackSelection != null
|
||||||
&& fallbackSelection.exclusionDurationMs != C.TIME_UNSET) {
|
&& fallbackSelection.type == LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK) {
|
||||||
exclusionSucceeded =
|
exclusionSucceeded =
|
||||||
chunkSource.maybeExcludeTrack(loadable, fallbackSelection.exclusionDurationMs);
|
chunkSource.maybeExcludeTrack(loadable, fallbackSelection.exclusionDurationMs);
|
||||||
}
|
}
|
||||||
|
@ -290,12 +290,13 @@ public class DefaultSsChunkSource implements SsChunkSource {
|
|||||||
boolean cancelable,
|
boolean cancelable,
|
||||||
LoadErrorHandlingPolicy.LoadErrorInfo loadErrorInfo,
|
LoadErrorHandlingPolicy.LoadErrorInfo loadErrorInfo,
|
||||||
LoadErrorHandlingPolicy loadErrorHandlingPolicy) {
|
LoadErrorHandlingPolicy loadErrorHandlingPolicy) {
|
||||||
|
@Nullable
|
||||||
FallbackSelection fallbackSelection =
|
FallbackSelection fallbackSelection =
|
||||||
loadErrorHandlingPolicy.getFallbackSelectionFor(
|
loadErrorHandlingPolicy.getFallbackSelectionFor(
|
||||||
createFallbackOptions(trackSelection), loadErrorInfo);
|
createFallbackOptions(trackSelection), loadErrorInfo);
|
||||||
return cancelable
|
return cancelable
|
||||||
|
&& fallbackSelection != null
|
||||||
&& fallbackSelection.type == LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK
|
&& fallbackSelection.type == LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK
|
||||||
&& fallbackSelection.exclusionDurationMs != C.TIME_UNSET
|
|
||||||
&& trackSelection.blacklist(
|
&& trackSelection.blacklist(
|
||||||
trackSelection.indexOf(chunk.trackFormat), fallbackSelection.exclusionDurationMs);
|
trackSelection.indexOf(chunk.trackFormat), fallbackSelection.exclusionDurationMs);
|
||||||
}
|
}
|
||||||
|
@ -177,8 +177,7 @@ public class FakeAdaptiveMediaPeriod
|
|||||||
positionUs,
|
positionUs,
|
||||||
DrmSessionManager.DRM_UNSUPPORTED,
|
DrmSessionManager.DRM_UNSUPPORTED,
|
||||||
new DrmSessionEventListener.EventDispatcher(),
|
new DrmSessionEventListener.EventDispatcher(),
|
||||||
new DefaultLoadErrorHandlingPolicy(
|
new DefaultLoadErrorHandlingPolicy(/* minimumLoadableRetryCount= */ 3),
|
||||||
/* minimumLoadableRetryCount= */ 3, /* locationExclusionEnabled= */ true),
|
|
||||||
mediaSourceEventDispatcher);
|
mediaSourceEventDispatcher);
|
||||||
streams[i] = sampleStream;
|
streams[i] = sampleStream;
|
||||||
sampleStreams.add(sampleStream);
|
sampleStreams.add(sampleStream);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user