/** * Populates a {@link Window} with data for the window at the specified index. Does not populate * {@link Window#tag}. * * @param windowIndex The index of the window. * @param window The {@link Window} to populate. Must not be null. * @return The populated {@link Window}, for convenience. */ public final Window getWindow(int windowIndex, Window window) { return getWindow(windowIndex, window, false); }
@Override @Nullable public final Object getCurrentTag() { int windowIndex = getCurrentWindowIndex(); Timeline timeline = getCurrentTimeline(); return windowIndex >= timeline.getWindowCount() ? null : timeline.getWindow(windowIndex, window, /* setTag= */ true).tag; }
@Override public Window getWindow( int windowIndex, Window window, boolean setTag, long defaultPositionProjectionUs) { return timeline.getWindow(windowIndex, window, setTag, defaultPositionProjectionUs); }
/** 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]); } }
/** * Populates a {@link Window} with data for the window at the specified index. * * @param windowIndex The index of the window. * @param window The {@link Window} to populate. Must not be null. * @param setTag Whether {@link Window#tag} should be populated. If false, the field will be set * to null. The caller should pass false for efficiency reasons unless the field is required. * @return The populated {@link Window}, for convenience. */ public final Window getWindow(int windowIndex, Window window, boolean setTag) { return getWindow(windowIndex, window, setTag, 0); }
/** 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]); } }
@Override @Nullable public Object getTag() { boolean hasTimeline = timeline != null && !timeline.isEmpty(); return hasTimeline ? timeline.getWindow(0, new Timeline.Window()).tag : null; }
@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); }
@Override public final boolean isCurrentWindowSeekable() { Timeline timeline = getCurrentTimeline(); return !timeline.isEmpty() && timeline.getWindow(getCurrentWindowIndex(), window).isSeekable; }
@Override public final boolean isCurrentWindowDynamic() { Timeline timeline = getCurrentTimeline(); return !timeline.isEmpty() && timeline.getWindow(getCurrentWindowIndex(), window).isDynamic; }
private boolean isLastInTimeline(MediaPeriodId id, boolean isLastMediaPeriodInPeriod) { int periodIndex = timeline.getIndexOfPeriod(id.periodUid); int windowIndex = timeline.getPeriod(periodIndex, period).windowIndex; return !timeline.getWindow(windowIndex, window).isDynamic && timeline.isLastPeriod(periodIndex, period, window, repeatMode, shuffleModeEnabled) && isLastMediaPeriodInPeriod; } }
@Override public final long getContentDuration() { Timeline timeline = getCurrentTimeline(); return timeline.isEmpty() ? C.TIME_UNSET : timeline.getWindow(getCurrentWindowIndex(), window).getDurationMs(); }
@Override public final Window getWindow( int windowIndex, Window window, boolean setTag, long defaultPositionProjectionUs) { int childIndex = getChildIndexByWindowIndex(windowIndex); int firstWindowIndexInChild = getFirstWindowIndexByChildIndex(childIndex); int firstPeriodIndexInChild = getFirstPeriodIndexByChildIndex(childIndex); getTimelineByChildIndex(childIndex) .getWindow( windowIndex - firstWindowIndexInChild, window, setTag, defaultPositionProjectionUs); window.firstPeriodIndex += firstPeriodIndexInChild; window.lastPeriodIndex += firstPeriodIndexInChild; return window; }
@Override @Nullable public Object getTag() { boolean hasTimeline = timeline != null && !timeline.isEmpty(); return hasTimeline ? timeline.getWindow(0, new Timeline.Window()).tag : null; }
private void next() { Timeline timeline = player.getCurrentTimeline(); if (timeline.isEmpty() || player.isPlayingAd()) { return; } int windowIndex = player.getCurrentWindowIndex(); int nextWindowIndex = player.getNextWindowIndex(); if (nextWindowIndex != C.INDEX_UNSET) { seekTo(nextWindowIndex, C.TIME_UNSET); } else if (timeline.getWindow(windowIndex, window).isDynamic) { seekTo(windowIndex, C.TIME_UNSET); } }
@Test public void testClippingToEndOfSourceWithUnsetDurationDoesNotSetDuration() throws IOException { // Create a child timeline that has an unknown duration. Timeline timeline = new SinglePeriodTimeline( /* durationUs= */ C.TIME_UNSET, /* isSeekable= */ true, /* isDynamic= */ false); // When clipping to the end, the clipped timeline should also have an unset duration. Timeline clippedTimeline = getClippedTimeline(timeline, TEST_CLIP_AMOUNT_US, C.TIME_END_OF_SOURCE); assertThat(clippedTimeline.getWindow(/* windowIndex= */ 0, window).getDurationUs()) .isEqualTo(C.TIME_UNSET); }
@Test public void testClippingStartAndEnd() throws IOException { Timeline timeline = new SinglePeriodTimeline(TEST_PERIOD_DURATION_US, true, false); Timeline clippedTimeline = getClippedTimeline( timeline, TEST_CLIP_AMOUNT_US, TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US * 2); assertThat(clippedTimeline.getWindow(0, window).getDurationUs()) .isEqualTo(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US * 3); assertThat(clippedTimeline.getPeriod(0, period).getDurationUs()) .isEqualTo(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US * 2); }
@Test public void testClippingStart() throws IOException { Timeline timeline = new SinglePeriodTimeline(TEST_PERIOD_DURATION_US, true, false); Timeline clippedTimeline = getClippedTimeline(timeline, TEST_CLIP_AMOUNT_US, TEST_PERIOD_DURATION_US); assertThat(clippedTimeline.getWindow(0, window).getDurationUs()) .isEqualTo(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US); assertThat(clippedTimeline.getPeriod(0, period).getDurationUs()) .isEqualTo(TEST_PERIOD_DURATION_US); }
@Test public void testClippingEnd() throws IOException { Timeline timeline = new SinglePeriodTimeline(TEST_PERIOD_DURATION_US, true, false); Timeline clippedTimeline = getClippedTimeline(timeline, 0, TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US); assertThat(clippedTimeline.getWindow(0, window).getDurationUs()) .isEqualTo(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US); assertThat(clippedTimeline.getPeriod(0, period).getDurationUs()) .isEqualTo(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US); }
@Override public long getDuration() { if (timeline.isEmpty()) { return C.INDEX_UNSET; } if (isPlayingAd()) { long adDurationUs = timeline.getPeriod(0, period).getAdDurationUs(adGroupIndex, adIndexInAdGroup); return C.usToMs(adDurationUs); } else { return timeline.getWindow(getCurrentWindowIndex(), window).getDurationMs(); } }