Add helper method to get uid of timeline period.

This removes the need to populate the entire period for the common usage of
getting the uid from the period.

Also add default implementation to get period by uid.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=205638265
This commit is contained in:
tonihei 2018-07-23 03:34:53 -07:00 committed by Oliver Woodman
parent 97e66ef11b
commit a67c73650e
13 changed files with 107 additions and 28 deletions

View File

@ -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

View File

@ -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,

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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.
*

View File

@ -66,7 +66,6 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
private final boolean isAtomic;
private final boolean useLazyPreparation;
private final Timeline.Window window;
private final Timeline.Period period;
private @Nullable ExoPlayer player;
private @Nullable Handler playerApplicationHandler;
@ -133,7 +132,6 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
this.isAtomic = isAtomic;
this.useLazyPreparation = useLazyPreparation;
window = new Timeline.Window();
period = new Timeline.Period();
addMediaSources(Arrays.asList(mediaSources));
}
@ -594,7 +592,7 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
windowOffsetUpdate,
periodOffsetUpdate);
}
mediaSourceHolder.timeline = deferredTimeline.cloneWithNewTimeline(timeline, period);
mediaSourceHolder.timeline = deferredTimeline.cloneWithNewTimeline(timeline);
if (!mediaSourceHolder.isPrepared && !timeline.isEmpty()) {
timeline.getWindow(/* windowIndex= */ 0, window);
long defaultPeriodPositionUs =
@ -823,11 +821,11 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
this.replacedId = replacedId;
}
public DeferredTimeline cloneWithNewTimeline(Timeline timeline, Period period) {
public DeferredTimeline cloneWithNewTimeline(Timeline timeline) {
return new DeferredTimeline(
timeline,
replacedId == DUMMY_ID && timeline.getPeriodCount() > 0
? timeline.getPeriod(0, period, true).uid
? timeline.getUidOfPeriod(0)
: replacedId);
}
@ -848,6 +846,12 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
public int getIndexOfPeriod(Object uid) {
return timeline.getIndexOfPeriod(DUMMY_ID.equals(uid) ? replacedId : uid);
}
@Override
public Object getUidOfPeriod(int periodIndex) {
Object uid = timeline.getUidOfPeriod(periodIndex);
return Util.areEqual(uid, replacedId) ? DUMMY_ID : uid;
}
}
/** Dummy placeholder timeline with one dynamic window with a period of indeterminate duration. */
@ -894,6 +898,11 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
public int getIndexOfPeriod(Object uid) {
return uid == DeferredTimeline.DUMMY_ID ? 0 : C.INDEX_UNSET;
}
@Override
public Object getUidOfPeriod(int periodIndex) {
return DeferredTimeline.DUMMY_ID;
}
}
}

View File

@ -77,4 +77,8 @@ public abstract class ForwardingTimeline extends Timeline {
return timeline.getIndexOfPeriod(uid);
}
@Override
public Object getUidOfPeriod(int periodIndex) {
return timeline.getUidOfPeriod(periodIndex);
}
}

View File

@ -193,4 +193,9 @@ public final class SinglePeriodTimeline extends Timeline {
return UID.equals(uid) ? 0 : C.INDEX_UNSET;
}
@Override
public Object getUidOfPeriod(int periodIndex) {
Assertions.checkIndex(periodIndex, 0, 1);
return UID;
}
}

View File

