use of com.google.android.exoplayer2.ExoPlayer in project ExoPlayer by google.
the class ExoPlayerTest method errorThrownDuringPlaylistUpdate_keepsConsistentPlayerState.
@Test
public void errorThrownDuringPlaylistUpdate_keepsConsistentPlayerState() {
FakeMediaSource source1 = new FakeMediaSource(new FakeTimeline(), ExoPlayerTestRunner.VIDEO_FORMAT, ExoPlayerTestRunner.AUDIO_FORMAT);
FakeMediaSource source2 = new FakeMediaSource(new FakeTimeline(), ExoPlayerTestRunner.AUDIO_FORMAT);
AtomicInteger audioRendererEnableCount = new AtomicInteger(0);
FakeRenderer videoRenderer = new FakeRenderer(C.TRACK_TYPE_VIDEO);
FakeRenderer audioRenderer = new FakeRenderer(C.TRACK_TYPE_AUDIO) {
@Override
protected void onEnabled(boolean joining, boolean mayRenderStartOfStream) throws ExoPlaybackException {
if (audioRendererEnableCount.incrementAndGet() == 2) {
// Fail when enabling the renderer for the second time during the playlist update.
throw createRendererException(new IllegalStateException(), ExoPlayerTestRunner.AUDIO_FORMAT, PlaybackException.ERROR_CODE_UNSPECIFIED);
}
}
};
AtomicReference<Timeline> timelineAfterError = new AtomicReference<>();
AtomicReference<TracksInfo> trackInfosAfterError = new AtomicReference<>();
AtomicReference<TrackSelectionArray> trackSelectionsAfterError = new AtomicReference<>();
AtomicInteger mediaItemIndexAfterError = new AtomicInteger();
ActionSchedule actionSchedule = new ActionSchedule.Builder(TAG).executeRunnable(new PlayerRunnable() {
@Override
public void run(ExoPlayer player) {
player.addAnalyticsListener(new AnalyticsListener() {
@Override
public void onPlayerError(EventTime eventTime, PlaybackException error) {
timelineAfterError.set(player.getCurrentTimeline());
trackInfosAfterError.set(player.getCurrentTracksInfo());
trackSelectionsAfterError.set(player.getCurrentTrackSelections());
mediaItemIndexAfterError.set(player.getCurrentMediaItemIndex());
}
});
}
}).pause().waitForIsLoading(true).waitForIsLoading(false).removeMediaItem(0).build();
ExoPlayerTestRunner testRunner = new ExoPlayerTestRunner.Builder(context).setMediaSources(source1, source2).setActionSchedule(actionSchedule).setRenderers(videoRenderer, audioRenderer).build();
assertThrows(ExoPlaybackException.class, () -> testRunner.start(/* doPrepare= */
true).blockUntilActionScheduleFinished(TIMEOUT_MS).blockUntilEnded(TIMEOUT_MS));
assertThat(timelineAfterError.get().getWindowCount()).isEqualTo(1);
assertThat(mediaItemIndexAfterError.get()).isEqualTo(0);
assertThat(trackInfosAfterError.get().getTrackGroupInfos()).hasSize(1);
assertThat(trackInfosAfterError.get().getTrackGroupInfos().get(0).getTrackGroup().getFormat(0)).isEqualTo(ExoPlayerTestRunner.AUDIO_FORMAT);
// Video renderer.
assertThat(trackSelectionsAfterError.get().get(0)).isNull();
// Audio renderer.
assertThat(trackSelectionsAfterError.get().get(1)).isNotNull();
}
use of com.google.android.exoplayer2.ExoPlayer in project ExoPlayer by google.
the class ExoPlayerTest method automaticWindowTransition_notifiesAvailableCommandsChanged.
@Test
public void automaticWindowTransition_notifiesAvailableCommandsChanged() throws Exception {
Player.Commands commandsWithSeekToNextWindow = createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, COMMAND_SEEK_TO_NEXT);
Player.Commands commandsWithSeekInCurrentAndToNextWindow = createWithDefaultCommands(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, COMMAND_SEEK_TO_NEXT, COMMAND_SEEK_BACK, COMMAND_SEEK_FORWARD);
Player.Commands commandsWithSeekInCurrentAndToPreviousWindow = createWithDefaultCommands(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM, COMMAND_SEEK_BACK, COMMAND_SEEK_FORWARD);
Player.Commands commandsWithSeekAnywhere = createWithDefaultCommands(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM, COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, COMMAND_SEEK_TO_NEXT, COMMAND_SEEK_BACK, COMMAND_SEEK_FORWARD);
Player.Listener mockListener = mock(Player.Listener.class);
ExoPlayer player = new TestExoPlayerBuilder(context).build();
player.addListener(mockListener);
player.addMediaSources(ImmutableList.of(new FakeMediaSource(), new FakeMediaSource(), new FakeMediaSource(), new FakeMediaSource()));
verify(mockListener).onAvailableCommandsChanged(commandsWithSeekToNextWindow);
// Check that there were no other calls to onAvailableCommandsChanged.
verify(mockListener).onAvailableCommandsChanged(any());
player.prepare();
runUntilPlaybackState(player, Player.STATE_READY);
verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrentAndToNextWindow);
verify(mockListener, times(2)).onAvailableCommandsChanged(any());
playUntilStartOfMediaItem(player, /* mediaItemIndex= */
1);
runUntilPendingCommandsAreFullyHandled(player);
verify(mockListener).onAvailableCommandsChanged(commandsWithSeekAnywhere);
verify(mockListener, times(3)).onAvailableCommandsChanged(any());
playUntilStartOfMediaItem(player, /* mediaItemIndex= */
2);
runUntilPendingCommandsAreFullyHandled(player);
verify(mockListener, times(3)).onAvailableCommandsChanged(any());
player.play();
runUntilPlaybackState(player, Player.STATE_ENDED);
verify(mockListener).onAvailableCommandsChanged(commandsWithSeekInCurrentAndToPreviousWindow);
verify(mockListener, times(4)).onAvailableCommandsChanged(any());
}
use of com.google.android.exoplayer2.ExoPlayer in project ExoPlayer by google.
the class ExoPlayerTest method seekBack_pastZero_seeksToZero.
@Test
public void seekBack_pastZero_seeksToZero() throws Exception {
ExoPlayer player = new TestExoPlayerBuilder(context).build();
Timeline fakeTimeline = new FakeTimeline(new TimelineWindowDefinition(/* isSeekable= */
true, /* isDynamic= */
true, /* durationUs= */
Util.msToUs(C.DEFAULT_SEEK_BACK_INCREMENT_MS)));
player.setMediaSource(new FakeMediaSource(fakeTimeline));
player.prepare();
TestPlayerRunHelper.playUntilPosition(player, /* mediaItemIndex= */
0, /* positionMs= */
C.DEFAULT_SEEK_BACK_INCREMENT_MS / 2);
player.seekBack();
assertThat(player.getCurrentPosition()).isEqualTo(0);
player.release();
}
use of com.google.android.exoplayer2.ExoPlayer in project ExoPlayer by google.
the class ExoPlayerTest method seekTo_whilePlayingAd_correctMasking.
@Test
public void seekTo_whilePlayingAd_correctMasking() throws Exception {
long contentDurationMs = 10_000;
long adDurationMs = 4_000;
AdPlaybackState adPlaybackState = new AdPlaybackState(/* adsId= */
new Object(), /* adGroupTimesUs...= */
0);
adPlaybackState = adPlaybackState.withAdCount(/* adGroupIndex= */
0, /* adCount= */
1);
adPlaybackState = adPlaybackState.withAdUri(/* adGroupIndex= */
0, /* adIndexInAdGroup= */
0, Uri.EMPTY);
long[][] durationsUs = new long[1][];
durationsUs[0] = new long[] { Util.msToUs(adDurationMs) };
adPlaybackState = adPlaybackState.withAdDurationsUs(durationsUs);
Timeline adTimeline = new FakeTimeline(new TimelineWindowDefinition(/* periodCount= */
1, /* id= */
0, /* isSeekable= */
true, /* isDynamic= */
false, /* durationUs= */
Util.msToUs(contentDurationMs), adPlaybackState));
FakeMediaSource adsMediaSource = new FakeMediaSource(adTimeline);
int[] mediaItemIndex = new int[] { C.INDEX_UNSET, C.INDEX_UNSET };
long[] positionMs = new long[] { C.TIME_UNSET, C.TIME_UNSET };
long[] bufferedPositionMs = new long[] { C.TIME_UNSET, C.TIME_UNSET };
long[] totalBufferedDurationMs = new long[] { C.TIME_UNSET, C.TIME_UNSET };
boolean[] isPlayingAd = new boolean[2];
ActionSchedule actionSchedule = new ActionSchedule.Builder(TAG).pause().waitForPlaybackState(Player.STATE_READY).waitForIsLoading(true).waitForIsLoading(false).executeRunnable(new PlayerRunnable() {
@Override
public void run(ExoPlayer player) {
player.seekTo(/* mediaItemIndex= */
0, /* positionMs= */
8000);
mediaItemIndex[0] = player.getCurrentMediaItemIndex();
isPlayingAd[0] = player.isPlayingAd();
positionMs[0] = player.getCurrentPosition();
bufferedPositionMs[0] = player.getBufferedPosition();
totalBufferedDurationMs[0] = player.getTotalBufferedDuration();
}
}).waitForPendingPlayerCommands().executeRunnable(new PlayerRunnable() {
@Override
public void run(ExoPlayer player) {
mediaItemIndex[1] = player.getCurrentMediaItemIndex();
isPlayingAd[1] = player.isPlayingAd();
positionMs[1] = player.getCurrentPosition();
bufferedPositionMs[1] = player.getBufferedPosition();
totalBufferedDurationMs[1] = player.getTotalBufferedDuration();
}
}).stop().build();
new ExoPlayerTestRunner.Builder(context).setMediaSources(adsMediaSource).setActionSchedule(actionSchedule).build().start().blockUntilActionScheduleFinished(TIMEOUT_MS).blockUntilEnded(TIMEOUT_MS);
assertThat(mediaItemIndex[0]).isEqualTo(0);
assertThat(isPlayingAd[0]).isTrue();
assertThat(positionMs[0]).isEqualTo(0);
assertThat(bufferedPositionMs[0]).isEqualTo(adDurationMs);
assertThat(totalBufferedDurationMs[0]).isEqualTo(adDurationMs);
assertThat(mediaItemIndex[1]).isEqualTo(0);
assertThat(isPlayingAd[1]).isTrue();
assertThat(positionMs[1]).isEqualTo(0);
assertThat(bufferedPositionMs[1]).isEqualTo(adDurationMs);
assertThat(totalBufferedDurationMs[1]).isEqualTo(adDurationMs);
}
use of com.google.android.exoplayer2.ExoPlayer in project ExoPlayer by google.
the class ExoPlayerTest method timelineRefresh_withModifiedMediaItem_doesNotNotifyMediaItemTransition.
@Test
public void timelineRefresh_withModifiedMediaItem_doesNotNotifyMediaItemTransition() throws Exception {
List<MediaItem> reportedMediaItems = new ArrayList<>();
List<Integer> reportedTransitionReasons = new ArrayList<>();
List<Timeline> reportedTimelines = new ArrayList<>();
MediaItem initialMediaItem = FakeTimeline.FAKE_MEDIA_ITEM.buildUpon().setTag(0).build();
TimelineWindowDefinition initialWindow = new TimelineWindowDefinition(/* periodCount= */
1, /* id= */
0, /* isSeekable= */
true, /* isDynamic= */
false, /* isLive= */
false, /* isPlaceholder= */
false, /* durationUs= */
10_000_000, /* defaultPositionUs= */
0, /* windowOffsetInFirstPeriodUs= */
0, ImmutableList.of(AdPlaybackState.NONE), initialMediaItem);
TimelineWindowDefinition secondWindow = new TimelineWindowDefinition(/* periodCount= */
1, /* id= */
0, /* isSeekable= */
true, /* isDynamic= */
false, /* isLive= */
false, /* isPlaceholder= */
false, /* durationUs= */
10_000_000, /* defaultPositionUs= */
0, /* windowOffsetInFirstPeriodUs= */
0, ImmutableList.of(AdPlaybackState.NONE), initialMediaItem.buildUpon().setTag(1).build());
FakeTimeline timeline = new FakeTimeline(initialWindow);
FakeTimeline newTimeline = new FakeTimeline(secondWindow);
FakeMediaSource mediaSource = new FakeMediaSource(timeline);
ExoPlayer player = new TestExoPlayerBuilder(context).build();
player.addListener(new Listener() {
@Override
public void onTimelineChanged(Timeline timeline, int reason) {
reportedTimelines.add(timeline);
}
@Override
public void onMediaItemTransition(@Nullable MediaItem mediaItem, int reason) {
reportedMediaItems.add(mediaItem);
reportedTransitionReasons.add(reason);
}
});
player.setMediaSource(mediaSource);
player.prepare();
player.play();
runUntilPlaybackState(player, Player.STATE_READY);
mediaSource.setNewSourceInfo(newTimeline);
runUntilPlaybackState(player, Player.STATE_ENDED);
assertTimelinesSame(reportedTimelines, ImmutableList.of(placeholderTimeline, timeline, newTimeline));
assertThat(reportedMediaItems).containsExactly(initialMediaItem).inOrder();
assertThat(reportedTransitionReasons).containsExactly(Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED).inOrder();
player.release();
}
Aggregations