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 f457701031..fc3783d56b 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
@@ -47,8 +47,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
private final long minTimeBetweenBufferReevaluationMs;
private final Clock clock;
- private TrackBitrateEstimator trackBitrateEstimator;
-
/** Creates an adaptive track selection factory with default parameters. */
public Factory() {
this(
@@ -202,19 +200,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
bufferedFractionToLiveEdgeForQualityIncrease;
this.minTimeBetweenBufferReevaluationMs = minTimeBetweenBufferReevaluationMs;
this.clock = clock;
- trackBitrateEstimator = TrackBitrateEstimator.DEFAULT;
- }
-
- /**
- * Sets a TrackBitrateEstimator.
- *
- *
This method is experimental, and will be renamed or removed in a future release.
- *
- * @param trackBitrateEstimator A {@link TrackBitrateEstimator}.
- */
- public final void experimental_setTrackBitrateEstimator(
- TrackBitrateEstimator trackBitrateEstimator) {
- this.trackBitrateEstimator = trackBitrateEstimator;
}
@Override
@@ -245,7 +230,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
AdaptiveTrackSelection adaptiveSelection =
createAdaptiveTrackSelection(
definition.group, bandwidthMeter, definition.tracks, totalFixedBandwidth);
- adaptiveSelection.experimental_setTrackBitrateEstimator(trackBitrateEstimator);
adaptiveSelections.add(adaptiveSelection);
selections[i] = adaptiveSelection;
}
@@ -312,11 +296,7 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
private final float bufferedFractionToLiveEdgeForQualityIncrease;
private final long minTimeBetweenBufferReevaluationMs;
private final Clock clock;
- private final Format[] formats;
- private final int[] formatBitrates;
- private final int[] trackBitrates;
- private TrackBitrateEstimator trackBitrateEstimator;
private float playbackSpeed;
private int selectedIndex;
private int reason;
@@ -419,27 +399,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
playbackSpeed = 1f;
reason = C.SELECTION_REASON_UNKNOWN;
lastBufferEvaluationMs = C.TIME_UNSET;
- trackBitrateEstimator = TrackBitrateEstimator.DEFAULT;
- formats = new Format[length];
- formatBitrates = new int[length];
- trackBitrates = new int[length];
- for (int i = 0; i < length; i++) {
- @SuppressWarnings("nullness:method.invocation.invalid")
- Format format = getFormat(i);
- formats[i] = format;
- formatBitrates[i] = formats[i].bitrate;
- }
- }
-
- /**
- * Sets a TrackBitrateEstimator.
- *
- *
This method is experimental, and will be renamed or removed in a future release.
- *
- * @param trackBitrateEstimator A {@link TrackBitrateEstimator}.
- */
- public void experimental_setTrackBitrateEstimator(TrackBitrateEstimator trackBitrateEstimator) {
- this.trackBitrateEstimator = trackBitrateEstimator;
}
/**
@@ -472,19 +431,16 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
MediaChunkIterator[] mediaChunkIterators) {
long nowMs = clock.elapsedRealtime();
- // 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);
+ selectedIndex = determineIdealSelectedIndex(nowMs);
return;
}
// Stash the current selection, then make a new one.
int currentSelectedIndex = selectedIndex;
- selectedIndex = determineIdealSelectedIndex(nowMs, trackBitrates);
+ selectedIndex = determineIdealSelectedIndex(nowMs);
if (selectedIndex == currentSelectedIndex) {
return;
}
@@ -548,7 +504,7 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
if (playoutBufferedDurationBeforeLastChunkUs < minDurationToRetainAfterDiscardUs) {
return queueSize;
}
- int idealSelectedIndex = determineIdealSelectedIndex(nowMs, formatBitrates);
+ int idealSelectedIndex = determineIdealSelectedIndex(nowMs);
Format idealFormat = getFormat(idealSelectedIndex);
// If the chunks contain video, discard from the first SD chunk beyond
// minDurationToRetainAfterDiscardUs whose resolution and bitrate are both lower than the ideal
@@ -613,16 +569,14 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
*
* @param nowMs The current time in the timebase of {@link Clock#elapsedRealtime()}, or {@link
* Long#MIN_VALUE} to ignore blacklisting.
- * @param trackBitrates The estimated track bitrates. May differ from format bitrates if more
- * accurate estimates of the current track bitrates are available.
*/
- private int determineIdealSelectedIndex(long nowMs, int[] trackBitrates) {
+ private int determineIdealSelectedIndex(long nowMs) {
long effectiveBitrate = bandwidthProvider.getAllocatedBandwidth();
int lowestBitrateNonBlacklistedIndex = 0;
for (int i = 0; i < length; i++) {
if (nowMs == Long.MIN_VALUE || !isBlacklisted(i, nowMs)) {
Format format = getFormat(i);
- if (canSelectFormat(format, trackBitrates[i], playbackSpeed, effectiveBitrate)) {
+ if (canSelectFormat(format, format.bitrate, playbackSpeed, effectiveBitrate)) {
return i;
} else {
lowestBitrateNonBlacklistedIndex = i;
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackBitrateEstimator.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackBitrateEstimator.java
deleted file mode 100644
index 1cd6c09bfe..0000000000
--- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackBitrateEstimator.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.exoplayer2.trackselection;
-
-import androidx.annotation.Nullable;
-import com.google.android.exoplayer2.Format;
-import com.google.android.exoplayer2.source.chunk.MediaChunk;
-import com.google.android.exoplayer2.source.chunk.MediaChunkIterator;
-import java.util.List;
-
-/** Estimates track bitrate values. */
-public interface TrackBitrateEstimator {
-
- /**
- * A {@link TrackBitrateEstimator} that returns the bitrate values defined in the track formats.
- */
- TrackBitrateEstimator DEFAULT =
- (formats, queue, iterators, bitrates) ->
- TrackSelectionUtil.getFormatBitrates(formats, bitrates);
-
- /**
- * Returns bitrate values for a set of tracks whose formats are given.
- *
- * @param formats The track formats.
- * @param queue The queue of already buffered {@link MediaChunk} instances. Must not be modified.
- * @param iterators An array of {@link MediaChunkIterator}s providing information about the
- * sequence of upcoming media chunks for each track.
- * @param bitrates An array into which the bitrate values will be written. If non-null, this array
- * is the one that will be returned.
- * @return Bitrate values for the tracks. As long as the format of a track has set bitrate, a
- * bitrate value is set in the returned array. Otherwise it might be set to {@link
- * Format#NO_VALUE}.
- */
- int[] getBitrates(
- Format[] formats,
- List extends MediaChunk> queue,
- MediaChunkIterator[] iterators,
- @Nullable int[] bitrates);
-}
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionUtil.java
index 71afd87b0f..0f2748b1ac 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionUtil.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionUtil.java
@@ -16,18 +16,9 @@
package com.google.android.exoplayer2.trackselection;
import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-import com.google.android.exoplayer2.C;
-import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.source.TrackGroupArray;
-import com.google.android.exoplayer2.source.chunk.MediaChunk;
-import com.google.android.exoplayer2.source.chunk.MediaChunkIterator;
-import com.google.android.exoplayer2.source.chunk.MediaChunkListIterator;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride;
import com.google.android.exoplayer2.trackselection.TrackSelection.Definition;
-import com.google.android.exoplayer2.util.Assertions;
-import java.util.Arrays;
-import java.util.List;
import org.checkerframework.checker.nullness.compatqual.NullableType;
/** Track selection related utility methods. */
@@ -106,261 +97,4 @@ public final class TrackSelectionUtil {
}
return builder.build();
}
-
- /**
- * Returns average bitrate for chunks in bits per second. Chunks are included in average until
- * {@code maxDurationMs} or the first unknown length chunk.
- *
- * @param iterator Iterator for media chunk sequences.
- * @param maxDurationUs Maximum duration of chunks to be included in average bitrate, in
- * microseconds.
- * @return Average bitrate for chunks in bits per second, or {@link Format#NO_VALUE} if there are
- * no chunks or the first chunk length is unknown.
- */
- public static int getAverageBitrate(MediaChunkIterator iterator, long maxDurationUs) {
- long totalDurationUs = 0;
- long totalLength = 0;
- while (iterator.next()) {
- long chunkLength = iterator.getDataSpec().length;
- if (chunkLength == C.LENGTH_UNSET) {
- break;
- }
- long chunkDurationUs = iterator.getChunkEndTimeUs() - iterator.getChunkStartTimeUs();
- if (totalDurationUs + chunkDurationUs >= maxDurationUs) {
- totalLength += chunkLength * (maxDurationUs - totalDurationUs) / chunkDurationUs;
- totalDurationUs = maxDurationUs;
- break;
- }
- totalDurationUs += chunkDurationUs;
- totalLength += chunkLength;
- }
- return totalDurationUs == 0
- ? Format.NO_VALUE
- : (int) (totalLength * C.BITS_PER_BYTE * C.MICROS_PER_SECOND / totalDurationUs);
- }
-
- /**
- * Returns bitrate values for a set of tracks whose upcoming media chunk iterators and formats are
- * given.
- *
- *
If an average bitrate can't be calculated, an estimation is calculated using average bitrate
- * of another track and the ratio of the bitrate values defined in the formats of the two tracks.
- *
- * @param iterators An array of {@link MediaChunkIterator}s providing information about the
- * sequence of upcoming media chunks for each track.
- * @param formats The track formats.
- * @param maxDurationUs Maximum duration of chunks to be included in average bitrate values, in
- * microseconds.
- * @param bitrates If not null, stores bitrate values in this array.
- * @return Average bitrate values for the tracks. If for a track, an average bitrate or an
- * estimation can't be calculated, {@link Format#NO_VALUE} is set.
- * @see #getAverageBitrate(MediaChunkIterator, long)
- */
- @VisibleForTesting
- /* package */ static int[] getBitratesUsingFutureInfo(
- MediaChunkIterator[] iterators,
- Format[] formats,
- long maxDurationUs,
- @Nullable int[] bitrates) {
- int trackCount = iterators.length;
- Assertions.checkArgument(trackCount == formats.length);
- if (trackCount == 0) {
- return new int[0];
- }
- if (bitrates == null) {
- bitrates = new int[trackCount];
- }
- if (maxDurationUs == 0) {
- Arrays.fill(bitrates, Format.NO_VALUE);
- return bitrates;
- }
-
- int[] formatBitrates = new int[trackCount];
- float[] bitrateRatios = new float[trackCount];
- boolean needEstimateBitrate = false;
- boolean canEstimateBitrate = false;
- for (int i = 0; i < trackCount; i++) {
- int bitrate = getAverageBitrate(iterators[i], maxDurationUs);
- if (bitrate != Format.NO_VALUE) {
- int formatBitrate = formats[i].bitrate;
- formatBitrates[i] = formatBitrate;
- if (formatBitrate != Format.NO_VALUE) {
- bitrateRatios[i] = ((float) bitrate) / formatBitrate;
- canEstimateBitrate = true;
- }
- } else {
- needEstimateBitrate = true;
- formatBitrates[i] = Format.NO_VALUE;
- }
- bitrates[i] = bitrate;
- }
-
- if (needEstimateBitrate && canEstimateBitrate) {
- estimateBitrates(bitrates, formats, formatBitrates, bitrateRatios);
- }
- return bitrates;
- }
-
- /**
- * Returns bitrate values for a set of tracks whose formats are given, using the given queue of
- * already buffered {@link MediaChunk} instances.
- *
- * @param queue The queue of already buffered {@link MediaChunk} instances. Must not be modified.
- * @param formats The track formats.
- * @param maxDurationUs Maximum duration of chunks to be included in average bitrate values, in
- * microseconds.
- * @param bitrates If not null, calculates bitrate values only for indexes set to Format.NO_VALUE
- * and stores result in this array.
- * @return Bitrate values for the tracks. If for a track, a bitrate value can't be calculated,
- * {@link Format#NO_VALUE} is set.
- * @see #getBitratesUsingFutureInfo(MediaChunkIterator[], Format[], long, int[])
- */
- @VisibleForTesting
- /* package */ static int[] getBitratesUsingPastInfo(
- List extends MediaChunk> queue,
- Format[] formats,
- long maxDurationUs,
- @Nullable int[] bitrates) {
- if (bitrates == null) {
- bitrates = new int[formats.length];
- Arrays.fill(bitrates, Format.NO_VALUE);
- }
- if (maxDurationUs == 0) {
- return bitrates;
- }
- int queueAverageBitrate = getAverageQueueBitrate(queue, maxDurationUs);
- if (queueAverageBitrate == Format.NO_VALUE) {
- return bitrates;
- }
- int queueFormatBitrate = queue.get(queue.size() - 1).trackFormat.bitrate;
- if (queueFormatBitrate != Format.NO_VALUE) {
- float queueBitrateRatio = ((float) queueAverageBitrate) / queueFormatBitrate;
- estimateBitrates(
- bitrates, formats, new int[] {queueFormatBitrate}, new float[] {queueBitrateRatio});
- }
- return bitrates;
- }
-
- /**
- * Returns bitrate values for a set of tracks whose formats are given, using the given upcoming
- * media chunk iterators and the queue of already buffered {@link MediaChunk}s.
- *
- * @param formats The track formats.
- * @param queue The queue of already buffered {@link MediaChunk}s. Must not be modified.
- * @param maxPastDurationUs Maximum duration of past chunks to be included in average bitrate
- * values, in microseconds.
- * @param iterators An array of {@link MediaChunkIterator}s providing information about the
- * sequence of upcoming media chunks for each track.
- * @param maxFutureDurationUs Maximum duration of future chunks to be included in average bitrate
- * values, in microseconds.
- * @param useFormatBitrateAsLowerBound Whether to return the estimated bitrate only if it's higher
- * than the bitrate of the track's format.
- * @param bitrates An array into which the bitrate values will be written. If non-null, this array
- * is the one that will be returned.
- * @return Bitrate values for the tracks. As long as the format of a track has set bitrate, a
- * bitrate value is set in the returned array. Otherwise it might be set to {@link
- * Format#NO_VALUE}.
- */
- public static int[] getBitratesUsingPastAndFutureInfo(
- Format[] formats,
- List extends MediaChunk> queue,
- long maxPastDurationUs,
- MediaChunkIterator[] iterators,
- long maxFutureDurationUs,
- boolean useFormatBitrateAsLowerBound,
- @Nullable int[] bitrates) {
- bitrates = getBitratesUsingFutureInfo(iterators, formats, maxFutureDurationUs, bitrates);
- getBitratesUsingPastInfo(queue, formats, maxPastDurationUs, bitrates);
- for (int i = 0; i < bitrates.length; i++) {
- int bitrate = bitrates[i];
- if (bitrate == Format.NO_VALUE
- || (useFormatBitrateAsLowerBound
- && formats[i].bitrate != Format.NO_VALUE
- && bitrate < formats[i].bitrate)) {
- bitrates[i] = formats[i].bitrate;
- }
- }
- return bitrates;
- }
-
- /**
- * Returns an array containing {@link Format#bitrate} values for given each format in order.
- *
- * @param formats The format array to copy {@link Format#bitrate} values.
- * @param bitrates If not null, stores bitrate values in this array.
- * @return An array containing {@link Format#bitrate} values for given each format in order.
- */
- public static int[] getFormatBitrates(Format[] formats, @Nullable int[] bitrates) {
- int trackCount = formats.length;
- if (bitrates == null) {
- bitrates = new int[trackCount];
- }
- for (int i = 0; i < trackCount; i++) {
- bitrates[i] = formats[i].bitrate;
- }
- return bitrates;
- }
-
- /**
- * Fills missing values in the given {@code bitrates} array by calculates an estimation using the
- * closest reference bitrate value.
- *
- * @param bitrates An array of bitrates to be filled with estimations. Missing values are set to
- * {@link Format#NO_VALUE}.
- * @param formats An array of formats, one for each bitrate.
- * @param referenceBitrates An array of reference bitrates which are used to calculate
- * estimations.
- * @param referenceBitrateRatios An array containing ratio of reference bitrates to their bitrate
- * estimates.
- */
- private static void estimateBitrates(
- int[] bitrates, Format[] formats, int[] referenceBitrates, float[] referenceBitrateRatios) {
- for (int i = 0; i < bitrates.length; i++) {
- if (bitrates[i] == Format.NO_VALUE) {
- int formatBitrate = formats[i].bitrate;
- if (formatBitrate != Format.NO_VALUE) {
- int closestReferenceBitrateIndex =
- getClosestBitrateIndex(formatBitrate, referenceBitrates);
- bitrates[i] =
- (int) (referenceBitrateRatios[closestReferenceBitrateIndex] * formatBitrate);
- }
- }
- }
- }
-
- private static int getAverageQueueBitrate(List extends MediaChunk> queue, long maxDurationUs) {
- if (queue.isEmpty()) {
- return Format.NO_VALUE;
- }
- MediaChunkListIterator iterator =
- new MediaChunkListIterator(getSingleFormatSubQueue(queue), /* reverseOrder= */ true);
- return getAverageBitrate(iterator, maxDurationUs);
- }
-
- private static List extends MediaChunk> getSingleFormatSubQueue(
- List extends MediaChunk> queue) {
- Format queueFormat = queue.get(queue.size() - 1).trackFormat;
- int queueSize = queue.size();
- for (int i = queueSize - 2; i >= 0; i--) {
- if (!queue.get(i).trackFormat.equals(queueFormat)) {
- return queue.subList(i + 1, queueSize);
- }
- }
- return queue;
- }
-
- private static int getClosestBitrateIndex(int formatBitrate, int[] formatBitrates) {
- int closestDistance = Integer.MAX_VALUE;
- int closestFormat = C.INDEX_UNSET;
- for (int j = 0; j < formatBitrates.length; j++) {
- if (formatBitrates[j] != Format.NO_VALUE) {
- int distance = Math.abs(formatBitrates[j] - formatBitrate);
- if (distance < closestDistance) {
- closestDistance = distance;
- closestFormat = j;
- }
- }
- }
- return closestFormat;
- }
}
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/WindowedTrackBitrateEstimator.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/WindowedTrackBitrateEstimator.java
deleted file mode 100644
index 25f7e4ea73..0000000000
--- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/WindowedTrackBitrateEstimator.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.exoplayer2.trackselection;
-
-import androidx.annotation.Nullable;
-import com.google.android.exoplayer2.C;
-import com.google.android.exoplayer2.Format;
-import com.google.android.exoplayer2.source.chunk.MediaChunk;
-import com.google.android.exoplayer2.source.chunk.MediaChunkIterator;
-import java.util.List;
-
-/** A {@link TrackBitrateEstimator} which derives estimates from a window of time. */
-public final class WindowedTrackBitrateEstimator implements TrackBitrateEstimator {
-
- private final long maxPastDurationUs;
- private final long maxFutureDurationUs;
- private final boolean useFormatBitrateAsLowerBound;
-
- /**
- * @param maxPastDurationMs Maximum duration of past chunks to be included in average bitrate
- * values, in milliseconds.
- * @param maxFutureDurationMs Maximum duration of future chunks to be included in average bitrate
- * values, in milliseconds.
- * @param useFormatBitrateAsLowerBound Whether to use the bitrate of the track's format as a lower
- * bound for the estimated bitrate.
- */
- public WindowedTrackBitrateEstimator(
- long maxPastDurationMs, long maxFutureDurationMs, boolean useFormatBitrateAsLowerBound) {
- this.maxPastDurationUs = C.msToUs(maxPastDurationMs);
- this.maxFutureDurationUs = C.msToUs(maxFutureDurationMs);
- this.useFormatBitrateAsLowerBound = useFormatBitrateAsLowerBound;
- }
-
- @Override
- public int[] getBitrates(
- Format[] formats,
- List extends MediaChunk> queue,
- MediaChunkIterator[] iterators,
- @Nullable int[] bitrates) {
- if (maxFutureDurationUs > 0 || maxPastDurationUs > 0) {
- return TrackSelectionUtil.getBitratesUsingPastAndFutureInfo(
- formats,
- queue,
- maxPastDurationUs,
- iterators,
- maxFutureDurationUs,
- useFormatBitrateAsLowerBound,
- bitrates);
- }
- return TrackSelectionUtil.getFormatBitrates(formats, bitrates);
- }
-}
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 456f7f7107..af935048e8 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
@@ -16,9 +16,6 @@
package com.google.android.exoplayer2.trackselection;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -37,13 +34,11 @@ import com.google.android.exoplayer2.trackselection.TrackSelection.Definition;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.util.MimeTypes;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
/** Unit test for {@link AdaptiveTrackSelection}. */
@@ -231,54 +226,6 @@ public final class AdaptiveTrackSelectionTest {
assertThat(adaptiveTrackSelection.getSelectionReason()).isEqualTo(C.SELECTION_REASON_ADAPTIVE);
}
- @Test
- public void testUpdateSelectedTrackSwitchUpIfTrackBitrateEstimateIsLow() {
- Format format1 = videoFormat(/* bitrate= */ 500, /* width= */ 320, /* height= */ 240);
- Format format2 = videoFormat(/* bitrate= */ 1000, /* width= */ 640, /* height= */ 480);
- Format format3 = videoFormat(/* bitrate= */ 2000, /* width= */ 960, /* height= */ 720);
- TrackGroup trackGroup = new TrackGroup(format1, format2, format3);
-
- // The second measurement onward returns 1500L, which isn't enough to switch up to format3 as
- // the format bitrate is 2000.
- when(mockBandwidthMeter.getBitrateEstimate()).thenReturn(1000L, 1500L);
-
- // But TrackBitrateEstimator returns 1500 for 3rd track so it should switch up.
- TrackBitrateEstimator estimator = mock(TrackBitrateEstimator.class);
- 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);
-
- adaptiveTrackSelection.updateSelectedTrack(
- /* playbackPositionUs= */ 0,
- /* bufferedDurationUs= */ AdaptiveTrackSelection
- .DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS
- * 1000,
- /* availableDurationUs= */ C.TIME_UNSET,
- /* queue= */ Collections.emptyList(),
- /* mediaChunkIterators= */ THREE_EMPTY_MEDIA_CHUNK_ITERATORS);
-
- ArgumentMatcher matcher =
- formats ->
- formats.length == 3
- && Arrays.asList(formats).containsAll(Arrays.asList(format1, format2, format3));
- verify(estimator)
- .getBitrates(
- argThat(matcher),
- eq(Collections.emptyList()),
- eq(THREE_EMPTY_MEDIA_CHUNK_ITERATORS),
- any());
- assertThat(adaptiveTrackSelection.getSelectedFormat()).isEqualTo(format3);
- assertThat(adaptiveTrackSelection.getSelectionReason()).isEqualTo(C.SELECTION_REASON_ADAPTIVE);
- }
-
@Test
public void testEvaluateQueueSizeReturnQueueSizeIfBandwidthIsNotImproved() {
Format format1 = videoFormat(/* bitrate= */ 500, /* width= */ 320, /* height= */ 240);
diff --git a/library/core/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectionUtilTest.java b/library/core/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectionUtilTest.java
deleted file mode 100644
index 963e90f139..0000000000
--- a/library/core/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectionUtilTest.java
+++ /dev/null
@@ -1,617 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.google.android.exoplayer2.trackselection;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.net.Uri;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import com.google.android.exoplayer2.C;
-import com.google.android.exoplayer2.Format;
-import com.google.android.exoplayer2.source.chunk.MediaChunkIterator;
-import com.google.android.exoplayer2.testutil.FakeMediaChunk;
-import com.google.android.exoplayer2.testutil.FakeMediaChunkIterator;
-import com.google.android.exoplayer2.upstream.DataSpec;
-import java.util.Arrays;
-import java.util.Collections;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** {@link TrackSelectionUtil} tests. */
-@RunWith(AndroidJUnit4.class)
-public class TrackSelectionUtilTest {
-
- public static final long MAX_DURATION_US = 30 * C.MICROS_PER_SECOND;
-
- @Test
- public void getAverageBitrate_emptyIterator_returnsNoValue() {
- assertThat(TrackSelectionUtil.getAverageBitrate(MediaChunkIterator.EMPTY, MAX_DURATION_US))
- .isEqualTo(Format.NO_VALUE);
- }
-
- @Test
- public void getAverageBitrate_oneChunk_returnsChunkBitrate() {
- long[] chunkTimeBoundariesSec = {12, 17};
- long[] chunkLengths = {10};
-
- FakeMediaChunkIterator iterator =
- new FakeMediaChunkIterator(chunkTimeBoundariesSec, chunkLengths);
-
- assertThat(TrackSelectionUtil.getAverageBitrate(iterator, MAX_DURATION_US)).isEqualTo(16);
- }
-
- @Test
- public void getAverageBitrate_multipleSameDurationChunks_returnsAverageChunkBitrate() {
- long[] chunkTimeBoundariesSec = {0, 5, 10};
- long[] chunkLengths = {10, 20};
-
- FakeMediaChunkIterator iterator =
- new FakeMediaChunkIterator(chunkTimeBoundariesSec, chunkLengths);
-
- assertThat(TrackSelectionUtil.getAverageBitrate(iterator, MAX_DURATION_US)).isEqualTo(24);
- }
-
- @Test
- public void getAverageBitrate_multipleDifferentDurationChunks_returnsAverageChunkBitrate() {
- long[] chunkTimeBoundariesSec = {0, 5, 15, 30};
- long[] chunkLengths = {10, 20, 30};
-
- FakeMediaChunkIterator iterator =
- new FakeMediaChunkIterator(chunkTimeBoundariesSec, chunkLengths);
-
- assertThat(TrackSelectionUtil.getAverageBitrate(iterator, MAX_DURATION_US)).isEqualTo(16);
- }
-
- @Test
- public void getAverageBitrate_firstChunkLengthUnset_returnsNoValue() {
- long[] chunkTimeBoundariesSec = {0, 5, 15, 30};
- long[] chunkLengths = {C.LENGTH_UNSET, 20, 30};
-
- FakeMediaChunkIterator iterator =
- new FakeMediaChunkIterator(chunkTimeBoundariesSec, chunkLengths);
-
- assertThat(TrackSelectionUtil.getAverageBitrate(iterator, MAX_DURATION_US))
- .isEqualTo(Format.NO_VALUE);
- }
-
- @Test
- public void getAverageBitrate_secondChunkLengthUnset_returnsFirstChunkBitrate() {
- long[] chunkTimeBoundariesSec = {0, 5, 15, 30};
- long[] chunkLengths = {10, C.LENGTH_UNSET, 30};
-
- FakeMediaChunkIterator iterator =
- new FakeMediaChunkIterator(chunkTimeBoundariesSec, chunkLengths);
-
- assertThat(TrackSelectionUtil.getAverageBitrate(iterator, MAX_DURATION_US)).isEqualTo(16);
- }
-
- @Test
- public void
- getAverageBitrate_chunksExceedingMaxDuration_returnsAverageChunkBitrateUpToMaxDuration() {
- long[] chunkTimeBoundariesSec = {0, 5, 15, 45, 50};
- long[] chunkLengths = {10, 20, 30, 100};
- FakeMediaChunkIterator iterator =
- new FakeMediaChunkIterator(chunkTimeBoundariesSec, chunkLengths);
-
- long maxDurationUs = 30 * C.MICROS_PER_SECOND;
- int averageBitrate = TrackSelectionUtil.getAverageBitrate(iterator, maxDurationUs);
-
- assertThat(averageBitrate).isEqualTo(12);
- }
-
- @Test
- public void getAverageBitrate_zeroMaxDuration_returnsNoValue() {
- long[] chunkTimeBoundariesSec = {0, 5, 10};
- long[] chunkLengths = {10, 20};
-
- FakeMediaChunkIterator iterator =
- new FakeMediaChunkIterator(chunkTimeBoundariesSec, chunkLengths);
-
- assertThat(TrackSelectionUtil.getAverageBitrate(iterator, /* maxDurationUs= */ 0))
- .isEqualTo(Format.NO_VALUE);
- }
-
- @Test
- public void getBitratesUsingFutureInfo_noIterator_returnsEmptyArray() {
- assertThat(
- TrackSelectionUtil.getBitratesUsingFutureInfo(
- new MediaChunkIterator[0], new Format[0], MAX_DURATION_US, /* bitrates= */ null))
- .hasLength(0);
- }
-
- @Test
- public void getBitratesUsingFutureInfo_emptyIterator_returnsNoValue() {
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingFutureInfo(
- new MediaChunkIterator[] {MediaChunkIterator.EMPTY},
- new Format[] {createFormatWithBitrate(10)},
- MAX_DURATION_US,
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(Format.NO_VALUE);
- }
-
- @Test
- public void getBitratesUsingFutureInfo_twoTracksZeroMaxDuration_returnsNoValue() {
- FakeMediaChunkIterator iterator1 =
- new FakeMediaChunkIterator(
- /* chunkTimeBoundariesSec= */ new long[] {0, 10}, /* chunkLengths= */ new long[] {10});
- FakeMediaChunkIterator iterator2 =
- new FakeMediaChunkIterator(
- /* chunkTimeBoundariesSec= */ new long[] {0, 5, 15, 30},
- /* chunkLengths= */ new long[] {10, 20, 30});
-
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingFutureInfo(
- new MediaChunkIterator[] {iterator1, iterator2},
- new Format[] {createFormatWithBitrate(10), createFormatWithBitrate(20)},
- /* maxDurationUs= */ 0,
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(Format.NO_VALUE, Format.NO_VALUE);
- }
-
- @Test
- public void getBitratesUsingFutureInfo_twoTracks_returnsBitrates() {
- FakeMediaChunkIterator iterator1 =
- new FakeMediaChunkIterator(
- /* chunkTimeBoundariesSec= */ new long[] {0, 10}, /* chunkLengths= */ new long[] {10});
- FakeMediaChunkIterator iterator2 =
- new FakeMediaChunkIterator(
- /* chunkTimeBoundariesSec= */ new long[] {0, 5, 15, 30},
- /* chunkLengths= */ new long[] {10, 20, 30});
-
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingFutureInfo(
- new MediaChunkIterator[] {iterator1, iterator2},
- new Format[] {createFormatWithBitrate(10), createFormatWithBitrate(20)},
- MAX_DURATION_US,
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(8, 16).inOrder();
- }
-
- @Test
- public void getBitratesUsingFutureInfo_bitratesArrayGiven_returnsTheSameArray() {
- FakeMediaChunkIterator iterator1 =
- new FakeMediaChunkIterator(
- /* chunkTimeBoundariesSec= */ new long[] {0, 10}, /* chunkLengths= */ new long[] {10});
- FakeMediaChunkIterator iterator2 =
- new FakeMediaChunkIterator(
- /* chunkTimeBoundariesSec= */ new long[] {0, 5, 15, 30},
- /* chunkLengths= */ new long[] {10, 20, 30});
-
- int[] bitratesArrayToUse = new int[2];
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingFutureInfo(
- new MediaChunkIterator[] {iterator1, iterator2},
- new Format[] {createFormatWithBitrate(10), createFormatWithBitrate(20)},
- MAX_DURATION_US,
- bitratesArrayToUse);
-
- assertThat(bitrates).isSameInstanceAs(bitratesArrayToUse);
- }
-
- @Test
- public void getBitratesUsingFutureInfo_emptyIterator_returnsEstimationUsingClosest() {
- FakeMediaChunkIterator iterator1 =
- new FakeMediaChunkIterator(
- /* chunkTimeBoundariesSec= */ new long[] {0, 5}, /* chunkLengths= */ new long[] {10});
- Format format1 = createFormatWithBitrate(10);
- MediaChunkIterator iterator2 = MediaChunkIterator.EMPTY;
- Format format2 = createFormatWithBitrate(20);
- FakeMediaChunkIterator iterator3 =
- new FakeMediaChunkIterator(
- /* chunkTimeBoundariesSec= */ new long[] {0, 5}, /* chunkLengths= */ new long[] {50});
- Format format3 = createFormatWithBitrate(25);
- FakeMediaChunkIterator iterator4 =
- new FakeMediaChunkIterator(
- /* chunkTimeBoundariesSec= */ new long[] {0, 5}, /* chunkLengths= */ new long[] {20});
- Format format4 = createFormatWithBitrate(30);
-
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingFutureInfo(
- new MediaChunkIterator[] {iterator1, iterator2, iterator3, iterator4},
- new Format[] {format1, format2, format3, format4},
- MAX_DURATION_US,
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(16, 64, 80, 32).inOrder();
- }
-
- @Test
- public void getBitratesUsingFutureInfo_formatWithoutBitrate_returnsNoValueForEmpty() {
- FakeMediaChunkIterator iterator1 =
- new FakeMediaChunkIterator(
- /* chunkTimeBoundariesSec= */ new long[] {0, 5}, /* chunkLengths= */ new long[] {10});
- Format format1 = createFormatWithBitrate(10);
- MediaChunkIterator iterator2 = MediaChunkIterator.EMPTY;
- Format format2 = createFormatWithBitrate(Format.NO_VALUE);
-
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingFutureInfo(
- new MediaChunkIterator[] {iterator1, iterator2},
- new Format[] {format1, format2},
- MAX_DURATION_US,
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(16, Format.NO_VALUE).inOrder();
- }
-
- @Test
- public void getBitratesUsingPastInfo_noFormat_returnsEmptyArray() {
- FakeMediaChunk chunk =
- createChunk(
- createFormatWithBitrate(10),
- /* length= */ 10,
- /* startTimeSec= */ 0,
- /* endTimeSec= */ 10);
-
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingPastInfo(
- Collections.singletonList(chunk), new Format[0], MAX_DURATION_US, /* bitrates= */ null);
-
- assertThat(bitrates).hasLength(0);
- }
-
- @Test
- public void getBitratesUsingPastInfo_emptyQueue_returnsNoValue() {
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingPastInfo(
- Collections.emptyList(),
- new Format[] {createFormatWithBitrate(10)},
- MAX_DURATION_US,
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(Format.NO_VALUE);
- }
-
- @Test
- public void getBitratesUsingPastInfo_oneChunkFormatNoBitrate_returnsNoValue() {
- Format format = createFormatWithBitrate(Format.NO_VALUE);
- FakeMediaChunk chunk =
- createChunk(format, /* length= */ 10, /* startTimeSec= */ 0, /* endTimeSec= */ 10);
-
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingPastInfo(
- Collections.singletonList(chunk),
- new Format[] {format},
- MAX_DURATION_US,
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(Format.NO_VALUE);
- }
-
- @Test
- public void getBitratesUsingPastInfo_oneChunkNoLength_returnsNoValue() {
- Format format = createFormatWithBitrate(10);
- FakeMediaChunk chunk =
- createChunk(
- format, /* length= */ C.LENGTH_UNSET, /* startTimeSec= */ 0, /* endTimeSec= */ 10);
-
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingPastInfo(
- Collections.singletonList(chunk),
- new Format[] {format},
- MAX_DURATION_US,
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(Format.NO_VALUE);
- }
-
- @Test
- public void getBitratesUsingPastInfo_oneChunkWithSameFormat_returnsBitrates() {
- Format format = createFormatWithBitrate(10);
- FakeMediaChunk chunk =
- createChunk(format, /* length= */ 10, /* startTimeSec= */ 0, /* endTimeSec= */ 10);
-
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingPastInfo(
- Collections.singletonList(chunk),
- new Format[] {format},
- MAX_DURATION_US,
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(8).inOrder();
- }
-
- @Test
- public void getBitratesUsingPastInfo_zeroMaxDuration_returnsNoValue() {
- Format format = createFormatWithBitrate(10);
- FakeMediaChunk chunk =
- createChunk(format, /* length= */ 10, /* startTimeSec= */ 0, /* endTimeSec= */ 10);
-
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingPastInfo(
- Collections.singletonList(chunk),
- new Format[] {format},
- /* maxDurationUs= */ 0,
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(Format.NO_VALUE).inOrder();
- }
-
- @Test
- public void getBitratesUsingPastInfo_multipleChunkWithSameFormat_returnsAverageBitrate() {
- Format format = createFormatWithBitrate(10);
- FakeMediaChunk chunk =
- createChunk(format, /* length= */ 10, /* startTimeSec= */ 0, /* endTimeSec= */ 10);
- FakeMediaChunk chunk2 =
- createChunk(format, /* length= */ 20, /* startTimeSec= */ 10, /* endTimeSec= */ 20);
-
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingPastInfo(
- Arrays.asList(chunk, chunk2),
- new Format[] {format},
- MAX_DURATION_US,
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(12).inOrder();
- }
-
- @Test
- public void getBitratesUsingPastInfo_oneChunkWithDifferentFormat_returnsEstimationBitrate() {
- FakeMediaChunk chunk =
- createChunk(
- createFormatWithBitrate(10),
- /* length= */ 10,
- /* startTimeSec= */ 0,
- /* endTimeSec= */ 10);
-
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingPastInfo(
- Collections.singletonList(chunk),
- new Format[] {createFormatWithBitrate(20)},
- MAX_DURATION_US,
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(16).inOrder();
- }
-
- @Test
- public void getBitratesUsingPastInfo_trackFormatNoBitrate_returnsNoValue() {
- FakeMediaChunk chunk =
- createChunk(
- createFormatWithBitrate(10),
- /* length= */ 10,
- /* startTimeSec= */ 0,
- /* endTimeSec= */ 10);
-
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingPastInfo(
- Collections.singletonList(chunk),
- new Format[] {createFormatWithBitrate(Format.NO_VALUE)},
- MAX_DURATION_US,
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(Format.NO_VALUE);
- }
-
- @Test
- public void getBitratesUsingPastInfo_multipleTracks_returnsBitrates() {
- FakeMediaChunk chunk =
- createChunk(
- createFormatWithBitrate(10),
- /* length= */ 10,
- /* startTimeSec= */ 0,
- /* endTimeSec= */ 10);
-
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingPastInfo(
- Collections.singletonList(chunk),
- new Format[] {createFormatWithBitrate(20), createFormatWithBitrate(30)},
- MAX_DURATION_US,
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(16, 24).inOrder();
- }
-
- @Test
- public void getBitratesUsingPastInfo_bitratesArrayGiven_returnsTheSameArray() {
- FakeMediaChunk chunk =
- createChunk(
- createFormatWithBitrate(10),
- /* length= */ 10,
- /* startTimeSec= */ 0,
- /* endTimeSec= */ 10);
-
- int[] bitratesArrayToUse = new int[2];
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingPastInfo(
- Collections.singletonList(chunk),
- new Format[] {createFormatWithBitrate(20), createFormatWithBitrate(30)},
- MAX_DURATION_US,
- bitratesArrayToUse);
-
- assertThat(bitrates).isSameInstanceAs(bitratesArrayToUse);
- }
-
- @Test
- public void
- getBitratesUsingPastInfo_multipleChunkExceedingMaxDuration_returnsAverageUntilMaxDuration() {
- Format format = createFormatWithBitrate(10);
- FakeMediaChunk chunk =
- createChunk(format, /* length= */ 10, /* startTimeSec= */ 0, /* endTimeSec= */ 20);
- FakeMediaChunk chunk2 =
- createChunk(format, /* length= */ 40, /* startTimeSec= */ 20, /* endTimeSec= */ 40);
-
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingPastInfo(
- Arrays.asList(chunk, chunk2),
- new Format[] {format},
- /* maxDurationUs= */ 30 * C.MICROS_PER_SECOND,
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(12).inOrder();
- }
-
- @Test
- public void
- getBitratesUsingPastInfo_chunksWithDifferentFormats_returnsChunkAverageBitrateForLastFormat() {
- FakeMediaChunk chunk =
- createChunk(
- createFormatWithBitrate(10),
- /* length= */ 10,
- /* startTimeSec= */ 0,
- /* endTimeSec= */ 10);
- FakeMediaChunk chunk2 =
- createChunk(
- createFormatWithBitrate(20),
- /* length= */ 40,
- /* startTimeSec= */ 10,
- /* endTimeSec= */ 20);
-
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingPastInfo(
- Arrays.asList(chunk, chunk2),
- new Format[] {createFormatWithBitrate(10)},
- MAX_DURATION_US,
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(16).inOrder();
- }
-
- @Test
- public void getBitratesUsingPastAndFutureInfo_noPastInfo_returnsBitratesUsingOnlyFutureInfo() {
- FakeMediaChunkIterator iterator1 =
- new FakeMediaChunkIterator(
- /* chunkTimeBoundariesSec= */ new long[] {0, 10}, /* chunkLengths= */ new long[] {10});
- FakeMediaChunkIterator iterator2 =
- new FakeMediaChunkIterator(
- /* chunkTimeBoundariesSec= */ new long[] {0, 5, 15, 30},
- /* chunkLengths= */ new long[] {10, 20, 30});
-
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingPastAndFutureInfo(
- new Format[] {createFormatWithBitrate(10), createFormatWithBitrate(20)},
- Collections.emptyList(),
- MAX_DURATION_US,
- new MediaChunkIterator[] {iterator1, iterator2},
- MAX_DURATION_US,
- /* useFormatBitrateAsLowerBound= */ false,
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(8, 16).inOrder();
- }
-
- @Test
- public void getBitratesUsingPastAndFutureInfo_noFutureInfo_returnsBitratesUsingOnlyPastInfo() {
- FakeMediaChunk chunk =
- createChunk(
- createFormatWithBitrate(10),
- /* length= */ 10,
- /* startTimeSec= */ 0,
- /* endTimeSec= */ 10);
-
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingPastAndFutureInfo(
- new Format[] {createFormatWithBitrate(20), createFormatWithBitrate(30)},
- Collections.singletonList(chunk),
- MAX_DURATION_US,
- new MediaChunkIterator[] {MediaChunkIterator.EMPTY, MediaChunkIterator.EMPTY},
- MAX_DURATION_US,
- /* useFormatBitrateAsLowerBound= */ false,
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(16, 24).inOrder();
- }
-
- @Test
- public void
- getBitratesUsingPastAndFutureInfo_pastAndFutureInfo_returnsBitratesUsingOnlyFutureInfo() {
- FakeMediaChunk chunk =
- createChunk(
- createFormatWithBitrate(5),
- /* length= */ 10,
- /* startTimeSec= */ 0,
- /* endTimeSec= */ 10);
- FakeMediaChunkIterator iterator1 =
- new FakeMediaChunkIterator(
- /* chunkTimeBoundariesSec= */ new long[] {0, 10}, /* chunkLengths= */ new long[] {10});
- FakeMediaChunkIterator iterator2 =
- new FakeMediaChunkIterator(
- /* chunkTimeBoundariesSec= */ new long[] {0, 5, 15, 30},
- /* chunkLengths= */ new long[] {10, 20, 30});
-
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingPastAndFutureInfo(
- new Format[] {createFormatWithBitrate(10), createFormatWithBitrate(20)},
- Collections.singletonList(chunk),
- MAX_DURATION_US,
- new MediaChunkIterator[] {iterator1, iterator2},
- MAX_DURATION_US,
- /* useFormatBitrateAsLowerBound= */ false,
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(8, 16).inOrder();
- }
-
- @Test
- public void getBitratesUsingPastAndFutureInfo_noPastAndFutureInfo_returnsBitratesOfFormats() {
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingPastAndFutureInfo(
- new Format[] {createFormatWithBitrate(10), createFormatWithBitrate(20)},
- Collections.emptyList(),
- MAX_DURATION_US,
- new MediaChunkIterator[] {MediaChunkIterator.EMPTY, MediaChunkIterator.EMPTY},
- MAX_DURATION_US,
- /* useFormatBitrateAsLowerBound= */ false,
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(10, 20).inOrder();
- }
-
- @Test
- public void
- getBitratesUsingPastAndFutureInfo_estimatesLowerAndUseFormatBitrateAsLowerBoundTrue_returnsBitratesOfFormats() {
- FakeMediaChunk chunk =
- createChunk(
- createFormatWithBitrate(10),
- /* length= */ 10,
- /* startTimeSec= */ 0,
- /* endTimeSec= */ 10);
-
- int[] bitrates =
- TrackSelectionUtil.getBitratesUsingPastAndFutureInfo(
- new Format[] {createFormatWithBitrate(20), createFormatWithBitrate(30)},
- Collections.singletonList(chunk),
- MAX_DURATION_US,
- new MediaChunkIterator[] {MediaChunkIterator.EMPTY, MediaChunkIterator.EMPTY},
- MAX_DURATION_US,
- /* useFormatBitrateAsLowerBound= */ true,
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(20, 30).inOrder();
- }
-
- private static FakeMediaChunk createChunk(
- Format format, int length, int startTimeSec, int endTimeSec) {
- DataSpec dataSpec =
- new DataSpec(
- Uri.EMPTY, /* absoluteStreamPosition= */ 0, length, /* key= */ null, /* flags= */ 0);
- return new FakeMediaChunk(
- dataSpec, format, startTimeSec * C.MICROS_PER_SECOND, endTimeSec * C.MICROS_PER_SECOND);
- }
-
- private static Format createFormatWithBitrate(int bitrate) {
- return Format.createSampleFormat(
- /* id= */ null,
- /* sampleMimeType= */ null,
- /* codecs= */ null,
- bitrate,
- /* drmInitData= */ null);
- }
-}
diff --git a/library/core/src/test/java/com/google/android/exoplayer2/trackselection/WindowedTrackBitrateEstimatorTest.java b/library/core/src/test/java/com/google/android/exoplayer2/trackselection/WindowedTrackBitrateEstimatorTest.java
deleted file mode 100644
index d40149baae..0000000000
--- a/library/core/src/test/java/com/google/android/exoplayer2/trackselection/WindowedTrackBitrateEstimatorTest.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.exoplayer2.trackselection;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.net.Uri;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import com.google.android.exoplayer2.C;
-import com.google.android.exoplayer2.Format;
-import com.google.android.exoplayer2.source.chunk.MediaChunk;
-import com.google.android.exoplayer2.source.chunk.MediaChunkIterator;
-import com.google.android.exoplayer2.testutil.FakeMediaChunk;
-import com.google.android.exoplayer2.testutil.FakeMediaChunkIterator;
-import com.google.android.exoplayer2.upstream.DataSpec;
-import java.util.Collections;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** {@link WindowedTrackBitrateEstimator} tests. */
-@RunWith(AndroidJUnit4.class)
-public class WindowedTrackBitrateEstimatorTest {
-
- private static final long MAX_DURATION_MS = 30_000;
-
- @Test
- public void getBitrates_zeroMaxDuration_returnsFormatBitrates() {
- WindowedTrackBitrateEstimator estimator =
- new WindowedTrackBitrateEstimator(
- /* maxPastDurationMs= */ 0,
- /* maxFutureDurationMs= */ 0,
- /* useFormatBitrateAsLowerBound= */ false);
- MediaChunk chunk = createMediaChunk(/* formatBitrate= */ 5, /* actualBitrate= */ 10);
- MediaChunkIterator iterator1 = createMediaChunkIteratorWithBitrate(8);
- MediaChunkIterator iterator2 = createMediaChunkIteratorWithBitrate(16);
- Format format1 = createFormatWithBitrate(10);
- Format format2 = createFormatWithBitrate(20);
-
- int[] bitrates =
- estimator.getBitrates(
- new Format[] {format1, format2},
- Collections.singletonList(chunk),
- new MediaChunkIterator[] {iterator1, iterator2},
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(10, 20).inOrder();
- }
-
- @Test
- public void getBitrates_futureMaxDurationSet_returnsEstimateUsingFutureChunks() {
- WindowedTrackBitrateEstimator estimator =
- new WindowedTrackBitrateEstimator(
- /* maxPastDurationMs= */ 0, MAX_DURATION_MS, /* useFormatBitrateAsLowerBound= */ false);
- MediaChunk chunk = createMediaChunk(/* formatBitrate= */ 5, /* actualBitrate= */ 10);
- MediaChunkIterator iterator1 = createMediaChunkIteratorWithBitrate(8);
- MediaChunkIterator iterator2 = createMediaChunkIteratorWithBitrate(16);
- Format format1 = createFormatWithBitrate(10);
- Format format2 = createFormatWithBitrate(20);
-
- int[] bitrates =
- estimator.getBitrates(
- new Format[] {format1, format2},
- Collections.singletonList(chunk),
- new MediaChunkIterator[] {iterator1, iterator2},
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(8, 16).inOrder();
- }
-
- @Test
- public void getBitrates_pastMaxDurationSet_returnsEstimateUsingPastChunks() {
- WindowedTrackBitrateEstimator estimator =
- new WindowedTrackBitrateEstimator(
- MAX_DURATION_MS,
- /* maxFutureDurationMs= */ 0,
- /* useFormatBitrateAsLowerBound= */ false);
- MediaChunk chunk = createMediaChunk(/* formatBitrate= */ 5, /* actualBitrate= */ 10);
- MediaChunkIterator iterator1 = createMediaChunkIteratorWithBitrate(8);
- MediaChunkIterator iterator2 = createMediaChunkIteratorWithBitrate(16);
- Format format1 = createFormatWithBitrate(10);
- Format format2 = createFormatWithBitrate(20);
-
- int[] bitrates =
- estimator.getBitrates(
- new Format[] {format1, format2},
- Collections.singletonList(chunk),
- new MediaChunkIterator[] {iterator1, iterator2},
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(16, 32).inOrder();
- }
-
- @Test
- public void
- getBitrates_useFormatBitrateAsLowerBoundSetTrue_returnsEstimateIfOnlyHigherThanFormat() {
- WindowedTrackBitrateEstimator estimator =
- new WindowedTrackBitrateEstimator(
- MAX_DURATION_MS, MAX_DURATION_MS, /* useFormatBitrateAsLowerBound= */ true);
- MediaChunk chunk = createMediaChunk(/* formatBitrate= */ 5, /* actualBitrate= */ 10);
- MediaChunkIterator iterator1 = createMediaChunkIteratorWithBitrate(80);
- MediaChunkIterator iterator2 = createMediaChunkIteratorWithBitrate(16);
- Format format1 = createFormatWithBitrate(10);
- Format format2 = createFormatWithBitrate(20);
-
- int[] bitrates =
- estimator.getBitrates(
- new Format[] {format1, format2},
- Collections.singletonList(chunk),
- new MediaChunkIterator[] {iterator1, iterator2},
- /* bitrates= */ null);
-
- assertThat(bitrates).asList().containsExactly(80, 20).inOrder();
- }
-
- @Test
- public void getBitrates_bitratesArrayGiven_returnsTheSameArray() {
- WindowedTrackBitrateEstimator estimator =
- new WindowedTrackBitrateEstimator(
- MAX_DURATION_MS, MAX_DURATION_MS, /* useFormatBitrateAsLowerBound= */ true);
- MediaChunk chunk = createMediaChunk(/* formatBitrate= */ 5, /* actualBitrate= */ 10);
- MediaChunkIterator iterator1 = createMediaChunkIteratorWithBitrate(8);
- MediaChunkIterator iterator2 = createMediaChunkIteratorWithBitrate(16);
- Format format1 = createFormatWithBitrate(10);
- Format format2 = createFormatWithBitrate(20);
-
- int[] bitratesArrayToUse = new int[2];
- int[] bitrates =
- estimator.getBitrates(
- new Format[] {format1, format2},
- Collections.singletonList(chunk),
- new MediaChunkIterator[] {iterator1, iterator2},
- bitratesArrayToUse);
-
- assertThat(bitrates).isSameInstanceAs(bitratesArrayToUse);
- }
-
- private static MediaChunk createMediaChunk(int formatBitrate, int actualBitrate) {
- int length = actualBitrate / C.BITS_PER_BYTE;
- DataSpec dataSpec =
- new DataSpec(
- Uri.EMPTY, /* absoluteStreamPosition= */ 0, length, /* key= */ null, /* flags= */ 0);
- Format format = createFormatWithBitrate(formatBitrate);
- return new FakeMediaChunk(
- dataSpec, format, /* startTimeUs= */ 0L, /* endTimeUs= */ C.MICROS_PER_SECOND);
- }
-
- private static Format createFormatWithBitrate(int bitrate) {
- return Format.createSampleFormat(
- /* id= */ null,
- /* sampleMimeType= */ null,
- /* codecs= */ null,
- bitrate,
- /* drmInitData= */ null);
- }
-
- private static MediaChunkIterator createMediaChunkIteratorWithBitrate(int bitrate) {
- return new FakeMediaChunkIterator(
- /* chunkTimeBoundariesSec= */ new long[] {0, 1},
- /* chunkLengths= */ new long[] {bitrate / C.BITS_PER_BYTE});
- }
-}