mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Add multi-period ExoPlayer unit test
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=143475824
This commit is contained in:
parent
dbfb187b6a
commit
b774660989
@ -21,7 +21,6 @@ import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
|
||||
import com.google.android.exoplayer2.source.MediaPeriod;
|
||||
import com.google.android.exoplayer2.source.MediaSource;
|
||||
import com.google.android.exoplayer2.source.SampleStream;
|
||||
import com.google.android.exoplayer2.source.SinglePeriodTimeline;
|
||||
import com.google.android.exoplayer2.source.TrackGroup;
|
||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
|
||||
@ -49,16 +48,9 @@ public final class ExoPlayerTest extends TestCase {
|
||||
*/
|
||||
private static final int TIMEOUT_MS = 10000;
|
||||
|
||||
/**
|
||||
* Tests playback of a source that exposes a single period.
|
||||
*/
|
||||
public void testPlayToEnd() throws Exception {
|
||||
PlayerWrapper playerWrapper = new PlayerWrapper();
|
||||
Format format = Format.createVideoSampleFormat(null, MimeTypes.VIDEO_H264, null,
|
||||
Format.NO_VALUE, Format.NO_VALUE, 1280, 720, Format.NO_VALUE, null, null);
|
||||
playerWrapper.setup(new SinglePeriodTimeline(0, false), null, format);
|
||||
playerWrapper.blockUntilEnded(TIMEOUT_MS);
|
||||
}
|
||||
private static final Format TEST_VIDEO_FORMAT = Format.createVideoSampleFormat(null,
|
||||
MimeTypes.VIDEO_H264, null, Format.NO_VALUE, Format.NO_VALUE, 1280, 720, Format.NO_VALUE,
|
||||
null, null);
|
||||
|
||||
/**
|
||||
* Tests playback of a source that exposes an empty timeline. Playback is expected to end without
|
||||
@ -68,6 +60,42 @@ public final class ExoPlayerTest extends TestCase {
|
||||
PlayerWrapper playerWrapper = new PlayerWrapper();
|
||||
playerWrapper.setup(Timeline.EMPTY, null, null);
|
||||
playerWrapper.blockUntilEnded(TIMEOUT_MS);
|
||||
assertEquals(0, playerWrapper.positionDiscontinuityCount);
|
||||
assertEquals(0, playerWrapper.videoRenderer.formatReadCount);
|
||||
assertEquals(0, playerWrapper.videoRenderer.bufferReadCount);
|
||||
assertFalse(playerWrapper.videoRenderer.isEnded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests playback of a source that exposes a single period.
|
||||
*/
|
||||
public void testPlaySinglePeriodTimeline() throws Exception {
|
||||
PlayerWrapper playerWrapper = new PlayerWrapper();
|
||||
Timeline timeline = new FakeTimeline(
|
||||
new TimelineWindowDefinition(false, false, 0));
|
||||
playerWrapper.setup(timeline, null, TEST_VIDEO_FORMAT);
|
||||
playerWrapper.blockUntilEnded(TIMEOUT_MS);
|
||||
assertEquals(0, playerWrapper.positionDiscontinuityCount);
|
||||
assertEquals(1, playerWrapper.videoRenderer.formatReadCount);
|
||||
assertEquals(1, playerWrapper.videoRenderer.bufferReadCount);
|
||||
assertTrue(playerWrapper.videoRenderer.isEnded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests playback of a source that exposes three periods.
|
||||
*/
|
||||
public void testPlayMultiPeriodTimeline() throws Exception {
|
||||
PlayerWrapper playerWrapper = new PlayerWrapper();
|
||||
Timeline timeline = new FakeTimeline(
|
||||
new TimelineWindowDefinition(false, false, 0),
|
||||
new TimelineWindowDefinition(false, false, 0),
|
||||
new TimelineWindowDefinition(false, false, 0));
|
||||
playerWrapper.setup(timeline, null, TEST_VIDEO_FORMAT);
|
||||
playerWrapper.blockUntilEnded(TIMEOUT_MS);
|
||||
assertEquals(2, playerWrapper.positionDiscontinuityCount);
|
||||
assertEquals(3, playerWrapper.videoRenderer.formatReadCount);
|
||||
assertEquals(1, playerWrapper.videoRenderer.bufferReadCount);
|
||||
assertTrue(playerWrapper.videoRenderer.isEnded);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -82,9 +110,12 @@ public final class ExoPlayerTest extends TestCase {
|
||||
private Timeline expectedTimeline;
|
||||
private Object expectedManifest;
|
||||
private Format expectedFormat;
|
||||
private FakeVideoRenderer videoRenderer;
|
||||
private ExoPlayer player;
|
||||
private Exception exception;
|
||||
|
||||
private int positionDiscontinuityCount;
|
||||
|
||||
public PlayerWrapper() {
|
||||
endedCountDownLatch = new CountDownLatch(1);
|
||||
playerThread = new HandlerThread("ExoPlayerTest thread");
|
||||
@ -113,8 +144,8 @@ public final class ExoPlayerTest extends TestCase {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Renderer fakeRenderer = new FakeVideoRenderer(expectedFormat);
|
||||
player = ExoPlayerFactory.newInstance(new Renderer[] {fakeRenderer},
|
||||
videoRenderer = new FakeVideoRenderer(expectedFormat);
|
||||
player = ExoPlayerFactory.newInstance(new Renderer[] {videoRenderer},
|
||||
new DefaultTrackSelector());
|
||||
player.addListener(PlayerWrapper.this);
|
||||
player.setPlayWhenReady(true);
|
||||
@ -184,8 +215,66 @@ public final class ExoPlayerTest extends TestCase {
|
||||
|
||||
@Override
|
||||
public void onPositionDiscontinuity() {
|
||||
// Should never happen.
|
||||
handleError(new IllegalStateException("Received position discontinuity"));
|
||||
positionDiscontinuityCount++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final class TimelineWindowDefinition {
|
||||
|
||||
public final boolean isSeekable;
|
||||
public final boolean isDynamic;
|
||||
public final long durationUs;
|
||||
|
||||
public TimelineWindowDefinition(boolean isSeekable, boolean isDynamic, long durationUs) {
|
||||
this.isSeekable = isSeekable;
|
||||
this.isDynamic = isDynamic;
|
||||
this.durationUs = durationUs;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final class FakeTimeline extends Timeline {
|
||||
|
||||
private final TimelineWindowDefinition[] windowDefinitions;
|
||||
|
||||
public FakeTimeline(TimelineWindowDefinition... windowDefinitions) {
|
||||
this.windowDefinitions = windowDefinitions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWindowCount() {
|
||||
return windowDefinitions.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Window getWindow(int windowIndex, Window window, boolean setIds,
|
||||
long defaultPositionProjectionUs) {
|
||||
TimelineWindowDefinition windowDefinition = windowDefinitions[windowIndex];
|
||||
Object id = setIds ? windowIndex : null;
|
||||
return window.set(id, C.TIME_UNSET, C.TIME_UNSET, windowDefinition.isSeekable,
|
||||
windowDefinition.isDynamic, 0, windowDefinition.durationUs, windowIndex, windowIndex, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPeriodCount() {
|
||||
return windowDefinitions.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Period getPeriod(int periodIndex, Period period, boolean setIds) {
|
||||
TimelineWindowDefinition windowDefinition = windowDefinitions[periodIndex];
|
||||
Object id = setIds ? periodIndex : null;
|
||||
return period.set(id, id, periodIndex, windowDefinition.durationUs, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndexOfPeriod(Object uid) {
|
||||
if (!(uid instanceof Integer)) {
|
||||
return C.INDEX_UNSET;
|
||||
}
|
||||
int index = (Integer) uid;
|
||||
return index >= 0 && index < windowDefinitions.length ? index : C.INDEX_UNSET;
|
||||
}
|
||||
|
||||
}
|
||||
@ -228,7 +317,6 @@ public final class ExoPlayerTest extends TestCase {
|
||||
Assertions.checkIndex(index, 0, timeline.getPeriodCount());
|
||||
assertTrue(preparedSource);
|
||||
assertFalse(releasedSource);
|
||||
assertEquals(0, index);
|
||||
assertEquals(0, positionUs);
|
||||
FakeMediaPeriod mediaPeriod = new FakeMediaPeriod(format);
|
||||
activeMediaPeriods.add(mediaPeriod);
|
||||
@ -332,7 +420,7 @@ public final class ExoPlayerTest extends TestCase {
|
||||
@Override
|
||||
public long getNextLoadPositionUs() {
|
||||
assertTrue(preparedPeriod);
|
||||
return 0;
|
||||
return C.TIME_END_OF_SOURCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -352,7 +440,6 @@ public final class ExoPlayerTest extends TestCase {
|
||||
private final Format format;
|
||||
|
||||
private boolean readFormat;
|
||||
private boolean readEndOfStream;
|
||||
|
||||
public FakeSampleStream(Format format) {
|
||||
this.format = format;
|
||||
@ -365,10 +452,8 @@ public final class ExoPlayerTest extends TestCase {
|
||||
|
||||
@Override
|
||||
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer) {
|
||||
Assertions.checkState(!readEndOfStream);
|
||||
if (readFormat) {
|
||||
buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
|
||||
readEndOfStream = true;
|
||||
return C.RESULT_BUFFER_READ;
|
||||
}
|
||||
formatHolder.format = format;
|
||||
@ -390,12 +475,14 @@ public final class ExoPlayerTest extends TestCase {
|
||||
|
||||
/**
|
||||
* Fake {@link Renderer} that supports any video format. The renderer verifies that it reads a
|
||||
* given {@link Format} then a buffer with the end of stream flag set.
|
||||
* given {@link Format}.
|
||||
*/
|
||||
private static final class FakeVideoRenderer extends BaseRenderer {
|
||||
|
||||
private final Format expectedFormat;
|
||||
|
||||
private int formatReadCount;
|
||||
private int bufferReadCount;
|
||||
private boolean isEnded;
|
||||
|
||||
public FakeVideoRenderer(Format expectedFormat) {
|
||||
@ -403,6 +490,11 @@ public final class ExoPlayerTest extends TestCase {
|
||||
this.expectedFormat = expectedFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPositionReset(long positionUs, boolean joining) throws ExoPlaybackException {
|
||||
isEnded = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException {
|
||||
if (isEnded) {
|
||||
@ -411,20 +503,23 @@ public final class ExoPlayerTest extends TestCase {
|
||||
|
||||
// Verify the format matches the expected format.
|
||||
FormatHolder formatHolder = new FormatHolder();
|
||||
readSource(formatHolder, null);
|
||||
assertEquals(expectedFormat, formatHolder.format);
|
||||
|
||||
// Verify that we get an end-of-stream buffer.
|
||||
DecoderInputBuffer buffer =
|
||||
new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
|
||||
readSource(null, buffer);
|
||||
assertTrue(buffer.isEndOfStream());
|
||||
isEnded = true;
|
||||
int result = readSource(formatHolder, buffer);
|
||||
if (result == C.RESULT_FORMAT_READ) {
|
||||
formatReadCount++;
|
||||
assertEquals(expectedFormat, formatHolder.format);
|
||||
} else if (result == C.RESULT_BUFFER_READ) {
|
||||
bufferReadCount++;
|
||||
if (buffer.isEndOfStream()) {
|
||||
isEnded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return isEnded;
|
||||
return isSourceReady();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
x
Reference in New Issue
Block a user