use of com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition in project ExoPlayer by google.
the class ExoPlayerTest method targetLiveOffsetInMedia_withInitialSeek_adjustsLiveOffsetToInitialSeek.
@Test
public void targetLiveOffsetInMedia_withInitialSeek_adjustsLiveOffsetToInitialSeek() throws Exception {
long windowStartUnixTimeMs = 987_654_321_000L;
long nowUnixTimeMs = windowStartUnixTimeMs + 20_000;
ExoPlayer player = new TestExoPlayerBuilder(context).setClock(new FakeClock(/* initialTimeMs= */
nowUnixTimeMs, /* isAutoAdvancing= */
true)).build();
Timeline timeline = new FakeTimeline(new TimelineWindowDefinition(/* periodCount= */
1, /* id= */
0, /* isSeekable= */
true, /* isDynamic= */
true, /* isLive= */
true, /* isPlaceholder= */
false, /* durationUs= */
1000 * C.MICROS_PER_SECOND, /* defaultPositionUs= */
8 * C.MICROS_PER_SECOND, /* windowOffsetInFirstPeriodUs= */
Util.msToUs(windowStartUnixTimeMs), ImmutableList.of(AdPlaybackState.NONE), new MediaItem.Builder().setUri(Uri.EMPTY).setLiveConfiguration(new MediaItem.LiveConfiguration.Builder().setTargetOffsetMs(9_000).build()).build()));
player.pause();
player.seekTo(18_000);
player.setMediaSource(new FakeMediaSource(timeline), /* resetPosition= */
false);
player.prepare();
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY);
long liveOffsetAtStart = player.getCurrentLiveOffset();
// Play until close to the end of the available live window.
TestPlayerRunHelper.playUntilPosition(player, /* mediaItemIndex= */
0, /* positionMs= */
999_000);
long liveOffsetAtEnd = player.getCurrentLiveOffset();
player.release();
// Target should have been permanently adjusted to 2 seconds.
// (initial now = 20 seconds in live window, initial seek to 18 seconds)
assertThat(liveOffsetAtStart).isIn(Range.closed(1_900L, 2_100L));
assertThat(liveOffsetAtEnd).isIn(Range.closed(1_900L, 2_100L));
}
use of com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition in project ExoPlayer by google.
the class ExoPlayerTest method isCommandAvailable_duringUnseekableLiveItemWithPreviousWindow_isTrueForSeekToPrevious.
@Test
public void isCommandAvailable_duringUnseekableLiveItemWithPreviousWindow_isTrueForSeekToPrevious() throws Exception {
Timeline timelineWithUnseekableLiveWindow = new FakeTimeline(new TimelineWindowDefinition(/* periodCount= */
1, /* id= */
0), new TimelineWindowDefinition(/* periodCount= */
1, /* id= */
1, /* 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.seekTo(/* mediaItemIndex= */
1, /* positionMs= */
0);
player.prepare();
runUntilPlaybackState(player, Player.STATE_READY);
assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS)).isTrue();
}
use of com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition in project ExoPlayer by google.
the class ExoPlayerTest method concatenatingMediaSourceRemoveMediaSourceWithSeek_overridesRemoval_callsOnPositionDiscontinuity.
@Test
public void concatenatingMediaSourceRemoveMediaSourceWithSeek_overridesRemoval_callsOnPositionDiscontinuity() throws Exception {
ExoPlayer player = new TestExoPlayerBuilder(context).build();
Player.Listener listener = mock(Player.Listener.class);
player.addListener(listener);
ConcatenatingMediaSource concatenatingMediaSource = new ConcatenatingMediaSource(new FakeMediaSource(new FakeTimeline(new TimelineWindowDefinition(/* periodCount= */
1, /* id= */
1, /* isSeekable= */
true, /* isDynamic= */
false, /* durationUs= */
10 * C.MICROS_PER_SECOND))), new FakeMediaSource(new FakeTimeline(new TimelineWindowDefinition(/* periodCount= */
1, /* id= */
2, /* isSeekable= */
true, /* isDynamic= */
false, /* durationUs= */
8 * C.MICROS_PER_SECOND))), new FakeMediaSource(new FakeTimeline(new TimelineWindowDefinition(/* periodCount= */
1, /* id= */
2, /* isSeekable= */
true, /* isDynamic= */
false, /* durationUs= */
6 * C.MICROS_PER_SECOND))));
player.addMediaSource(concatenatingMediaSource);
player.prepare();
TestPlayerRunHelper.playUntilPosition(player, /* mediaItemIndex= */
1, /* positionMs= */
5 * C.MILLIS_PER_SECOND);
concatenatingMediaSource.removeMediaSource(1);
player.seekTo(/* mediaItemIndex= */
0, /* positionMs= */
1234);
TestPlayerRunHelper.runUntilPendingCommandsAreFullyHandled(player);
concatenatingMediaSource.removeMediaSource(0);
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);
inOrder.verify(listener).onPositionDiscontinuity(any(), any(), eq(Player.DISCONTINUITY_REASON_AUTO_TRANSITION));
// SEEK overrides concatenating media source modification.
inOrder.verify(listener).onPositionDiscontinuity(oldPosition.capture(), newPosition.capture(), eq(Player.DISCONTINUITY_REASON_SEEK));
inOrder.verify(listener).onPositionDiscontinuity(oldPosition.capture(), newPosition.capture(), eq(Player.DISCONTINUITY_REASON_REMOVE));
// This fails once out of a hundred test runs due to a race condition whether the seek or the
// removal arrives first in EPI.
// inOrder.verify(listener, never()).onPositionDiscontinuity(any(), any(), anyInt());
List<Player.PositionInfo> oldPositions = oldPosition.getAllValues();
List<Player.PositionInfo> newPositions = newPosition.getAllValues();
assertThat(oldPositions.get(0).mediaItemIndex).isEqualTo(1);
assertThat(oldPositions.get(0).positionMs).isIn(Range.closed(4980L, 5000L));
assertThat(oldPositions.get(0).contentPositionMs).isIn(Range.closed(4980L, 5000L));
assertThat(newPositions.get(0).mediaItemIndex).isEqualTo(0);
assertThat(newPositions.get(0).positionMs).isEqualTo(1234);
assertThat(newPositions.get(0).contentPositionMs).isEqualTo(1234);
assertThat(oldPositions.get(1).mediaItemIndex).isEqualTo(0);
assertThat(oldPositions.get(1).positionMs).isEqualTo(1234);
assertThat(oldPositions.get(1).contentPositionMs).isEqualTo(1234);
assertThat(newPositions.get(1).mediaItemIndex).isEqualTo(0);
assertThat(newPositions.get(1).positionMs).isEqualTo(1234);
assertThat(newPositions.get(1).contentPositionMs).isEqualTo(1234);
player.release();
}
use of com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition in project ExoPlayer by google.
the class ExoPlayerTest method playlistWithMediaWithStartOffsets_andStartOffsetChangesDuringPreparation_appliesCorrectRenderingOffsetToAllPeriods.
/**
* This tests that renderer offsets and buffer times in the renderer are set correctly even when
* the sources have a window-to-period offset and a non-zero default start position. The start
* offset of the first source is also updated during preparation to make sure the player adapts
* everything accordingly.
*/
@Test
public void playlistWithMediaWithStartOffsets_andStartOffsetChangesDuringPreparation_appliesCorrectRenderingOffsetToAllPeriods() throws Exception {
List<Long> rendererStreamOffsetsUs = new ArrayList<>();
List<Long> firstBufferTimesUsWithOffset = new ArrayList<>();
FakeRenderer renderer = new FakeRenderer(C.TRACK_TYPE_VIDEO) {
boolean pendingFirstBufferTime = false;
@Override
protected void onStreamChanged(Format[] formats, long startPositionUs, long offsetUs) {
rendererStreamOffsetsUs.add(offsetUs);
pendingFirstBufferTime = true;
}
@Override
protected boolean shouldProcessBuffer(long bufferTimeUs, long playbackPositionUs) {
if (pendingFirstBufferTime) {
firstBufferTimesUsWithOffset.add(bufferTimeUs);
pendingFirstBufferTime = false;
}
return super.shouldProcessBuffer(bufferTimeUs, playbackPositionUs);
}
};
Timeline timelineWithOffsets = new FakeTimeline(new TimelineWindowDefinition(/* periodCount= */
1, /* id= */
new Object(), /* isSeekable= */
true, /* isDynamic= */
false, /* isLive= */
false, /* isPlaceholder= */
false, TimelineWindowDefinition.DEFAULT_WINDOW_DURATION_US, /* defaultPositionUs= */
4_567_890, /* windowOffsetInFirstPeriodUs= */
1_234_567, AdPlaybackState.NONE));
ExoPlayer player = new TestExoPlayerBuilder(context).setRenderers(renderer).build();
long firstSampleTimeUs = 4_567_890 + 1_234_567;
FakeMediaSource firstMediaSource = new FakeMediaSource(/* timeline= */
null, DrmSessionManager.DRM_UNSUPPORTED, (unusedFormat, unusedMediaPeriodId) -> ImmutableList.of(oneByteSample(firstSampleTimeUs, C.BUFFER_FLAG_KEY_FRAME), END_OF_STREAM_ITEM), ExoPlayerTestRunner.VIDEO_FORMAT);
FakeMediaSource secondMediaSource = new FakeMediaSource(timelineWithOffsets, DrmSessionManager.DRM_UNSUPPORTED, (unusedFormat, unusedMediaPeriodId) -> ImmutableList.of(oneByteSample(firstSampleTimeUs, C.BUFFER_FLAG_KEY_FRAME), END_OF_STREAM_ITEM), ExoPlayerTestRunner.VIDEO_FORMAT);
player.setMediaSources(ImmutableList.of(firstMediaSource, secondMediaSource));
// Start playback and wait until player is idly waiting for an update of the first source.
player.prepare();
player.play();
runUntilPendingCommandsAreFullyHandled(player);
// Update media with a non-zero default start position and window offset.
firstMediaSource.setNewSourceInfo(timelineWithOffsets);
// Wait until player transitions to second source (which also has non-zero offsets).
runUntilPositionDiscontinuity(player, Player.DISCONTINUITY_REASON_AUTO_TRANSITION);
assertThat(player.getCurrentMediaItemIndex()).isEqualTo(1);
player.release();
assertThat(rendererStreamOffsetsUs).hasSize(2);
assertThat(firstBufferTimesUsWithOffset).hasSize(2);
// Assert that the offsets and buffer times match the expected sample time.
assertThat(firstBufferTimesUsWithOffset.get(0)).isEqualTo(rendererStreamOffsetsUs.get(0) + firstSampleTimeUs);
assertThat(firstBufferTimesUsWithOffset.get(1)).isEqualTo(rendererStreamOffsetsUs.get(1) + firstSampleTimeUs);
// Assert that the second source continues rendering seamlessly at the point where the first one
// ended.
long periodDurationUs = timelineWithOffsets.getPeriod(/* periodIndex= */
0, new Timeline.Period()).durationUs;
assertThat(firstBufferTimesUsWithOffset.get(1)).isEqualTo(rendererStreamOffsetsUs.get(0) + periodDurationUs);
}
use of com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition in project ExoPlayer by google.
the class ExoPlayerTest method noTargetLiveOffsetInMedia_doesNotAdjustLiveOffset.
@Test
public void noTargetLiveOffsetInMedia_doesNotAdjustLiveOffset() throws Exception {
long windowStartUnixTimeMs = 987_654_321_000L;
long nowUnixTimeMs = windowStartUnixTimeMs + 20_000;
ExoPlayer player = new TestExoPlayerBuilder(context).setClock(new FakeClock(/* initialTimeMs= */
nowUnixTimeMs, /* isAutoAdvancing= */
true)).build();
Timeline liveTimelineWithoutTargetLiveOffset = new FakeTimeline(new TimelineWindowDefinition(/* periodCount= */
1, /* id= */
0, /* isSeekable= */
true, /* isDynamic= */
true, /* isLive= */
true, /* isPlaceholder= */
false, /* durationUs= */
1000 * C.MICROS_PER_SECOND, /* defaultPositionUs= */
8 * C.MICROS_PER_SECOND, /* windowOffsetInFirstPeriodUs= */
Util.msToUs(windowStartUnixTimeMs), ImmutableList.of(AdPlaybackState.NONE), new MediaItem.Builder().setUri(Uri.EMPTY).build()));
player.pause();
player.setMediaSource(new FakeMediaSource(liveTimelineWithoutTargetLiveOffset));
player.prepare();
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY);
long liveOffsetAtStart = player.getCurrentLiveOffset();
// Verify test setup (now = 20 seconds in live window, default start position = 8 seconds).
assertThat(liveOffsetAtStart).isIn(Range.closed(11_900L, 12_100L));
// Play until close to the end of the available live window.
TestPlayerRunHelper.playUntilPosition(player, /* mediaItemIndex= */
0, /* positionMs= */
999_000);
long liveOffsetAtEnd = player.getCurrentLiveOffset();
player.release();
// Assert that live offset is still the same (i.e. unadjusted).
assertThat(liveOffsetAtEnd).isIn(Range.closed(11_900L, 12_100L));
}
Aggregations