diff --git a/library/src/main/java/com/google/android/exoplayer/chunk/FormatEvaluator.java b/library/src/main/java/com/google/android/exoplayer/chunk/FormatEvaluator.java index a5f0e45ae0..973f4a3b2d 100644 --- a/library/src/main/java/com/google/android/exoplayer/chunk/FormatEvaluator.java +++ b/library/src/main/java/com/google/android/exoplayer/chunk/FormatEvaluator.java @@ -266,23 +266,25 @@ public interface FormatEvaluator { public void evaluateFormat(long bufferedDurationUs, boolean[] blacklistFlags, Evaluation evaluation) { Format current = evaluation.format; - Format ideal = determineIdealFormat(formats, blacklistFlags, + Format selected = determineIdealFormat(formats, blacklistFlags, bandwidthMeter.getBitrateEstimate()); - boolean isHigher = current != null && ideal.bitrate > current.bitrate; - boolean isLower = current != null && ideal.bitrate < current.bitrate; - if (isHigher && bufferedDurationUs < minDurationForQualityIncreaseUs) { - // The ideal format is a higher quality, but we have insufficient buffer to safely switch - // up. Defer switching up for now. - ideal = current; - } else if (isLower && bufferedDurationUs >= maxDurationForQualityDecreaseUs) { - // The ideal format is a lower quality, but we have sufficient buffer to defer switching - // down for now. - ideal = current; + if (current != null && isEnabledFormat(current, blacklistFlags)) { + if (selected.bitrate > current.bitrate + && bufferedDurationUs < minDurationForQualityIncreaseUs) { + // The ideal format is a higher quality, but we have insufficient buffer to safely switch + // up. Defer switching up for now. + selected = current; + } else if (selected.bitrate < current.bitrate + && bufferedDurationUs >= maxDurationForQualityDecreaseUs) { + // The ideal format is a lower quality, but we have sufficient buffer to defer switching + // down for now. + selected = current; + } } - if (current != null && ideal != current) { + if (current != null && selected != current) { evaluation.trigger = TRIGGER_ADAPTIVE; } - evaluation.format = ideal; + evaluation.format = selected; } @Override @@ -340,6 +342,15 @@ public interface FormatEvaluator { return formats[lowestBitrateNonBlacklistedIndex]; } + private boolean isEnabledFormat(Format format, boolean[] blacklistFlags) { + for (int i = 0; i < formats.length; i++) { + if (format == formats[i]) { + return !blacklistFlags[i]; + } + } + return false; + } + } } diff --git a/playbacktests/src/main/java/com/google/android/exoplayer/playbacktests/util/ExoHostedTest.java b/playbacktests/src/main/java/com/google/android/exoplayer/playbacktests/util/ExoHostedTest.java index bff8ff0d2f..1d7c7dda64 100644 --- a/playbacktests/src/main/java/com/google/android/exoplayer/playbacktests/util/ExoHostedTest.java +++ b/playbacktests/src/main/java/com/google/android/exoplayer/playbacktests/util/ExoHostedTest.java @@ -52,9 +52,12 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen } public static final long MAX_PLAYING_TIME_DISCREPANCY_MS = 2000; + public static final long EXPECTED_PLAYING_TIME_MEDIA_DURATION_MS = -1; + public static final long EXPECTED_PLAYING_TIME_UNSET = -2; private final String tag; - private final boolean fullPlaybackNoSeeking; + private final boolean failOnPlayerError; + private final long expectedPlayingTimeMs; private final CodecCounters videoCodecCounters; private final CodecCounters audioCodecCounters; @@ -74,11 +77,30 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen * @param tag A tag to use for logging. * @param fullPlaybackNoSeeking Whether the test will play the target media in full without * seeking. If set to true, the test will assert that the total time spent playing the media - * was within {@link #MAX_PLAYING_TIME_DISCREPANCY_MS} of the media duration. + * was within {@link #MAX_PLAYING_TIME_DISCREPANCY_MS} of the media duration. If set to false, + * the test will not assert an expected playing time. */ public ExoHostedTest(String tag, boolean fullPlaybackNoSeeking) { + this(tag, fullPlaybackNoSeeking ? EXPECTED_PLAYING_TIME_MEDIA_DURATION_MS + : EXPECTED_PLAYING_TIME_UNSET, false); + } + + /** + * @param tag A tag to use for logging. + * @param expectedPlayingTimeMs The expected playing time. If set to a non-negative value, the + * test will assert that the total time spent playing the media was within + * {@link #MAX_PLAYING_TIME_DISCREPANCY_MS} of the specified value. + * {@link #EXPECTED_PLAYING_TIME_MEDIA_DURATION_MS} should be passed to assert that the + * expected playing time equals the duration of the media being played. Else + * {@link #EXPECTED_PLAYING_TIME_UNSET} should be passed to indicate that the test should not + * assert an expected playing time. + * @param failOnPlayerError True if a player error should be considered a test failure. False + * otherwise. + */ + public ExoHostedTest(String tag, long expectedPlayingTimeMs, boolean failOnPlayerError) { this.tag = tag; - this.fullPlaybackNoSeeking = fullPlaybackNoSeeking; + this.expectedPlayingTimeMs = expectedPlayingTimeMs; + this.failOnPlayerError = failOnPlayerError; videoCodecCounters = new CodecCounters(); audioCodecCounters = new CodecCounters(); } @@ -133,16 +155,18 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen @Override public final void onFinished() { - if (playerError != null) { + if (failOnPlayerError && playerError != null) { throw new Error(playerError); } logMetrics(audioCodecCounters, videoCodecCounters); - if (fullPlaybackNoSeeking) { + if (expectedPlayingTimeMs != EXPECTED_PLAYING_TIME_UNSET) { + long playingTimeToAssertMs = expectedPlayingTimeMs == EXPECTED_PLAYING_TIME_MEDIA_DURATION_MS + ? sourceDurationMs : expectedPlayingTimeMs; // Assert that the playback spanned the correct duration of time. - long minAllowedActualPlayingTimeMs = sourceDurationMs - MAX_PLAYING_TIME_DISCREPANCY_MS; - long maxAllowedActualPlayingTimeMs = sourceDurationMs + MAX_PLAYING_TIME_DISCREPANCY_MS; - Assert.assertTrue("Total playing time: " + totalPlayingTimeMs + ". Actual media duration: " - + sourceDurationMs, minAllowedActualPlayingTimeMs <= totalPlayingTimeMs + long minAllowedActualPlayingTimeMs = playingTimeToAssertMs - MAX_PLAYING_TIME_DISCREPANCY_MS; + long maxAllowedActualPlayingTimeMs = playingTimeToAssertMs + MAX_PLAYING_TIME_DISCREPANCY_MS; + Assert.assertTrue("Total playing time: " + totalPlayingTimeMs + ". Expected: " + + playingTimeToAssertMs, minAllowedActualPlayingTimeMs <= totalPlayingTimeMs && totalPlayingTimeMs <= maxAllowedActualPlayingTimeMs); } // Make any additional assertions.