@Override public int getPeriodCount() { return timeline.getPeriodCount(); }
private IllegalMergeException checkTimelineMerges(Timeline timeline) { if (periodCount == PERIOD_COUNT_UNSET) { periodCount = timeline.getPeriodCount(); } else if (timeline.getPeriodCount() != periodCount) { return new IllegalMergeException(IllegalMergeException.REASON_PERIOD_COUNT_MISMATCH); } return null; }
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); }
/** * Asserts that the durations of the periods in the {@link Timeline} and the durations in the * given sequence are equal. */ public static void assertPeriodDurations(Timeline timeline, long... durationsUs) { int periodCount = timeline.getPeriodCount(); assertThat(periodCount).isEqualTo(durationsUs.length); Period period = new Period(); for (int i = 0; i < periodCount; i++) { assertThat(timeline.getPeriod(i, period).durationUs).isEqualTo(durationsUs[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"); } }
/** Asserts that periods' {@link Period#getAdGroupCount()} are set correctly. */ public static void assertAdGroupCounts(Timeline timeline, int... expectedAdGroupCounts) { Period period = new Period(); for (int i = 0; i < timeline.getPeriodCount(); i++) { timeline.getPeriod(i, period); assertThat(period.getAdGroupCount()).isEqualTo(expectedAdGroupCounts[i]); } } }
private void onAdSourceInfoRefreshed(MediaSource mediaSource, int adGroupIndex, int adIndexInAdGroup, Timeline timeline) { Assertions.checkArgument(timeline.getPeriodCount() == 1); adGroupTimelines[adGroupIndex][adIndexInAdGroup] = timeline; List<DeferredMediaPeriod> mediaPeriods = deferredMediaPeriodByAdMediaSource.remove(mediaSource); if (mediaPeriods != null) { Object periodUid = timeline.getUidOfPeriod(/* periodIndex= */ 0); for (int i = 0; i < mediaPeriods.size(); i++) { DeferredMediaPeriod mediaPeriod = mediaPeriods.get(i); MediaPeriodId adSourceMediaPeriodId = new MediaPeriodId(periodUid, mediaPeriod.id.windowSequenceNumber); mediaPeriod.createPeriod(adSourceMediaPeriodId); } } maybeUpdateSourceInfo(); }
/** * 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 onTimelineChanged(Timeline timeline, Object manifest, int reason) { int periodCount = timeline.getPeriodCount(); int windowCount = timeline.getWindowCount(); Log.d(TAG, "sourceInfo [periodCount=" + periodCount + ", windowCount=" + windowCount); for (int i = 0; i < Math.min(periodCount, MAX_TIMELINE_ITEM_LINES); i++) { timeline.getPeriod(i, period); Log.d(TAG, " " + "period [" + getTimeString(period.getDurationMs()) + "]"); } if (periodCount > MAX_TIMELINE_ITEM_LINES) { Log.d(TAG, " ..."); } for (int i = 0; i < Math.min(windowCount, MAX_TIMELINE_ITEM_LINES); i++) { timeline.getWindow(i, window); Log.d(TAG, " " + "window [" + getTimeString(window.getDurationMs()) + ", " + window.isSeekable + ", " + window.isDynamic + "]"); } if (windowCount > MAX_TIMELINE_ITEM_LINES) { Log.d(TAG, " ..."); } Log.d(TAG, "]"); }
@Override public void onTimelineChanged( Timeline timeline, @Nullable Object manifest, @Player.TimelineChangeReason int reason) { if (reason == Player.TIMELINE_CHANGE_REASON_RESET) { // The player is being reset and this source will be released. return; } Assertions.checkArgument(timeline.getPeriodCount() == 1); this.timeline = timeline; long contentDurationUs = timeline.getPeriod(0, period).durationUs; contentDurationMs = C.usToMs(contentDurationUs); if (contentDurationUs != C.TIME_UNSET) { adPlaybackState = adPlaybackState.withContentDurationUs(contentDurationUs); } updateImaStateForPlayerState(); }
/** * Given a period index into an old timeline, finds the first subsequent period that also exists * in a new timeline. The uid of this period in the new timeline is returned. * * @param oldPeriodUid The index of the period in the old timeline. * @param oldTimeline The old timeline. * @param newTimeline The new timeline. * @return The uid in the new timeline of the first subsequent period, or null if no such period * was found. */ private @Nullable Object resolveSubsequentPeriod( Object oldPeriodUid, Timeline oldTimeline, Timeline newTimeline) { int oldPeriodIndex = oldTimeline.getIndexOfPeriod(oldPeriodUid); int newPeriodIndex = C.INDEX_UNSET; int maxIterations = oldTimeline.getPeriodCount(); for (int i = 0; i < maxIterations && newPeriodIndex == C.INDEX_UNSET; i++) { oldPeriodIndex = oldTimeline.getNextPeriodIndex(oldPeriodIndex, period, window, repeatMode, shuffleModeEnabled); if (oldPeriodIndex == C.INDEX_UNSET) { // We've reached the end of the old timeline. break; } newPeriodIndex = newTimeline.getIndexOfPeriod(oldTimeline.getUidOfPeriod(oldPeriodIndex)); } return newPeriodIndex == C.INDEX_UNSET ? null : newTimeline.getUidOfPeriod(newPeriodIndex); }
/** * Asserts that the durations of the periods in the {@link Timeline} and the durations in the * given sequence are equal. */ public static void assertPeriodDurations(Timeline timeline, long... durationsUs) { int periodCount = timeline.getPeriodCount(); assertThat(periodCount).isEqualTo(durationsUs.length); Period period = new Period(); for (int i = 0; i < periodCount; i++) { assertThat(timeline.getPeriod(i, period).durationUs).isEqualTo(durationsUs[i]); } }
accumulatedPeriodCounts[i + 1] = accumulatedPeriodCounts[i] + expectedPeriodCounts[i]; assertThat(timeline.getPeriodCount()) .isEqualTo(accumulatedPeriodCounts[accumulatedPeriodCounts.length - 1]); Window window = new Window(); for (int i = 0; i < timeline.getPeriodCount(); i++) { timeline.getPeriod(i, period, true); while (i >= accumulatedPeriodCounts[expectedWindowIndex + 1]) {
/** * Removes the item at the given index from the media queue. * * @param itemIndex The index of the item to remove. * @return Whether the removal was successful. */ public boolean removeItem(int itemIndex) { concatenatingMediaSource.removeMediaSource(itemIndex); if (currentPlayer == castPlayer) { if (castPlayer.getPlaybackState() != Player.STATE_IDLE) { Timeline castTimeline = castPlayer.getCurrentTimeline(); if (castTimeline.getPeriodCount() <= itemIndex) { return false; } castPlayer.removeItem((int) castTimeline.getPeriod(itemIndex, new Period()).id); } } mediaQueue.remove(itemIndex); if (itemIndex == currentItemIndex && itemIndex == mediaQueue.size()) { maybeSetCurrentItemAndNotify(C.INDEX_UNSET); } else if (itemIndex < currentItemIndex) { maybeSetCurrentItemAndNotify(currentItemIndex - 1); } return true; }
/** Asserts that periods' {@link Period#getAdGroupCount()} are set correctly. */ public static void assertAdGroupCounts(Timeline timeline, int... expectedAdGroupCounts) { Period period = new Period(); for (int i = 0; i < timeline.getPeriodCount(); i++) { timeline.getPeriod(i, period); assertThat(period.getAdGroupCount()).isEqualTo(expectedAdGroupCounts[i]); } } }
/** * Moves an item within the queue. * * @param fromIndex The index of the item to move. * @param toIndex The target index of the item in the queue. * @return Whether the item move was successful. */ public boolean moveItem(int fromIndex, int toIndex) { // Player update. concatenatingMediaSource.moveMediaSource(fromIndex, toIndex); if (currentPlayer == castPlayer && castPlayer.getPlaybackState() != Player.STATE_IDLE) { Timeline castTimeline = castPlayer.getCurrentTimeline(); int periodCount = castTimeline.getPeriodCount(); if (periodCount <= fromIndex || periodCount <= toIndex) { return false; } int elementId = (int) castTimeline.getPeriod(fromIndex, new Period()).id; castPlayer.moveItem(elementId, toIndex); } mediaQueue.add(toIndex, mediaQueue.remove(fromIndex)); // Index update. if (fromIndex == currentItemIndex) { maybeSetCurrentItemAndNotify(toIndex); } else if (fromIndex < currentItemIndex && toIndex >= currentItemIndex) { maybeSetCurrentItemAndNotify(currentItemIndex - 1); } else if (fromIndex > currentItemIndex && toIndex <= currentItemIndex) { maybeSetCurrentItemAndNotify(currentItemIndex + 1); } return true; }
@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); }
/** * Creates and releases all periods (including ad periods) defined in the last timeline to be * returned from {@link #prepareSource()}, {@link #assertTimelineChange()} or {@link * #assertTimelineChangeBlocking()}. The {@link MediaPeriodId#windowSequenceNumber} is set to the * index of the window. */ public void assertPrepareAndReleaseAllPeriods() throws InterruptedException { Timeline.Period period = new Timeline.Period(); for (int i = 0; i < timeline.getPeriodCount(); i++) { timeline.getPeriod(i, period, /* setIds= */ true); assertPrepareAndReleasePeriod(new MediaPeriodId(period.uid, period.windowIndex)); for (int adGroupIndex = 0; adGroupIndex < period.getAdGroupCount(); adGroupIndex++) { for (int adIndex = 0; adIndex < period.getAdCountInAdGroup(adGroupIndex); adIndex++) { assertPrepareAndReleasePeriod( new MediaPeriodId(period.uid, adGroupIndex, adIndex, period.windowIndex)); } } } }
/** * Creates and releases all periods (including ad periods) defined in the last timeline to be * returned from {@link #prepareSource()}, {@link #assertTimelineChange()} or {@link * #assertTimelineChangeBlocking()}. The {@link MediaPeriodId#windowSequenceNumber} is set to the * index of the window. */ public void assertPrepareAndReleaseAllPeriods() throws InterruptedException { Timeline.Period period = new Timeline.Period(); for (int i = 0; i < timeline.getPeriodCount(); i++) { timeline.getPeriod(i, period, /* setIds= */ true); assertPrepareAndReleasePeriod(new MediaPeriodId(period.uid, period.windowIndex)); for (int adGroupIndex = 0; adGroupIndex < period.getAdGroupCount(); adGroupIndex++) { for (int adIndex = 0; adIndex < period.getAdCountInAdGroup(adGroupIndex); adIndex++) { assertPrepareAndReleasePeriod( new MediaPeriodId(period.uid, adGroupIndex, adIndex, period.windowIndex)); } } } }
new MediaPeriodId( timeline.getUidOfPeriod(/* periodIndex= */ 0), /* windowSequenceNumber= */ 1)); if (timeline.getPeriodCount() > 1) { period1 = new EventWindowAndPeriodId(