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