Add TrackSelectionUtil getBitratesUsingPastInfo
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=220066159
This commit is contained in:
parent
894bac6173
commit
0afd9c17e6
@ -17,8 +17,12 @@ package com.google.android.exoplayer2.trackselection;
|
||||
|
||||
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.source.chunk.MediaChunkListIterator;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/** Track selection related utility methods. */
|
||||
public final class TrackSelectionUtil {
|
||||
@ -58,10 +62,11 @@ public final class TrackSelectionUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns average 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.
|
||||
* Returns bitrate values for a set of tracks whose upcoming media chunk iterators and formats are
|
||||
* given.
|
||||
*
|
||||
* <p>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.
|
||||
@ -72,7 +77,7 @@ public final class TrackSelectionUtil {
|
||||
* estimation can't be calculated, {@link Format#NO_VALUE} is set.
|
||||
* @see #getAverageBitrate(MediaChunkIterator, long)
|
||||
*/
|
||||
public static int[] getAverageBitrates(
|
||||
public static int[] getBitratesUsingFutureInfo(
|
||||
MediaChunkIterator[] iterators, Format[] formats, long maxDurationUs) {
|
||||
int trackCount = iterators.length;
|
||||
Assertions.checkArgument(trackCount == formats.length);
|
||||
@ -102,26 +107,82 @@ public final class TrackSelectionUtil {
|
||||
}
|
||||
|
||||
if (needEstimateBitrate && canEstimateBitrate) {
|
||||
for (int i = 0; i < trackCount; i++) {
|
||||
if (bitrates[i] == Format.NO_VALUE) {
|
||||
int formatBitrate = formats[i].bitrate;
|
||||
if (formatBitrate != Format.NO_VALUE) {
|
||||
int closestFormat = findClosestBitrateFormat(formatBitrate, formatBitrates);
|
||||
bitrates[i] = (int) (bitrateRatios[closestFormat] * formatBitrate);
|
||||
}
|
||||
}
|
||||
}
|
||||
estimateBitrates(bitrates, formats, formatBitrates, bitrateRatios);
|
||||
}
|
||||
return bitrates;
|
||||
}
|
||||
|
||||
private static int findClosestBitrateFormat(int formatBitrate, int[] formatBitrates) {
|
||||
/**
|
||||
* 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.
|
||||
* @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)
|
||||
*/
|
||||
public static int[] getBitratesUsingPastInfo(
|
||||
List<? extends MediaChunk> queue, Format[] formats, long maxDurationUs) {
|
||||
int[] bitrates = new int[formats.length];
|
||||
Arrays.fill(bitrates, Format.NO_VALUE);
|
||||
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;
|
||||
}
|
||||
|
||||
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 void estimateBitrates(
|
||||
int[] bitrates, Format[] formats, int[] formatBitrates, float[] bitrateRatios) {
|
||||
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 closestFormat = getClosestBitrateIndex(formatBitrate, formatBitrates);
|
||||
bitrates[i] = (int) (bitrateRatios[closestFormat] * formatBitrate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -18,12 +18,14 @@ package com.google.android.exoplayer2.trackselection;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.source.chunk.BaseMediaChunkIterator;
|
||||
import com.google.android.exoplayer2.source.chunk.MediaChunkIterator;
|
||||
import com.google.android.exoplayer2.testutil.FakeMediaChunk;
|
||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
@ -96,11 +98,12 @@ public class TrackSelectionUtilTest {
|
||||
getAverageBitrate_chunksExceedingMaxDuration_returnsAverageChunkBitrateUpToMaxDuration() {
|
||||
long[] chunkTimeBoundariesSec = {0, 5, 15, 45, 50};
|
||||
long[] chunkLengths = {10, 20, 30, 100};
|
||||
|
||||
FakeIterator iterator = new FakeIterator(chunkTimeBoundariesSec, chunkLengths);
|
||||
|
||||
assertThat(TrackSelectionUtil.getAverageBitrate(iterator, 30 * C.MICROS_PER_SECOND))
|
||||
.isEqualTo(12);
|
||||
long maxDurationUs = 30 * C.MICROS_PER_SECOND;
|
||||
int averageBitrate = TrackSelectionUtil.getAverageBitrate(iterator, maxDurationUs);
|
||||
|
||||
assertThat(averageBitrate).isEqualTo(12);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -115,26 +118,26 @@ public class TrackSelectionUtilTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAverageBitrates_noIterator_returnsEmptyArray() {
|
||||
public void getBitratesUsingFutureInfo_noIterator_returnsEmptyArray() {
|
||||
assertThat(
|
||||
TrackSelectionUtil.getAverageBitrates(
|
||||
TrackSelectionUtil.getBitratesUsingFutureInfo(
|
||||
new MediaChunkIterator[0], new Format[0], MAX_DURATION_US))
|
||||
.hasLength(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAverageBitrates_emptyIterator_returnsNoValue() {
|
||||
int[] averageBitrates =
|
||||
TrackSelectionUtil.getAverageBitrates(
|
||||
public void getBitratesUsingFutureInfo_emptyIterator_returnsNoValue() {
|
||||
int[] bitrates =
|
||||
TrackSelectionUtil.getBitratesUsingFutureInfo(
|
||||
new MediaChunkIterator[] {MediaChunkIterator.EMPTY},
|
||||
new Format[] {createFormatWithBitrate(10)},
|
||||
MAX_DURATION_US);
|
||||
|
||||
assertThat(averageBitrates).asList().containsExactly(Format.NO_VALUE);
|
||||
assertThat(bitrates).asList().containsExactly(Format.NO_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAverageBitrates_twoTracks_returnsAverageChunkBitrates() {
|
||||
public void getBitratesUsingFutureInfo_twoTracksZeroMaxDuration_returnsNoValue() {
|
||||
FakeIterator iterator1 =
|
||||
new FakeIterator(
|
||||
/* chunkTimeBoundariesSec= */ new long[] {0, 10}, /* chunkLengths= */ new long[] {10});
|
||||
@ -143,35 +146,62 @@ public class TrackSelectionUtilTest {
|
||||
/* chunkTimeBoundariesSec= */ new long[] {0, 5, 15, 30},
|
||||
/* chunkLengths= */ new long[] {10, 20, 30});
|
||||
|
||||
int[] averageBitrates =
|
||||
TrackSelectionUtil.getAverageBitrates(
|
||||
int[] bitrates =
|
||||
TrackSelectionUtil.getBitratesUsingFutureInfo(
|
||||
new MediaChunkIterator[] {iterator1, iterator2},
|
||||
new Format[] {createFormatWithBitrate(10), createFormatWithBitrate(20)},
|
||||
/* maxDurationUs= */ 0);
|
||||
|
||||
assertThat(bitrates).asList().containsExactly(Format.NO_VALUE, Format.NO_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBitratesUsingFutureInfo_twoTracks_returnsBitrates() {
|
||||
FakeIterator iterator1 =
|
||||
new FakeIterator(
|
||||
/* chunkTimeBoundariesSec= */ new long[] {0, 10}, /* chunkLengths= */ new long[] {10});
|
||||
FakeIterator iterator2 =
|
||||
new FakeIterator(
|
||||
/* 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);
|
||||
|
||||
assertThat(averageBitrates).asList().containsExactly(8, 16).inOrder();
|
||||
assertThat(bitrates).asList().containsExactly(8, 16).inOrder();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAverageBitrates_oneEmptyIteratorOneWithChunks_returnsEstimationForEmpty() {
|
||||
public void getBitratesUsingFutureInfo_emptyIterator_returnsEstimationUsingClosest() {
|
||||
FakeIterator iterator1 =
|
||||
new FakeIterator(
|
||||
/* chunkTimeBoundariesSec= */ new long[] {0, 5}, /* chunkLengths= */ new long[] {10});
|
||||
Format format1 = createFormatWithBitrate(10);
|
||||
MediaChunkIterator iterator2 = MediaChunkIterator.EMPTY;
|
||||
Format format2 = createFormatWithBitrate(20);
|
||||
FakeIterator iterator3 =
|
||||
new FakeIterator(
|
||||
/* chunkTimeBoundariesSec= */ new long[] {0, 5}, /* chunkLengths= */ new long[] {50});
|
||||
Format format3 = createFormatWithBitrate(25);
|
||||
FakeIterator iterator4 =
|
||||
new FakeIterator(
|
||||
/* chunkTimeBoundariesSec= */ new long[] {0, 5}, /* chunkLengths= */ new long[] {20});
|
||||
Format format4 = createFormatWithBitrate(30);
|
||||
|
||||
int[] averageBitrates =
|
||||
TrackSelectionUtil.getAverageBitrates(
|
||||
new MediaChunkIterator[] {iterator1, iterator2},
|
||||
new Format[] {format1, format2},
|
||||
int[] bitrates =
|
||||
TrackSelectionUtil.getBitratesUsingFutureInfo(
|
||||
new MediaChunkIterator[] {iterator1, iterator2, iterator3, iterator4},
|
||||
new Format[] {format1, format2, format3, format4},
|
||||
MAX_DURATION_US);
|
||||
|
||||
assertThat(averageBitrates).asList().containsExactly(16, 32).inOrder();
|
||||
assertThat(bitrates).asList().containsExactly(16, 64, 80, 32).inOrder();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAverageBitrates_formatWithoutBitrate_returnsNoValueForEmpty() {
|
||||
public void getBitratesUsingFutureInfo_formatWithoutBitrate_returnsNoValueForEmpty() {
|
||||
FakeIterator iterator1 =
|
||||
new FakeIterator(
|
||||
/* chunkTimeBoundariesSec= */ new long[] {0, 5}, /* chunkLengths= */ new long[] {10});
|
||||
@ -179,16 +209,212 @@ public class TrackSelectionUtilTest {
|
||||
MediaChunkIterator iterator2 = MediaChunkIterator.EMPTY;
|
||||
Format format2 = createFormatWithBitrate(Format.NO_VALUE);
|
||||
|
||||
int[] averageBitrates =
|
||||
TrackSelectionUtil.getAverageBitrates(
|
||||
int[] bitrates =
|
||||
TrackSelectionUtil.getBitratesUsingFutureInfo(
|
||||
new MediaChunkIterator[] {iterator1, iterator2},
|
||||
new Format[] {format1, format2},
|
||||
MAX_DURATION_US);
|
||||
|
||||
assertThat(averageBitrates).asList().containsExactly(16, Format.NO_VALUE).inOrder();
|
||||
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);
|
||||
|
||||
assertThat(bitrates).hasLength(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBitratesUsingPastInfo_emptyQueue_returnsNoValue() {
|
||||
int[] bitrates =
|
||||
TrackSelectionUtil.getBitratesUsingPastInfo(
|
||||
Collections.emptyList(), new Format[] {createFormatWithBitrate(10)}, MAX_DURATION_US);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
assertThat(bitrates).asList().containsExactly(16, 24).inOrder();
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
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);
|
||||
|
||||
assertThat(bitrates).asList().containsExactly(16).inOrder();
|
||||
}
|
||||
|
||||
private static FakeMediaChunk createChunk(
|
||||
Format format, int length, int startTimeSec, int endTimeSec) {
|
||||
DataSpec dataSpec = new DataSpec(Uri.EMPTY, 0, length, null, 0);
|
||||
return new FakeMediaChunk(
|
||||
dataSpec, format, startTimeSec * C.MICROS_PER_SECOND, endTimeSec * C.MICROS_PER_SECOND);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static Format createFormatWithBitrate(int bitrate) {
|
||||
return Format.createSampleFormat(null, null, null, bitrate, null);
|
||||
}
|
||||
|
@ -30,9 +30,13 @@ public final class FakeMediaChunk extends MediaChunk {
|
||||
private static final DataSource DATA_SOURCE = new DefaultHttpDataSource("TEST_AGENT", null);
|
||||
|
||||
public FakeMediaChunk(Format trackFormat, long startTimeUs, long endTimeUs) {
|
||||
this(new DataSpec(Uri.EMPTY), trackFormat, startTimeUs, endTimeUs);
|
||||
}
|
||||
|
||||
public FakeMediaChunk(DataSpec dataSpec, Format trackFormat, long startTimeUs, long endTimeUs) {
|
||||
super(
|
||||
DATA_SOURCE,
|
||||
new DataSpec(Uri.EMPTY),
|
||||
dataSpec,
|
||||
trackFormat,
|
||||
C.SELECTION_REASON_ADAPTIVE,
|
||||
/* trackSelectionData= */ null,
|
||||
|
Loading…
x
Reference in New Issue
Block a user