mirror of
https://github.com/samsonjs/media.git
synced 2026-03-26 09:35:47 +00:00
Add repeat mode support to Timeline implementations.
(Relating to GitHub Issue #2577) The Timeline base class provides the default implementation. Timeline wrappers (e.g. ClippingTimeline, ConcatatedTimeline) forward all requests to the respective inner timelines. Some like ConcatenatedTimeline add their own additional logic to bridge between the child timelines. In addition, ConcatenatedTimeline and LoopingTimeline now have a common abstract base class as they share most of their code. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=155509269
This commit is contained in:
parent
4abf64b7ef
commit
8a210becef
5 changed files with 255 additions and 89 deletions
|
|
@ -145,7 +145,16 @@ public abstract class Timeline {
|
|||
* @return The index of the next window, or {@link C#INDEX_UNSET} if this is the last window.
|
||||
*/
|
||||
public int getNextWindowIndex(int windowIndex, @ExoPlayer.RepeatMode int repeatMode) {
|
||||
return windowIndex == getWindowCount() - 1 ? C.INDEX_UNSET : windowIndex + 1;
|
||||
switch (repeatMode) {
|
||||
case ExoPlayer.REPEAT_MODE_OFF:
|
||||
return windowIndex == getWindowCount() - 1 ? C.INDEX_UNSET : windowIndex + 1;
|
||||
case ExoPlayer.REPEAT_MODE_ONE:
|
||||
return windowIndex;
|
||||
case ExoPlayer.REPEAT_MODE_ALL:
|
||||
return windowIndex == getWindowCount() - 1 ? 0 : windowIndex + 1;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -157,7 +166,16 @@ public abstract class Timeline {
|
|||
* @return The index of the previous window, or {@link C#INDEX_UNSET} if this is the first window.
|
||||
*/
|
||||
public int getPreviousWindowIndex(int windowIndex, @ExoPlayer.RepeatMode int repeatMode) {
|
||||
return windowIndex == 0 ? C.INDEX_UNSET : windowIndex - 1;
|
||||
switch (repeatMode) {
|
||||
case ExoPlayer.REPEAT_MODE_OFF:
|
||||
return windowIndex == 0 ? C.INDEX_UNSET : windowIndex - 1;
|
||||
case ExoPlayer.REPEAT_MODE_ONE:
|
||||
return windowIndex;
|
||||
case ExoPlayer.REPEAT_MODE_ALL:
|
||||
return windowIndex == 0 ? getWindowCount() - 1 : windowIndex - 1;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer2.source;
|
||||
|
||||
import android.util.Pair;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.ExoPlayer;
|
||||
import com.google.android.exoplayer2.Timeline;
|
||||
|
||||
/**
|
||||
* Abstract base class for the concatenation of one or more {@link Timeline}s.
|
||||
*/
|
||||
/* package */ abstract class AbstractConcatenatedTimeline extends Timeline {
|
||||
|
||||
@Override
|
||||
public int getNextWindowIndex(int windowIndex, @ExoPlayer.RepeatMode int repeatMode) {
|
||||
int childIndex = getChildIndexForWindow(windowIndex);
|
||||
int firstWindowIndexInChild = getFirstWindowIndexInChild(childIndex);
|
||||
int nextWindowIndexInChild = getChild(childIndex).getNextWindowIndex(
|
||||
windowIndex - firstWindowIndexInChild,
|
||||
repeatMode == ExoPlayer.REPEAT_MODE_ALL ? ExoPlayer.REPEAT_MODE_OFF : repeatMode);
|
||||
if (nextWindowIndexInChild == C.INDEX_UNSET) {
|
||||
if (childIndex < getChildCount() - 1) {
|
||||
childIndex++;
|
||||
} else if (repeatMode == ExoPlayer.REPEAT_MODE_ALL) {
|
||||
childIndex = 0;
|
||||
} else {
|
||||
return C.INDEX_UNSET;
|
||||
}
|
||||
firstWindowIndexInChild = getFirstWindowIndexInChild(childIndex);
|
||||
nextWindowIndexInChild = 0;
|
||||
}
|
||||
return firstWindowIndexInChild + nextWindowIndexInChild;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPreviousWindowIndex(int windowIndex, @ExoPlayer.RepeatMode int repeatMode) {
|
||||
int childIndex = getChildIndexForWindow(windowIndex);
|
||||
int firstWindowIndexInChild = getFirstWindowIndexInChild(childIndex);
|
||||
int previousWindowIndexInChild = getChild(childIndex).getPreviousWindowIndex(
|
||||
windowIndex - firstWindowIndexInChild,
|
||||
repeatMode == ExoPlayer.REPEAT_MODE_ALL ? ExoPlayer.REPEAT_MODE_OFF : repeatMode);
|
||||
if (previousWindowIndexInChild == C.INDEX_UNSET) {
|
||||
if (childIndex > 0) {
|
||||
childIndex--;
|
||||
} else if (repeatMode == ExoPlayer.REPEAT_MODE_ALL) {
|
||||
childIndex = getChildCount() - 1;
|
||||
} else {
|
||||
return C.INDEX_UNSET;
|
||||
}
|
||||
firstWindowIndexInChild = getFirstWindowIndexInChild(childIndex);
|
||||
previousWindowIndexInChild = getChild(childIndex).getWindowCount() - 1;
|
||||
}
|
||||
return firstWindowIndexInChild + previousWindowIndexInChild;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Window getWindow(int windowIndex, Window window, boolean setIds,
|
||||
long defaultPositionProjectionUs) {
|
||||
int childIndex = getChildIndexForWindow(windowIndex);
|
||||
int firstWindowIndexInChild = getFirstWindowIndexInChild(childIndex);
|
||||
int firstPeriodIndexInChild = getFirstPeriodIndexInChild(childIndex);
|
||||
getChild(childIndex).getWindow(windowIndex - firstWindowIndexInChild, window, setIds,
|
||||
defaultPositionProjectionUs);
|
||||
window.firstPeriodIndex += firstPeriodIndexInChild;
|
||||
window.lastPeriodIndex += firstPeriodIndexInChild;
|
||||
return window;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Period getPeriod(int periodIndex, Period period, boolean setIds) {
|
||||
int childIndex = getChildIndexForPeriod(periodIndex);
|
||||
int firstWindowIndexInChild = getFirstWindowIndexInChild(childIndex);
|
||||
int firstPeriodIndexInChild = getFirstPeriodIndexInChild(childIndex);
|
||||
getChild(childIndex).getPeriod(periodIndex - firstPeriodIndexInChild, period, setIds);
|
||||
period.windowIndex += firstWindowIndexInChild;
|
||||
if (setIds) {
|
||||
period.uid = Pair.create(childIndex, period.uid);
|
||||
}
|
||||
return period;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int getIndexOfPeriod(Object uid) {
|
||||
if (!(uid instanceof Pair)) {
|
||||
return C.INDEX_UNSET;
|
||||
}
|
||||
Pair<?, ?> childIndexAndPeriodId = (Pair<?, ?>) uid;
|
||||
if (!(childIndexAndPeriodId.first instanceof Integer)) {
|
||||
return C.INDEX_UNSET;
|
||||
}
|
||||
int childIndex = (Integer) childIndexAndPeriodId.first;
|
||||
Object periodId = childIndexAndPeriodId.second;
|
||||
if (childIndex < 0 || childIndex >= getChildCount()) {
|
||||
return C.INDEX_UNSET;
|
||||
}
|
||||
int periodIndexInChild = getChild(childIndex).getIndexOfPeriod(periodId);
|
||||
return periodIndexInChild == C.INDEX_UNSET ? C.INDEX_UNSET
|
||||
: getFirstPeriodIndexInChild(childIndex) + periodIndexInChild;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of concatenated child timelines.
|
||||
*/
|
||||
protected abstract int getChildCount();
|
||||
|
||||
/**
|
||||
* Returns a child timeline by index.
|
||||
*/
|
||||
protected abstract Timeline getChild(int childIndex);
|
||||
|
||||
/**
|
||||
* Returns the index of the child timeline to which the period with the given index belongs.
|
||||
*/
|
||||
protected abstract int getChildIndexForPeriod(int periodIndex);
|
||||
|
||||
/**
|
||||
* Returns the first period index belonging to the child timeline with the given index.
|
||||
*/
|
||||
protected abstract int getFirstPeriodIndexInChild(int childIndex);
|
||||
|
||||
/**
|
||||
* Returns the index of the child timeline to which the window with the given index belongs.
|
||||
*/
|
||||
protected abstract int getChildIndexForWindow(int windowIndex);
|
||||
|
||||
/**
|
||||
* Returns the first window index belonging to the child timeline with the given index.
|
||||
*/
|
||||
protected abstract int getFirstWindowIndexInChild(int childIndex);
|
||||
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ package com.google.android.exoplayer2.source;
|
|||
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.ExoPlayer;
|
||||
import com.google.android.exoplayer2.ExoPlayer.RepeatMode;
|
||||
import com.google.android.exoplayer2.Timeline;
|
||||
import com.google.android.exoplayer2.upstream.Allocator;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
|
|
@ -142,6 +143,16 @@ public final class ClippingMediaSource implements MediaSource, MediaSource.Liste
|
|||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNextWindowIndex(int windowIndex, @RepeatMode int repeatMode) {
|
||||
return timeline.getNextWindowIndex(windowIndex, repeatMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPreviousWindowIndex(int windowIndex, @RepeatMode int repeatMode) {
|
||||
return timeline.getPreviousWindowIndex(windowIndex, repeatMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Window getWindow(int windowIndex, Window window, boolean setIds,
|
||||
long defaultPositionProjectionUs) {
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.source;
|
||||
|
||||
import android.util.Pair;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.ExoPlayer;
|
||||
import com.google.android.exoplayer2.Timeline;
|
||||
import com.google.android.exoplayer2.upstream.Allocator;
|
||||
|
|
@ -38,6 +36,7 @@ public final class ConcatenatingMediaSource implements MediaSource {
|
|||
private final Object[] manifests;
|
||||
private final Map<MediaPeriod, Integer> sourceIndexByMediaPeriod;
|
||||
private final boolean[] duplicateFlags;
|
||||
private final boolean isRepeatOneAtomic;
|
||||
|
||||
private Listener listener;
|
||||
private ConcatenatedTimeline timeline;
|
||||
|
|
@ -47,7 +46,19 @@ public final class ConcatenatingMediaSource implements MediaSource {
|
|||
* {@link MediaSource} instance to be present more than once in the array.
|
||||
*/
|
||||
public ConcatenatingMediaSource(MediaSource... mediaSources) {
|
||||
this(false, mediaSources);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isRepeatOneAtomic Whether the concatenated media source shall be treated as atomic
|
||||
* (i.e., repeated in its entirety) when repeat mode is set to
|
||||
* {@code ExoPlayer.REPEAT_MODE_ONE}.
|
||||
* @param mediaSources The {@link MediaSource}s to concatenate. It is valid for the same
|
||||
* {@link MediaSource} instance to be present more than once in the array.
|
||||
*/
|
||||
public ConcatenatingMediaSource(boolean isRepeatOneAtomic, MediaSource... mediaSources) {
|
||||
this.mediaSources = mediaSources;
|
||||
this.isRepeatOneAtomic = isRepeatOneAtomic;
|
||||
timelines = new Timeline[mediaSources.length];
|
||||
manifests = new Object[mediaSources.length];
|
||||
sourceIndexByMediaPeriod = new HashMap<>();
|
||||
|
|
@ -81,8 +92,8 @@ public final class ConcatenatingMediaSource implements MediaSource {
|
|||
|
||||
@Override
|
||||
public MediaPeriod createPeriod(int index, Allocator allocator, long positionUs) {
|
||||
int sourceIndex = timeline.getSourceIndexForPeriod(index);
|
||||
int periodIndexInSource = index - timeline.getFirstPeriodIndexInSource(sourceIndex);
|
||||
int sourceIndex = timeline.getChildIndexForPeriod(index);
|
||||
int periodIndexInSource = index - timeline.getFirstPeriodIndexInChild(sourceIndex);
|
||||
MediaPeriod mediaPeriod = mediaSources[sourceIndex].createPeriod(periodIndexInSource, allocator,
|
||||
positionUs);
|
||||
sourceIndexByMediaPeriod.put(mediaPeriod, sourceIndex);
|
||||
|
|
@ -123,7 +134,7 @@ public final class ConcatenatingMediaSource implements MediaSource {
|
|||
return;
|
||||
}
|
||||
}
|
||||
timeline = new ConcatenatedTimeline(timelines.clone());
|
||||
timeline = new ConcatenatedTimeline(timelines.clone(), isRepeatOneAtomic);
|
||||
listener.onSourceInfoRefreshed(timeline, manifests.clone());
|
||||
}
|
||||
|
||||
|
|
@ -144,13 +155,14 @@ public final class ConcatenatingMediaSource implements MediaSource {
|
|||
/**
|
||||
* A {@link Timeline} that is the concatenation of one or more {@link Timeline}s.
|
||||
*/
|
||||
private static final class ConcatenatedTimeline extends Timeline {
|
||||
private static final class ConcatenatedTimeline extends AbstractConcatenatedTimeline {
|
||||
|
||||
private final Timeline[] timelines;
|
||||
private final int[] sourcePeriodOffsets;
|
||||
private final int[] sourceWindowOffsets;
|
||||
private final boolean isRepeatOneAtomic;
|
||||
|
||||
public ConcatenatedTimeline(Timeline[] timelines) {
|
||||
public ConcatenatedTimeline(Timeline[] timelines, boolean isRepeatOneAtomic) {
|
||||
int[] sourcePeriodOffsets = new int[timelines.length];
|
||||
int[] sourceWindowOffsets = new int[timelines.length];
|
||||
long periodCount = 0;
|
||||
|
|
@ -167,6 +179,7 @@ public final class ConcatenatingMediaSource implements MediaSource {
|
|||
this.timelines = timelines;
|
||||
this.sourcePeriodOffsets = sourcePeriodOffsets;
|
||||
this.sourceWindowOffsets = sourceWindowOffsets;
|
||||
this.isRepeatOneAtomic = isRepeatOneAtomic;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -174,70 +187,55 @@ public final class ConcatenatingMediaSource implements MediaSource {
|
|||
return sourceWindowOffsets[sourceWindowOffsets.length - 1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Window getWindow(int windowIndex, Window window, boolean setIds,
|
||||
long defaultPositionProjectionUs) {
|
||||
int sourceIndex = getSourceIndexForWindow(windowIndex);
|
||||
int firstWindowIndexInSource = getFirstWindowIndexInSource(sourceIndex);
|
||||
int firstPeriodIndexInSource = getFirstPeriodIndexInSource(sourceIndex);
|
||||
timelines[sourceIndex].getWindow(windowIndex - firstWindowIndexInSource, window, setIds,
|
||||
defaultPositionProjectionUs);
|
||||
window.firstPeriodIndex += firstPeriodIndexInSource;
|
||||
window.lastPeriodIndex += firstPeriodIndexInSource;
|
||||
return window;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPeriodCount() {
|
||||
return sourcePeriodOffsets[sourcePeriodOffsets.length - 1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Period getPeriod(int periodIndex, Period period, boolean setIds) {
|
||||
int sourceIndex = getSourceIndexForPeriod(periodIndex);
|
||||
int firstWindowIndexInSource = getFirstWindowIndexInSource(sourceIndex);
|
||||
int firstPeriodIndexInSource = getFirstPeriodIndexInSource(sourceIndex);
|
||||
timelines[sourceIndex].getPeriod(periodIndex - firstPeriodIndexInSource, period, setIds);
|
||||
period.windowIndex += firstWindowIndexInSource;
|
||||
if (setIds) {
|
||||
period.uid = Pair.create(sourceIndex, period.uid);
|
||||
public int getNextWindowIndex(int windowIndex, @ExoPlayer.RepeatMode int repeatMode) {
|
||||
if (isRepeatOneAtomic && repeatMode == ExoPlayer.REPEAT_MODE_ONE) {
|
||||
repeatMode = ExoPlayer.REPEAT_MODE_ALL;
|
||||
}
|
||||
return period;
|
||||
return super.getNextWindowIndex(windowIndex, repeatMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndexOfPeriod(Object uid) {
|
||||
if (!(uid instanceof Pair)) {
|
||||
return C.INDEX_UNSET;
|
||||
public int getPreviousWindowIndex(int windowIndex, @ExoPlayer.RepeatMode int repeatMode) {
|
||||
if (isRepeatOneAtomic && repeatMode == ExoPlayer.REPEAT_MODE_ONE) {
|
||||
repeatMode = ExoPlayer.REPEAT_MODE_ALL;
|
||||
}
|
||||
Pair<?, ?> sourceIndexAndPeriodId = (Pair<?, ?>) uid;
|
||||
if (!(sourceIndexAndPeriodId.first instanceof Integer)) {
|
||||
return C.INDEX_UNSET;
|
||||
}
|
||||
int sourceIndex = (Integer) sourceIndexAndPeriodId.first;
|
||||
Object periodId = sourceIndexAndPeriodId.second;
|
||||
if (sourceIndex < 0 || sourceIndex >= timelines.length) {
|
||||
return C.INDEX_UNSET;
|
||||
}
|
||||
int periodIndexInSource = timelines[sourceIndex].getIndexOfPeriod(periodId);
|
||||
return periodIndexInSource == C.INDEX_UNSET ? C.INDEX_UNSET
|
||||
: getFirstPeriodIndexInSource(sourceIndex) + periodIndexInSource;
|
||||
return super.getPreviousWindowIndex(windowIndex, repeatMode);
|
||||
}
|
||||
|
||||
private int getSourceIndexForPeriod(int periodIndex) {
|
||||
@Override
|
||||
protected int getChildCount() {
|
||||
return timelines.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Timeline getChild(int childIndex) {
|
||||
return timelines[childIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getChildIndexForPeriod(int periodIndex) {
|
||||
return Util.binarySearchFloor(sourcePeriodOffsets, periodIndex, true, false) + 1;
|
||||
}
|
||||
|
||||
private int getFirstPeriodIndexInSource(int sourceIndex) {
|
||||
return sourceIndex == 0 ? 0 : sourcePeriodOffsets[sourceIndex - 1];
|
||||
@Override
|
||||
protected int getFirstPeriodIndexInChild(int childIndex) {
|
||||
return childIndex == 0 ? 0 : sourcePeriodOffsets[childIndex - 1];
|
||||
}
|
||||
|
||||
private int getSourceIndexForWindow(int windowIndex) {
|
||||
@Override
|
||||
protected int getChildIndexForWindow(int windowIndex) {
|
||||
return Util.binarySearchFloor(sourceWindowOffsets, windowIndex, true, false) + 1;
|
||||
}
|
||||
|
||||
private int getFirstWindowIndexInSource(int sourceIndex) {
|
||||
return sourceIndex == 0 ? 0 : sourceWindowOffsets[sourceIndex - 1];
|
||||
@Override
|
||||
protected int getFirstWindowIndexInChild(int childIndex) {
|
||||
return childIndex == 0 ? 0 : sourceWindowOffsets[childIndex - 1];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.source;
|
||||
|
||||
import android.util.Pair;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.ExoPlayer;
|
||||
import com.google.android.exoplayer2.Timeline;
|
||||
|
|
@ -91,7 +90,7 @@ public final class LoopingMediaSource implements MediaSource {
|
|||
childSource.releaseSource();
|
||||
}
|
||||
|
||||
private static final class LoopingTimeline extends Timeline {
|
||||
private static final class LoopingTimeline extends AbstractConcatenatedTimeline {
|
||||
|
||||
private final Timeline childTimeline;
|
||||
private final int childPeriodCount;
|
||||
|
|
@ -112,47 +111,40 @@ public final class LoopingMediaSource implements MediaSource {
|
|||
return childWindowCount * loopCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Window getWindow(int windowIndex, Window window, boolean setIds,
|
||||
long defaultPositionProjectionUs) {
|
||||
childTimeline.getWindow(windowIndex % childWindowCount, window, setIds,
|
||||
defaultPositionProjectionUs);
|
||||
int periodIndexOffset = (windowIndex / childWindowCount) * childPeriodCount;
|
||||
window.firstPeriodIndex += periodIndexOffset;
|
||||
window.lastPeriodIndex += periodIndexOffset;
|
||||
return window;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPeriodCount() {
|
||||
return childPeriodCount * loopCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Period getPeriod(int periodIndex, Period period, boolean setIds) {
|
||||
childTimeline.getPeriod(periodIndex % childPeriodCount, period, setIds);
|
||||
int loopCount = (periodIndex / childPeriodCount);
|
||||
period.windowIndex += loopCount * childWindowCount;
|
||||
if (setIds) {
|
||||
period.uid = Pair.create(loopCount, period.uid);
|
||||
}
|
||||
return period;
|
||||
protected Timeline getChild(int childIndex) {
|
||||
return childTimeline;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndexOfPeriod(Object uid) {
|
||||
if (!(uid instanceof Pair)) {
|
||||
return C.INDEX_UNSET;
|
||||
}
|
||||
Pair<?, ?> loopCountAndChildUid = (Pair<?, ?>) uid;
|
||||
if (!(loopCountAndChildUid.first instanceof Integer)) {
|
||||
return C.INDEX_UNSET;
|
||||
}
|
||||
int loopCount = (Integer) loopCountAndChildUid.first;
|
||||
int periodIndexOffset = loopCount * childPeriodCount;
|
||||
return childTimeline.getIndexOfPeriod(loopCountAndChildUid.second) + periodIndexOffset;
|
||||
protected int getChildCount() {
|
||||
return loopCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getChildIndexForPeriod(int periodIndex) {
|
||||
return periodIndex / childPeriodCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getFirstPeriodIndexInChild(int childIndex) {
|
||||
return childIndex * childPeriodCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getChildIndexForWindow(int windowIndex) {
|
||||
return windowIndex / childWindowCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getFirstWindowIndexInChild(int childIndex) {
|
||||
return childIndex * childWindowCount;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class InfinitelyLoopingTimeline extends Timeline {
|
||||
|
|
@ -169,14 +161,16 @@ public final class LoopingMediaSource implements MediaSource {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getNextWindowIndex(int currentWindowIndex, @ExoPlayer.RepeatMode int repeatMode) {
|
||||
return currentWindowIndex < getWindowCount() - 1 ? currentWindowIndex + 1 : 0;
|
||||
public int getNextWindowIndex(int windowIndex, @ExoPlayer.RepeatMode int repeatMode) {
|
||||
int childNextWindowIndex = childTimeline.getNextWindowIndex(windowIndex, repeatMode);
|
||||
return childNextWindowIndex == C.INDEX_UNSET ? 0 : childNextWindowIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPreviousWindowIndex(int currentWindowIndex,
|
||||
@ExoPlayer.RepeatMode int repeatMode) {
|
||||
return currentWindowIndex > 0 ? currentWindowIndex - 1 : getWindowCount() - 1;
|
||||
public int getPreviousWindowIndex(int windowIndex, @ExoPlayer.RepeatMode int repeatMode) {
|
||||
int childPreviousWindowIndex = childTimeline.getPreviousWindowIndex(windowIndex, repeatMode);
|
||||
return childPreviousWindowIndex == C.INDEX_UNSET ? getWindowCount() - 1
|
||||
: childPreviousWindowIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Reference in a new issue