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 b39a5d19f0..dd2d0001f8 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 @@ -391,7 +391,7 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { this.minTimeBetweenBufferReevaluationMs = minTimeBetweenBufferReevaluationMs; this.clock = clock; playbackSpeed = 1f; - reason = C.SELECTION_REASON_INITIAL; + reason = C.SELECTION_REASON_UNKNOWN; lastBufferEvaluationMs = C.TIME_UNSET; trackBitrateEstimator = TrackBitrateEstimator.DEFAULT; formats = new Format[length]; @@ -403,9 +403,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { formats[i] = format; formatBitrates[i] = formats[i].bitrate; } - @SuppressWarnings("nullness:method.invocation.invalid") - int selectedIndex = determineIdealSelectedIndex(Long.MIN_VALUE, formatBitrates); - this.selectedIndex = selectedIndex; } /** @@ -453,6 +450,13 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { // Update the estimated track bitrates. trackBitrateEstimator.getBitrates(formats, queue, mediaChunkIterators, trackBitrates); + // Make initial selection + if (reason == C.SELECTION_REASON_UNKNOWN) { + reason = C.SELECTION_REASON_INITIAL; + selectedIndex = determineIdealSelectedIndex(nowMs, trackBitrates); + return; + } + // Stash the current selection, then make a new one. int currentSelectedIndex = selectedIndex; selectedIndex = determineIdealSelectedIndex(nowMs, trackBitrates); 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 c3836e63f6..bf6b935161 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 @@ -244,7 +244,14 @@ public final class AdaptiveTrackSelectionTest { // But TrackBitrateEstimator returns 1500 for 3rd track so it should switch up. TrackBitrateEstimator estimator = mock(TrackBitrateEstimator.class); - when(estimator.getBitrates(any(), any(), any(), any())).thenReturn(new int[] {500, 1000, 1500}); + when(estimator.getBitrates(any(), any(), any(), any())) + .then( + (invocation) -> { + int[] returnValue = new int[] {500, 1000, 1500}; + int[] inputArray = (int[]) invocation.getArguments()[3]; + System.arraycopy(returnValue, 0, inputArray, 0, returnValue.length); + return returnValue; + }); adaptiveTrackSelection = adaptiveTrackSelection(trackGroup); adaptiveTrackSelection.experimental_setTrackBitrateEstimator(estimator); @@ -385,49 +392,64 @@ public final class AdaptiveTrackSelectionTest { private AdaptiveTrackSelection adaptiveTrackSelectionWithMinDurationForQualityIncreaseMs( TrackGroup trackGroup, long minDurationForQualityIncreaseMs) { - return new AdaptiveTrackSelection( - trackGroup, - selectedAllTracksInGroup(trackGroup), - mockBandwidthMeter, - minDurationForQualityIncreaseMs, - AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS, - AdaptiveTrackSelection.DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS, - /* bandwidthFraction= */ 1.0f, - AdaptiveTrackSelection.DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE, - AdaptiveTrackSelection.DEFAULT_MIN_TIME_BETWEEN_BUFFER_REEVALUTATION_MS, - fakeClock); + return prepareTrackSelection( + new AdaptiveTrackSelection( + trackGroup, + selectedAllTracksInGroup(trackGroup), + mockBandwidthMeter, + minDurationForQualityIncreaseMs, + AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS, + AdaptiveTrackSelection.DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS, + /* bandwidthFraction= */ 1.0f, + AdaptiveTrackSelection.DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE, + AdaptiveTrackSelection.DEFAULT_MIN_TIME_BETWEEN_BUFFER_REEVALUTATION_MS, + fakeClock)); } private AdaptiveTrackSelection adaptiveTrackSelectionWithMaxDurationForQualityDecreaseMs( TrackGroup trackGroup, long maxDurationForQualityDecreaseMs) { - return new AdaptiveTrackSelection( - trackGroup, - selectedAllTracksInGroup(trackGroup), - mockBandwidthMeter, - AdaptiveTrackSelection.DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS, - maxDurationForQualityDecreaseMs, - AdaptiveTrackSelection.DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS, - /* bandwidthFraction= */ 1.0f, - AdaptiveTrackSelection.DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE, - AdaptiveTrackSelection.DEFAULT_MIN_TIME_BETWEEN_BUFFER_REEVALUTATION_MS, - fakeClock); + return prepareTrackSelection( + new AdaptiveTrackSelection( + trackGroup, + selectedAllTracksInGroup(trackGroup), + mockBandwidthMeter, + AdaptiveTrackSelection.DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS, + maxDurationForQualityDecreaseMs, + AdaptiveTrackSelection.DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS, + /* bandwidthFraction= */ 1.0f, + AdaptiveTrackSelection.DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE, + AdaptiveTrackSelection.DEFAULT_MIN_TIME_BETWEEN_BUFFER_REEVALUTATION_MS, + fakeClock)); } private AdaptiveTrackSelection adaptiveTrackSelectionWithMinTimeBetweenBufferReevaluationMs( TrackGroup trackGroup, long durationToRetainAfterDiscardMs, long minTimeBetweenBufferReevaluationMs) { - return new AdaptiveTrackSelection( - trackGroup, - selectedAllTracksInGroup(trackGroup), - mockBandwidthMeter, - AdaptiveTrackSelection.DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS, - AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS, - durationToRetainAfterDiscardMs, - /* bandwidthFraction= */ 1.0f, - AdaptiveTrackSelection.DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE, - minTimeBetweenBufferReevaluationMs, - fakeClock); + return prepareTrackSelection( + new AdaptiveTrackSelection( + trackGroup, + selectedAllTracksInGroup(trackGroup), + mockBandwidthMeter, + AdaptiveTrackSelection.DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS, + AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS, + durationToRetainAfterDiscardMs, + /* bandwidthFraction= */ 1.0f, + AdaptiveTrackSelection.DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE, + minTimeBetweenBufferReevaluationMs, + fakeClock)); + } + + private AdaptiveTrackSelection prepareTrackSelection( + AdaptiveTrackSelection adaptiveTrackSelection) { + adaptiveTrackSelection.enable(); + adaptiveTrackSelection.updateSelectedTrack( + /* playbackPositionUs= */ 0, + /* bufferedDurationUs= */ 0, + /* availableDurationUs= */ C.TIME_UNSET, + /* queue= */ Collections.emptyList(), + /* mediaChunkIterators= */ THREE_EMPTY_MEDIA_CHUNK_ITERATORS); + return adaptiveTrackSelection; } private int[] selectedAllTracksInGroup(TrackGroup trackGroup) {