From 6e5ae87cae43ebc9794f8d075e0fda1267900213 Mon Sep 17 00:00:00 2001 From: tonihei Date: Mon, 5 Mar 2018 07:44:26 -0800 Subject: [PATCH] Remove initial bitrate estimate from AdaptiveTrackSelection. This value can now be set in the DefaultBandwidthMeter instead. As a result NO_VALUE can be removed from BandwidthMeter as we now always provide an estimate. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=187865341 --- RELEASENOTES.md | 2 + .../AdaptiveTrackSelection.java | 46 +++++--------- .../exoplayer2/upstream/BandwidthMeter.java | 21 ++----- .../upstream/DefaultBandwidthMeter.java | 2 +- .../AdaptiveTrackSelectionTest.java | 60 ++++++++----------- 5 files changed, 46 insertions(+), 85 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 2821346ea8..94eebd87af 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -2,6 +2,8 @@ ### dev-v2 (not yet released) ### +* Moved initial bitrate estimate from `AdaptiveTrackSelection` to + `DefaultBandwidthMeter`. * UI components: * Add support for listening to `AspectRatioFrameLayout`'s aspect ratio update ([#3736](https://github.com/google/ExoPlayer/issues/3736)). diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelection.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelection.java index 973155c2e3..b28dc6ca6f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelection.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelection.java @@ -36,7 +36,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { public static final class Factory implements TrackSelection.Factory { private final BandwidthMeter bandwidthMeter; - private final int maxInitialBitrate; private final int minDurationForQualityIncreaseMs; private final int maxDurationForQualityDecreaseMs; private final int minDurationToRetainAfterDiscardMs; @@ -51,7 +50,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { public Factory(BandwidthMeter bandwidthMeter) { this( bandwidthMeter, - DEFAULT_MAX_INITIAL_BITRATE, DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS, DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS, DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS, @@ -63,26 +61,26 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { /** * @param bandwidthMeter Provides an estimate of the currently available bandwidth. - * @param maxInitialBitrate The maximum bitrate in bits per second that should be assumed - * when a bandwidth estimate is unavailable. - * @param minDurationForQualityIncreaseMs The minimum duration of buffered data required for - * the selected track to switch to one of higher quality. - * @param maxDurationForQualityDecreaseMs The maximum duration of buffered data required for - * the selected track to switch to one of lower quality. + * @param minDurationForQualityIncreaseMs The minimum duration of buffered data required for the + * selected track to switch to one of higher quality. + * @param maxDurationForQualityDecreaseMs The maximum duration of buffered data required for the + * selected track to switch to one of lower quality. * @param minDurationToRetainAfterDiscardMs When switching to a track of significantly higher * quality, the selection may indicate that media already buffered at the lower quality can * be discarded to speed up the switch. This is the minimum duration of media that must be * retained at the lower quality. * @param bandwidthFraction The fraction of the available bandwidth that the selection should - * consider available for use. Setting to a value less than 1 is recommended to account - * for inaccuracies in the bandwidth estimator. + * consider available for use. Setting to a value less than 1 is recommended to account for + * inaccuracies in the bandwidth estimator. */ - public Factory(BandwidthMeter bandwidthMeter, int maxInitialBitrate, - int minDurationForQualityIncreaseMs, int maxDurationForQualityDecreaseMs, - int minDurationToRetainAfterDiscardMs, float bandwidthFraction) { + public Factory( + BandwidthMeter bandwidthMeter, + int minDurationForQualityIncreaseMs, + int maxDurationForQualityDecreaseMs, + int minDurationToRetainAfterDiscardMs, + float bandwidthFraction) { this( bandwidthMeter, - maxInitialBitrate, minDurationForQualityIncreaseMs, maxDurationForQualityDecreaseMs, minDurationToRetainAfterDiscardMs, @@ -93,9 +91,7 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { } /** - * @param bandwidthMeter Provides an estimate of the currently available bandwidth. - * @param maxInitialBitrate The maximum bitrate in bits per second that should be assumed when a - * bandwidth estimate is unavailable. + * @param bandwidthMeter Provides an estimate of the currently available bandwidth.. * @param minDurationForQualityIncreaseMs The minimum duration of buffered data required for the * selected track to switch to one of higher quality. * @param maxDurationForQualityDecreaseMs The maximum duration of buffered data required for the @@ -121,7 +117,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { */ public Factory( BandwidthMeter bandwidthMeter, - int maxInitialBitrate, int minDurationForQualityIncreaseMs, int maxDurationForQualityDecreaseMs, int minDurationToRetainAfterDiscardMs, @@ -130,7 +125,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { long minTimeBetweenBufferReevaluationMs, Clock clock) { this.bandwidthMeter = bandwidthMeter; - this.maxInitialBitrate = maxInitialBitrate; this.minDurationForQualityIncreaseMs = minDurationForQualityIncreaseMs; this.maxDurationForQualityDecreaseMs = maxDurationForQualityDecreaseMs; this.minDurationToRetainAfterDiscardMs = minDurationToRetainAfterDiscardMs; @@ -147,7 +141,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { group, tracks, bandwidthMeter, - maxInitialBitrate, minDurationForQualityIncreaseMs, maxDurationForQualityDecreaseMs, minDurationToRetainAfterDiscardMs, @@ -156,10 +149,8 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { minTimeBetweenBufferReevaluationMs, clock); } - } - public static final int DEFAULT_MAX_INITIAL_BITRATE = 800000; public static final int DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS = 10000; public static final int DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS = 25000; public static final int DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS = 25000; @@ -168,7 +159,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { public static final long DEFAULT_MIN_TIME_BETWEEN_BUFFER_REEVALUTATION_MS = 2000; private final BandwidthMeter bandwidthMeter; - private final int maxInitialBitrate; private final long minDurationForQualityIncreaseUs; private final long maxDurationForQualityDecreaseUs; private final long minDurationToRetainAfterDiscardUs; @@ -194,7 +184,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { group, tracks, bandwidthMeter, - DEFAULT_MAX_INITIAL_BITRATE, DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS, DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS, DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS, @@ -209,8 +198,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { * @param tracks The indices of the selected tracks within the {@link TrackGroup}. Must not be * empty. May be in any order. * @param bandwidthMeter Provides an estimate of the currently available bandwidth. - * @param maxInitialBitrate The maximum bitrate in bits per second that should be assumed when a - * bandwidth estimate is unavailable. * @param minDurationForQualityIncreaseMs The minimum duration of buffered data required for the * selected track to switch to one of higher quality. * @param maxDurationForQualityDecreaseMs The maximum duration of buffered data required for the @@ -237,7 +224,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { TrackGroup group, int[] tracks, BandwidthMeter bandwidthMeter, - int maxInitialBitrate, long minDurationForQualityIncreaseMs, long maxDurationForQualityDecreaseMs, long minDurationToRetainAfterDiscardMs, @@ -247,7 +233,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { Clock clock) { super(group, tracks); this.bandwidthMeter = bandwidthMeter; - this.maxInitialBitrate = maxInitialBitrate; this.minDurationForQualityIncreaseUs = minDurationForQualityIncreaseMs * 1000L; this.maxDurationForQualityDecreaseUs = maxDurationForQualityDecreaseMs * 1000L; this.minDurationToRetainAfterDiscardUs = minDurationToRetainAfterDiscardMs * 1000L; @@ -369,9 +354,7 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { * Long#MIN_VALUE} to ignore blacklisting. */ private int determineIdealSelectedIndex(long nowMs) { - long bitrateEstimate = bandwidthMeter.getBitrateEstimate(); - long effectiveBitrate = bitrateEstimate == BandwidthMeter.NO_ESTIMATE - ? maxInitialBitrate : (long) (bitrateEstimate * bandwidthFraction); + long effectiveBitrate = (long) (bandwidthMeter.getBitrateEstimate() * bandwidthFraction); int lowestBitrateNonBlacklistedIndex = 0; for (int i = 0; i < length; i++) { if (nowMs == Long.MIN_VALUE || !isBlacklisted(i, nowMs)) { @@ -393,5 +376,4 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { ? (long) (availableDurationUs * bufferedFractionToLiveEdgeForQualityIncrease) : minDurationForQualityIncreaseUs; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/BandwidthMeter.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/BandwidthMeter.java index 21bdddf9b8..0a3fb967a8 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/BandwidthMeter.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/BandwidthMeter.java @@ -27,28 +27,17 @@ public interface BandwidthMeter { /** * Called periodically to indicate that bytes have been transferred. - *

