use of com.google.android.exoplayer2.ExoPlayer in project ExoPlayer by google.
the class ExoPlayerTest method recursivePlayerChangesAreReportedInCorrectOrder.
@Test
public void recursivePlayerChangesAreReportedInCorrectOrder() throws Exception {
// The listener stops the player as soon as it's ready (which should report a timeline and state
// change) and sets playWhenReady to false when the timeline callback is received.
final AtomicReference<Player> playerReference = new AtomicReference<>();
final List<Boolean> playerListenerPlayWhenReady = new ArrayList<>();
final List<Integer> playerListenerStates = new ArrayList<>();
List<Integer> sequence = new ArrayList<>();
final Player.Listener playerListener = new Player.Listener() {
@Override
public void onPlaybackStateChanged(@Player.State int playbackState) {
playerListenerStates.add(playbackState);
if (playbackState == Player.STATE_READY) {
playerReference.get().stop(/* reset= */
true);
sequence.add(0);
}
}
@Override
public void onTimelineChanged(Timeline timeline, int reason) {
if (timeline.isEmpty()) {
playerReference.get().pause();
sequence.add(1);
}
}
@Override
public void onPlayWhenReadyChanged(boolean playWhenReady, @Player.PlayWhenReadyChangeReason int reason) {
playerListenerPlayWhenReady.add(playWhenReady);
sequence.add(2);
}
};
ActionSchedule actionSchedule = new ActionSchedule.Builder(TAG).executeRunnable(new PlayerRunnable() {
@Override
public void run(ExoPlayer player) {
playerReference.set(player);
player.addListener(playerListener);
}
}).build();
new ExoPlayerTestRunner.Builder(context).setActionSchedule(actionSchedule).build().start().blockUntilEnded(TIMEOUT_MS);
assertThat(playerListenerStates).containsExactly(Player.STATE_BUFFERING, Player.STATE_READY, Player.STATE_IDLE).inOrder();
assertThat(playerListenerPlayWhenReady).containsExactly(false).inOrder();
assertThat(sequence).containsExactly(0, 1, 2).inOrder();
}
use of com.google.android.exoplayer2.ExoPlayer in project ExoPlayer by google.
the class ExoPlayerTest method invalidSeekFallsBackToSubsequentPeriodOfTheRemovedPeriod.
@Test
public void invalidSeekFallsBackToSubsequentPeriodOfTheRemovedPeriod() throws Exception {
Timeline timeline = new FakeTimeline();
CountDownLatch sourceReleasedCountDownLatch = new CountDownLatch(/* count= */
1);
MediaSource mediaSourceToRemove = new FakeMediaSource(timeline) {
@Override
protected void releaseSourceInternal() {
super.releaseSourceInternal();
sourceReleasedCountDownLatch.countDown();
}
};
ConcatenatingMediaSource mediaSource = new ConcatenatingMediaSource(mediaSourceToRemove, new FakeMediaSource(timeline));
final int[] windowCount = { C.INDEX_UNSET };
final long[] position = { C.TIME_UNSET };
ActionSchedule actionSchedule = new ActionSchedule.Builder(TAG).pause().waitForPlaybackState(Player.STATE_READY).executeRunnable(new PlayerRunnable() {
@Override
public void run(ExoPlayer player) {
mediaSource.removeMediaSource(/* index= */
0);
try {
// Wait until the source to be removed is released on the playback thread. So
// the timeline in EPII has one window only, but the update here in EPI is
// stuck until we finished our executable here. So when seeking below, we will
// seek in the timeline which still has two windows in EPI, but when the seek
// arrives in EPII the actual timeline has one window only. Hence it tries to
// find the subsequent period of the removed period and finds it.
player.getClock().onThreadBlocked();
sourceReleasedCountDownLatch.await();
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
player.seekTo(/* mediaItemIndex= */
0, /* positionMs= */
1000L);
}
}).waitForPendingPlayerCommands().executeRunnable(new PlayerRunnable() {
@Override
public void run(ExoPlayer player) {
windowCount[0] = player.getCurrentTimeline().getWindowCount();
position[0] = player.getCurrentPosition();
}
}).play().build();
new ExoPlayerTestRunner.Builder(context).setMediaSources(mediaSource).setActionSchedule(actionSchedule).build().start().blockUntilActionScheduleFinished(TIMEOUT_MS).blockUntilEnded(TIMEOUT_MS);
// Expect the first window to be the current.
assertThat(windowCount[0]).isEqualTo(1);
// Expect the position to be in the default position.
assertThat(position[0]).isEqualTo(0L);
}
use of com.google.android.exoplayer2.ExoPlayer in project ExoPlayer by google.
the class ExoPlayerTest method isCommandAvailable_duringUnseekableLiveItem_isFalseForSeekToPrevious.
@Test
public void isCommandAvailable_duringUnseekableLiveItem_isFalseForSeekToPrevious() throws Exception {
Timeline timelineWithUnseekableLiveWindow = new FakeTimeline(new TimelineWindowDefinition(/* periodCount= */
1, /* id= */
0, /* isSeekable= */
false, /* isDynamic= */
true, /* isLive= */
true, /* isPlaceholder= */
false, /* durationUs= */
C.TIME_UNSET, /* defaultPositionUs= */
10_000_000, TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US, AdPlaybackState.NONE));
ExoPlayer player = new TestExoPlayerBuilder(context).build();
player.addMediaSource(new FakeMediaSource(timelineWithUnseekableLiveWindow));
player.prepare();
runUntilPlaybackState(player, Player.STATE_READY);
assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS)).isFalse();
}
use of com.google.android.exoplayer2.ExoPlayer in project ExoPlayer by google.
the class ExoPlayerTest method illegalSeekPositionDoesThrow.
@Test
public void illegalSeekPositionDoesThrow() throws Exception {
final IllegalSeekPositionException[] exception = new IllegalSeekPositionException[1];
ActionSchedule actionSchedule = new ActionSchedule.Builder(TAG).waitForPlaybackState(Player.STATE_BUFFERING).executeRunnable(new PlayerRunnable() {
@Override
public void run(ExoPlayer player) {
try {
player.seekTo(/* mediaItemIndex= */
100, /* positionMs= */
0);
} catch (IllegalSeekPositionException e) {
exception[0] = e;
}
}
}).waitForPlaybackState(Player.STATE_ENDED).build();
new ExoPlayerTestRunner.Builder(context).setActionSchedule(actionSchedule).build().start().blockUntilActionScheduleFinished(TIMEOUT_MS).blockUntilEnded(TIMEOUT_MS);
assertThat(exception[0]).isNotNull();
}
use of com.google.android.exoplayer2.ExoPlayer in project ExoPlayer by google.
the class ExoPlayerTest method adInMovingLiveWindow_keepsContentPosition.
@Test
public void adInMovingLiveWindow_keepsContentPosition() throws Exception {
ExoPlayer player = new TestExoPlayerBuilder(context).build();
AdPlaybackState adPlaybackState = FakeTimeline.createAdPlaybackState(/* adsPerAdGroup= */
1, /* adGroupTimesUs...= */
42_000_004_000_000L);
Timeline liveTimeline1 = new FakeTimeline(new TimelineWindowDefinition(/* periodCount= */
1, /* id= */
0, /* isSeekable= */
true, /* isDynamic= */
true, /* isLive= */
true, /* isPlaceholder= */
false, /* durationUs= */
10_000_000, /* defaultPositionUs= */
3_000_000, /* windowOffsetInFirstPeriodUs= */
42_000_000_000_000L, adPlaybackState));
Timeline liveTimeline2 = new FakeTimeline(new TimelineWindowDefinition(/* periodCount= */
1, /* id= */
0, /* isSeekable= */
true, /* isDynamic= */
true, /* isLive= */
true, /* isPlaceholder= */
false, /* durationUs= */
10_000_000, /* defaultPositionUs= */
3_000_000, /* windowOffsetInFirstPeriodUs= */
42_000_002_000_000L, adPlaybackState));
FakeMediaSource fakeMediaSource = new FakeMediaSource(liveTimeline1);
player.setMediaSource(fakeMediaSource);
player.prepare();
player.play();
// Wait until the ad is playing.
runUntilPositionDiscontinuity(player, Player.DISCONTINUITY_REASON_AUTO_TRANSITION);
long contentPositionBeforeLiveWindowUpdateMs = player.getContentPosition();
fakeMediaSource.setNewSourceInfo(liveTimeline2);
runUntilTimelineChanged(player);
long contentPositionAfterLiveWindowUpdateMs = player.getContentPosition();
player.release();
assertThat(contentPositionBeforeLiveWindowUpdateMs).isEqualTo(4000);
assertThat(contentPositionAfterLiveWindowUpdateMs).isEqualTo(2000);
}
Aggregations