From 5ca84ebfd8bc933c676c3b1c5e8194ab21a95002 Mon Sep 17 00:00:00 2001 From: tonihei Date: Wed, 2 Aug 2017 09:26:58 -0700 Subject: [PATCH] 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 --- .../source/AbstractConcatenatedTimeline.java | 141 ++++++++---------- .../source/ConcatenatingMediaSource.java | 61 ++++---- .../DynamicConcatenatingMediaSource.java | 45 +++--- .../exoplayer2/source/LoopingMediaSource.java | 40 +++-- 4 files changed, 148 insertions(+), 139 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/AbstractConcatenatedTimeline.java b/library/core/src/main/java/com/google/android/exoplayer2/source/AbstractConcatenatedTimeline.java index 3bee3cc73f..42ac938677 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/AbstractConcatenatedTimeline.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/AbstractConcatenatedTimeline.java @@ -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); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java index 2c998e8a06..5d2bbcc33e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java @@ -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; + } + } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/DynamicConcatenatingMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/DynamicConcatenatingMediaSource.java index 79f7d8dd48..c2d2e5f11e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/DynamicConcatenatingMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/DynamicConcatenatingMediaSource.java @@ -397,6 +397,7 @@ public final class DynamicConcatenatingMediaSource implements MediaSource, ExoPl public ConcatenatedTimeline(Collection 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 { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/LoopingMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/LoopingMediaSource.java index f0032e0ee0..a6e93a92b9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/LoopingMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/LoopingMediaSource.java @@ -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; } }