- * Note: The estimated bitrate is typically derived from more information than just - * {@code bytes} and {@code elapsedMs}. + * + *

Note: The estimated bitrate is typically derived from more information than just {@code + * bytes} and {@code elapsedMs}. * * @param elapsedMs The time taken to transfer the bytes, in milliseconds. * @param bytes The number of bytes transferred. - * @param bitrate The estimated bitrate in bits/sec, or {@link #NO_ESTIMATE} if an estimate is - * not available. + * @param bitrate The estimated bitrate in bits/sec. */ void onBandwidthSample(int elapsedMs, long bytes, long bitrate); - } - /** - * Indicates no bandwidth estimate is available. - */ - long NO_ESTIMATE = -1; - - /** - * Returns the estimated bandwidth in bits/sec, or {@link #NO_ESTIMATE} if an estimate is not - * available. - */ + /** Returns the estimated bandwidth in bits/sec. */ long getBitrateEstimate(); - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultBandwidthMeter.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultBandwidthMeter.java index 0b9c30a483..f32965619a 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultBandwidthMeter.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultBandwidthMeter.java @@ -28,7 +28,7 @@ import com.google.android.exoplayer2.util.SlidingPercentile; public final class DefaultBandwidthMeter implements BandwidthMeter, TransferListener { /** Default initial bitrate estimate in bits per second. */ - public static final long DEFAULT_INITIAL_BITRATE_ESTIMATE = BandwidthMeter.NO_ESTIMATE; + public static final long DEFAULT_INITIAL_BITRATE_ESTIMATE = 1_000_000; /** Default maximum weight for the sliding window. */ public static final int DEFAULT_SLIDING_WINDOW_MAX_WEIGHT = 2000; diff --git a/library/core/src/test/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelectionTest.java b/library/core/src/test/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelectionTest.java index 956174f43b..4026bc0c37 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelectionTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelectionTest.java @@ -52,7 +52,6 @@ public final class AdaptiveTrackSelectionTest { public void setUp() { initMocks(this); fakeClock = new FakeClock(0); - when(mockBandwidthMeter.getBitrateEstimate()).thenReturn(BandwidthMeter.NO_ESTIMATE); } @Test @@ -62,7 +61,8 @@ public final class AdaptiveTrackSelectionTest { Format format3 = videoFormat(/* bitrate= */ 2000, /* width= */ 960, /* height= */ 720); TrackGroup trackGroup = new TrackGroup(format1, format2, format3); - adaptiveTrackSelection = adaptiveTrackSelection(trackGroup, /* initialBitrate= */ 1000); + when(mockBandwidthMeter.getBitrateEstimate()).thenReturn(1000L); + adaptiveTrackSelection = adaptiveTrackSelection(trackGroup); assertThat(adaptiveTrackSelection.getSelectedFormat()).isEqualTo(format2); assertThat(adaptiveTrackSelection.getSelectionReason()).isEqualTo(C.SELECTION_REASON_INITIAL); @@ -76,8 +76,7 @@ public final class AdaptiveTrackSelectionTest { TrackGroup trackGroup = new TrackGroup(format1, format2, format3); when(mockBandwidthMeter.getBitrateEstimate()).thenReturn(500L); - - adaptiveTrackSelection = adaptiveTrackSelection(trackGroup, /* initialBitrate= */ 1000); + adaptiveTrackSelection = adaptiveTrackSelection(trackGroup); assertThat(adaptiveTrackSelection.getSelectedFormat()).isEqualTo(format1); assertThat(adaptiveTrackSelection.getSelectionReason()).isEqualTo(C.SELECTION_REASON_INITIAL); @@ -90,13 +89,12 @@ public final class AdaptiveTrackSelectionTest { Format format3 = videoFormat(/* bitrate= */ 2000, /* width= */ 960, /* height= */ 720); TrackGroup trackGroup = new TrackGroup(format1, format2, format3); - // initially bandwidth meter does not have any estimation. The second measurement onward returns - // 2000L, which prompts the track selection to switch up if possible. - when(mockBandwidthMeter.getBitrateEstimate()).thenReturn(BandwidthMeter.NO_ESTIMATE, 2000L); - + // The second measurement onward returns 2000L, which prompts the track selection to switch up + // if possible. + when(mockBandwidthMeter.getBitrateEstimate()).thenReturn(1000L, 2000L); adaptiveTrackSelection = adaptiveTrackSelectionWithMinDurationForQualityIncreaseMs( - trackGroup, /* initialBitrate= */ 1000, /* minDurationForQualityIncreaseMs= */ 10_000); + trackGroup, /* minDurationForQualityIncreaseMs= */ 10_000); adaptiveTrackSelection.updateSelectedTrack( /* playbackPositionUs= */ 0, @@ -117,13 +115,12 @@ public final class AdaptiveTrackSelectionTest { Format format3 = videoFormat(/* bitrate= */ 2000, /* width= */ 960, /* height= */ 720); TrackGroup trackGroup = new TrackGroup(format1, format2, format3); - // initially bandwidth meter does not have any estimation. The second measurement onward returns - // 2000L, which prompts the track selection to switch up if possible. - when(mockBandwidthMeter.getBitrateEstimate()).thenReturn(BandwidthMeter.NO_ESTIMATE, 2000L); - + // The second measurement onward returns 2000L, which prompts the track selection to switch up + // if possible. + when(mockBandwidthMeter.getBitrateEstimate()).thenReturn(1000L, 2000L); adaptiveTrackSelection = adaptiveTrackSelectionWithMinDurationForQualityIncreaseMs( - trackGroup, /* initialBitrate= */ 1000, /* minDurationForQualityIncreaseMs= */ 10_000); + trackGroup, /* minDurationForQualityIncreaseMs= */ 10_000); adaptiveTrackSelection.updateSelectedTrack( /* playbackPositionUs= */ 0, @@ -144,13 +141,12 @@ public final class AdaptiveTrackSelectionTest { Format format3 = videoFormat(/* bitrate= */ 2000, /* width= */ 960, /* height= */ 720); TrackGroup trackGroup = new TrackGroup(format1, format2, format3); - // initially bandwidth meter does not have any estimation. The second measurement onward returns - // 500L, which prompts the track selection to switch down if necessary. - when(mockBandwidthMeter.getBitrateEstimate()).thenReturn(BandwidthMeter.NO_ESTIMATE, 500L); - + // The second measurement onward returns 500L, which prompts the track selection to switch down + // if necessary. + when(mockBandwidthMeter.getBitrateEstimate()).thenReturn(1000L, 500L); adaptiveTrackSelection = adaptiveTrackSelectionWithMaxDurationForQualityDecreaseMs( - trackGroup, /* initialBitrate= */ 1000, /* maxDurationForQualityDecreaseMs= */ 25_000); + trackGroup, /* maxDurationForQualityDecreaseMs= */ 25_000); adaptiveTrackSelection.updateSelectedTrack( /* playbackPositionUs= */ 0, @@ -171,13 +167,12 @@ public final class AdaptiveTrackSelectionTest { Format format3 = videoFormat(/* bitrate= */ 2000, /* width= */ 960, /* height= */ 720); TrackGroup trackGroup = new TrackGroup(format1, format2, format3); - // initially bandwidth meter does not have any estimation. The second measurement onward returns - // 500L, which prompts the track selection to switch down if necessary. - when(mockBandwidthMeter.getBitrateEstimate()).thenReturn(BandwidthMeter.NO_ESTIMATE, 500L); - + // The second measurement onward returns 500L, which prompts the track selection to switch down + // if necessary. + when(mockBandwidthMeter.getBitrateEstimate()).thenReturn(1000L, 500L); adaptiveTrackSelection = adaptiveTrackSelectionWithMaxDurationForQualityDecreaseMs( - trackGroup, /* initialBitrate= */ 1000, /* maxDurationForQualityDecreaseMs= */ 25_000); + trackGroup, /* maxDurationForQualityDecreaseMs= */ 25_000); adaptiveTrackSelection.updateSelectedTrack( /* playbackPositionUs= */ 0, @@ -210,7 +205,7 @@ public final class AdaptiveTrackSelectionTest { queue.add(chunk3); when(mockBandwidthMeter.getBitrateEstimate()).thenReturn(500L); - adaptiveTrackSelection = adaptiveTrackSelection(trackGroup, /* initialBitrate= */ 1000); + adaptiveTrackSelection = adaptiveTrackSelection(trackGroup); int size = adaptiveTrackSelection.evaluateQueueSize(0, queue); assertThat(size).isEqualTo(3); @@ -238,7 +233,6 @@ public final class AdaptiveTrackSelectionTest { adaptiveTrackSelection = adaptiveTrackSelectionWithMinTimeBetweenBufferReevaluationMs( trackGroup, - /* initialBitrate= */ 1000, /* durationToRetainAfterDiscardMs= */ 15_000, /* minTimeBetweenBufferReevaluationMs= */ 2000); @@ -276,7 +270,6 @@ public final class AdaptiveTrackSelectionTest { adaptiveTrackSelection = adaptiveTrackSelectionWithMinTimeBetweenBufferReevaluationMs( trackGroup, - /* initialBitrate= */ 1000, /* durationToRetainAfterDiscardMs= */ 15_000, /* minTimeBetweenBufferReevaluationMs= */ 2000); @@ -294,12 +287,11 @@ public final class AdaptiveTrackSelectionTest { assertThat(newSize).isEqualTo(2); } - private AdaptiveTrackSelection adaptiveTrackSelection(TrackGroup trackGroup, int initialBitrate) { + private AdaptiveTrackSelection adaptiveTrackSelection(TrackGroup trackGroup) { return new AdaptiveTrackSelection( trackGroup, selectedAllTracksInGroup(trackGroup), mockBandwidthMeter, - initialBitrate, AdaptiveTrackSelection.DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS, AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS, AdaptiveTrackSelection.DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS, @@ -310,12 +302,11 @@ public final class AdaptiveTrackSelectionTest { } private AdaptiveTrackSelection adaptiveTrackSelectionWithMinDurationForQualityIncreaseMs( - TrackGroup trackGroup, int initialBitrate, long minDurationForQualityIncreaseMs) { + TrackGroup trackGroup, long minDurationForQualityIncreaseMs) { return new AdaptiveTrackSelection( trackGroup, selectedAllTracksInGroup(trackGroup), mockBandwidthMeter, - initialBitrate, minDurationForQualityIncreaseMs, AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS, AdaptiveTrackSelection.DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS, @@ -326,12 +317,11 @@ public final class AdaptiveTrackSelectionTest { } private AdaptiveTrackSelection adaptiveTrackSelectionWithMaxDurationForQualityDecreaseMs( - TrackGroup trackGroup, int initialBitrate, long maxDurationForQualityDecreaseMs) { + TrackGroup trackGroup, long maxDurationForQualityDecreaseMs) { return new AdaptiveTrackSelection( trackGroup, selectedAllTracksInGroup(trackGroup), mockBandwidthMeter, - initialBitrate, AdaptiveTrackSelection.DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS, maxDurationForQualityDecreaseMs, AdaptiveTrackSelection.DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS, @@ -343,18 +333,16 @@ public final class AdaptiveTrackSelectionTest { private AdaptiveTrackSelection adaptiveTrackSelectionWithMinTimeBetweenBufferReevaluationMs( TrackGroup trackGroup, - int initialBitrate, long durationToRetainAfterDiscardMs, long minTimeBetweenBufferReevaluationMs) { return new AdaptiveTrackSelection( trackGroup, selectedAllTracksInGroup(trackGroup), mockBandwidthMeter, - initialBitrate, AdaptiveTrackSelection.DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS, AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS, durationToRetainAfterDiscardMs, - /* bandwidth fraction= */ 1.0f, + /* bandwidthFraction= */ 1.0f, AdaptiveTrackSelection.DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE, minTimeBetweenBufferReevaluationMs, fakeClock);