diff --git a/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastTimeline.java b/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastTimeline.java index b3d6fe4ee6..4939e62a2b 100644 --- a/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastTimeline.java +++ b/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastTimeline.java @@ -107,6 +107,11 @@ import java.util.Map; return uid instanceof Integer ? idsToIndex.get((int) uid, C.INDEX_UNSET) : C.INDEX_UNSET; } + @Override + public Object getUidOfPeriod(int periodIndex) { + return ids[periodIndex]; + } + // equals and hashCode implementations. @Override diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java index cc338385cd..ba80407860 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java @@ -904,7 +904,7 @@ import java.util.Collections; pendingMessageInfo.setResolvedPosition( periodPosition.first, periodPosition.second, - playbackInfo.timeline.getPeriod(periodPosition.first, period, true).uid); + playbackInfo.timeline.getUidOfPeriod(periodPosition.first)); } else { // Position has been resolved for a previous timeline. Try to find the updated period index. int index = playbackInfo.timeline.getIndexOfPeriod(pendingMessageInfo.resolvedPeriodUid); @@ -1203,8 +1203,8 @@ import java.util.Collections; return; } MediaPeriodHolder periodHolder = queue.getFrontPeriod(); - Object playingPeriodUid = periodHolder == null - ? oldTimeline.getPeriod(playingPeriodIndex, period, true).uid : periodHolder.uid; + Object playingPeriodUid = + periodHolder == null ? oldTimeline.getUidOfPeriod(playingPeriodIndex) : periodHolder.uid; int periodIndex = timeline.getIndexOfPeriod(playingPeriodUid); if (periodIndex == C.INDEX_UNSET) { // We didn't find the current period in the new timeline. Attempt to resolve a subsequent @@ -1221,11 +1221,10 @@ import java.util.Collections; newPeriodIndex = defaultPosition.first; contentPositionUs = defaultPosition.second; MediaPeriodId periodId = queue.resolveMediaPeriodIdForAds(newPeriodIndex, contentPositionUs); - timeline.getPeriod(newPeriodIndex, period, true); if (periodHolder != null) { // Clear the index of each holder that doesn't contain the default position. If a holder // contains the default position then update its index so it can be re-used when seeking. - Object newPeriodUid = period.uid; + Object newPeriodUid = timeline.getUidOfPeriod(newPeriodIndex); periodHolder.info = periodHolder.info.copyWithPeriodIndex(C.INDEX_UNSET); while (periodHolder.next != null) { periodHolder = periodHolder.next; @@ -1293,8 +1292,7 @@ import java.util.Collections; // We've reached the end of the old timeline. break; } - newPeriodIndex = newTimeline.getIndexOfPeriod( - oldTimeline.getPeriod(oldPeriodIndex, period, true).uid); + newPeriodIndex = newTimeline.getIndexOfPeriod(oldTimeline.getUidOfPeriod(oldPeriodIndex)); } return newPeriodIndex; } @@ -1338,8 +1336,7 @@ import java.util.Collections; return periodPosition; } // Attempt to find the mapped period in the internal timeline. - int periodIndex = timeline.getIndexOfPeriod( - seekTimeline.getPeriod(periodPosition.first, period, true).uid); + int periodIndex = timeline.getIndexOfPeriod(seekTimeline.getUidOfPeriod(periodPosition.first)); if (periodIndex != C.INDEX_UNSET) { // We successfully located the period in the internal timeline. return Pair.create(periodIndex, periodPosition.second); @@ -1497,7 +1494,7 @@ import java.util.Collections; if (info == null) { mediaSource.maybeThrowSourceInfoRefreshError(); } else { - Object uid = playbackInfo.timeline.getPeriod(info.id.periodIndex, period, true).uid; + Object uid = playbackInfo.timeline.getUidOfPeriod(info.id.periodIndex); MediaPeriod mediaPeriod = queue.enqueueNextMediaPeriod( rendererCapabilities, diff --git a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java index 010de547a2..be618275c4 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java @@ -314,7 +314,7 @@ import com.google.android.exoplayer2.util.Assertions; } else { // Check this period holder still follows the previous one, based on the new timeline. if (periodIndex == C.INDEX_UNSET - || !periodHolder.uid.equals(timeline.getPeriod(periodIndex, period, true).uid)) { + || !periodHolder.uid.equals(timeline.getUidOfPeriod(periodIndex))) { // The holder uid is inconsistent with the new timeline. return !removeAfter(previousPeriodHolder); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/Timeline.java b/library/core/src/main/java/com/google/android/exoplayer2/Timeline.java index 600fbc3014..a1a0e9b152 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/Timeline.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/Timeline.java @@ -520,6 +520,11 @@ public abstract class Timeline { public int getIndexOfPeriod(Object uid) { return C.INDEX_UNSET; } + + @Override + public Object getUidOfPeriod(int periodIndex) { + throw new IndexOutOfBoundsException(); + } }; /** @@ -737,6 +742,17 @@ public abstract class Timeline { return Pair.create(periodIndex, periodPositionUs); } + /** + * Populates a {@link Period} with data for the period with the specified unique identifier. + * + * @param periodUid The unique identifier of the period. + * @param period The {@link Period} to populate. Must not be null. + * @return The populated {@link Period}, for convenience. + */ + public Period getPeriodByUid(Object periodUid, Period period) { + return getPeriod(getIndexOfPeriod(periodUid), period, /* setIds= */ true); + } + /** * Populates a {@link Period} with data for the period at the specified index. Does not populate * {@link Period#id} and {@link Period#uid}. @@ -770,4 +786,11 @@ public abstract class Timeline { */ public abstract int getIndexOfPeriod(Object uid); + /** + * Returns the unique id of the period identified by its index in the timeline. + * + * @param periodIndex The index of the period. + * @return The unique id of the period. + */ + public abstract Object getUidOfPeriod(int periodIndex); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java b/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java index 1d51e68d4a..3efe0a00cc 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java @@ -784,8 +784,7 @@ public class AnalyticsCollector if (newTimeline.isEmpty() || timeline.isEmpty()) { return mediaPeriod; } - Object uid = - timeline.getPeriod(mediaPeriod.mediaPeriodId.periodIndex, period, /* setIds= */ true).uid; + Object uid = timeline.getUidOfPeriod(mediaPeriod.mediaPeriodId.periodIndex); int newPeriodIndex = newTimeline.getIndexOfPeriod(uid); if (newPeriodIndex == C.INDEX_UNSET) { return mediaPeriod; 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 8663b4c05c..305a249e4a 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 @@ -168,6 +168,19 @@ import com.google.android.exoplayer2.Timeline; return window; } + @Override + public final Period getPeriodByUid(Object uid, Period period) { + Pair childUidAndPeriodUid = (Pair) uid; + Object childUid = childUidAndPeriodUid.first; + Object periodUid = childUidAndPeriodUid.second; + int childIndex = getChildIndexByChildUid(childUid); + int firstWindowIndexInChild = getFirstWindowIndexByChildIndex(childIndex); + getTimelineByChildIndex(childIndex).getPeriodByUid(periodUid, period); + period.windowIndex += firstWindowIndexInChild; + period.uid = uid; + return period; + } + @Override public final Period getPeriod(int periodIndex, Period period, boolean setIds) { int childIndex = getChildIndexByPeriodIndex(periodIndex); @@ -199,6 +212,15 @@ import com.google.android.exoplayer2.Timeline; : getFirstPeriodIndexByChildIndex(childIndex) + periodIndexInChild; } + @Override + public final Object getUidOfPeriod(int periodIndex) { + int childIndex = getChildIndexByPeriodIndex(periodIndex); + int firstPeriodIndexInChild = getFirstPeriodIndexByChildIndex(childIndex); + Object periodUidInChild = + getTimelineByChildIndex(childIndex).getUidOfPeriod(periodIndex - firstPeriodIndexInChild); + return Pair.create(getChildUidByChildIndex(childIndex), periodUidInChild); + } + /** * Returns the index of the child timeline containing the given period index. * 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 01a8cd3425..985c43fa55 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 @@ -66,7 +66,6 @@ public class ConcatenatingMediaSource extends CompositeMediaSource 0 - ? timeline.getPeriod(0, period, true).uid + ? timeline.getUidOfPeriod(0) : replacedId); } @@ -848,6 +846,12 @@ public class ConcatenatingMediaSource extends CompositeMediaSource