mirror of
https://github.com/androidx/media.git
synced 2025-05-17 04:29:55 +08:00
Remove child data holder helper from AbstractConcatenatedTimeline.
This helper class required a scratch instance to write on. Such a scratch instance may violate the immuatability of the timelines if used by multiple threads simultaneously. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=163992458
This commit is contained in:
parent
412138b2ea
commit
5ca84ebfd8
@ -25,68 +25,25 @@ import com.google.android.exoplayer2.Timeline;
|
||||
*/
|
||||
/* package */ abstract class AbstractConcatenatedTimeline extends Timeline {
|
||||
|
||||
/**
|
||||
* Meta data of a child timeline.
|
||||
*/
|
||||
protected static final class ChildDataHolder {
|
||||
private final int childCount;
|
||||
|
||||
/**
|
||||
* Child timeline.
|
||||
*/
|
||||
public Timeline timeline;
|
||||
|
||||
/**
|
||||
* First period index belonging to the child timeline.
|
||||
*/
|
||||
public int firstPeriodIndexInChild;
|
||||
|
||||
/**
|
||||
* First window index belonging to the child timeline.
|
||||
*/
|
||||
public int firstWindowIndexInChild;
|
||||
|
||||
/**
|
||||
* UID of child timeline.
|
||||
*/
|
||||
public Object uid;
|
||||
|
||||
/**
|
||||
* Set child holder data.
|
||||
*
|
||||
* @param timeline Child timeline.
|
||||
* @param firstPeriodIndexInChild First period index belonging to the child timeline.
|
||||
* @param firstWindowIndexInChild First window index belonging to the child timeline.
|
||||
* @param uid UID of child timeline.
|
||||
*/
|
||||
public void setData(Timeline timeline, int firstPeriodIndexInChild, int firstWindowIndexInChild,
|
||||
Object uid) {
|
||||
this.timeline = timeline;
|
||||
this.firstPeriodIndexInChild = firstPeriodIndexInChild;
|
||||
this.firstWindowIndexInChild = firstWindowIndexInChild;
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final ChildDataHolder childDataHolder;
|
||||
|
||||
public AbstractConcatenatedTimeline() {
|
||||
childDataHolder = new ChildDataHolder();
|
||||
public AbstractConcatenatedTimeline(int childCount) {
|
||||
this.childCount = childCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNextWindowIndex(int windowIndex, @Player.RepeatMode int repeatMode) {
|
||||
getChildDataByWindowIndex(windowIndex, childDataHolder);
|
||||
int firstWindowIndexInChild = childDataHolder.firstWindowIndexInChild;
|
||||
int nextWindowIndexInChild = childDataHolder.timeline.getNextWindowIndex(
|
||||
int childIndex = getChildIndexByWindowIndex(windowIndex);
|
||||
int firstWindowIndexInChild = getFirstWindowIndexByChildIndex(childIndex);
|
||||
int nextWindowIndexInChild = getTimelineByChildIndex(childIndex).getNextWindowIndex(
|
||||
windowIndex - firstWindowIndexInChild,
|
||||
repeatMode == Player.REPEAT_MODE_ALL ? Player.REPEAT_MODE_OFF : repeatMode);
|
||||
if (nextWindowIndexInChild != C.INDEX_UNSET) {
|
||||
return firstWindowIndexInChild + nextWindowIndexInChild;
|
||||
} else {
|
||||
firstWindowIndexInChild += childDataHolder.timeline.getWindowCount();
|
||||
if (firstWindowIndexInChild < getWindowCount()) {
|
||||
return firstWindowIndexInChild;
|
||||
int nextChildIndex = childIndex + 1;
|
||||
if (nextChildIndex < childCount) {
|
||||
return getFirstWindowIndexByChildIndex(nextChildIndex);
|
||||
} else if (repeatMode == Player.REPEAT_MODE_ALL) {
|
||||
return 0;
|
||||
} else {
|
||||
@ -97,9 +54,9 @@ import com.google.android.exoplayer2.Timeline;
|
||||
|
||||
@Override
|
||||
public int getPreviousWindowIndex(int windowIndex, @Player.RepeatMode int repeatMode) {
|
||||
getChildDataByWindowIndex(windowIndex, childDataHolder);
|
||||
int firstWindowIndexInChild = childDataHolder.firstWindowIndexInChild;
|
||||
int previousWindowIndexInChild = childDataHolder.timeline.getPreviousWindowIndex(
|
||||
int childIndex = getChildIndexByWindowIndex(windowIndex);
|
||||
int firstWindowIndexInChild = getFirstWindowIndexByChildIndex(childIndex);
|
||||
int previousWindowIndexInChild = getTimelineByChildIndex(childIndex).getPreviousWindowIndex(
|
||||
windowIndex - firstWindowIndexInChild,
|
||||
repeatMode == Player.REPEAT_MODE_ALL ? Player.REPEAT_MODE_OFF : repeatMode);
|
||||
if (previousWindowIndexInChild != C.INDEX_UNSET) {
|
||||
@ -118,11 +75,11 @@ import com.google.android.exoplayer2.Timeline;
|
||||
@Override
|
||||
public final Window getWindow(int windowIndex, Window window, boolean setIds,
|
||||
long defaultPositionProjectionUs) {
|
||||
getChildDataByWindowIndex(windowIndex, childDataHolder);
|
||||
int firstWindowIndexInChild = childDataHolder.firstWindowIndexInChild;
|
||||
int firstPeriodIndexInChild = childDataHolder.firstPeriodIndexInChild;
|
||||
childDataHolder.timeline.getWindow(windowIndex - firstWindowIndexInChild, window, setIds,
|
||||
defaultPositionProjectionUs);
|
||||
int childIndex = getChildIndexByWindowIndex(windowIndex);
|
||||
int firstWindowIndexInChild = getFirstWindowIndexByChildIndex(childIndex);
|
||||
int firstPeriodIndexInChild = getFirstPeriodIndexByChildIndex(childIndex);
|
||||
getTimelineByChildIndex(childIndex).getWindow(windowIndex - firstWindowIndexInChild, window,
|
||||
setIds, defaultPositionProjectionUs);
|
||||
window.firstPeriodIndex += firstPeriodIndexInChild;
|
||||
window.lastPeriodIndex += firstPeriodIndexInChild;
|
||||
return window;
|
||||
@ -130,13 +87,14 @@ import com.google.android.exoplayer2.Timeline;
|
||||
|
||||
@Override
|
||||
public final Period getPeriod(int periodIndex, Period period, boolean setIds) {
|
||||
getChildDataByPeriodIndex(periodIndex, childDataHolder);
|
||||
int firstWindowIndexInChild = childDataHolder.firstWindowIndexInChild;
|
||||
int firstPeriodIndexInChild = childDataHolder.firstPeriodIndexInChild;
|
||||
childDataHolder.timeline.getPeriod(periodIndex - firstPeriodIndexInChild, period, setIds);
|
||||
int childIndex = getChildIndexByPeriodIndex(periodIndex);
|
||||
int firstWindowIndexInChild = getFirstWindowIndexByChildIndex(childIndex);
|
||||
int firstPeriodIndexInChild = getFirstPeriodIndexByChildIndex(childIndex);
|
||||
getTimelineByChildIndex(childIndex).getPeriod(periodIndex - firstPeriodIndexInChild, period,
|
||||
setIds);
|
||||
period.windowIndex += firstWindowIndexInChild;
|
||||
if (setIds) {
|
||||
period.uid = Pair.create(childDataHolder.uid, period.uid);
|
||||
period.uid = Pair.create(getChildUidByChildIndex(childIndex), period.uid);
|
||||
}
|
||||
return period;
|
||||
}
|
||||
@ -149,37 +107,64 @@ import com.google.android.exoplayer2.Timeline;
|
||||
Pair<?, ?> childUidAndPeriodUid = (Pair<?, ?>) uid;
|
||||
Object childUid = childUidAndPeriodUid.first;
|
||||
Object periodUid = childUidAndPeriodUid.second;
|
||||
if (!getChildDataByChildUid(childUid, childDataHolder)) {
|
||||
int childIndex = getChildIndexByChildUid(childUid);
|
||||
if (childIndex == C.INDEX_UNSET) {
|
||||
return C.INDEX_UNSET;
|
||||
}
|
||||
int periodIndexInChild = childDataHolder.timeline.getIndexOfPeriod(periodUid);
|
||||
int periodIndexInChild = getTimelineByChildIndex(childIndex).getIndexOfPeriod(periodUid);
|
||||
return periodIndexInChild == C.INDEX_UNSET ? C.INDEX_UNSET
|
||||
: childDataHolder.firstPeriodIndexInChild + periodIndexInChild;
|
||||
: getFirstPeriodIndexByChildIndex(childIndex) + periodIndexInChild;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates {@link ChildDataHolder} for the child timeline containing the given period index.
|
||||
* Returns the index of the child timeline containing the given period index.
|
||||
*
|
||||
* @param periodIndex A valid period index within the bounds of the timeline.
|
||||
* @param childData A data holder to be populated.
|
||||
*/
|
||||
protected abstract void getChildDataByPeriodIndex(int periodIndex, ChildDataHolder childData);
|
||||
protected abstract int getChildIndexByPeriodIndex(int periodIndex);
|
||||
|
||||
/**
|
||||
* Populates {@link ChildDataHolder} for the child timeline containing the given window index.
|
||||
* Returns the index of the child timeline containing the given window index.
|
||||
*
|
||||
* @param windowIndex A valid window index within the bounds of the timeline.
|
||||
* @param childData A data holder to be populated.
|
||||
*/
|
||||
protected abstract void getChildDataByWindowIndex(int windowIndex, ChildDataHolder childData);
|
||||
protected abstract int getChildIndexByWindowIndex(int windowIndex);
|
||||
|
||||
/**
|
||||
* Populates {@link ChildDataHolder} for the child timeline with the given UID.
|
||||
* Returns the index of the child timeline with the given UID or {@link C#INDEX_UNSET} if not
|
||||
* found.
|
||||
*
|
||||
* @param childUid A child UID.
|
||||
* @param childData A data holder to be populated.
|
||||
* @return Whether a child with the given UID was found.
|
||||
* @return Index of child timeline or {@link C#INDEX_UNSET} if UID was not found.
|
||||
*/
|
||||
protected abstract boolean getChildDataByChildUid(Object childUid, ChildDataHolder childData);
|
||||
protected abstract int getChildIndexByChildUid(Object childUid);
|
||||
|
||||
/**
|
||||
* Returns the child timeline for the child with the given index.
|
||||
*
|
||||
* @param childIndex A valid child index within the bounds of the timeline.
|
||||
*/
|
||||
protected abstract Timeline getTimelineByChildIndex(int childIndex);
|
||||
|
||||
/**
|
||||
* Returns the first period index belonging to the child timeline with the given index.
|
||||
*
|
||||
* @param childIndex A valid child index within the bounds of the timeline.
|
||||
*/
|
||||
protected abstract int getFirstPeriodIndexByChildIndex(int childIndex);
|
||||
|
||||
/**
|
||||
* Returns the first window index belonging to the child timeline with the given index.
|
||||
*
|
||||
* @param childIndex A valid child index within the bounds of the timeline.
|
||||
*/
|
||||
protected abstract int getFirstWindowIndexByChildIndex(int childIndex);
|
||||
|
||||
/**
|
||||
* Returns the UID of the child timeline with the given index.
|
||||
*
|
||||
* @param childIndex A valid child index within the bounds of the timeline.
|
||||
*/
|
||||
protected abstract Object getChildUidByChildIndex(int childIndex);
|
||||
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.google.android.exoplayer2.source;
|
||||
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.ExoPlayer;
|
||||
import com.google.android.exoplayer2.Player;
|
||||
import com.google.android.exoplayer2.Timeline;
|
||||
@ -97,7 +98,7 @@ public final class ConcatenatingMediaSource implements MediaSource {
|
||||
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) {
|
||||
int sourceIndex = timeline.getChildIndexByPeriodIndex(id.periodIndex);
|
||||
MediaPeriodId periodIdInSource =
|
||||
new MediaPeriodId(id.periodIndex - timeline.getFirstPeriodIndexInChild(sourceIndex));
|
||||
new MediaPeriodId(id.periodIndex - timeline.getFirstPeriodIndexByChildIndex(sourceIndex));
|
||||
MediaPeriod mediaPeriod = mediaSources[sourceIndex].createPeriod(periodIdInSource, allocator);
|
||||
sourceIndexByMediaPeriod.put(mediaPeriod, sourceIndex);
|
||||
return mediaPeriod;
|
||||
@ -166,6 +167,7 @@ public final class ConcatenatingMediaSource implements MediaSource {
|
||||
private final boolean isRepeatOneAtomic;
|
||||
|
||||
public ConcatenatedTimeline(Timeline[] timelines, boolean isRepeatOneAtomic) {
|
||||
super(timelines.length);
|
||||
int[] sourcePeriodOffsets = new int[timelines.length];
|
||||
int[] sourceWindowOffsets = new int[timelines.length];
|
||||
long periodCount = 0;
|
||||
@ -212,44 +214,43 @@ public final class ConcatenatingMediaSource implements MediaSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getChildDataByPeriodIndex(int periodIndex, ChildDataHolder childData) {
|
||||
int childIndex = getChildIndexByPeriodIndex(periodIndex);
|
||||
getChildDataByChildIndex(childIndex, childData);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getChildDataByWindowIndex(int windowIndex, ChildDataHolder childData) {
|
||||
int childIndex = Util.binarySearchFloor(sourceWindowOffsets, windowIndex, true, false) + 1;
|
||||
getChildDataByChildIndex(childIndex, childData);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getChildDataByChildUid(Object childUid, ChildDataHolder childData) {
|
||||
if (!(childUid instanceof Integer)) {
|
||||
return false;
|
||||
}
|
||||
int childIndex = (Integer) childUid;
|
||||
getChildDataByChildIndex(childIndex, childData);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void getChildDataByChildIndex(int childIndex, ChildDataHolder childData) {
|
||||
childData.setData(timelines[childIndex], getFirstPeriodIndexInChild(childIndex),
|
||||
getFirstWindowIndexInChild(childIndex), childIndex);
|
||||
}
|
||||
|
||||
private int getChildIndexByPeriodIndex(int periodIndex) {
|
||||
protected int getChildIndexByPeriodIndex(int periodIndex) {
|
||||
return Util.binarySearchFloor(sourcePeriodOffsets, periodIndex, true, false) + 1;
|
||||
}
|
||||
|
||||
private int getFirstPeriodIndexInChild(int childIndex) {
|
||||
@Override
|
||||
protected int getChildIndexByWindowIndex(int windowIndex) {
|
||||
return Util.binarySearchFloor(sourceWindowOffsets, windowIndex, true, false) + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getChildIndexByChildUid(Object childUid) {
|
||||
if (!(childUid instanceof Integer)) {
|
||||
return C.INDEX_UNSET;
|
||||
}
|
||||
return (Integer) childUid;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Timeline getTimelineByChildIndex(int childIndex) {
|
||||
return timelines[childIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getFirstPeriodIndexByChildIndex(int childIndex) {
|
||||
return childIndex == 0 ? 0 : sourcePeriodOffsets[childIndex - 1];
|
||||
}
|
||||
|
||||
private int getFirstWindowIndexInChild(int childIndex) {
|
||||
@Override
|
||||
protected int getFirstWindowIndexByChildIndex(int childIndex) {
|
||||
return childIndex == 0 ? 0 : sourceWindowOffsets[childIndex - 1];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getChildUidByChildIndex(int childIndex) {
|
||||
return childIndex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -397,6 +397,7 @@ public final class DynamicConcatenatingMediaSource implements MediaSource, ExoPl
|
||||
|
||||
public ConcatenatedTimeline(Collection<MediaSourceHolder> mediaSourceHolders, int windowCount,
|
||||
int periodCount) {
|
||||
super(mediaSourceHolders.size());
|
||||
this.windowCount = windowCount;
|
||||
this.periodCount = periodCount;
|
||||
int childCount = mediaSourceHolders.size();
|
||||
@ -416,28 +417,42 @@ public final class DynamicConcatenatingMediaSource implements MediaSource, ExoPl
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getChildDataByPeriodIndex(int periodIndex, ChildDataHolder childDataHolder) {
|
||||
int index = Util.binarySearchFloor(firstPeriodInChildIndices, periodIndex, true, false);
|
||||
setChildData(index, childDataHolder);
|
||||
protected int getChildIndexByPeriodIndex(int periodIndex) {
|
||||
return Util.binarySearchFloor(firstPeriodInChildIndices, periodIndex, true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getChildDataByWindowIndex(int windowIndex, ChildDataHolder childDataHolder) {
|
||||
int index = Util.binarySearchFloor(firstWindowInChildIndices, windowIndex, true, false);
|
||||
setChildData(index, childDataHolder);
|
||||
protected int getChildIndexByWindowIndex(int windowIndex) {
|
||||
return Util.binarySearchFloor(firstWindowInChildIndices, windowIndex, true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getChildDataByChildUid(Object childUid, ChildDataHolder childDataHolder) {
|
||||
protected int getChildIndexByChildUid(Object childUid) {
|
||||
if (!(childUid instanceof Integer)) {
|
||||
return false;
|
||||
return C.INDEX_UNSET;
|
||||
}
|
||||
int index = childIndexByUid.get((int) childUid, -1);
|
||||
if (index == -1) {
|
||||
return false;
|
||||
}
|
||||
setChildData(index, childDataHolder);
|
||||
return true;
|
||||
return index == -1 ? C.INDEX_UNSET : index;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Timeline getTimelineByChildIndex(int childIndex) {
|
||||
return timelines[childIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getFirstPeriodIndexByChildIndex(int childIndex) {
|
||||
return firstPeriodInChildIndices[childIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getFirstWindowIndexByChildIndex(int childIndex) {
|
||||
return firstWindowInChildIndices[childIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getChildUidByChildIndex(int childIndex) {
|
||||
return uids[childIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -450,10 +465,6 @@ public final class DynamicConcatenatingMediaSource implements MediaSource, ExoPl
|
||||
return periodCount;
|
||||
}
|
||||
|
||||
private void setChildData(int srcIndex, ChildDataHolder dest) {
|
||||
dest.setData(timelines[srcIndex], firstPeriodInChildIndices[srcIndex],
|
||||
firstWindowInChildIndices[srcIndex], uids[srcIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class DeferredTimeline extends Timeline {
|
||||
|
@ -101,6 +101,7 @@ public final class LoopingMediaSource implements MediaSource {
|
||||
private final int loopCount;
|
||||
|
||||
public LoopingTimeline(Timeline childTimeline, int loopCount) {
|
||||
super(loopCount);
|
||||
this.childTimeline = childTimeline;
|
||||
childPeriodCount = childTimeline.getPeriodCount();
|
||||
childWindowCount = childTimeline.getWindowCount();
|
||||
@ -120,30 +121,41 @@ public final class LoopingMediaSource implements MediaSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getChildDataByPeriodIndex(int periodIndex, ChildDataHolder childData) {
|
||||
int childIndex = periodIndex / childPeriodCount;
|
||||
getChildDataByChildIndex(childIndex, childData);
|
||||
protected int getChildIndexByPeriodIndex(int periodIndex) {
|
||||
return periodIndex / childPeriodCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getChildDataByWindowIndex(int windowIndex, ChildDataHolder childData) {
|
||||
int childIndex = windowIndex / childWindowCount;
|
||||
getChildDataByChildIndex(childIndex, childData);
|
||||
protected int getChildIndexByWindowIndex(int windowIndex) {
|
||||
return windowIndex / childWindowCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getChildDataByChildUid(Object childUid, ChildDataHolder childData) {
|
||||
protected int getChildIndexByChildUid(Object childUid) {
|
||||
if (!(childUid instanceof Integer)) {
|
||||
return false;
|
||||
return C.INDEX_UNSET;
|
||||
}
|
||||
int childIndex = (Integer) childUid;
|
||||
getChildDataByChildIndex(childIndex, childData);
|
||||
return true;
|
||||
return (Integer) childUid;
|
||||
}
|
||||
|
||||
private void getChildDataByChildIndex(int childIndex, ChildDataHolder childData) {
|
||||
childData.setData(childTimeline, childIndex * childPeriodCount, childIndex * childWindowCount,
|
||||
childIndex);
|
||||
@Override
|
||||
protected Timeline getTimelineByChildIndex(int childIndex) {
|
||||
return childTimeline;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getFirstPeriodIndexByChildIndex(int childIndex) {
|
||||
return childIndex * childPeriodCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getFirstWindowIndexByChildIndex(int childIndex) {
|
||||
return childIndex * childWindowCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getChildUidByChildIndex(int childIndex) {
|
||||
return childIndex;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user