Add multi-period ExoPlayer unit test

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=143475824
This commit is contained in:
olly 2017-01-03 12:57:18 -08:00 committed by Oliver Woodman
parent dbfb187b6a
commit b774660989

View File

@ -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