@ -23,7 +23,6 @@ import android.os.ConditionVariable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.ShuffleOrder.DefaultShuffleOrder;
import com.google.android.exoplayer2.testutil.DummyMainThread;
@ -876,21 +875,20 @@ public final class ConcatenatingMediaSourceTest {
@Test
public void testReleaseAndReprepareSource() throws IOException {
Period period = new Period();
FakeMediaSource[] fakeMediaSources = createMediaSources(/* count= */ 2);
mediaSource.addMediaSource(fakeMediaSources[0]); // Child source with 1 period.
mediaSource.addMediaSource(fakeMediaSources[1]); // Child source with 2 periods.
Timeline timeline = testRunner.prepareSource();
Object periodId0 = timeline.getPeriod(/* periodIndex= */ 0, period, /* setIds= */ true).uid;
Object periodId1 = timeline.getPeriod(/* periodIndex= */ 1, period, /* setIds= */ true).uid;
Object periodId2 = timeline.getPeriod(/* periodIndex= */ 2, period, /* setIds= */ true).uid;
Object periodId0 = timeline.getUidOfPeriod(/* periodIndex= */ 0);
Object periodId1 = timeline.getUidOfPeriod(/* periodIndex= */ 1);
Object periodId2 = timeline.getUidOfPeriod(/* periodIndex= */ 2);
testRunner.releaseSource();
mediaSource.moveMediaSource(/* currentIndex= */ 1, /* newIndex= */ 0);
timeline = testRunner.prepareSource();
Object newPeriodId0 = timeline.getPeriod(/* periodIndex= */ 0, period, /* setIds= */ true).uid;
Object newPeriodId1 = timeline.getPeriod(/* periodIndex= */ 1, period, /* setIds= */ true).uid;
Object newPeriodId2 = timeline.getPeriod(/* periodIndex= */ 2, period, /* setIds= */ true).uid;
Object newPeriodId0 = timeline.getUidOfPeriod(/* periodIndex= */ 0);
Object newPeriodId1 = timeline.getUidOfPeriod(/* periodIndex= */ 1);
Object newPeriodId2 = timeline.getUidOfPeriod(/* periodIndex= */ 2);
assertThat(newPeriodId0).isEqualTo(periodId1);
assertThat(newPeriodId1).isEqualTo(periodId2);
assertThat(newPeriodId2).isEqualTo(periodId0);

View File

@ -1204,6 +1204,11 @@ public final class DashMediaSource extends BaseMediaSource {
- defaultStartPositionInPeriodUs;
}
@Override
public Object getUidOfPeriod(int periodIndex) {
Assertions.checkIndex(periodIndex, 0, getPeriodCount());
return firstPeriodId + periodIndex;
}
}
private final class DefaultPlayerEmsgCallback implements PlayerEmsgCallback {

View File

@ -19,6 +19,7 @@ import android.util.Pair;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.ads.AdPlaybackState;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
import java.util.Arrays;
@ -206,15 +207,25 @@ public final class FakeTimeline extends Timeline {
@Override
public int getIndexOfPeriod(Object uid) {
Period period = new Period();
for (int i = 0; i < getPeriodCount(); i++) {
if (getPeriod(i, period, true).uid.equals(uid)) {
if (getUidOfPeriod(i).equals(uid)) {
return i;
}
}
return C.INDEX_UNSET;
}
@Override
public Object getUidOfPeriod(int periodIndex) {
Assertions.checkIndex(periodIndex, 0, getPeriodCount());
int windowIndex =
Util.binarySearchFloor(
periodOffsets, periodIndex, /* inclusive= */ true, /* stayInBounds= */ false);
int windowPeriodIndex = periodIndex - periodOffsets[windowIndex];
TimelineWindowDefinition windowDefinition = windowDefinitions[windowIndex];
return Pair.create(windowDefinition.id, windowPeriodIndex);
}
private static TimelineWindowDefinition[] createDefaultWindowDefinitions(int windowCount) {
TimelineWindowDefinition[] windowDefinitions = new TimelineWindowDefinition[windowCount];
for (int i = 0; i < windowCount; i++) {

View File

@ -141,6 +141,7 @@ public final class TimelineAsserts {
}
assertThat(period.windowIndex).isEqualTo(expectedWindowIndex);
assertThat(timeline.getIndexOfPeriod(period.uid)).isEqualTo(i);
assertThat(timeline.getUidOfPeriod(i)).isEqualTo(period.uid);
for (int repeatMode : REPEAT_MODES) {
if (i < accumulatedPeriodCounts[expectedWindowIndex + 1] - 1) {
assertThat(timeline.getNextPeriodIndex(i, period, window, repeatMode, false))