From 452f68fb6c5f8a9e4dac0efec3e4e956f09a63e9 Mon Sep 17 00:00:00 2001 From: Oliver Woodman Date: Tue, 20 Oct 2020 14:52:14 +0100 Subject: [PATCH] Merge pull request #7867 from GeneticGenesis:pc/update-expected-http-statuses-for-failover PiperOrigin-RevId: 338051017 --- RELEASENOTES.md | 3 + .../DefaultLoadErrorHandlingPolicy.java | 5 +- .../DefaultLoadErrorHandlingPolicyTest.java | 55 ++++++++++++------- 3 files changed, 42 insertions(+), 21 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index f8381ce4e2..910781495c 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -51,6 +51,9 @@ ([#8005](https://github.com/google/ExoPlayer/issues/8005)). * Make FLV files seekable by using the key frame index ([#7378](https://github.com/google/ExoPlayer/issues/7378)). +* Adaptive playback (DASH / HLS / SmoothStreaming): + * Add 403, 500 and 503 to the list of HTTP status codes that can trigger + failover to another quality variant. * HLS: * Fix crash affecting chunkful preparation of master playlists that start with an I-FRAME only variant diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultLoadErrorHandlingPolicy.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultLoadErrorHandlingPolicy.java index 366bd6509e..dc5aefac6d 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultLoadErrorHandlingPolicy.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultLoadErrorHandlingPolicy.java @@ -72,9 +72,12 @@ public class DefaultLoadErrorHandlingPolicy implements LoadErrorHandlingPolicy { IOException exception = loadErrorInfo.exception; if (exception instanceof InvalidResponseCodeException) { int responseCode = ((InvalidResponseCodeException) exception).responseCode; - return responseCode == 404 // HTTP 404 Not Found. + return 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. ? DEFAULT_TRACK_BLACKLIST_MS : C.TIME_UNSET; } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/upstream/DefaultLoadErrorHandlingPolicyTest.java b/library/core/src/test/java/com/google/android/exoplayer2/upstream/DefaultLoadErrorHandlingPolicyTest.java index 50b06c14db..02a7210683 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/upstream/DefaultLoadErrorHandlingPolicyTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/upstream/DefaultLoadErrorHandlingPolicyTest.java @@ -47,41 +47,46 @@ public final class DefaultLoadErrorHandlingPolicyTest { private static final MediaLoadData PLACEHOLDER_MEDIA_LOAD_DATA = new MediaLoadData(/* dataType= */ C.DATA_TYPE_UNKNOWN); + @Test + public void getExclusionDurationMsFor_responseCode403() { + InvalidResponseCodeException exception = buildInvalidResponseCodeException(403, "Forbidden"); + assertThat(getDefaultPolicyExclusionDurationMsFor(exception)) + .isEqualTo(DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_BLACKLIST_MS); + } + @Test public void getExclusionDurationMsFor_responseCode404() { - InvalidResponseCodeException exception = - new InvalidResponseCodeException( - 404, - "Not Found", - Collections.emptyMap(), - new DataSpec(Uri.EMPTY), - /* responseBody= */ Util.EMPTY_BYTE_ARRAY); + InvalidResponseCodeException exception = buildInvalidResponseCodeException(404, "Not found"); assertThat(getDefaultPolicyExclusionDurationMsFor(exception)) .isEqualTo(DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_BLACKLIST_MS); } @Test public void getExclusionDurationMsFor_responseCode410() { + InvalidResponseCodeException exception = buildInvalidResponseCodeException(410, "Gone"); + assertThat(getDefaultPolicyExclusionDurationMsFor(exception)) + .isEqualTo(DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_BLACKLIST_MS); + } + + @Test + public void getExclusionDurationMsFor_responseCode500() { InvalidResponseCodeException exception = - new InvalidResponseCodeException( - 410, - "Gone", - Collections.emptyMap(), - new DataSpec(Uri.EMPTY), - /* responseBody= */ Util.EMPTY_BYTE_ARRAY); + buildInvalidResponseCodeException(500, "Internal server error"); + assertThat(getDefaultPolicyExclusionDurationMsFor(exception)) + .isEqualTo(DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_BLACKLIST_MS); + } + + @Test + public void getExclusionDurationMsFor_responseCode503() { + InvalidResponseCodeException exception = + buildInvalidResponseCodeException(503, "Service unavailable"); assertThat(getDefaultPolicyExclusionDurationMsFor(exception)) .isEqualTo(DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_BLACKLIST_MS); } @Test public void getExclusionDurationMsFor_dontExcludeUnexpectedHttpCodes() { - InvalidResponseCodeException exception = - new InvalidResponseCodeException( - 500, - "Internal Server Error", - Collections.emptyMap(), - new DataSpec(Uri.EMPTY), - /* responseBody= */ Util.EMPTY_BYTE_ARRAY); + InvalidResponseCodeException exception = buildInvalidResponseCodeException(418, "I'm a teapot"); assertThat(getDefaultPolicyExclusionDurationMsFor(exception)).isEqualTo(C.TIME_UNSET); } @@ -120,4 +125,14 @@ public final class DefaultLoadErrorHandlingPolicyTest { PLACEHOLDER_LOAD_EVENT_INFO, PLACEHOLDER_MEDIA_LOAD_DATA, exception, errorCount); return new DefaultLoadErrorHandlingPolicy().getRetryDelayMsFor(loadErrorInfo); } + + private static InvalidResponseCodeException buildInvalidResponseCodeException( + int statusCode, String message) { + return new InvalidResponseCodeException( + statusCode, + message, + Collections.emptyMap(), + new DataSpec(Uri.EMPTY), + /* responseBody= */ Util.EMPTY_BYTE_ARRAY); + } }