/** * Returns whether the timeline is empty. */ public final boolean isEmpty() { return getWindowCount() == 0; }
@Override public int getWindowCount() { return timeline.getWindowCount(); }
/** * Returns the index of the last window in the playback order depending on whether shuffling is * enabled. * * @param shuffleModeEnabled Whether shuffling is enabled. * @return The index of the last window in the playback order, or {@link C#INDEX_UNSET} if the * timeline is empty. */ public int getLastWindowIndex(boolean shuffleModeEnabled) { return isEmpty() ? C.INDEX_UNSET : getWindowCount() - 1; }
/** * Asserts that previous window indices for each window depending on the repeat mode and the * shuffle mode are equal to the given sequence. */ public static void assertPreviousWindowIndices( Timeline timeline, @Player.RepeatMode int repeatMode, boolean shuffleModeEnabled, int... expectedPreviousWindowIndices) { for (int i = 0; i < timeline.getWindowCount(); i++) { assertThat(timeline.getPreviousWindowIndex(i, repeatMode, shuffleModeEnabled)) .isEqualTo(expectedPreviousWindowIndices[i]); } }
/** * Asserts that next window indices for each window depending on the repeat mode and the shuffle * mode are equal to the given sequence. */ public static void assertNextWindowIndices( Timeline timeline, @Player.RepeatMode int repeatMode, boolean shuffleModeEnabled, int... expectedNextWindowIndices) { for (int i = 0; i < timeline.getWindowCount(); i++) { assertThat(timeline.getNextWindowIndex(i, repeatMode, shuffleModeEnabled)) .isEqualTo(expectedNextWindowIndices[i]); } }
/** * Asserts that window tags are set correctly. * * @param expectedWindowTags A list of expected window tags. If a tag is unknown or not important * {@code null} can be passed to skip this window. */ public static void assertWindowTags(Timeline timeline, Object... expectedWindowTags) { Window window = new Window(); assertThat(timeline.getWindowCount()).isEqualTo(expectedWindowTags.length); for (int i = 0; i < timeline.getWindowCount(); i++) { timeline.getWindow(i, window, true); if (expectedWindowTags[i] != null) { assertThat(window.tag).isEqualTo(expectedWindowTags[i]); } } }
private void removeMediaSourceInternal(int index) { MediaSourceHolder holder = mediaSourceHolders.remove(index); mediaSourceByUid.remove(holder.uid); Timeline oldTimeline = holder.timeline; correctOffsets( index, /* childIndexUpdate= */ -1, -oldTimeline.getWindowCount(), -oldTimeline.getPeriodCount()); holder.isRemoved = true; maybeReleaseChildSource(holder); }
@Override public void onAddQueueItem(Player player, MediaDescriptionCompat description) { onAddQueueItem(player, description, player.getCurrentTimeline().getWindowCount()); }
@Override @Nullable public final Object getCurrentTag() { int windowIndex = getCurrentWindowIndex(); Timeline timeline = getCurrentTimeline(); return windowIndex >= timeline.getWindowCount() ? null : timeline.getWindow(windowIndex, window, /* setTag= */ true).tag; }
/** Asserts that window properties {@link Window}.isDynamic are set correctly. */ public static void assertWindowIsDynamic(Timeline timeline, boolean... windowIsDynamic) { Window window = new Window(); for (int i = 0; i < timeline.getWindowCount(); i++) { timeline.getWindow(i, window, true); assertThat(window.isDynamic).isEqualTo(windowIsDynamic[i]); } }
public LoopingTimeline(Timeline childTimeline, int loopCount) { super(/* isAtomic= */ false, new UnshuffledShuffleOrder(loopCount)); this.childTimeline = childTimeline; childPeriodCount = childTimeline.getPeriodCount(); childWindowCount = childTimeline.getWindowCount(); this.loopCount = loopCount; if (childPeriodCount > 0) { Assertions.checkState(loopCount <= Integer.MAX_VALUE / childPeriodCount, "LoopingMediaSource contains too many periods"); } }
/** * Creates a new timeline with a single period containing ads. * * @param contentTimeline The timeline of the content alongside which ads will be played. It must * have one window and one period. * @param adPlaybackState The state of the period's ads. */ public SinglePeriodAdTimeline(Timeline contentTimeline, AdPlaybackState adPlaybackState) { super(contentTimeline); Assertions.checkState(contentTimeline.getPeriodCount() == 1); Assertions.checkState(contentTimeline.getWindowCount() == 1); this.adPlaybackState = adPlaybackState; }
@Override public void onSkipToQueueItem(Player player, long id) { Timeline timeline = player.getCurrentTimeline(); if (timeline.isEmpty() || player.isPlayingAd()) { return; } int windowIndex = (int) id; if (0 <= windowIndex && windowIndex < timeline.getWindowCount()) { player.seekTo(windowIndex, C.TIME_UNSET); } }
@Override public final void onCurrentWindowIndexChanged(Player player) { if (activeQueueItemId == MediaSessionCompat.QueueItem.UNKNOWN_ID || player.getCurrentTimeline().getWindowCount() > maxQueueSize) { publishFloatingQueueWindow(player); } else if (!player.getCurrentTimeline().isEmpty()) { activeQueueItemId = player.getCurrentWindowIndex(); } }
private EventTime generateEventTime(@Nullable MediaPeriodInfo mediaPeriodInfo) { Assertions.checkNotNull(player); if (mediaPeriodInfo == null) { int windowIndex = player.getCurrentWindowIndex(); mediaPeriodInfo = mediaPeriodQueueTracker.tryResolveWindowIndex(windowIndex); if (mediaPeriodInfo == null) { Timeline timeline = player.getCurrentTimeline(); boolean windowIsInTimeline = windowIndex < timeline.getWindowCount(); return generateEventTime( windowIsInTimeline ? timeline : Timeline.EMPTY, windowIndex, /* mediaPeriodId= */ null); } } return generateEventTime( mediaPeriodInfo.timeline, mediaPeriodInfo.windowIndex, mediaPeriodInfo.mediaPeriodId); }
private EventTime generateMediaPeriodEventTime( int windowIndex, @Nullable MediaPeriodId mediaPeriodId) { Assertions.checkNotNull(player); if (mediaPeriodId != null) { MediaPeriodInfo mediaPeriodInfo = mediaPeriodQueueTracker.getMediaPeriodInfo(mediaPeriodId); return mediaPeriodInfo != null ? generateEventTime(mediaPeriodInfo) : generateEventTime(Timeline.EMPTY, windowIndex, mediaPeriodId); } Timeline timeline = player.getCurrentTimeline(); boolean windowIsInTimeline = windowIndex < timeline.getWindowCount(); return generateEventTime( windowIsInTimeline ? timeline : Timeline.EMPTY, windowIndex, /* mediaPeriodId= */ null); }
/** * Asserts that previous window indices for each window depending on the repeat mode and the * shuffle mode are equal to the given sequence. */ public static void assertPreviousWindowIndices( Timeline timeline, @Player.RepeatMode int repeatMode, boolean shuffleModeEnabled, int... expectedPreviousWindowIndices) { for (int i = 0; i < timeline.getWindowCount(); i++) { assertThat(timeline.getPreviousWindowIndex(i, repeatMode, shuffleModeEnabled)) .isEqualTo(expectedPreviousWindowIndices[i]); } }
/** Asserts that window properties {@link Window}.isDynamic are set correctly. */ public static void assertWindowIsDynamic(Timeline timeline, boolean... windowIsDynamic) { Window window = new Window(); for (int i = 0; i < timeline.getWindowCount(); i++) { timeline.getWindow(i, window, true); assertThat(window.isDynamic).isEqualTo(windowIsDynamic[i]); } }
@Test public void testNoClipping() throws IOException { Timeline timeline = new SinglePeriodTimeline(TEST_PERIOD_DURATION_US, true, false); Timeline clippedTimeline = getClippedTimeline(timeline, 0, TEST_PERIOD_DURATION_US); assertThat(clippedTimeline.getWindowCount()).isEqualTo(1); assertThat(clippedTimeline.getPeriodCount()).isEqualTo(1); assertThat(clippedTimeline.getWindow(0, window).getDurationUs()) .isEqualTo(TEST_PERIOD_DURATION_US); assertThat(clippedTimeline.getPeriod(0, period).getDurationUs()) .isEqualTo(TEST_PERIOD_DURATION_US); }
@Test public void testCustomCallbackAfterPreparationAddSingle() throws IOException { DummyMainThread dummyMainThread = new DummyMainThread(); try { testRunner.prepareSource(); final TimelineGrabber timelineGrabber = new TimelineGrabber(testRunner); dummyMainThread.runOnMainThread( () -> mediaSource.addMediaSource(createFakeMediaSource(), timelineGrabber)); Timeline timeline = timelineGrabber.assertTimelineChangeBlocking(); assertThat(timeline.getWindowCount()).isEqualTo(1); } finally { dummyMainThread.release(); } }