Commit 8a210bec by tonihei Committed by Oliver Woodman

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
parent 4abf64b7
...@@ -145,7 +145,16 @@ public abstract class Timeline { ...@@ -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. * @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) { public int getNextWindowIndex(int windowIndex, @ExoPlayer.RepeatMode int repeatMode) {
switch (repeatMode) {
case ExoPlayer.REPEAT_MODE_OFF:
return windowIndex == getWindowCount() - 1 ? C.INDEX_UNSET : windowIndex + 1; 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 { ...@@ -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. * @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) { public int getPreviousWindowIndex(int windowIndex, @ExoPlayer.RepeatMode int repeatMode) {
switch (repeatMode) {
case ExoPlayer.REPEAT_MODE_OFF:
return windowIndex == 0 ? C.INDEX_UNSET : windowIndex - 1; 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();
}
} }
/** /**
......
/*
* 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; ...@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.source;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayer.RepeatMode;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
...@@ -143,6 +144,16 @@ public final class ClippingMediaSource implements MediaSource, MediaSource.Liste ...@@ -143,6 +144,16 @@ public final class ClippingMediaSource implements MediaSource, MediaSource.Liste
} }
@Override @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, public Window getWindow(int windowIndex, Window window, boolean setIds,
long defaultPositionProjectionUs) { long defaultPositionProjectionUs) {
window = timeline.getWindow(0, window, setIds, defaultPositionProjectionUs); window = timeline.getWindow(0, window, setIds, defaultPositionProjectionUs);
......
...@@ -15,8 +15,6 @@ ...@@ -15,8 +15,6 @@
*/ */
package com.google.android.exoplayer2.source; 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.ExoPlayer;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
...@@ -38,6 +36,7 @@ public final class ConcatenatingMediaSource implements MediaSource { ...@@ -38,6 +36,7 @@ public final class ConcatenatingMediaSource implements MediaSource {
private final Object[] manifests; private final Object[] manifests;
private final Map<MediaPeriod, Integer> sourceIndexByMediaPeriod; private final Map<MediaPeriod, Integer> sourceIndexByMediaPeriod;
private final boolean[] duplicateFlags; private final boolean[] duplicateFlags;
private final boolean isRepeatOneAtomic;
private Listener listener; private Listener listener;
private ConcatenatedTimeline timeline; private ConcatenatedTimeline timeline;
...@@ -47,7 +46,19 @@ public final class ConcatenatingMediaSource implements MediaSource { ...@@ -47,7 +46,19 @@ public final class ConcatenatingMediaSource implements MediaSource {
* {@link MediaSource} instance to be present more than once in the array. * {@link MediaSource} instance to be present more than once in the array.
*/ */
public ConcatenatingMediaSource(MediaSource... mediaSources) { 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.mediaSources = mediaSources;
this.isRepeatOneAtomic = isRepeatOneAtomic;
timelines = new Timeline[mediaSources.length]; timelines = new Timeline[mediaSources.length];
manifests = new Object[mediaSources.length]; manifests = new Object[mediaSources.length];
sourceIndexByMediaPeriod = new HashMap<>(); sourceIndexByMediaPeriod = new HashMap<>();
...@@ -81,8 +92,8 @@ public final class ConcatenatingMediaSource implements MediaSource { ...@@ -81,8 +92,8 @@ public final class ConcatenatingMediaSource implements MediaSource {
@Override @Override
public MediaPeriod createPeriod(int index, Allocator allocator, long positionUs) { public MediaPeriod createPeriod(int index, Allocator allocator, long positionUs) {
int sourceIndex = timeline.getSourceIndexForPeriod(index); int sourceIndex = timeline.getChildIndexForPeriod(index);
int periodIndexInSource = index - timeline.getFirstPeriodIndexInSource(sourceIndex); int periodIndexInSource = index - timeline.getFirstPeriodIndexInChild(sourceIndex);
MediaPeriod mediaPeriod = mediaSources[sourceIndex].createPeriod(periodIndexInSource, allocator, MediaPeriod mediaPeriod = mediaSources[sourceIndex].createPeriod(periodIndexInSource, allocator,
positionUs); positionUs);
sourceIndexByMediaPeriod.put(mediaPeriod, sourceIndex); sourceIndexByMediaPeriod.put(mediaPeriod, sourceIndex);
...@@ -123,7 +134,7 @@ public final class ConcatenatingMediaSource implements MediaSource { ...@@ -123,7 +134,7 @@ public final class ConcatenatingMediaSource implements MediaSource {
return; return;
} }
} }
timeline = new ConcatenatedTimeline(timelines.clone()); timeline = new ConcatenatedTimeline(timelines.clone(), isRepeatOneAtomic);
listener.onSourceInfoRefreshed(timeline, manifests.clone()); listener.onSourceInfoRefreshed(timeline, manifests.clone());
} }
...@@ -144,13 +155,14 @@ public final class ConcatenatingMediaSource implements MediaSource { ...@@ -144,13 +155,14 @@ public final class ConcatenatingMediaSource implements MediaSource {
/** /**
* A {@link Timeline} that is the concatenation of one or more {@link Timeline}s. * 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 Timeline[] timelines;
private final int[] sourcePeriodOffsets; private final int[] sourcePeriodOffsets;
private final int[] sourceWindowOffsets; 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[] sourcePeriodOffsets = new int[timelines.length];
int[] sourceWindowOffsets = new int[timelines.length]; int[] sourceWindowOffsets = new int[timelines.length];
long periodCount = 0; long periodCount = 0;
...@@ -167,6 +179,7 @@ public final class ConcatenatingMediaSource implements MediaSource { ...@@ -167,6 +179,7 @@ public final class ConcatenatingMediaSource implements MediaSource {
this.timelines = timelines; this.timelines = timelines;
this.sourcePeriodOffsets = sourcePeriodOffsets; this.sourcePeriodOffsets = sourcePeriodOffsets;
this.sourceWindowOffsets = sourceWindowOffsets; this.sourceWindowOffsets = sourceWindowOffsets;
this.isRepeatOneAtomic = isRepeatOneAtomic;
} }
@Override @Override
...@@ -175,69 +188,54 @@ public final class ConcatenatingMediaSource implements MediaSource { ...@@ -175,69 +188,54 @@ public final class ConcatenatingMediaSource implements MediaSource {
} }
@Override @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() { public int getPeriodCount() {
return sourcePeriodOffsets[sourcePeriodOffsets.length - 1]; return sourcePeriodOffsets[sourcePeriodOffsets.length - 1];
} }
@Override @Override
public Period getPeriod(int periodIndex, Period period, boolean setIds) { public int getNextWindowIndex(int windowIndex, @ExoPlayer.RepeatMode int repeatMode) {
int sourceIndex = getSourceIndexForPeriod(periodIndex); if (isRepeatOneAtomic && repeatMode == ExoPlayer.REPEAT_MODE_ONE) {
int firstWindowIndexInSource = getFirstWindowIndexInSource(sourceIndex); repeatMode = ExoPlayer.REPEAT_MODE_ALL;
int firstPeriodIndexInSource = getFirstPeriodIndexInSource(sourceIndex);
timelines[sourceIndex].getPeriod(periodIndex - firstPeriodIndexInSource, period, setIds);
period.windowIndex += firstWindowIndexInSource;
if (setIds) {
period.uid = Pair.create(sourceIndex, period.uid);
} }
return period; return super.getNextWindowIndex(windowIndex, repeatMode);
} }
@Override @Override
public int getIndexOfPeriod(Object uid) { public int getPreviousWindowIndex(int windowIndex, @ExoPlayer.RepeatMode int repeatMode) {
if (!(uid instanceof Pair)) { if (isRepeatOneAtomic && repeatMode == ExoPlayer.REPEAT_MODE_ONE) {
return C.INDEX_UNSET; repeatMode = ExoPlayer.REPEAT_MODE_ALL;
} }
Pair<?, ?> sourceIndexAndPeriodId = (Pair<?, ?>) uid; return super.getPreviousWindowIndex(windowIndex, repeatMode);
if (!(sourceIndexAndPeriodId.first instanceof Integer)) {
return C.INDEX_UNSET;
} }
int sourceIndex = (Integer) sourceIndexAndPeriodId.first;
Object periodId = sourceIndexAndPeriodId.second; @Override
if (sourceIndex < 0 || sourceIndex >= timelines.length) { protected int getChildCount() {
return C.INDEX_UNSET; return timelines.length;
} }
int periodIndexInSource = timelines[sourceIndex].getIndexOfPeriod(periodId);
return periodIndexInSource == C.INDEX_UNSET ? C.INDEX_UNSET @Override
: getFirstPeriodIndexInSource(sourceIndex) + periodIndexInSource; protected Timeline getChild(int childIndex) {
return timelines[childIndex];
} }
private int getSourceIndexForPeriod(int periodIndex) { @Override
protected int getChildIndexForPeriod(int periodIndex) {
return Util.binarySearchFloor(sourcePeriodOffsets, periodIndex, true, false) + 1; return Util.binarySearchFloor(sourcePeriodOffsets, periodIndex, true, false) + 1;
} }
private int getFirstPeriodIndexInSource(int sourceIndex) { @Override
return sourceIndex == 0 ? 0 : sourcePeriodOffsets[sourceIndex - 1]; 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; return Util.binarySearchFloor(sourceWindowOffsets, windowIndex, true, false) + 1;
} }
private int getFirstWindowIndexInSource(int sourceIndex) { @Override
return sourceIndex == 0 ? 0 : sourceWindowOffsets[sourceIndex - 1]; protected int getFirstWindowIndexInChild(int childIndex) {
return childIndex == 0 ? 0 : sourceWindowOffsets[childIndex - 1];
} }
} }
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
*/ */
package com.google.android.exoplayer2.source; package com.google.android.exoplayer2.source;
import android.util.Pair;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
...@@ -91,7 +90,7 @@ public final class LoopingMediaSource implements MediaSource { ...@@ -91,7 +90,7 @@ public final class LoopingMediaSource implements MediaSource {
childSource.releaseSource(); childSource.releaseSource();
} }
private static final class LoopingTimeline extends Timeline { private static final class LoopingTimeline extends AbstractConcatenatedTimeline {
private final Timeline childTimeline; private final Timeline childTimeline;
private final int childPeriodCount; private final int childPeriodCount;
...@@ -113,46 +112,39 @@ public final class LoopingMediaSource implements MediaSource { ...@@ -113,46 +112,39 @@ public final class LoopingMediaSource implements MediaSource {
} }
@Override @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() { public int getPeriodCount() {
return childPeriodCount * loopCount; return childPeriodCount * loopCount;
} }
@Override @Override
public Period getPeriod(int periodIndex, Period period, boolean setIds) { protected Timeline getChild(int childIndex) {
childTimeline.getPeriod(periodIndex % childPeriodCount, period, setIds); return childTimeline;
int loopCount = (periodIndex / childPeriodCount);
period.windowIndex += loopCount * childWindowCount;
if (setIds) {
period.uid = Pair.create(loopCount, period.uid);
} }
return period;
@Override
protected int getChildCount() {
return loopCount;
} }
@Override @Override
public int getIndexOfPeriod(Object uid) { protected int getChildIndexForPeriod(int periodIndex) {
if (!(uid instanceof Pair)) { return periodIndex / childPeriodCount;
return C.INDEX_UNSET;
} }
Pair<?, ?> loopCountAndChildUid = (Pair<?, ?>) uid;
if (!(loopCountAndChildUid.first instanceof Integer)) { @Override
return C.INDEX_UNSET; protected int getFirstPeriodIndexInChild(int childIndex) {
return childIndex * childPeriodCount;
} }
int loopCount = (Integer) loopCountAndChildUid.first;
int periodIndexOffset = loopCount * childPeriodCount; @Override
return childTimeline.getIndexOfPeriod(loopCountAndChildUid.second) + periodIndexOffset; protected int getChildIndexForWindow(int windowIndex) {
return windowIndex / childWindowCount;
} }
@Override
protected int getFirstWindowIndexInChild(int childIndex) {
return childIndex * childWindowCount;
}
} }
private static final class InfinitelyLoopingTimeline extends Timeline { private static final class InfinitelyLoopingTimeline extends Timeline {
...@@ -169,14 +161,16 @@ public final class LoopingMediaSource implements MediaSource { ...@@ -169,14 +161,16 @@ public final class LoopingMediaSource implements MediaSource {
} }
@Override @Override
public int getNextWindowIndex(int currentWindowIndex, @ExoPlayer.RepeatMode int repeatMode) { public int getNextWindowIndex(int windowIndex, @ExoPlayer.RepeatMode int repeatMode) {
return currentWindowIndex < getWindowCount() - 1 ? currentWindowIndex + 1 : 0; int childNextWindowIndex = childTimeline.getNextWindowIndex(windowIndex, repeatMode);
return childNextWindowIndex == C.INDEX_UNSET ? 0 : childNextWindowIndex;
} }
@Override @Override
public int getPreviousWindowIndex(int currentWindowIndex, public int getPreviousWindowIndex(int windowIndex, @ExoPlayer.RepeatMode int repeatMode) {
@ExoPlayer.RepeatMode int repeatMode) { int childPreviousWindowIndex = childTimeline.getPreviousWindowIndex(windowIndex, repeatMode);
return currentWindowIndex > 0 ? currentWindowIndex - 1 : getWindowCount() - 1; return childPreviousWindowIndex == C.INDEX_UNSET ? getWindowCount() - 1
: childPreviousWindowIndex;
} }
@Override @Override
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment