use of androidx.media3.exoplayer.source.SinglePeriodTimeline in project media by androidx.
the class TimelineTest method singlePeriodTimeline.
@Test
public void singlePeriodTimeline() {
Timeline timeline = new FakeTimeline(new TimelineWindowDefinition(1, 111));
TimelineAsserts.assertWindowTags(timeline, 111);
TimelineAsserts.assertPeriodCounts(timeline, 1);
TimelineAsserts.assertPreviousWindowIndices(timeline, Player.REPEAT_MODE_OFF, false, C.INDEX_UNSET);
TimelineAsserts.assertPreviousWindowIndices(timeline, Player.REPEAT_MODE_ONE, false, 0);
TimelineAsserts.assertPreviousWindowIndices(timeline, Player.REPEAT_MODE_ALL, false, 0);
TimelineAsserts.assertNextWindowIndices(timeline, Player.REPEAT_MODE_OFF, false, C.INDEX_UNSET);
TimelineAsserts.assertNextWindowIndices(timeline, Player.REPEAT_MODE_ONE, false, 0);
TimelineAsserts.assertNextWindowIndices(timeline, Player.REPEAT_MODE_ALL, false, 0);
}
use of androidx.media3.exoplayer.source.SinglePeriodTimeline in project media by androidx.
the class ProgressiveMediaSource method notifySourceInfoRefreshed.
// Internal methods.
private void notifySourceInfoRefreshed() {
// TODO: Split up isDynamic into multiple fields to indicate which values may change. Then
// indicate that the duration may change until it's known. See [internal: b/69703223].
Timeline timeline = new SinglePeriodTimeline(timelineDurationUs, timelineIsSeekable, /* isDynamic= */
false, /* useLiveConfiguration= */
timelineIsLive, /* manifest= */
null, mediaItem);
if (timelineIsPlaceholder) {
// TODO: Actually prepare the extractors during preparation so that we don't need a
// placeholder. See https://github.com/google/ExoPlayer/issues/4727.
timeline = new ForwardingTimeline(timeline) {
@Override
public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) {
super.getWindow(windowIndex, window, defaultPositionProjectionUs);
window.isPlaceholder = true;
return window;
}
@Override
public Period getPeriod(int periodIndex, Period period, boolean setIds) {
super.getPeriod(periodIndex, period, setIds);
period.isPlaceholder = true;
return period;
}
};
}
refreshSourceInfo(timeline);
}
use of androidx.media3.exoplayer.source.SinglePeriodTimeline in project media by androidx.
the class ExoPlayerTest method targetLiveOffsetInMedia_unknownWindowStartTime_doesNotAdjustLiveOffset.
@Test
public void targetLiveOffsetInMedia_unknownWindowStartTime_doesNotAdjustLiveOffset() throws Exception {
FakeClock fakeClock = new FakeClock(/* initialTimeMs= */
987_654_321L, /* isAutoAdvancing= */
true);
ExoPlayer player = new TestExoPlayerBuilder(context).setClock(fakeClock).build();
MediaItem mediaItem = new MediaItem.Builder().setUri(Uri.EMPTY).setLiveConfiguration(new MediaItem.LiveConfiguration.Builder().setTargetOffsetMs(4_000).build()).build();
Timeline liveTimeline = new SinglePeriodTimeline(/* presentationStartTimeMs= */
C.TIME_UNSET, /* windowStartTimeMs= */
C.TIME_UNSET, /* elapsedRealtimeEpochOffsetMs= */
C.TIME_UNSET, /* periodDurationUs= */
1000 * C.MICROS_PER_SECOND, /* windowDurationUs= */
1000 * C.MICROS_PER_SECOND, /* windowPositionInPeriodUs= */
0, /* windowDefaultStartPositionUs= */
0, /* isSeekable= */
true, /* isDynamic= */
true, /* suppressPositionProjection= */
false, /* manifest= */
null, mediaItem, mediaItem.liveConfiguration);
player.pause();
player.setMediaSource(new FakeMediaSource(liveTimeline));
player.prepare();
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY);
long playbackStartTimeMs = fakeClock.elapsedRealtime();
TestPlayerRunHelper.playUntilPosition(player, /* mediaItemIndex= */
0, /* positionMs= */
999_000);
long playbackEndTimeMs = fakeClock.elapsedRealtime();
player.release();
// Assert that the time it took to play 999 seconds of media is 999 seconds (asserting that no
// playback speed adjustment was used).
assertThat(playbackEndTimeMs - playbackStartTimeMs).isEqualTo(999_000);
}
use of androidx.media3.exoplayer.source.SinglePeriodTimeline in project media by androidx.
the class HlsMediaSource method onPrimaryPlaylistRefreshed.
@Override
public void onPrimaryPlaylistRefreshed(HlsMediaPlaylist mediaPlaylist) {
long windowStartTimeMs = mediaPlaylist.hasProgramDateTime ? Util.usToMs(mediaPlaylist.startTimeUs) : C.TIME_UNSET;
// For playlist types EVENT and VOD we know segments are never removed, so the presentation
// started at the same time as the window. Otherwise, we don't know the presentation start time.
long presentationStartTimeMs = mediaPlaylist.playlistType == HlsMediaPlaylist.PLAYLIST_TYPE_EVENT || mediaPlaylist.playlistType == HlsMediaPlaylist.PLAYLIST_TYPE_VOD ? windowStartTimeMs : C.TIME_UNSET;
// The multivariant playlist is non-null because the first playlist has been fetched by now.
HlsManifest manifest = new HlsManifest(checkNotNull(playlistTracker.getMultivariantPlaylist()), mediaPlaylist);
SinglePeriodTimeline timeline = playlistTracker.isLive() ? createTimelineForLive(mediaPlaylist, presentationStartTimeMs, windowStartTimeMs, manifest) : createTimelineForOnDemand(mediaPlaylist, presentationStartTimeMs, windowStartTimeMs, manifest);
refreshSourceInfo(timeline);
}
use of androidx.media3.exoplayer.source.SinglePeriodTimeline in project media by androidx.
the class SsMediaSource method processManifest.
// Internal methods
private void processManifest() {
for (int i = 0; i < mediaPeriods.size(); i++) {
mediaPeriods.get(i).updateManifest(manifest);
}
long startTimeUs = Long.MAX_VALUE;
long endTimeUs = Long.MIN_VALUE;
for (StreamElement element : manifest.streamElements) {
if (element.chunkCount > 0) {
startTimeUs = min(startTimeUs, element.getStartTimeUs(0));
endTimeUs = max(endTimeUs, element.getStartTimeUs(element.chunkCount - 1) + element.getChunkDurationUs(element.chunkCount - 1));
}
}
Timeline timeline;
if (startTimeUs == Long.MAX_VALUE) {
long periodDurationUs = manifest.isLive ? C.TIME_UNSET : 0;
timeline = new SinglePeriodTimeline(periodDurationUs, /* windowDurationUs= */
0, /* windowPositionInPeriodUs= */
0, /* windowDefaultStartPositionUs= */
0, /* isSeekable= */
true, /* isDynamic= */
manifest.isLive, /* useLiveConfiguration= */
manifest.isLive, manifest, mediaItem);
} else if (manifest.isLive) {
if (manifest.dvrWindowLengthUs != C.TIME_UNSET && manifest.dvrWindowLengthUs > 0) {
startTimeUs = max(startTimeUs, endTimeUs - manifest.dvrWindowLengthUs);
}
long durationUs = endTimeUs - startTimeUs;
long defaultStartPositionUs = durationUs - Util.msToUs(livePresentationDelayMs);
if (defaultStartPositionUs < MIN_LIVE_DEFAULT_START_POSITION_US) {
// The default start position is too close to the start of the live window. Set it to the
// minimum default start position provided the window is at least twice as big. Else set
// it to the middle of the window.
defaultStartPositionUs = min(MIN_LIVE_DEFAULT_START_POSITION_US, durationUs / 2);
}
timeline = new SinglePeriodTimeline(/* periodDurationUs= */
C.TIME_UNSET, durationUs, startTimeUs, defaultStartPositionUs, /* isSeekable= */
true, /* isDynamic= */
true, /* useLiveConfiguration= */
true, manifest, mediaItem);
} else {
long durationUs = manifest.durationUs != C.TIME_UNSET ? manifest.durationUs : endTimeUs - startTimeUs;
timeline = new SinglePeriodTimeline(startTimeUs + durationUs, durationUs, startTimeUs, /* windowDefaultStartPositionUs= */
0, /* isSeekable= */
true, /* isDynamic= */
false, /* useLiveConfiguration= */
false, manifest, mediaItem);
}
refreshSourceInfo(timeline);
}
Aggregations