Commit d51b98dd by tonihei Committed by Oliver Woodman

Replace period index with uid in MediaPeriodId.

The MediaPeriodId with index is only properly defined together with a
timeline containing the index. Changing it to the period uid allows to use
the MediaPeriodId independent of the corresponding timeline.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=209430257
parent 2cd7d710
Showing with 220 additions and 189 deletions
......@@ -327,10 +327,10 @@ import java.util.concurrent.CopyOnWriteArraySet;
} else {
long windowPositionUs = positionMs == C.TIME_UNSET
? timeline.getWindow(windowIndex, window).getDefaultPositionUs() : C.msToUs(positionMs);
Pair<Integer, Long> periodIndexAndPosition =
Pair<Object, Long> periodUidAndPosition =
timeline.getPeriodPosition(window, period, windowIndex, windowPositionUs);
maskingWindowPositionMs = C.usToMs(windowPositionUs);
maskingPeriodIndex = periodIndexAndPosition.first;
maskingPeriodIndex = timeline.getIndexOfPeriod(periodUidAndPosition.first);
}
internalPlayer.seekTo(timeline, windowIndex, C.msToUs(positionMs));
for (Player.EventListener listener : listeners) {
......@@ -464,7 +464,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
if (shouldMaskPosition()) {
return maskingPeriodIndex;
} else {
return playbackInfo.periodId.periodIndex;
return playbackInfo.timeline.getIndexOfPeriod(playbackInfo.periodId.periodUid);
}
}
......@@ -473,7 +473,8 @@ import java.util.concurrent.CopyOnWriteArraySet;
if (shouldMaskPosition()) {
return maskingWindowIndex;
} else {
return playbackInfo.timeline.getPeriod(playbackInfo.periodId.periodIndex, period).windowIndex;
return playbackInfo.timeline.getPeriodByUid(playbackInfo.periodId.periodUid, period)
.windowIndex;
}
}
......@@ -499,7 +500,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
}
if (isPlayingAd()) {
MediaPeriodId periodId = playbackInfo.periodId;
timeline.getPeriod(periodId.periodIndex, period);
timeline.getPeriodByUid(periodId.periodUid, period);
long adDurationUs = period.getAdDurationUs(periodId.adGroupIndex, periodId.adIndexInAdGroup);
return C.usToMs(adDurationUs);
} else {
......@@ -572,7 +573,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
@Override
public long getContentPosition() {
if (isPlayingAd()) {
playbackInfo.timeline.getPeriod(playbackInfo.periodId.periodIndex, period);
playbackInfo.timeline.getPeriodByUid(playbackInfo.periodId.periodUid, period);
return period.getPositionInWindowMs() + C.usToMs(playbackInfo.contentPositionUs);
} else {
return getCurrentPosition();
......@@ -591,7 +592,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
long contentBufferedPositionUs = playbackInfo.bufferedPositionUs;
if (playbackInfo.loadingMediaPeriodId.isAd()) {
Timeline.Period loadingPeriod =
playbackInfo.timeline.getPeriod(playbackInfo.loadingMediaPeriodId.periodIndex, period);
playbackInfo.timeline.getPeriodByUid(playbackInfo.loadingMediaPeriodId.periodUid, period);
contentBufferedPositionUs =
loadingPeriod.getAdGroupTimeUs(playbackInfo.loadingMediaPeriodId.adGroupIndex);
if (contentBufferedPositionUs == C.TIME_END_OF_SOURCE) {
......@@ -761,7 +762,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
private long periodPositionUsToWindowPositionMs(MediaPeriodId periodId, long positionUs) {
long positionMs = C.usToMs(positionUs);
playbackInfo.timeline.getPeriod(periodId.periodIndex, period);
playbackInfo.timeline.getPeriodByUid(periodId.periodUid, period);
positionMs += period.getPositionInWindowMs();
return positionMs;
}
......
......@@ -62,7 +62,6 @@ import com.google.android.exoplayer2.util.Assertions;
* @param trackSelector The track selector.
* @param allocator The allocator.
* @param mediaSource The media source that produced the media period.
* @param uid The unique identifier for the containing timeline period.
* @param info Information used to identify this media period in its timeline period.
*/
public MediaPeriodHolder(
......@@ -71,13 +70,12 @@ import com.google.android.exoplayer2.util.Assertions;
TrackSelector trackSelector,
Allocator allocator,
MediaSource mediaSource,
Object uid,
MediaPeriodInfo info) {
this.rendererCapabilities = rendererCapabilities;
this.rendererPositionOffsetUs = rendererPositionOffsetUs - info.startPositionUs;
this.trackSelector = trackSelector;
this.mediaSource = mediaSource;
this.uid = Assertions.checkNotNull(uid);
this.uid = Assertions.checkNotNull(info.id.periodUid);
this.info = info;
sampleStreams = new SampleStream[rendererCapabilities.length];
mayRetainStreamFlags = new boolean[rendererCapabilities.length];
......
......@@ -62,20 +62,6 @@ import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
this.isFinal = isFinal;
}
/**
* Returns a copy of this instance with the period identifier's period index set to the specified
* value.
*/
public MediaPeriodInfo copyWithPeriodIndex(int periodIndex) {
return new MediaPeriodInfo(
id.copyWithPeriodIndex(periodIndex),
startPositionUs,
contentPositionUs,
durationUs,
isLastInTimelinePeriod,
isFinal);
}
/** Returns a copy of this instance with the start position set to the specified value. */
public MediaPeriodInfo copyWithStartPositionUs(long startPositionUs) {
return new MediaPeriodInfo(
......
......@@ -29,7 +29,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
* Dummy media period id used while the timeline is empty and no period id is specified. This id
* is used when playback infos are created with {@link #createDummy(long, TrackSelectorResult)}.
*/
public static final MediaPeriodId DUMMY_MEDIA_PERIOD_ID = new MediaPeriodId(/* periodIndex= */ 0);
public static final MediaPeriodId DUMMY_MEDIA_PERIOD_ID =
new MediaPeriodId(/* periodUid= */ new Object());
/** The current {@link Timeline}. */
public final Timeline timeline;
......@@ -149,23 +150,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
startPositionUs);
}
public PlaybackInfo copyWithPeriodIndex(int periodIndex) {
return new PlaybackInfo(
timeline,
manifest,
periodId.copyWithPeriodIndex(periodIndex),
startPositionUs,
contentPositionUs,
playbackState,
isLoading,
trackGroups,
trackSelectorResult,
loadingMediaPeriodId,
bufferedPositionUs,
totalBufferedDurationUs,
positionUs);
}
public PlaybackInfo copyWithTimeline(Timeline timeline, Object manifest) {
return new PlaybackInfo(
timeline,
......
......@@ -702,13 +702,13 @@ public abstract class Timeline {
* Calls {@link #getPeriodPosition(Window, Period, int, long, long)} with a zero default position
* projection.
*/
public final Pair<Integer, Long> getPeriodPosition(Window window, Period period, int windowIndex,
long windowPositionUs) {
public final Pair<Object, Long> getPeriodPosition(
Window window, Period period, int windowIndex, long windowPositionUs) {
return getPeriodPosition(window, period, windowIndex, windowPositionUs, 0);
}
/**
* Converts (windowIndex, windowPositionUs) to the corresponding (periodIndex, periodPositionUs).
* Converts (windowIndex, windowPositionUs) to the corresponding (periodUid, periodPositionUs).
*
* @param window A {@link Window} that may be overwritten.
* @param period A {@link Period} that may be overwritten.
......@@ -717,12 +717,16 @@ public abstract class Timeline {
* start position.
* @param defaultPositionProjectionUs If {@code windowPositionUs} is {@link C#TIME_UNSET}, the
* duration into the future by which the window's position should be projected.
* @return The corresponding (periodIndex, periodPositionUs), or null if {@code #windowPositionUs}
* @return The corresponding (periodUid, periodPositionUs), or null if {@code #windowPositionUs}
* is {@link C#TIME_UNSET}, {@code defaultPositionProjectionUs} is non-zero, and the window's
* position could not be projected by {@code defaultPositionProjectionUs}.
*/
public final Pair<Integer, Long> getPeriodPosition(Window window, Period period, int windowIndex,
long windowPositionUs, long defaultPositionProjectionUs) {
public final Pair<Object, Long> getPeriodPosition(
Window window,
Period period,
int windowIndex,
long windowPositionUs,
long defaultPositionProjectionUs) {
Assertions.checkIndex(windowIndex, 0, getWindowCount());
getWindow(windowIndex, window, false, defaultPositionProjectionUs);
if (windowPositionUs == C.TIME_UNSET) {
......@@ -733,13 +737,13 @@ public abstract class Timeline {
}
int periodIndex = window.firstPeriodIndex;
long periodPositionUs = window.getPositionInFirstPeriodUs() + windowPositionUs;
long periodDurationUs = getPeriod(periodIndex, period).getDurationUs();
long periodDurationUs = getPeriod(periodIndex, period, /* setIds= */ true).getDurationUs();
while (periodDurationUs != C.TIME_UNSET && periodPositionUs >= periodDurationUs
&& periodIndex < window.lastPeriodIndex) {
periodPositionUs -= periodDurationUs;
periodDurationUs = getPeriod(++periodIndex, period).getDurationUs();
periodDurationUs = getPeriod(++periodIndex, period, /* setIds= */ true).getDurationUs();
}
return Pair.create(periodIndex, periodPositionUs);
return Pair.create(period.uid, periodPositionUs);
}
/**
......
......@@ -705,11 +705,10 @@ public class AnalyticsCollector
public @Nullable MediaPeriodId tryResolveWindowIndex(int windowIndex) {
MediaPeriodId match = null;
if (timeline != null) {
int timelinePeriodCount = timeline.getPeriodCount();
for (int i = 0; i < activeMediaPeriods.size(); i++) {
WindowAndMediaPeriodId mediaPeriod = activeMediaPeriods.get(i);
int periodIndex = mediaPeriod.mediaPeriodId.periodIndex;
if (periodIndex < timelinePeriodCount
int periodIndex = timeline.getIndexOfPeriod(mediaPeriod.mediaPeriodId.periodUid);
if (periodIndex != C.INDEX_UNSET
&& timeline.getPeriod(periodIndex, period).windowIndex == windowIndex) {
if (match != null) {
// Ambiguous match.
......@@ -731,10 +730,10 @@ public class AnalyticsCollector
public void onTimelineChanged(Timeline timeline) {
for (int i = 0; i < activeMediaPeriods.size(); i++) {
activeMediaPeriods.set(
i, updateMediaPeriodToNewTimeline(activeMediaPeriods.get(i), timeline));
i, updateWindowIndexToNewTimeline(activeMediaPeriods.get(i), timeline));
}
if (readingMediaPeriod != null) {
readingMediaPeriod = updateMediaPeriodToNewTimeline(readingMediaPeriod, timeline);
readingMediaPeriod = updateWindowIndexToNewTimeline(readingMediaPeriod, timeline);
}
this.timeline = timeline;
updateLastReportedPlayingMediaPeriod();
......@@ -779,19 +778,17 @@ public class AnalyticsCollector
}
}
private WindowAndMediaPeriodId updateMediaPeriodToNewTimeline(
private WindowAndMediaPeriodId updateWindowIndexToNewTimeline(
WindowAndMediaPeriodId mediaPeriod, Timeline newTimeline) {
if (newTimeline.isEmpty() || timeline.isEmpty()) {
return mediaPeriod;
}
Object uid = timeline.getUidOfPeriod(mediaPeriod.mediaPeriodId.periodIndex);
int newPeriodIndex = newTimeline.getIndexOfPeriod(uid);
int newPeriodIndex = newTimeline.getIndexOfPeriod(mediaPeriod.mediaPeriodId.periodUid);
if (newPeriodIndex == C.INDEX_UNSET) {
return mediaPeriod;
}
int newWindowIndex = newTimeline.getPeriod(newPeriodIndex, period).windowIndex;
return new WindowAndMediaPeriodId(
newWindowIndex, mediaPeriod.mediaPeriodId.copyWithPeriodIndex(newPeriodIndex));
return new WindowAndMediaPeriodId(newWindowIndex, mediaPeriod.mediaPeriodId);
}
}
......
......@@ -30,6 +30,37 @@ import com.google.android.exoplayer2.Timeline;
private final boolean isAtomic;
/**
* Returns UID of child timeline from a concatenated period UID.
*
* @param concatenatedUid UID of a period in a concatenated timeline.
* @return UID of the child timeline this period belongs to.
*/
public static Object getChildTimelineUidFromConcatenatedUid(Object concatenatedUid) {
return ((Pair<?, ?>) concatenatedUid).first;
}
/**
* Returns UID of the period in the child timeline from a concatenated period UID.
*
* @param concatenatedUid UID of a period in a concatenated timeline.
* @return UID of the period in the child timeline.
*/
public static Object getChildPeriodUidFromConcatenatedUid(Object concatenatedUid) {
return ((Pair<?, ?>) concatenatedUid).second;
}
/**
* Returns concatenated UID for a period in a child timeline.
*
* @param childTimelineUid UID of the child timeline this period belongs to.
* @param childPeriodUid UID of the period in the child timeline.
* @return UID of the period in the concatenated timeline.
*/
public static Object getConcatenatedUid(Object childTimelineUid, Object childPeriodUid) {
return Pair.create(childTimelineUid, childPeriodUid);
}
/**
* Sets up a concatenated timeline with a shuffle order of child timelines.
*
* @param isAtomic Whether the child timelines shall be treated as atomic, i.e., treated as a
......@@ -170,9 +201,8 @@ import com.google.android.exoplayer2.Timeline;
@Override
public final Period getPeriodByUid(Object uid, Period period) {
Pair<?, ?> childUidAndPeriodUid = (Pair<?, ?>) uid;
Object childUid = childUidAndPeriodUid.first;
Object periodUid = childUidAndPeriodUid.second;
Object childUid = getChildTimelineUidFromConcatenatedUid(uid);
Object periodUid = getChildPeriodUidFromConcatenatedUid(uid);
int childIndex = getChildIndexByChildUid(childUid);
int firstWindowIndexInChild = getFirstWindowIndexByChildIndex(childIndex);
getTimelineByChildIndex(childIndex).getPeriodByUid(periodUid, period);
......@@ -190,7 +220,7 @@ import com.google.android.exoplayer2.Timeline;
setIds);
period.windowIndex += firstWindowIndexInChild;
if (setIds) {
period.uid = Pair.create(getChildUidByChildIndex(childIndex), period.uid);
period.uid = getConcatenatedUid(getChildUidByChildIndex(childIndex), period.uid);
}
return period;
}
......@@ -200,9 +230,8 @@ import com.google.android.exoplayer2.Timeline;
if (!(uid instanceof Pair)) {
return C.INDEX_UNSET;
}
Pair<?, ?> childUidAndPeriodUid = (Pair<?, ?>) uid;
Object childUid = childUidAndPeriodUid.first;
Object periodUid = childUidAndPeriodUid.second;
Object childUid = getChildTimelineUidFromConcatenatedUid(uid);
Object periodUid = getChildPeriodUidFromConcatenatedUid(uid);
int childIndex = getChildIndexByChildUid(childUid);
if (childIndex == C.INDEX_UNSET) {
return C.INDEX_UNSET;
......@@ -218,7 +247,7 @@ import com.google.android.exoplayer2.Timeline;
int firstPeriodIndexInChild = getFirstPeriodIndexByChildIndex(childIndex);
Object periodUidInChild =
getTimelineByChildIndex(childIndex).getUidOfPeriod(periodIndex - firstPeriodIndexInChild);
return Pair.create(getChildUidByChildIndex(childIndex), periodUidInChild);
return getConcatenatedUid(getChildUidByChildIndex(childIndex), periodUidInChild);
}
/**
......
......@@ -60,8 +60,8 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
// Accessed on the playback thread.
private final List<MediaSourceHolder> mediaSourceHolders;
private final MediaSourceHolder query;
private final Map<MediaPeriod, MediaSourceHolder> mediaSourceByMediaPeriod;
private final Map<Object, MediaSourceHolder> mediaSourceByUid;
private final List<Runnable> pendingOnCompletionActions;
private final boolean isAtomic;
private final boolean useLazyPreparation;
......@@ -125,10 +125,10 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
}
this.shuffleOrder = shuffleOrder.getLength() > 0 ? shuffleOrder.cloneAndClear() : shuffleOrder;
this.mediaSourceByMediaPeriod = new IdentityHashMap<>();
this.mediaSourceByUid = new HashMap<>();
this.mediaSourcesPublic = new ArrayList<>();
this.mediaSourceHolders = new ArrayList<>();
this.pendingOnCompletionActions = new ArrayList<>();
this.query = new MediaSourceHolder(/* mediaSource= */ null);
this.isAtomic = isAtomic;
this.useLazyPreparation = useLazyPreparation;
window = new Timeline.Window();
......@@ -451,8 +451,8 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
@Override
public final MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) {
int mediaSourceHolderIndex = findMediaSourceHolderByPeriodIndex(id.periodIndex);
MediaSourceHolder holder = mediaSourceHolders.get(mediaSourceHolderIndex);
Object mediaSourceHolderUid = getMediaSourceHolderUid(id.periodUid);
MediaSourceHolder holder = Assertions.checkNotNull(mediaSourceByUid.get(mediaSourceHolderUid));
DeferredMediaPeriod mediaPeriod = new DeferredMediaPeriod(holder.mediaSource, id, allocator);
mediaSourceByMediaPeriod.put(mediaPeriod, holder);
holder.activeMediaPeriods.add(mediaPeriod);
......@@ -460,8 +460,7 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
holder.hasStartedPreparing = true;
prepareChildSource(holder, holder.mediaSource);
} else if (holder.isPrepared) {
MediaPeriodId idInSource =
id.copyWithPeriodIndex(id.periodIndex - holder.firstPeriodIndexInChild);
MediaPeriodId idInSource = id.copyWithPeriodUid(getChildPeriodUid(holder, id.periodUid));
mediaPeriod.createPeriod(idInSource);
}
return mediaPeriod;
......@@ -482,6 +481,7 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
public final void releaseSourceInternal() {
super.releaseSourceInternal();
mediaSourceHolders.clear();
mediaSourceByUid.clear();
player = null;
playerApplicationHandler = null;
shuffleOrder = shuffleOrder.cloneAndClear();
......@@ -506,8 +506,8 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
// by this media source. Otherwise it does not belong to this child source.
if (mediaSourceHolder.activeMediaPeriods.get(i).id.windowSequenceNumber
== mediaPeriodId.windowSequenceNumber) {
return mediaPeriodId.copyWithPeriodIndex(
mediaPeriodId.periodIndex + mediaSourceHolder.firstPeriodIndexInChild);
Object periodUid = getPeriodUid(mediaSourceHolder, mediaPeriodId.periodUid);
return mediaPeriodId.copyWithPeriodUid(periodUid);
}
}
return null;
......@@ -633,6 +633,7 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
newMediaSourceHolder.timeline.getWindowCount(),
newMediaSourceHolder.timeline.getPeriodCount());
mediaSourceHolders.add(newIndex, newMediaSourceHolder);
mediaSourceByUid.put(newMediaSourceHolder.uid, newMediaSourceHolder);
if (!useLazyPreparation) {
newMediaSourceHolder.hasStartedPreparing = true;
prepareChildSource(newMediaSourceHolder, newMediaSourceHolder.mediaSource);
......@@ -672,8 +673,8 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
DeferredMediaPeriod deferredMediaPeriod = mediaSourceHolder.activeMediaPeriods.get(i);
deferredMediaPeriod.setDefaultPreparePositionUs(defaultPeriodPositionUs);
MediaPeriodId idInSource =
deferredMediaPeriod.id.copyWithPeriodIndex(
deferredMediaPeriod.id.periodIndex - mediaSourceHolder.firstPeriodIndexInChild);
deferredMediaPeriod.id.copyWithPeriodUid(
getChildPeriodUid(mediaSourceHolder, deferredMediaPeriod.id.periodUid));
deferredMediaPeriod.createPeriod(idInSource);
}
mediaSourceHolder.isPrepared = true;
......@@ -689,6 +690,7 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
private void removeMediaSourceInternal(int index) {
MediaSourceHolder holder = mediaSourceHolders.remove(index);
mediaSourceByUid.remove(holder.uid);
Timeline oldTimeline = holder.timeline;
correctOffsets(
index,
......@@ -727,17 +729,22 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
}
}
private int findMediaSourceHolderByPeriodIndex(int periodIndex) {
query.firstPeriodIndexInChild = periodIndex;
int index = Collections.binarySearch(mediaSourceHolders, query);
if (index < 0) {
return -index - 2;
}
while (index < mediaSourceHolders.size() - 1
&& mediaSourceHolders.get(index + 1).firstPeriodIndexInChild == periodIndex) {
index++;
/** Return uid of media source holder from period uid of concatenated source. */
private static Object getMediaSourceHolderUid(Object periodUid) {
return ConcatenatedTimeline.getChildTimelineUidFromConcatenatedUid(periodUid);
}
/** Return uid of child period from period uid of concatenated source. */
private static Object getChildPeriodUid(MediaSourceHolder holder, Object periodUid) {
Object childUid = ConcatenatedTimeline.getChildPeriodUidFromConcatenatedUid(periodUid);
return childUid.equals(DeferredTimeline.DUMMY_ID) ? holder.timeline.replacedId : childUid;
}
private static Object getPeriodUid(MediaSourceHolder holder, Object childPeriodUid) {
if (holder.timeline.replacedId.equals(childPeriodUid)) {
childPeriodUid = DeferredTimeline.DUMMY_ID;
}
return index;
return ConcatenatedTimeline.getConcatenatedUid(holder.uid, childPeriodUid);
}
/** Data class to hold playlist media sources together with meta data needed to process them. */
......
......@@ -371,7 +371,6 @@ public final class ExtractorMediaSource extends BaseMediaSource
@Override
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) {
Assertions.checkArgument(id.periodIndex == 0);
DataSource dataSource = dataSourceFactory.createDataSource();
if (transferListener != null) {
dataSource.addTransferListener(transferListener);
......
......@@ -40,8 +40,6 @@ public final class LoopingMediaSource extends CompositeMediaSource<Void> {
private final Map<MediaPeriodId, MediaPeriodId> childMediaPeriodIdToMediaPeriodId;
private final Map<MediaPeriod, MediaPeriodId> mediaPeriodToChildMediaPeriodId;
private int childPeriodCount;
/**
* Loops the provided source indefinitely. Note that it is usually better to use
* {@link ExoPlayer#setRepeatMode(int)}.
......@@ -80,7 +78,8 @@ public final class LoopingMediaSource extends CompositeMediaSource<Void> {
if (loopCount == Integer.MAX_VALUE) {
return childSource.createPeriod(id, allocator);
}
MediaPeriodId childMediaPeriodId = id.copyWithPeriodIndex(id.periodIndex % childPeriodCount);
Object childPeriodUid = LoopingTimeline.getChildPeriodUidFromConcatenatedUid(id.periodUid);
MediaPeriodId childMediaPeriodId = id.copyWithPeriodUid(childPeriodUid);
childMediaPeriodIdToMediaPeriodId.put(childMediaPeriodId, id);
MediaPeriod mediaPeriod = childSource.createPeriod(childMediaPeriodId, allocator);
mediaPeriodToChildMediaPeriodId.put(mediaPeriod, childMediaPeriodId);
......@@ -97,15 +96,8 @@ public final class LoopingMediaSource extends CompositeMediaSource<Void> {
}
@Override
public void releaseSourceInternal() {
super.releaseSourceInternal();
childPeriodCount = 0;
}
@Override
protected void onChildSourceInfoRefreshed(
Void id, MediaSource mediaSource, Timeline timeline, @Nullable Object manifest) {
childPeriodCount = timeline.getPeriodCount();
Timeline loopingTimeline =
loopCount != Integer.MAX_VALUE
? new LoopingTimeline(timeline, loopCount)
......
......@@ -66,10 +66,8 @@ public interface MediaSource {
*/
final class MediaPeriodId {
/**
* The timeline period index.
*/
public final int periodIndex;
/** The unique id of the timeline period. */
public final Object periodUid;
/**
* If the media period is in an ad group, the index of the ad group in the period.
......@@ -103,72 +101,70 @@ public interface MediaSource {
* Creates a media period identifier for a dummy period which is not part of a buffered sequence
* of windows.
*
* @param periodIndex The period index.
* @param periodUid The unique id of the timeline period.
*/
public MediaPeriodId(int periodIndex) {
this(periodIndex, C.INDEX_UNSET);
public MediaPeriodId(Object periodUid) {
this(periodUid, C.INDEX_UNSET);
}
/**
* Creates a media period identifier for the specified period in the timeline.
*
* @param periodIndex The timeline period index.
* @param periodUid The unique id of the timeline period.
* @param windowSequenceNumber The sequence number of the window in the buffered sequence of
* windows this media period is part of.
*/
public MediaPeriodId(int periodIndex, long windowSequenceNumber) {
this(periodIndex, C.INDEX_UNSET, C.INDEX_UNSET, windowSequenceNumber, C.TIME_END_OF_SOURCE);
public MediaPeriodId(Object periodUid, long windowSequenceNumber) {
this(periodUid, C.INDEX_UNSET, C.INDEX_UNSET, windowSequenceNumber, C.TIME_END_OF_SOURCE);
}
/**
* Creates a media period identifier for the specified clipped period in the timeline.
*
* @param periodIndex The timeline period index.
* @param periodUid The unique id of the timeline period.
* @param windowSequenceNumber The sequence number of the window in the buffered sequence of
* windows this media period is part of.
* @param endPositionUs The end position of the media period within the timeline period, in
* microseconds.
*/
public MediaPeriodId(int periodIndex, long windowSequenceNumber, long endPositionUs) {
this(periodIndex, C.INDEX_UNSET, C.INDEX_UNSET, windowSequenceNumber, endPositionUs);
public MediaPeriodId(Object periodUid, long windowSequenceNumber, long endPositionUs) {
this(periodUid, C.INDEX_UNSET, C.INDEX_UNSET, windowSequenceNumber, endPositionUs);
}
/**
* Creates a media period identifier that identifies an ad within an ad group at the specified
* timeline period.
*
* @param periodIndex The index of the timeline period that contains the ad group.
* @param periodUid The unique id of the timeline period that contains the ad group.
* @param adGroupIndex The index of the ad group.
* @param adIndexInAdGroup The index of the ad in the ad group.
* @param windowSequenceNumber The sequence number of the window in the buffered sequence of
* windows this media period is part of.
*/
public MediaPeriodId(
int periodIndex, int adGroupIndex, int adIndexInAdGroup, long windowSequenceNumber) {
this(periodIndex, adGroupIndex, adIndexInAdGroup, windowSequenceNumber, C.TIME_END_OF_SOURCE);
Object periodUid, int adGroupIndex, int adIndexInAdGroup, long windowSequenceNumber) {
this(periodUid, adGroupIndex, adIndexInAdGroup, windowSequenceNumber, C.TIME_END_OF_SOURCE);
}
private MediaPeriodId(
int periodIndex,
Object periodUid,
int adGroupIndex,
int adIndexInAdGroup,
long windowSequenceNumber,
long endPositionUs) {
this.periodIndex = periodIndex;
this.periodUid = periodUid;
this.adGroupIndex = adGroupIndex;
this.adIndexInAdGroup = adIndexInAdGroup;
this.windowSequenceNumber = windowSequenceNumber;
this.endPositionUs = endPositionUs;
}
/**
* Returns a copy of this period identifier but with {@code newPeriodIndex} as its period index.
*/
public MediaPeriodId copyWithPeriodIndex(int newPeriodIndex) {
return periodIndex == newPeriodIndex
/** Returns a copy of this period identifier but with {@code newPeriodUid} as its period uid. */
public MediaPeriodId copyWithPeriodUid(Object newPeriodUid) {
return periodUid.equals(newPeriodUid)
? this
: new MediaPeriodId(
newPeriodIndex, adGroupIndex, adIndexInAdGroup, windowSequenceNumber, endPositionUs);
newPeriodUid, adGroupIndex, adIndexInAdGroup, windowSequenceNumber, endPositionUs);
}
/**
......@@ -188,7 +184,7 @@ public interface MediaSource {
}
MediaPeriodId periodId = (MediaPeriodId) obj;
return periodIndex == periodId.periodIndex
return periodUid.equals(periodId.periodUid)
&& adGroupIndex == periodId.adGroupIndex
&& adIndexInAdGroup == periodId.adIndexInAdGroup
&& windowSequenceNumber == periodId.windowSequenceNumber
......@@ -198,14 +194,13 @@ public interface MediaSource {
@Override
public int hashCode() {
int result = 17;
result = 31 * result + periodIndex;
result = 31 * result + periodUid.hashCode();
result = 31 * result + adGroupIndex;
result = 31 * result + adIndexInAdGroup;
result = 31 * result + (int) windowSequenceNumber;
result = 31 * result + (int) endPositionUs;
return result;
}
}
/**
......
......@@ -68,10 +68,10 @@ public final class MergingMediaSource extends CompositeMediaSource<Integer> {
private static final int PERIOD_COUNT_UNSET = -1;
private final MediaSource[] mediaSources;
private final Timeline[] timelines;
private final ArrayList<MediaSource> pendingTimelineSources;
private final CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory;
private Timeline primaryTimeline;
private Object primaryManifest;
private int periodCount;
private IllegalMergeException mergeError;
......@@ -95,6 +95,7 @@ public final class MergingMediaSource extends CompositeMediaSource<Integer> {
this.compositeSequenceableLoaderFactory = compositeSequenceableLoaderFactory;
pendingTimelineSources = new ArrayList<>(Arrays.asList(mediaSources));
periodCount = PERIOD_COUNT_UNSET;
timelines = new Timeline[mediaSources.length];
}
@Override
......@@ -119,8 +120,11 @@ public final class MergingMediaSource extends CompositeMediaSource<Integer> {
@Override
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) {
MediaPeriod[] periods = new MediaPeriod[mediaSources.length];
int periodIndex = timelines[0].getIndexOfPeriod(id.periodUid);
for (int i = 0; i < periods.length; i++) {
periods[i] = mediaSources[i].createPeriod(id, allocator);
MediaPeriodId childMediaPeriodId =
id.copyWithPeriodUid(timelines[i].getUidOfPeriod(periodIndex));
periods[i] = mediaSources[i].createPeriod(childMediaPeriodId, allocator);
}
return new MergingMediaPeriod(compositeSequenceableLoaderFactory, periods);
}
......@@ -136,7 +140,7 @@ public final class MergingMediaSource extends CompositeMediaSource<Integer> {
@Override
public void releaseSourceInternal() {
super.releaseSourceInternal();
primaryTimeline = null;
Arrays.fill(timelines, null);
primaryManifest = null;
periodCount = PERIOD_COUNT_UNSET;
mergeError = null;
......@@ -154,12 +158,12 @@ public final class MergingMediaSource extends CompositeMediaSource<Integer> {
return;
}
pendingTimelineSources.remove(mediaSource);
timelines[id] = timeline;
if (mediaSource == mediaSources[0]) {
primaryTimeline = timeline;
primaryManifest = manifest;
}
if (pendingTimelineSources.isEmpty()) {
refreshSourceInfo(primaryTimeline, primaryManifest);
refreshSourceInfo(timelines[0], primaryManifest);
}
}
......
......@@ -308,7 +308,6 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
@Override
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) {
Assertions.checkArgument(id.periodIndex == 0);
return new SingleSampleMediaPeriod(
dataSpec,
dataSourceFactory,
......
......@@ -176,7 +176,7 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
// Used to identify the content "child" source for CompositeMediaSource.
private static final MediaPeriodId DUMMY_CONTENT_MEDIA_PERIOD_ID =
new MediaPeriodId(/* periodIndex= */ 0);
new MediaPeriodId(/* periodUid= */ new Object());
private final MediaSource contentMediaSource;
private final MediaSourceFactory adMediaSourceFactory;
......@@ -194,7 +194,7 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
private Object contentManifest;
private AdPlaybackState adPlaybackState;
private MediaSource[][] adGroupMediaSources;
private long[][] adDurationsUs;
private Timeline[][] adGroupTimelines;
/**
* Constructs a new source that inserts ads linearly with the content specified by {@code
......@@ -309,7 +309,7 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
deferredMediaPeriodByAdMediaSource = new HashMap<>();
period = new Timeline.Period();
adGroupMediaSources = new MediaSource[0][];
adDurationsUs = new long[0][];
adGroupTimelines = new Timeline[0][];
adsLoader.setSupportedContentTypes(adMediaSourceFactory.getSupportedTypes());
}
......@@ -341,8 +341,7 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
int adCount = adIndexInAdGroup + 1;
adGroupMediaSources[adGroupIndex] =
Arrays.copyOf(adGroupMediaSources[adGroupIndex], adCount);
adDurationsUs[adGroupIndex] = Arrays.copyOf(adDurationsUs[adGroupIndex], adCount);
Arrays.fill(adDurationsUs[adGroupIndex], oldAdCount, adCount, C.TIME_UNSET);
adGroupTimelines[adGroupIndex] = Arrays.copyOf(adGroupTimelines[adGroupIndex], adCount);
}
adGroupMediaSources[adGroupIndex][adIndexInAdGroup] = adMediaSource;
deferredMediaPeriodByAdMediaSource.put(adMediaSource, new ArrayList<>());
......@@ -354,8 +353,9 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
new AdPrepareErrorListener(adUri, adGroupIndex, adIndexInAdGroup));
List<DeferredMediaPeriod> mediaPeriods = deferredMediaPeriodByAdMediaSource.get(mediaSource);
if (mediaPeriods == null) {
MediaPeriodId adSourceMediaPeriodId =
new MediaPeriodId(/* periodIndex= */ 0, id.windowSequenceNumber);
Object periodUid =
adGroupTimelines[adGroupIndex][adIndexInAdGroup].getUidOfPeriod(/* periodIndex= */ 0);
MediaPeriodId adSourceMediaPeriodId = new MediaPeriodId(periodUid, id.windowSequenceNumber);
deferredMediaPeriod.createPeriod(adSourceMediaPeriodId);
} else {
// Keep track of the deferred media period so it can be populated with the real media period
......@@ -391,7 +391,7 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
contentManifest = null;
adPlaybackState = null;
adGroupMediaSources = new MediaSource[0][];
adDurationsUs = new long[0][];
adGroupTimelines = new Timeline[0][];
mainHandler.post(adsLoader::detachPlayer);
}
......@@ -424,8 +424,8 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
if (this.adPlaybackState == null) {
adGroupMediaSources = new MediaSource[adPlaybackState.adGroupCount][];
Arrays.fill(adGroupMediaSources, new MediaSource[0]);
adDurationsUs = new long[adPlaybackState.adGroupCount][];
Arrays.fill(adDurationsUs, new long[0]);
adGroupTimelines = new Timeline[adPlaybackState.adGroupCount][];
Arrays.fill(adGroupTimelines, new Timeline[0]);
}
this.adPlaybackState = adPlaybackState;
maybeUpdateSourceInfo();
......@@ -440,13 +440,14 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
private void onAdSourceInfoRefreshed(MediaSource mediaSource, int adGroupIndex,
int adIndexInAdGroup, Timeline timeline) {
Assertions.checkArgument(timeline.getPeriodCount() == 1);
adDurationsUs[adGroupIndex][adIndexInAdGroup] = timeline.getPeriod(0, period).getDurationUs();
adGroupTimelines[adGroupIndex][adIndexInAdGroup] = timeline;
List<DeferredMediaPeriod> mediaPeriods = deferredMediaPeriodByAdMediaSource.remove(mediaSource);
if (mediaPeriods != null) {
Object periodUid = timeline.getUidOfPeriod(/* periodIndex= */ 0);
for (int i = 0; i < mediaPeriods.size(); i++) {
DeferredMediaPeriod mediaPeriod = mediaPeriods.get(i);
MediaPeriodId adSourceMediaPeriodId =
new MediaPeriodId(/* periodIndex= */ 0, mediaPeriod.id.windowSequenceNumber);
new MediaPeriodId(periodUid, mediaPeriod.id.windowSequenceNumber);
mediaPeriod.createPeriod(adSourceMediaPeriodId);
}
}
......@@ -455,7 +456,7 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
private void maybeUpdateSourceInfo() {
if (adPlaybackState != null && contentTimeline != null) {
adPlaybackState = adPlaybackState.withAdDurationsUs(adDurationsUs);
adPlaybackState = adPlaybackState.withAdDurationsUs(getAdDurations(adGroupTimelines, period));
Timeline timeline =
adPlaybackState.adGroupCount == 0
? contentTimeline
......@@ -464,6 +465,20 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
}
}
private static long[][] getAdDurations(Timeline[][] adTimelines, Timeline.Period period) {
long[][] adDurations = new long[adTimelines.length][];
for (int i = 0; i < adTimelines.length; i++) {
adDurations[i] = new long[adTimelines[i].length];
for (int j = 0; j < adTimelines[i].length; j++) {
adDurations[i][j] =
adTimelines[i][j] == null
? C.TIME_UNSET
: adTimelines[i][j].getPeriod(/* periodIndex= */ 0, period).getDurationUs();
}
}
return adDurations;
}
/** Listener for component events. All methods are called on the main thread. */
private final class ComponentListener implements AdsLoader.EventListener {
......
......@@ -456,7 +456,8 @@ public class EventLogger implements AnalyticsListener {
private String getEventTimeString(EventTime eventTime) {
String windowPeriodString = "window=" + eventTime.windowIndex;
if (eventTime.mediaPeriodId != null) {
windowPeriodString += ", period=" + eventTime.mediaPeriodId.periodIndex;
windowPeriodString +=
", period=" + eventTime.timeline.getIndexOfPeriod(eventTime.mediaPeriodId.periodUid);
if (eventTime.mediaPeriodId.isAd()) {
windowPeriodString += ", adGroup=" + eventTime.mediaPeriodId.adGroupIndex;
windowPeriodString += ", ad=" + eventTime.mediaPeriodId.adIndexInAdGroup;
......
......@@ -187,10 +187,28 @@ public final class ExoPlayerTest {
@Test
public void testReadAheadToEndDoesNotResetRenderer() throws Exception {
// Use sufficiently short periods to ensure the player attempts to read all at once.
TimelineWindowDefinition windowDefinition =
TimelineWindowDefinition windowDefinition0 =
new TimelineWindowDefinition(
/* isSeekable= */ false, /* isDynamic= */ false, /* durationUs= */ 100_000);
Timeline timeline = new FakeTimeline(windowDefinition, windowDefinition, windowDefinition);
/* periodCount= */ 1,
/* id= */ 0,
/* isSeekable= */ false,
/* isDynamic= */ false,
/* durationUs= */ 100_000);
TimelineWindowDefinition windowDefinition1 =
new TimelineWindowDefinition(
/* periodCount= */ 1,
/* id= */ 1,
/* isSeekable= */ false,
/* isDynamic= */ false,
/* durationUs= */ 100_000);
TimelineWindowDefinition windowDefinition2 =
new TimelineWindowDefinition(
/* periodCount= */ 1,
/* id= */ 2,
/* isSeekable= */ false,
/* isDynamic= */ false,
/* durationUs= */ 100_000);
Timeline timeline = new FakeTimeline(windowDefinition0, windowDefinition1, windowDefinition2);
final FakeRenderer videoRenderer = new FakeRenderer(Builder.VIDEO_FORMAT);
FakeMediaClockRenderer audioRenderer =
new FakeMediaClockRenderer(Builder.AUDIO_FORMAT) {
......@@ -2019,9 +2037,12 @@ public final class ExoPlayerTest {
// Assert that the second period was re-created from the new timeline.
assertThat(mediaSource.getCreatedMediaPeriods())
.containsExactly(
new MediaPeriodId(/* periodIndex= */ 0, /* windowSequenceNumber= */ 0),
new MediaPeriodId(/* periodIndex= */ 1, /* windowSequenceNumber= */ 1),
new MediaPeriodId(/* periodIndex= */ 1, /* windowSequenceNumber= */ 2))
new MediaPeriodId(
timeline1.getUidOfPeriod(/* periodIndex= */ 0), /* windowSequenceNumber= */ 0),
new MediaPeriodId(
timeline1.getUidOfPeriod(/* periodIndex= */ 1), /* windowSequenceNumber= */ 1),
new MediaPeriodId(
timeline2.getUidOfPeriod(/* periodIndex= */ 1), /* windowSequenceNumber= */ 2))
.inOrder();
}
......@@ -2057,10 +2078,14 @@ public final class ExoPlayerTest {
testRunner.assertPlayedPeriodIndices(0, 1, 0, 1);
assertThat(mediaSource.getCreatedMediaPeriods())
.containsAllOf(
new MediaPeriodId(/* periodIndex= */ 0, /* windowSequenceNumber= */ 0),
new MediaPeriodId(/* periodIndex= */ 1, /* windowSequenceNumber= */ 0));
new MediaPeriodId(
timeline.getUidOfPeriod(/* periodIndex= */ 0), /* windowSequenceNumber= */ 0),
new MediaPeriodId(
timeline.getUidOfPeriod(/* periodIndex= */ 1), /* windowSequenceNumber= */ 0));
assertThat(mediaSource.getCreatedMediaPeriods())
.doesNotContain(new MediaPeriodId(/* periodIndex= */ 1, /* windowSequenceNumber= */ 1));
.doesNotContain(
new MediaPeriodId(
timeline.getUidOfPeriod(/* periodIndex= */ 1), /* windowSequenceNumber= */ 1));
}
@Test
......
......@@ -469,11 +469,11 @@ public final class ClippingMediaSourceTest {
private static MediaLoadData getClippingMediaSourceMediaLoadData(
long clippingStartUs, long clippingEndUs, final long eventStartUs, final long eventEndUs)
throws IOException {
Timeline timeline =
new SinglePeriodTimeline(
TEST_PERIOD_DURATION_US, /* isSeekable= */ true, /* isDynamic= */ false);
FakeMediaSource fakeMediaSource =
new FakeMediaSource(
new SinglePeriodTimeline(
TEST_PERIOD_DURATION_US, /* isSeekable= */ true, /* isDynamic= */ false),
/* manifest= */ null) {
new FakeMediaSource(timeline, /* manifest= */ null) {
@Override
protected FakeMediaPeriod createFakeMediaPeriod(
MediaPeriodId id,
......@@ -516,7 +516,8 @@ public final class ClippingMediaSourceTest {
testRunner.prepareSource();
// Create period to send the test event configured above.
testRunner.createPeriod(
new MediaPeriodId(/* periodIndex= */ 0, /* windowSequenceNumber= */ 0));
new MediaPeriodId(
timeline.getUidOfPeriod(/* periodIndex= */ 0), /* windowSequenceNumber= */ 0));
assertThat(reportedMediaLoadData[0]).isNotNull();
} finally {
testRunner.release();
......@@ -580,7 +581,9 @@ public final class ClippingMediaSourceTest {
clippedTimelines[0] = testRunner.prepareSource();
MediaPeriod mediaPeriod =
testRunner.createPeriod(
new MediaPeriodId(/* periodIndex= */ 0, /* windowSequenceNumber= */ 0));
new MediaPeriodId(
clippedTimelines[0].getUidOfPeriod(/* periodIndex= */ 0),
/* windowSequenceNumber= */ 0));
for (int i = 0; i < additionalTimelines.length; i++) {
fakeMediaSource.setNewSourceInfo(additionalTimelines[i], /* newManifest= */ null);
clippedTimelines[i + 1] = testRunner.assertTimelineChangeBlocking();
......
......@@ -45,11 +45,11 @@ public final class SinglePeriodTimelineTest {
public void testGetPeriodPositionDynamicWindowUnknownDuration() {
SinglePeriodTimeline timeline = new SinglePeriodTimeline(C.TIME_UNSET, false, true);
// Should return null with any positive position projection.
Pair<Integer, Long> position = timeline.getPeriodPosition(window, period, 0, C.TIME_UNSET, 1);
Pair<Object, Long> position = timeline.getPeriodPosition(window, period, 0, C.TIME_UNSET, 1);
assertThat(position).isNull();
// Should return (0, 0) without a position projection.
position = timeline.getPeriodPosition(window, period, 0, C.TIME_UNSET, 0);
assertThat(position.first).isEqualTo(0);
assertThat(position.first).isEqualTo(timeline.getUidOfPeriod(0));
assertThat(position.second).isEqualTo(0);
}
......@@ -66,16 +66,16 @@ public final class SinglePeriodTimelineTest {
/* isDynamic= */ true,
/* tag= */ null);
// Should return null with a positive position projection beyond window duration.
Pair<Integer, Long> position = timeline.getPeriodPosition(window, period, 0, C.TIME_UNSET,
windowDurationUs + 1);
Pair<Object, Long> position =
timeline.getPeriodPosition(window, period, 0, C.TIME_UNSET, windowDurationUs + 1);
assertThat(position).isNull();
// Should return (0, duration) with a projection equal to window duration.
position = timeline.getPeriodPosition(window, period, 0, C.TIME_UNSET, windowDurationUs);
assertThat(position.first).isEqualTo(0);
assertThat(position.first).isEqualTo(timeline.getUidOfPeriod(0));
assertThat(position.second).isEqualTo(windowDurationUs);
// Should return (0, 0) without a position projection.
position = timeline.getPeriodPosition(window, period, 0, C.TIME_UNSET, 0);
assertThat(position.first).isEqualTo(0);
assertThat(position.first).isEqualTo(timeline.getUidOfPeriod(0));
assertThat(position.second).isEqualTo(0);
}
......
......@@ -73,8 +73,8 @@ import java.util.List;
private final PlayerEmsgHandler playerEmsgHandler;
private final IdentityHashMap<ChunkSampleStream<DashChunkSource>, PlayerTrackEmsgHandler>
trackEmsgHandlerBySampleStream;
private final EventDispatcher eventDispatcher;
private EventDispatcher eventDispatcher;
private @Nullable Callback callback;
private ChunkSampleStream<DashChunkSource>[] sampleStreams;
private EventSampleStream[] eventSampleStreams;
......@@ -131,13 +131,6 @@ import java.util.List;
*/
public void updateManifest(DashManifest manifest, int periodIndex) {
this.manifest = manifest;
if (this.periodIndex != periodIndex) {
eventDispatcher =
eventDispatcher.withParameters(
/* windowIndex= */ 0,
eventDispatcher.mediaPeriodId.copyWithPeriodIndex(periodIndex),
manifest.getPeriod(periodIndex).startMs);
}
this.periodIndex = periodIndex;
playerEmsgHandler.updateManifest(manifest);
if (sampleStreams != null) {
......
......@@ -631,7 +631,7 @@ public final class DashMediaSource extends BaseMediaSource {
@Override
public MediaPeriod createPeriod(MediaPeriodId periodId, Allocator allocator) {
int periodIndex = periodId.periodIndex;
int periodIndex = (Integer) periodId.periodUid - firstPeriodId;
EventDispatcher periodEventDispatcher =
createEventDispatcher(periodId, manifest.getPeriod(periodIndex).startMs);
DashMediaPeriod mediaPeriod =
......
......@@ -425,7 +425,6 @@ public final class HlsMediaSource extends BaseMediaSource
@Override
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) {
Assertions.checkArgument(id.periodIndex == 0);
EventDispatcher eventDispatcher = createEventDispatcher(id);
return new HlsMediaPeriod(
extractorFactory,
......
......@@ -525,7 +525,6 @@ public final class SsMediaSource extends BaseMediaSource
@Override
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) {
Assertions.checkArgument(id.periodIndex == 0);
EventDispatcher eventDispatcher = createEventDispatcher(id);
SsMediaPeriod period =
new SsMediaPeriod(
......
......@@ -53,7 +53,7 @@ public class FakeAdaptiveMediaSource extends FakeMediaSource {
Allocator allocator,
EventDispatcher eventDispatcher,
@Nullable TransferListener transferListener) {
Period period = timeline.getPeriod(id.periodIndex, new Period());
Period period = timeline.getPeriodByUid(id.periodUid, new Period());
return new FakeAdaptiveMediaPeriod(
trackGroupArray,
eventDispatcher,
......
......@@ -111,8 +111,9 @@ public class FakeMediaSource extends BaseMediaSource {
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) {
assertThat(preparedSource).isTrue();
assertThat(releasedSource).isFalse();
Assertions.checkIndex(id.periodIndex, 0, timeline.getPeriodCount());
Period period = timeline.getPeriod(id.periodIndex, new Period());
int periodIndex = timeline.getIndexOfPeriod(id.periodUid);
Assertions.checkArgument(periodIndex != C.INDEX_UNSET);
Period period = timeline.getPeriod(periodIndex, new Period());
EventDispatcher eventDispatcher =
createEventDispatcher(period.windowIndex, id, period.getPositionInWindowMs());
FakeMediaPeriod mediaPeriod =
......
......@@ -251,12 +251,12 @@ public class MediaSourceTestRunner {
public void assertPrepareAndReleaseAllPeriods() throws InterruptedException {
Timeline.Period period = new Timeline.Period();
for (int i = 0; i < timeline.getPeriodCount(); i++) {
timeline.getPeriod(i, period);
assertPrepareAndReleasePeriod(new MediaPeriodId(i, period.windowIndex));
timeline.getPeriod(i, period, /* setIds= */ true);
assertPrepareAndReleasePeriod(new MediaPeriodId(period.uid, period.windowIndex));
for (int adGroupIndex = 0; adGroupIndex < period.getAdGroupCount(); adGroupIndex++) {
for (int adIndex = 0; adIndex < period.getAdCountInAdGroup(adGroupIndex); adIndex++) {
assertPrepareAndReleasePeriod(
new MediaPeriodId(i, adGroupIndex, adIndex, period.windowIndex));
new MediaPeriodId(period.uid, adGroupIndex, adIndex, period.windowIndex));
}
}
}
......@@ -272,7 +272,7 @@ public class MediaSourceTestRunner {
// to releasePeriod.
MediaPeriodId secondMediaPeriodId =
new MediaPeriodId(
mediaPeriodId.periodIndex,
mediaPeriodId.periodUid,
mediaPeriodId.adGroupIndex,
mediaPeriodId.adIndexInAdGroup,
mediaPeriodId.windowSequenceNumber + 1000);
......@@ -322,8 +322,8 @@ public class MediaSourceTestRunner {
int windowIndex = windowIndexAndMediaPeriodId.first;
MediaPeriodId mediaPeriodId = windowIndexAndMediaPeriodId.second;
if (expectedLoads.remove(mediaPeriodId)) {
assertThat(windowIndex)
.isEqualTo(timeline.getPeriod(mediaPeriodId.periodIndex, period).windowIndex);
int periodIndex = timeline.getIndexOfPeriod(mediaPeriodId.periodUid);
assertThat(windowIndex).isEqualTo(timeline.getPeriod(periodIndex, period).windowIndex);
}
}
assertWithMessage("Not all expected media source loads have been completed.")
......
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