use of androidx.media3.test.utils.FakeTimeline.TimelineWindowDefinition in project media by androidx.
the class ExoPlayerTest method seekForward_pastDuration_seeksToDuration.
@Test
public void seekForward_pastDuration_seeksToDuration() throws Exception {
ExoPlayer player = new TestExoPlayerBuilder(context).build();
Timeline fakeTimeline = new FakeTimeline(new TimelineWindowDefinition(/* isSeekable= */
true, /* isDynamic= */
true, /* durationUs= */
Util.msToUs(C.DEFAULT_SEEK_FORWARD_INCREMENT_MS / 2)));
player.setMediaSource(new FakeMediaSource(fakeTimeline));
player.prepare();
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY);
player.seekForward();
assertThat(player.getCurrentPosition()).isEqualTo(C.DEFAULT_SEEK_FORWARD_INCREMENT_MS / 2 - 1);
player.release();
}
use of androidx.media3.test.utils.FakeTimeline.TimelineWindowDefinition in project media by androidx.
the class ExoPlayerTest method repeatMode_windowTransition_callsOnPositionDiscontinuityAndOnMediaItemTransition.
@Test
public void repeatMode_windowTransition_callsOnPositionDiscontinuityAndOnMediaItemTransition() throws Exception {
ExoPlayer player = new TestExoPlayerBuilder(context).build();
Player.Listener listener = mock(Player.Listener.class);
FakeMediaSource secondMediaSource = new FakeMediaSource(new FakeTimeline(new TimelineWindowDefinition(/* periodCount= */
1, /* id= */
2, /* isSeekable= */
true, /* isDynamic= */
false, /* durationUs= */
20 * C.MICROS_PER_SECOND)));
player.addListener(listener);
player.setMediaSource(new FakeMediaSource(new FakeTimeline(new TimelineWindowDefinition(/* periodCount= */
1, /* id= */
1, /* isSeekable= */
true, /* isDynamic= */
false, /* durationUs= */
10 * C.MICROS_PER_SECOND))));
player.setRepeatMode(Player.REPEAT_MODE_ONE);
player.prepare();
player.play();
TestPlayerRunHelper.runUntilPositionDiscontinuity(player, Player.DISCONTINUITY_REASON_AUTO_TRANSITION);
player.setRepeatMode(Player.REPEAT_MODE_ALL);
player.play();
TestPlayerRunHelper.runUntilPositionDiscontinuity(player, Player.DISCONTINUITY_REASON_AUTO_TRANSITION);
player.addMediaSource(secondMediaSource);
player.seekTo(/* mediaItemIndex= */
1, /* positionMs= */
C.TIME_UNSET);
player.play();
TestPlayerRunHelper.runUntilPositionDiscontinuity(player, Player.DISCONTINUITY_REASON_AUTO_TRANSITION);
player.setRepeatMode(Player.REPEAT_MODE_OFF);
player.play();
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_ENDED);
ArgumentCaptor<Player.PositionInfo> oldPosition = ArgumentCaptor.forClass(Player.PositionInfo.class);
ArgumentCaptor<Player.PositionInfo> newPosition = ArgumentCaptor.forClass(Player.PositionInfo.class);
InOrder inOrder = inOrder(listener);
// Expect media item transition for repeat mode ONE to be attributed to
// DISCONTINUITY_REASON_REPEAT.
inOrder.verify(listener).onPositionDiscontinuity(oldPosition.capture(), newPosition.capture(), eq(Player.DISCONTINUITY_REASON_AUTO_TRANSITION));
Player.PositionInfo oldPositionInfo = oldPosition.getValue();
Player.PositionInfo newPositionInfo = newPosition.getValue();
assertThat(oldPositionInfo.periodUid).isEqualTo(newPositionInfo.periodUid);
assertThat(oldPositionInfo.periodIndex).isEqualTo(newPositionInfo.periodIndex);
assertThat(oldPositionInfo.mediaItemIndex).isEqualTo(newPositionInfo.mediaItemIndex);
assertThat(oldPositionInfo.mediaItem.localConfiguration.tag).isEqualTo(1);
assertThat(oldPositionInfo.windowUid).isEqualTo(newPositionInfo.windowUid);
assertThat(oldPositionInfo.positionMs).isEqualTo(10_000);
assertThat(oldPositionInfo.contentPositionMs).isEqualTo(10_000);
assertThat(newPositionInfo.positionMs).isEqualTo(0);
assertThat(newPositionInfo.contentPositionMs).isEqualTo(0);
inOrder.verify(listener).onMediaItemTransition(any(), eq(Player.MEDIA_ITEM_TRANSITION_REASON_REPEAT));
// Expect media item transition for repeat mode ALL with a single item to be attributed to
// DISCONTINUITY_REASON_REPEAT.
inOrder.verify(listener).onPositionDiscontinuity(oldPosition.capture(), newPosition.capture(), eq(Player.DISCONTINUITY_REASON_AUTO_TRANSITION));
oldPositionInfo = oldPosition.getValue();
newPositionInfo = newPosition.getValue();
assertThat(oldPositionInfo.periodUid).isEqualTo(newPositionInfo.periodUid);
assertThat(oldPositionInfo.periodIndex).isEqualTo(newPositionInfo.periodIndex);
assertThat(oldPositionInfo.mediaItemIndex).isEqualTo(newPositionInfo.mediaItemIndex);
assertThat(oldPositionInfo.mediaItem.localConfiguration.tag).isEqualTo(1);
assertThat(oldPositionInfo.windowUid).isEqualTo(newPositionInfo.windowUid);
assertThat(oldPositionInfo.positionMs).isEqualTo(10_000);
assertThat(oldPositionInfo.contentPositionMs).isEqualTo(10_000);
assertThat(newPositionInfo.positionMs).isEqualTo(0);
assertThat(newPositionInfo.contentPositionMs).isEqualTo(0);
inOrder.verify(listener).onMediaItemTransition(any(), eq(Player.MEDIA_ITEM_TRANSITION_REASON_REPEAT));
// Expect media item transition for repeat mode ALL with more than one item which is attributed
// to DISCONTINUITY_REASON_AUTO_TRANSITION not DISCONTINUITY_REASON_REPEAT.
inOrder.verify(listener).onPositionDiscontinuity(oldPosition.capture(), newPosition.capture(), eq(Player.DISCONTINUITY_REASON_AUTO_TRANSITION));
oldPositionInfo = oldPosition.getValue();
newPositionInfo = newPosition.getValue();
assertThat(oldPositionInfo.mediaItemIndex).isEqualTo(1);
assertThat(oldPositionInfo.mediaItem.localConfiguration.tag).isEqualTo(2);
assertThat(oldPositionInfo.windowUid).isNotEqualTo(newPositionInfo.windowUid);
assertThat(oldPositionInfo.positionMs).isEqualTo(20_000);
assertThat(oldPositionInfo.contentPositionMs).isEqualTo(20_000);
assertThat(newPositionInfo.positionMs).isEqualTo(0);
assertThat(newPositionInfo.mediaItemIndex).isEqualTo(0);
inOrder.verify(listener).onMediaItemTransition(any(), eq(Player.MEDIA_ITEM_TRANSITION_REASON_AUTO));
// Last auto transition from media item 0 to media item 1 not caused by repeat mode.
inOrder.verify(listener).onPositionDiscontinuity(any(), any(), eq(Player.DISCONTINUITY_REASON_AUTO_TRANSITION));
inOrder.verify(listener).onMediaItemTransition(any(), eq(Player.MEDIA_ITEM_TRANSITION_REASON_AUTO));
// No more callbacks called.
inOrder.verify(listener, never()).onPositionDiscontinuity(any(), any(), eq(Player.DISCONTINUITY_REASON_AUTO_TRANSITION));
inOrder.verify(listener, never()).onMediaItemTransition(any(), anyInt());
player.release();
}
use of androidx.media3.test.utils.FakeTimeline.TimelineWindowDefinition in project media by androidx.
the class ExoPlayerTest method seekTo_seekOverMidRoll_callsOnDiscontinuityCorrectly.
@Test
public void seekTo_seekOverMidRoll_callsOnDiscontinuityCorrectly() throws Exception {
ExoPlayer player = new TestExoPlayerBuilder(context).build();
Player.Listener listener = mock(Player.Listener.class);
player.addListener(listener);
AdPlaybackState adPlaybackState = FakeTimeline.createAdPlaybackState(/* adsPerAdGroup= */
1, /* adGroupTimesUs...= */
2 * C.MICROS_PER_SECOND);
TimelineWindowDefinition adTimeline = new TimelineWindowDefinition(/* periodCount= */
1, /* id= */
0, /* isSeekable= */
true, /* isDynamic= */
false, /* isLive= */
false, /* isPlaceholder= */
false, /* durationUs= */
10 * C.MICROS_PER_SECOND, /* defaultPositionUs= */
0, /* windowOffsetInFirstPeriodUs= */
0, adPlaybackState);
player.setMediaSource(new FakeMediaSource(new FakeTimeline(adTimeline)));
player.prepare();
TestPlayerRunHelper.playUntilPosition(player, /* mediaItemIndex= */
0, /* positionMs= */
1000);
player.seekTo(/* positionMs= */
8_000);
player.play();
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_ENDED);
ArgumentCaptor<Player.PositionInfo> oldPosition = ArgumentCaptor.forClass(Player.PositionInfo.class);
ArgumentCaptor<Player.PositionInfo> newPosition = ArgumentCaptor.forClass(Player.PositionInfo.class);
verify(listener).onPositionDiscontinuity(oldPosition.capture(), newPosition.capture(), eq(Player.DISCONTINUITY_REASON_SEEK));
verify(listener).onPositionDiscontinuity(oldPosition.capture(), newPosition.capture(), eq(Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT));
verify(listener).onPositionDiscontinuity(oldPosition.capture(), newPosition.capture(), eq(Player.DISCONTINUITY_REASON_AUTO_TRANSITION));
verify(listener, never()).onPositionDiscontinuity(any(), any(), eq(Player.DISCONTINUITY_REASON_REMOVE));
verify(listener, never()).onPositionDiscontinuity(any(), any(), eq(Player.DISCONTINUITY_REASON_SKIP));
List<Player.PositionInfo> oldPositions = oldPosition.getAllValues();
List<Player.PositionInfo> newPositions = newPosition.getAllValues();
// SEEK behind mid roll
assertThat(oldPositions.get(0).mediaItemIndex).isEqualTo(0);
assertThat(oldPositions.get(0).positionMs).isIn(Range.closed(980L, 1_000L));
assertThat(oldPositions.get(0).contentPositionMs).isIn(Range.closed(980L, 1_000L));
assertThat(oldPositions.get(0).adGroupIndex).isEqualTo(-1);
assertThat(oldPositions.get(0).adIndexInAdGroup).isEqualTo(-1);
assertThat(newPositions.get(0).mediaItemIndex).isEqualTo(0);
assertThat(newPositions.get(0).positionMs).isEqualTo(8_000);
assertThat(newPositions.get(0).contentPositionMs).isEqualTo(8_000);
assertThat(newPositions.get(0).adGroupIndex).isEqualTo(-1);
assertThat(newPositions.get(0).adIndexInAdGroup).isEqualTo(-1);
// SEEK_ADJUSTMENT back to ad
assertThat(oldPositions.get(1).mediaItemIndex).isEqualTo(0);
assertThat(oldPositions.get(1).positionMs).isEqualTo(8_000);
assertThat(oldPositions.get(1).contentPositionMs).isEqualTo(8_000);
assertThat(oldPositions.get(1).adGroupIndex).isEqualTo(-1);
assertThat(oldPositions.get(1).adIndexInAdGroup).isEqualTo(-1);
assertThat(newPositions.get(1).mediaItemIndex).isEqualTo(0);
assertThat(newPositions.get(1).positionMs).isEqualTo(0);
assertThat(newPositions.get(1).contentPositionMs).isEqualTo(8000);
assertThat(newPositions.get(1).adGroupIndex).isEqualTo(0);
assertThat(newPositions.get(1).adIndexInAdGroup).isEqualTo(0);
// AUTO_TRANSITION back to content
assertThat(oldPositions.get(2).mediaItemIndex).isEqualTo(0);
assertThat(oldPositions.get(2).positionMs).isEqualTo(5_000);
assertThat(oldPositions.get(2).contentPositionMs).isEqualTo(8_000);
assertThat(oldPositions.get(2).adGroupIndex).isEqualTo(0);
assertThat(oldPositions.get(2).adIndexInAdGroup).isEqualTo(0);
assertThat(newPositions.get(2).mediaItemIndex).isEqualTo(0);
assertThat(newPositions.get(2).positionMs).isEqualTo(8_000);
assertThat(newPositions.get(2).contentPositionMs).isEqualTo(8_000);
assertThat(newPositions.get(2).adGroupIndex).isEqualTo(-1);
assertThat(newPositions.get(2).adIndexInAdGroup).isEqualTo(-1);
player.release();
}
use of androidx.media3.test.utils.FakeTimeline.TimelineWindowDefinition in project media by androidx.
the class ExoPlayerTest method seekToIndexWithEmptyMultiWindowMediaSource_usesLazyPreparation.
@Test
public void seekToIndexWithEmptyMultiWindowMediaSource_usesLazyPreparation() throws Exception {
Timeline fakeTimeline = new FakeTimeline(new TimelineWindowDefinition(/* isSeekable= */
true, /* isDynamic= */
false, /* durationUs= */
10_000_000));
ConcatenatingMediaSource concatenatingMediaSource = new ConcatenatingMediaSource(/* isAtomic= */
false);
int[] currentMediaItemIndices = new int[2];
long[] currentPlaybackPositions = new long[2];
long[] windowCounts = new long[2];
int seekToMediaItemIndex = 1;
ActionSchedule actionSchedule = new ActionSchedule.Builder(TAG).waitForPlaybackState(Player.STATE_ENDED).executeRunnable(new PlayerRunnable() {
@Override
public void run(ExoPlayer player) {
currentMediaItemIndices[0] = player.getCurrentMediaItemIndex();
currentPlaybackPositions[0] = player.getCurrentPosition();
windowCounts[0] = player.getCurrentTimeline().getWindowCount();
}
}).executeRunnable(() -> concatenatingMediaSource.addMediaSources(Arrays.asList(new FakeMediaSource(fakeTimeline, ExoPlayerTestRunner.VIDEO_FORMAT), new FakeMediaSource(fakeTimeline, ExoPlayerTestRunner.VIDEO_FORMAT)))).waitForTimelineChanged().executeRunnable(new PlayerRunnable() {
@Override
public void run(ExoPlayer player) {
currentMediaItemIndices[1] = player.getCurrentMediaItemIndex();
currentPlaybackPositions[1] = player.getCurrentPosition();
windowCounts[1] = player.getCurrentTimeline().getWindowCount();
}
}).build();
new ExoPlayerTestRunner.Builder(context).setMediaSources(concatenatingMediaSource).setUseLazyPreparation(/* useLazyPreparation= */
true).initialSeek(seekToMediaItemIndex, 5000).setActionSchedule(actionSchedule).build().start().blockUntilActionScheduleFinished(TIMEOUT_MS).blockUntilEnded(TIMEOUT_MS);
assertArrayEquals(new long[] { 0, 2 }, windowCounts);
assertArrayEquals(new int[] { seekToMediaItemIndex, seekToMediaItemIndex }, currentMediaItemIndices);
assertArrayEquals(new long[] { 5_000, 5_000 }, currentPlaybackPositions);
}
use of androidx.media3.test.utils.FakeTimeline.TimelineWindowDefinition in project media by androidx.
the class ExoPlayerTest method resettingMediaSourcesGivesFreshSourceInfo.
@Test
public void resettingMediaSourcesGivesFreshSourceInfo() throws Exception {
FakeRenderer renderer = new FakeRenderer(C.TRACK_TYPE_VIDEO);
Timeline firstTimeline = new FakeTimeline(new TimelineWindowDefinition(/* isSeekable= */
true, /* isDynamic= */
false, /* durationUs= */
1_000_000_000));
MediaSource firstSource = new FakeMediaSource(firstTimeline, ExoPlayerTestRunner.VIDEO_FORMAT);
AtomicBoolean secondSourcePrepared = new AtomicBoolean();
MediaSource secondSource = new FakeMediaSource(new FakeTimeline(), ExoPlayerTestRunner.VIDEO_FORMAT) {
@Override
public synchronized void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) {
super.prepareSourceInternal(mediaTransferListener);
secondSourcePrepared.set(true);
}
};
Timeline thirdTimeline = new FakeTimeline();
MediaSource thirdSource = new FakeMediaSource(thirdTimeline, ExoPlayerTestRunner.VIDEO_FORMAT);
ExoPlayer player = new TestExoPlayerBuilder(context).setRenderers(renderer).build();
Player.Listener mockPlayerListener = mock(Player.Listener.class);
player.addListener(mockPlayerListener);
player.setMediaSource(firstSource);
player.prepare();
player.play();
runUntilTimelineChanged(player);
player.setMediaSource(secondSource);
runMainLooperUntil(secondSourcePrepared::get);
player.setMediaSource(thirdSource);
runUntilPlaybackState(player, Player.STATE_ENDED);
// The first source's preparation completed with a real timeline. When the second source was
// prepared, it immediately exposed a placeholder timeline, but the source info refresh from the
// second source was suppressed as we replace it with the third source before the update
// arrives.
InOrder inOrder = inOrder(mockPlayerListener);
inOrder.verify(mockPlayerListener).onTimelineChanged(argThat(noUid(placeholderTimeline)), eq(Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED));
inOrder.verify(mockPlayerListener).onTimelineChanged(argThat(noUid(firstTimeline)), eq(Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE));
inOrder.verify(mockPlayerListener).onTimelineChanged(argThat(noUid(placeholderTimeline)), eq(Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED));
inOrder.verify(mockPlayerListener).onPositionDiscontinuity(any(), any(), eq(Player.DISCONTINUITY_REASON_REMOVE));
inOrder.verify(mockPlayerListener).onTimelineChanged(argThat(noUid(placeholderTimeline)), eq(Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED));
inOrder.verify(mockPlayerListener).onPositionDiscontinuity(any(), any(), eq(Player.DISCONTINUITY_REASON_REMOVE));
inOrder.verify(mockPlayerListener).onTimelineChanged(argThat(noUid(thirdTimeline)), eq(Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE));
inOrder.verify(mockPlayerListener).onTracksChanged(eq(new TrackGroupArray(new TrackGroup(ExoPlayerTestRunner.VIDEO_FORMAT))), any());
assertThat(renderer.isEnded).isTrue();
}
Aggregations