From 0b3fa5176a5df7a96a8214c0f7c89c466dbbbe43 Mon Sep 17 00:00:00 2001 From: tonihei Date: Mon, 23 Jul 2018 02:53:28 -0700 Subject: [PATCH] Move media period end position from MediaperiodInfo to MediaPeriodId. The end position is needed to make the MediaPeriodId unique as multiple content periods may only vary in this parameter. This also simplfies some other comparisons where the end position needed to be compared in addition to the media period id. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=205634508 --- .../exoplayer2/ExoPlayerImplInternal.java | 15 +------ .../android/exoplayer2/MediaPeriodHolder.java | 6 +-- .../android/exoplayer2/MediaPeriodInfo.java | 11 +---- .../android/exoplayer2/MediaPeriodQueue.java | 44 ++++++++++--------- .../exoplayer2/source/MediaSource.java | 41 +++++++++++++++-- 5 files changed, 67 insertions(+), 50 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java index 22205e77f4..cc338385cd 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java @@ -676,7 +676,7 @@ import java.util.Collections; MediaPeriodHolder oldPlayingPeriodHolder = queue.getPlayingPeriod(); MediaPeriodHolder newPlayingPeriodHolder = oldPlayingPeriodHolder; while (newPlayingPeriodHolder != null) { - if (shouldKeepPeriodHolder(periodId, periodPositionUs, newPlayingPeriodHolder)) { + if (periodId.equals(newPlayingPeriodHolder.info.id) && newPlayingPeriodHolder.prepared) { queue.removeAfter(newPlayingPeriodHolder); break; } @@ -712,19 +712,6 @@ import java.util.Collections; return periodPositionUs; } - private boolean shouldKeepPeriodHolder( - MediaPeriodId seekPeriodId, long positionUs, MediaPeriodHolder holder) { - if (seekPeriodId.equals(holder.info.id) && holder.prepared) { - playbackInfo.timeline.getPeriod(holder.info.id.periodIndex, period); - int nextAdGroupIndex = period.getAdGroupIndexAfterPositionUs(positionUs); - if (nextAdGroupIndex == C.INDEX_UNSET - || period.getAdGroupTimeUs(nextAdGroupIndex) == holder.info.endPositionUs) { - return true; - } - } - return false; - } - private void resetRendererPosition(long periodPositionUs) throws ExoPlaybackException { rendererPositionUs = !queue.hasPlayingPeriod() diff --git a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java index c4d69b7e7a..d9dde9d4e8 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java @@ -82,13 +82,13 @@ import com.google.android.exoplayer2.util.Assertions; sampleStreams = new SampleStream[rendererCapabilities.length]; mayRetainStreamFlags = new boolean[rendererCapabilities.length]; MediaPeriod mediaPeriod = mediaSource.createPeriod(info.id, allocator); - if (info.endPositionUs != C.TIME_END_OF_SOURCE) { + if (info.id.endPositionUs != C.TIME_END_OF_SOURCE) { mediaPeriod = new ClippingMediaPeriod( mediaPeriod, /* enableInitialDiscontinuity= */ true, /* startUs= */ 0, - info.endPositionUs); + info.id.endPositionUs); } this.mediaPeriod = mediaPeriod; } @@ -219,7 +219,7 @@ import com.google.android.exoplayer2.util.Assertions; public void release() { updatePeriodTrackSelectorResult(null); try { - if (info.endPositionUs != C.TIME_END_OF_SOURCE) { + if (info.id.endPositionUs != C.TIME_END_OF_SOURCE) { mediaSource.releasePeriod(((ClippingMediaPeriod) mediaPeriod).mediaPeriod); } else { mediaSource.releasePeriod(mediaPeriod); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodInfo.java b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodInfo.java index fce1780b71..b887e8222e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodInfo.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodInfo.java @@ -25,18 +25,13 @@ import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; public final MediaPeriodId id; /** The start position of the media to play within the media period, in microseconds. */ public final long startPositionUs; - /** - * The end position of the media to play within the media period, in microseconds, or {@link - * C#TIME_END_OF_SOURCE} if the end position is the end of the media period. - */ - public final long endPositionUs; /** * If this is an ad, the position to play in the next content media period. {@link C#TIME_UNSET} * otherwise. */ public final long contentPositionUs; /** - * The duration of the media period, like {@link #endPositionUs} but with {@link + * The duration of the media period, like {@link MediaPeriodId#endPositionUs} but with {@link * C#TIME_END_OF_SOURCE} resolved to the timeline period duration. May be {@link C#TIME_UNSET} if * the end position is not known. */ @@ -55,14 +50,12 @@ import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; MediaPeriodInfo( MediaPeriodId id, long startPositionUs, - long endPositionUs, long contentPositionUs, long durationUs, boolean isLastInTimelinePeriod, boolean isFinal) { this.id = id; this.startPositionUs = startPositionUs; - this.endPositionUs = endPositionUs; this.contentPositionUs = contentPositionUs; this.durationUs = durationUs; this.isLastInTimelinePeriod = isLastInTimelinePeriod; @@ -77,7 +70,6 @@ import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; return new MediaPeriodInfo( id.copyWithPeriodIndex(periodIndex), startPositionUs, - endPositionUs, contentPositionUs, durationUs, isLastInTimelinePeriod, @@ -89,7 +81,6 @@ import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; return new MediaPeriodInfo( id, startPositionUs, - endPositionUs, contentPositionUs, durationUs, isLastInTimelinePeriod, diff --git a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java index 17a8ddd8d4..010de547a2 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java @@ -391,7 +391,12 @@ import com.google.android.exoplayer2.util.Assertions; timeline.getPeriod(periodIndex, period); int adGroupIndex = period.getAdGroupIndexForPositionUs(positionUs); if (adGroupIndex == C.INDEX_UNSET) { - return new MediaPeriodId(periodIndex, windowSequenceNumber); + int nextAdGroupIndex = period.getAdGroupIndexAfterPositionUs(positionUs); + long endPositionUs = + nextAdGroupIndex == C.INDEX_UNSET + ? C.TIME_END_OF_SOURCE + : period.getAdGroupTimeUs(nextAdGroupIndex); + return new MediaPeriodId(periodIndex, windowSequenceNumber, endPositionUs); } else { int adIndexInAdGroup = period.getFirstAdIndexToPlay(adGroupIndex); return new MediaPeriodId(periodIndex, adGroupIndex, adIndexInAdGroup, windowSequenceNumber); @@ -450,7 +455,6 @@ import com.google.android.exoplayer2.util.Assertions; private boolean canKeepMediaPeriodHolder(MediaPeriodHolder periodHolder, MediaPeriodInfo info) { MediaPeriodInfo periodHolderInfo = periodHolder.info; return periodHolderInfo.startPositionUs == info.startPositionUs - && periodHolderInfo.endPositionUs == info.endPositionUs && periodHolderInfo.id.equals(info.id); } @@ -593,14 +597,14 @@ import com.google.android.exoplayer2.util.Assertions; mediaPeriodInfo.contentPositionUs, currentPeriodId.windowSequenceNumber); } - } else if (mediaPeriodInfo.endPositionUs != C.TIME_END_OF_SOURCE) { + } else if (mediaPeriodInfo.id.endPositionUs != C.TIME_END_OF_SOURCE) { // Play the next ad group if it's available. - int nextAdGroupIndex = period.getAdGroupIndexForPositionUs(mediaPeriodInfo.endPositionUs); + int nextAdGroupIndex = period.getAdGroupIndexForPositionUs(mediaPeriodInfo.id.endPositionUs); if (nextAdGroupIndex == C.INDEX_UNSET) { // The next ad group can't be played. Play content from the ad group position instead. return getMediaPeriodInfoForContent( currentPeriodId.periodIndex, - mediaPeriodInfo.endPositionUs, + mediaPeriodInfo.id.endPositionUs, currentPeriodId.windowSequenceNumber); } int adIndexInAdGroup = period.getFirstAdIndexToPlay(nextAdGroupIndex); @@ -610,7 +614,7 @@ import com.google.android.exoplayer2.util.Assertions; currentPeriodId.periodIndex, nextAdGroupIndex, adIndexInAdGroup, - mediaPeriodInfo.endPositionUs, + mediaPeriodInfo.id.endPositionUs, currentPeriodId.windowSequenceNumber); } else { // Check if the postroll ad should be played. @@ -639,18 +643,18 @@ import com.google.android.exoplayer2.util.Assertions; private MediaPeriodInfo getUpdatedMediaPeriodInfo(MediaPeriodInfo info, MediaPeriodId newId) { long startPositionUs = info.startPositionUs; - long endPositionUs = info.endPositionUs; - boolean isLastInPeriod = isLastInPeriod(newId, endPositionUs); + boolean isLastInPeriod = isLastInPeriod(newId); boolean isLastInTimeline = isLastInTimeline(newId, isLastInPeriod); timeline.getPeriod(newId.periodIndex, period); long durationUs = newId.isAd() ? period.getAdDurationUs(newId.adGroupIndex, newId.adIndexInAdGroup) - : (endPositionUs == C.TIME_END_OF_SOURCE ? period.getDurationUs() : endPositionUs); + : (newId.endPositionUs == C.TIME_END_OF_SOURCE + ? period.getDurationUs() + : newId.endPositionUs); return new MediaPeriodInfo( newId, startPositionUs, - endPositionUs, info.contentPositionUs, durationUs, isLastInPeriod, @@ -683,7 +687,7 @@ import com.google.android.exoplayer2.util.Assertions; long windowSequenceNumber) { MediaPeriodId id = new MediaPeriodId(periodIndex, adGroupIndex, adIndexInAdGroup, windowSequenceNumber); - boolean isLastInPeriod = isLastInPeriod(id, C.TIME_END_OF_SOURCE); + boolean isLastInPeriod = isLastInPeriod(id); boolean isLastInTimeline = isLastInTimeline(id, isLastInPeriod); long durationUs = timeline @@ -696,7 +700,6 @@ import com.google.android.exoplayer2.util.Assertions; return new MediaPeriodInfo( id, startPositionUs, - C.TIME_END_OF_SOURCE, contentPositionUs, durationUs, isLastInPeriod, @@ -705,21 +708,22 @@ import com.google.android.exoplayer2.util.Assertions; private MediaPeriodInfo getMediaPeriodInfoForContent( int periodIndex, long startPositionUs, long windowSequenceNumber) { - MediaPeriodId id = new MediaPeriodId(periodIndex, windowSequenceNumber); - timeline.getPeriod(id.periodIndex, period); int nextAdGroupIndex = period.getAdGroupIndexAfterPositionUs(startPositionUs); - long endUs = + long endPositionUs = nextAdGroupIndex == C.INDEX_UNSET ? C.TIME_END_OF_SOURCE : period.getAdGroupTimeUs(nextAdGroupIndex); - boolean isLastInPeriod = isLastInPeriod(id, endUs); + MediaPeriodId id = new MediaPeriodId(periodIndex, windowSequenceNumber, endPositionUs); + timeline.getPeriod(id.periodIndex, period); + boolean isLastInPeriod = isLastInPeriod(id); boolean isLastInTimeline = isLastInTimeline(id, isLastInPeriod); - long durationUs = endUs == C.TIME_END_OF_SOURCE ? period.getDurationUs() : endUs; + long durationUs = + endPositionUs == C.TIME_END_OF_SOURCE ? period.getDurationUs() : endPositionUs; return new MediaPeriodInfo( - id, startPositionUs, endUs, C.TIME_UNSET, durationUs, isLastInPeriod, isLastInTimeline); + id, startPositionUs, C.TIME_UNSET, durationUs, isLastInPeriod, isLastInTimeline); } - private boolean isLastInPeriod(MediaPeriodId id, long endPositionUs) { + private boolean isLastInPeriod(MediaPeriodId id) { int adGroupCount = timeline.getPeriod(id.periodIndex, period).getAdGroupCount(); if (adGroupCount == 0) { return true; @@ -729,7 +733,7 @@ import com.google.android.exoplayer2.util.Assertions; boolean isAd = id.isAd(); if (period.getAdGroupTimeUs(lastAdGroupIndex) != C.TIME_END_OF_SOURCE) { // There's no postroll ad. - return !isAd && endPositionUs == C.TIME_END_OF_SOURCE; + return !isAd && id.endPositionUs == C.TIME_END_OF_SOURCE; } int postrollAdCount = period.getAdCountInAdGroup(lastAdGroupIndex); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSource.java index 1590235d15..241d19143f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSource.java @@ -91,6 +91,15 @@ public interface MediaSource { */ public final long windowSequenceNumber; + /** + * The end position of the media to play within the media period, in microseconds, or {@link + * C#TIME_END_OF_SOURCE} if the end position is the end of the media period. + * + *

Note that this only applies if the media period is for content (i.e., not for an ad) and + * is clipped to the position of the next ad group. + */ + public final long endPositionUs; + /** * Creates a media period identifier for a dummy period which is not part of a buffered sequence * of windows. @@ -109,7 +118,20 @@ public interface MediaSource { * windows this media period is part of. */ public MediaPeriodId(int periodIndex, long windowSequenceNumber) { - this(periodIndex, C.INDEX_UNSET, C.INDEX_UNSET, windowSequenceNumber); + this(periodIndex, 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 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); } /** @@ -124,10 +146,20 @@ public interface MediaSource { */ public MediaPeriodId( int periodIndex, int adGroupIndex, int adIndexInAdGroup, long windowSequenceNumber) { + this(periodIndex, adGroupIndex, adIndexInAdGroup, windowSequenceNumber, C.TIME_END_OF_SOURCE); + } + + private MediaPeriodId( + int periodIndex, + int adGroupIndex, + int adIndexInAdGroup, + long windowSequenceNumber, + long endPositionUs) { this.periodIndex = periodIndex; this.adGroupIndex = adGroupIndex; this.adIndexInAdGroup = adIndexInAdGroup; this.windowSequenceNumber = windowSequenceNumber; + this.endPositionUs = endPositionUs; } /** @@ -136,7 +168,8 @@ public interface MediaSource { public MediaPeriodId copyWithPeriodIndex(int newPeriodIndex) { return periodIndex == newPeriodIndex ? this - : new MediaPeriodId(newPeriodIndex, adGroupIndex, adIndexInAdGroup, windowSequenceNumber); + : new MediaPeriodId( + newPeriodIndex, adGroupIndex, adIndexInAdGroup, windowSequenceNumber, endPositionUs); } /** @@ -159,7 +192,8 @@ public interface MediaSource { return periodIndex == periodId.periodIndex && adGroupIndex == periodId.adGroupIndex && adIndexInAdGroup == periodId.adIndexInAdGroup - && windowSequenceNumber == periodId.windowSequenceNumber; + && windowSequenceNumber == periodId.windowSequenceNumber + && endPositionUs == periodId.endPositionUs; } @Override @@ -169,6 +203,7 @@ public interface MediaSource { result = 31 * result + adGroupIndex; result = 31 * result + adIndexInAdGroup; result = 31 * result + (int) windowSequenceNumber; + result = 31 * result + (int) endPositionUs; return result; }