From 67780bfbc28b2da0069ce91ec4116ec6b1d331cb Mon Sep 17 00:00:00 2001 From: tonihei Date: Thu, 15 Feb 2018 06:29:45 -0800 Subject: [PATCH] Add window sequence number to MediaPeriodId. All media periods are part of a queue of windows buffered and played by ExoPlayer. When repeating windows, the current MediaPeriodId is insufficient to distinguish between the repetitions of the same period. This makes it hard to see to which media period load events belong to, and it is also difficult to determine whether two media periods belong to the same logical window or whether they are part of different repetitions of the same window. Therefore this change adds a unique sequence number to each window in the sequence of windows and this sequence number is saved as part of the MediaPeriodId. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=185829509 --- .../android/exoplayer2/MediaPeriodQueue.java | 124 +++++++++++++++--- .../android/exoplayer2/PlaybackInfo.java | 2 +- .../exoplayer2/source/MediaSource.java | 47 +++++-- .../exoplayer2/source/ads/AdsMediaSource.java | 5 +- .../android/exoplayer2/ExoPlayerTest.java | 5 +- .../source/ConcatenatingMediaSourceTest.java | 26 +++- .../DynamicConcatenatingMediaSourceTest.java | 38 ++++-- .../testutil/MediaSourceTestRunner.java | 8 +- 8 files changed, 200 insertions(+), 55 deletions(-) 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 208a235777..3efff58f5d 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 @@ -44,6 +44,7 @@ import com.google.android.exoplayer2.util.Assertions; private final Timeline.Period period; private final Timeline.Window window; + private long nextWindowSequenceNumber; private Timeline timeline; private @RepeatMode int repeatMode; private boolean shuffleModeEnabled; @@ -368,18 +369,70 @@ import com.google.android.exoplayer2.util.Assertions; * @return The identifier for the first media period to play, taking into account unplayed ads. */ public MediaPeriodId resolveMediaPeriodIdForAds(int periodIndex, long positionUs) { - timeline.getPeriod(periodIndex, period); - int adGroupIndex = period.getAdGroupIndexForPositionUs(positionUs); - if (adGroupIndex == C.INDEX_UNSET) { - return new MediaPeriodId(periodIndex); - } else { - int adIndexInAdGroup = period.getFirstAdIndexToPlay(adGroupIndex); - return new MediaPeriodId(periodIndex, adGroupIndex, adIndexInAdGroup); - } + long windowSequenceNumber = resolvePeriodIndexToWindowSequenceNumber(periodIndex); + return resolveMediaPeriodIdForAds(periodIndex, positionUs, windowSequenceNumber); } // Internal methods. + /** + * Resolves the specified timeline period and position to a {@link MediaPeriodId} that should be + * played, returning an identifier for an ad group if one needs to be played before the specified + * position, or an identifier for a content media period if not. + * + * @param periodIndex The index of the timeline period to play. + * @param positionUs The next content position in the period to play. + * @param windowSequenceNumber The sequence number of the window in the buffered sequence of + * windows this period is part of. + * @return The identifier for the first media period to play, taking into account unplayed ads. + */ + private MediaPeriodId resolveMediaPeriodIdForAds( + int periodIndex, long positionUs, long windowSequenceNumber) { + timeline.getPeriod(periodIndex, period); + int adGroupIndex = period.getAdGroupIndexForPositionUs(positionUs); + if (adGroupIndex == C.INDEX_UNSET) { + return new MediaPeriodId(periodIndex, windowSequenceNumber); + } else { + int adIndexInAdGroup = period.getFirstAdIndexToPlay(adGroupIndex); + return new MediaPeriodId(periodIndex, adGroupIndex, adIndexInAdGroup, windowSequenceNumber); + } + } + + /** + * Resolves the specified period index to a corresponding window sequence number. Either by + * reusing the window sequence number of an existing matching media period or by creating a new + * window sequence number. + * + * @param periodIndex The index of the timeline period. + * @return A window sequence number for a media period created for this timeline period. + */ + private long resolvePeriodIndexToWindowSequenceNumber(int periodIndex) { + Object periodUid = timeline.getPeriod(periodIndex, period, /* setIds= */ true).uid; + MediaPeriodHolder mediaPeriodHolder = getFrontPeriod(); + while (mediaPeriodHolder != null) { + if (mediaPeriodHolder.uid.equals(periodUid)) { + // Reuse window sequence number of first exact period match. + return mediaPeriodHolder.info.id.windowSequenceNumber; + } + mediaPeriodHolder = mediaPeriodHolder.next; + } + int windowIndex = period.windowIndex; + mediaPeriodHolder = getFrontPeriod(); + while (mediaPeriodHolder != null) { + int indexOfHolderInTimeline = timeline.getIndexOfPeriod(mediaPeriodHolder.uid); + if (indexOfHolderInTimeline != C.INDEX_UNSET) { + int holderWindowIndex = timeline.getPeriod(indexOfHolderInTimeline, period).windowIndex; + if (holderWindowIndex == windowIndex) { + // As an alternative, try to match other periods of the same window. + return mediaPeriodHolder.info.id.windowSequenceNumber; + } + } + mediaPeriodHolder = mediaPeriodHolder.next; + } + // If no match is found, create new sequence number. + return nextWindowSequenceNumber++; + } + /** * Returns whether {@code periodHolder} can be kept for playing the media period described by * {@code info}. @@ -466,7 +519,10 @@ import com.google.android.exoplayer2.util.Assertions; } long startPositionUs; - int nextWindowIndex = timeline.getPeriod(nextPeriodIndex, period).windowIndex; + int nextWindowIndex = + timeline.getPeriod(nextPeriodIndex, period, /* setIds= */ true).windowIndex; + Object nextPeriodUid = period.uid; + long windowSequenceNumber = mediaPeriodInfo.id.windowSequenceNumber; if (timeline.getWindow(nextWindowIndex, window).firstPeriodIndex == nextPeriodIndex) { // We're starting to buffer a new window. When playback transitions to this window we'll // want it to be from its default start position. The expected delay until playback @@ -487,10 +543,16 @@ import com.google.android.exoplayer2.util.Assertions; } nextPeriodIndex = defaultPosition.first; startPositionUs = defaultPosition.second; + if (mediaPeriodHolder.next != null && mediaPeriodHolder.next.uid.equals(nextPeriodUid)) { + windowSequenceNumber = mediaPeriodHolder.next.info.id.windowSequenceNumber; + } else { + windowSequenceNumber = nextWindowSequenceNumber++; + } } else { startPositionUs = 0; } - MediaPeriodId periodId = resolveMediaPeriodIdForAds(nextPeriodIndex, startPositionUs); + MediaPeriodId periodId = + resolveMediaPeriodIdForAds(nextPeriodIndex, startPositionUs, windowSequenceNumber); return getMediaPeriodInfo(periodId, startPositionUs, startPositionUs); } @@ -512,11 +574,14 @@ import com.google.android.exoplayer2.util.Assertions; currentPeriodId.periodIndex, adGroupIndex, nextAdIndexInAdGroup, - mediaPeriodInfo.contentPositionUs); + mediaPeriodInfo.contentPositionUs, + currentPeriodId.windowSequenceNumber); } else { // Play content from the ad group position. return getMediaPeriodInfoForContent( - currentPeriodId.periodIndex, mediaPeriodInfo.contentPositionUs); + currentPeriodId.periodIndex, + mediaPeriodInfo.contentPositionUs, + currentPeriodId.windowSequenceNumber); } } else if (mediaPeriodInfo.endPositionUs != C.TIME_END_OF_SOURCE) { // Play the next ad group if it's available. @@ -524,7 +589,9 @@ import com.google.android.exoplayer2.util.Assertions; 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); + currentPeriodId.periodIndex, + mediaPeriodInfo.endPositionUs, + currentPeriodId.windowSequenceNumber); } int adIndexInAdGroup = period.getFirstAdIndexToPlay(nextAdGroupIndex); return !period.isAdAvailable(nextAdGroupIndex, adIndexInAdGroup) @@ -533,7 +600,8 @@ import com.google.android.exoplayer2.util.Assertions; currentPeriodId.periodIndex, nextAdGroupIndex, adIndexInAdGroup, - mediaPeriodInfo.endPositionUs); + mediaPeriodInfo.endPositionUs, + currentPeriodId.windowSequenceNumber); } else { // Check if the postroll ad should be played. int adGroupCount = period.getAdGroupCount(); @@ -551,7 +619,11 @@ import com.google.android.exoplayer2.util.Assertions; } long contentDurationUs = period.getDurationUs(); return getMediaPeriodInfoForAd( - currentPeriodId.periodIndex, adGroupIndex, adIndexInAdGroup, contentDurationUs); + currentPeriodId.periodIndex, + adGroupIndex, + adIndexInAdGroup, + contentDurationUs, + currentPeriodId.windowSequenceNumber); } } @@ -583,15 +655,24 @@ import com.google.android.exoplayer2.util.Assertions; return null; } return getMediaPeriodInfoForAd( - id.periodIndex, id.adGroupIndex, id.adIndexInAdGroup, contentPositionUs); + id.periodIndex, + id.adGroupIndex, + id.adIndexInAdGroup, + contentPositionUs, + id.windowSequenceNumber); } else { - return getMediaPeriodInfoForContent(id.periodIndex, startPositionUs); + return getMediaPeriodInfoForContent(id.periodIndex, startPositionUs, id.windowSequenceNumber); } } private MediaPeriodInfo getMediaPeriodInfoForAd( - int periodIndex, int adGroupIndex, int adIndexInAdGroup, long contentPositionUs) { - MediaPeriodId id = new MediaPeriodId(periodIndex, adGroupIndex, adIndexInAdGroup); + int periodIndex, + int adGroupIndex, + int adIndexInAdGroup, + long contentPositionUs, + long windowSequenceNumber) { + MediaPeriodId id = + new MediaPeriodId(periodIndex, adGroupIndex, adIndexInAdGroup, windowSequenceNumber); boolean isLastInPeriod = isLastInPeriod(id, C.TIME_END_OF_SOURCE); boolean isLastInTimeline = isLastInTimeline(id, isLastInPeriod); long durationUs = @@ -612,8 +693,9 @@ import com.google.android.exoplayer2.util.Assertions; isLastInTimeline); } - private MediaPeriodInfo getMediaPeriodInfoForContent(int periodIndex, long startPositionUs) { - MediaPeriodId id = new MediaPeriodId(periodIndex); + 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 = diff --git a/library/core/src/main/java/com/google/android/exoplayer2/PlaybackInfo.java b/library/core/src/main/java/com/google/android/exoplayer2/PlaybackInfo.java index bb39bf3d0b..3ff2ec9461 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/PlaybackInfo.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/PlaybackInfo.java @@ -41,7 +41,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; this( timeline, /* manifest= */ null, - new MediaPeriodId(0), + new MediaPeriodId(/* periodIndex= */ 0), startPositionUs, /* contentPositionUs =*/ C.TIME_UNSET, Player.STATE_IDLE, 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 25da60cb74..02bd0cdbc7 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 @@ -63,12 +63,6 @@ public interface MediaSource { */ final class MediaPeriodId { - /** - * Value for unset media period identifiers. - */ - public static final MediaPeriodId UNSET = - new MediaPeriodId(C.INDEX_UNSET, C.INDEX_UNSET, C.INDEX_UNSET); - /** * The timeline period index. */ @@ -86,13 +80,32 @@ public interface MediaSource { */ public final int adIndexInAdGroup; + /** + * The sequence number of the window in the buffered sequence of windows this media period is + * part of. {@link C#INDEX_UNSET} if the media period id is not part of a buffered sequence of + * windows. + */ + public final long windowSequenceNumber; + + /** + * Creates a media period identifier for a dummy period which is not part of a buffered sequence + * of windows. + * + * @param periodIndex The period index. + */ + public MediaPeriodId(int periodIndex) { + this(periodIndex, C.INDEX_UNSET); + } + /** * Creates a media period identifier for the specified 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. */ - public MediaPeriodId(int periodIndex) { - this(periodIndex, C.INDEX_UNSET, C.INDEX_UNSET); + public MediaPeriodId(int periodIndex, long windowSequenceNumber) { + this(periodIndex, C.INDEX_UNSET, C.INDEX_UNSET, windowSequenceNumber); } /** @@ -102,19 +115,24 @@ public interface MediaSource { * @param periodIndex The index 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) { + public MediaPeriodId( + int periodIndex, int adGroupIndex, int adIndexInAdGroup, long windowSequenceNumber) { this.periodIndex = periodIndex; this.adGroupIndex = adGroupIndex; this.adIndexInAdGroup = adIndexInAdGroup; + this.windowSequenceNumber = windowSequenceNumber; } /** * Returns a copy of this period identifier but with {@code newPeriodIndex} as its period index. */ public MediaPeriodId copyWithPeriodIndex(int newPeriodIndex) { - return periodIndex == newPeriodIndex ? this - : new MediaPeriodId(newPeriodIndex, adGroupIndex, adIndexInAdGroup); + return periodIndex == newPeriodIndex + ? this + : new MediaPeriodId(newPeriodIndex, adGroupIndex, adIndexInAdGroup, windowSequenceNumber); } /** @@ -134,8 +152,10 @@ public interface MediaSource { } MediaPeriodId periodId = (MediaPeriodId) obj; - return periodIndex == periodId.periodIndex && adGroupIndex == periodId.adGroupIndex - && adIndexInAdGroup == periodId.adIndexInAdGroup; + return periodIndex == periodId.periodIndex + && adGroupIndex == periodId.adGroupIndex + && adIndexInAdGroup == periodId.adIndexInAdGroup + && windowSequenceNumber == periodId.windowSequenceNumber; } @Override @@ -144,6 +164,7 @@ public interface MediaSource { result = 31 * result + periodIndex; result = 31 * result + adGroupIndex; result = 31 * result + adIndexInAdGroup; + result = 31 * result + (int) windowSequenceNumber; return result; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java index 8c4d85ff4c..854be90d1c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java @@ -235,7 +235,10 @@ public final class AdsMediaSource extends CompositeMediaSource { } MediaSource mediaSource = adGroupMediaSources[adGroupIndex][adIndexInAdGroup]; DeferredMediaPeriod deferredMediaPeriod = - new DeferredMediaPeriod(mediaSource, new MediaPeriodId(0), allocator); + new DeferredMediaPeriod( + mediaSource, + new MediaPeriodId(/* periodIndex= */ 0, id.windowSequenceNumber), + allocator); deferredMediaPeriod.setPrepareErrorListener( new AdPrepareErrorListener(adGroupIndex, adIndexInAdGroup)); List mediaPeriods = deferredMediaPeriodByAdMediaSource.get(mediaSource); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java b/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java index 7faa349705..3d0cde5df8 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java @@ -1802,7 +1802,10 @@ public final class ExoPlayerTest { testRunner.assertPlayedPeriodIndices(0, 1); // Assert that the second period was re-created from the new timeline. assertThat(mediaSource.getCreatedMediaPeriods()) - .containsExactly(new MediaPeriodId(0), new MediaPeriodId(1), new MediaPeriodId(1)) + .containsExactly( + new MediaPeriodId(/* periodIndex= */ 0, /* windowSequenceNumber= */ 0), + new MediaPeriodId(/* periodIndex= */ 1, /* windowSequenceNumber= */ 1), + new MediaPeriodId(/* periodIndex= */ 1, /* windowSequenceNumber= */ 2)) .inOrder(); } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/source/ConcatenatingMediaSourceTest.java b/library/core/src/test/java/com/google/android/exoplayer2/source/ConcatenatingMediaSourceTest.java index d7cf8db4bc..ccc3ddea46 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/source/ConcatenatingMediaSourceTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/source/ConcatenatingMediaSourceTest.java @@ -245,12 +245,26 @@ public final class ConcatenatingMediaSourceTest { // Create all periods and assert period creation of child media sources has been called. testRunner.assertPrepareAndReleaseAllPeriods(); - mediaSourceContentOnly.assertMediaPeriodCreated(new MediaPeriodId(0)); - mediaSourceContentOnly.assertMediaPeriodCreated(new MediaPeriodId(1)); - mediaSourceWithAds.assertMediaPeriodCreated(new MediaPeriodId(0)); - mediaSourceWithAds.assertMediaPeriodCreated(new MediaPeriodId(1)); - mediaSourceWithAds.assertMediaPeriodCreated(new MediaPeriodId(0, 0, 0)); - mediaSourceWithAds.assertMediaPeriodCreated(new MediaPeriodId(1, 0, 0)); + mediaSourceContentOnly.assertMediaPeriodCreated( + new MediaPeriodId(/* periodIndex= */ 0, /* windowSequenceNumber= */ 0)); + mediaSourceContentOnly.assertMediaPeriodCreated( + new MediaPeriodId(/* periodIndex= */ 1, /* windowSequenceNumber= */ 0)); + mediaSourceWithAds.assertMediaPeriodCreated( + new MediaPeriodId(/* periodIndex= */ 0, /* windowSequenceNumber= */ 1)); + mediaSourceWithAds.assertMediaPeriodCreated( + new MediaPeriodId(/* periodIndex= */ 1, /* windowSequenceNumber= */ 1)); + mediaSourceWithAds.assertMediaPeriodCreated( + new MediaPeriodId( + /* periodIndex= */ 0, + /* adGroupIndex= */ 0, + /* adIndexInAdGroup= */ 0, + /* windowSequenceNumber= */ 1)); + mediaSourceWithAds.assertMediaPeriodCreated( + new MediaPeriodId( + /* periodIndex= */ 1, + /* adGroupIndex= */ 0, + /* adIndexInAdGroup= */ 0, + /* windowSequenceNumber= */ 1)); } finally { testRunner.release(); } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/source/DynamicConcatenatingMediaSourceTest.java b/library/core/src/test/java/com/google/android/exoplayer2/source/DynamicConcatenatingMediaSourceTest.java index a58a427b67..d71b02d39a 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/source/DynamicConcatenatingMediaSourceTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/source/DynamicConcatenatingMediaSourceTest.java @@ -267,12 +267,16 @@ public final class DynamicConcatenatingMediaSourceTest { // Create a period from an unprepared lazy media source and assert Callback.onPrepared is not // called yet. - MediaPeriod lazyPeriod = testRunner.createPeriod(new MediaPeriodId(0)); + MediaPeriod lazyPeriod = + testRunner.createPeriod( + new MediaPeriodId(/* periodIndex= */ 0, /* windowSequenceNumber= */ 0)); CountDownLatch preparedCondition = testRunner.preparePeriod(lazyPeriod, 0); assertThat(preparedCondition.getCount()).isEqualTo(1); // Assert that a second period can also be created and released without problems. - MediaPeriod secondLazyPeriod = testRunner.createPeriod(new MediaPeriodId(0)); + MediaPeriod secondLazyPeriod = + testRunner.createPeriod( + new MediaPeriodId(/* periodIndex= */ 0, /* windowSequenceNumber= */ 0)); testRunner.releasePeriod(secondLazyPeriod); // Trigger source info refresh for lazy media source. Assert that now all information is @@ -653,12 +657,26 @@ public final class DynamicConcatenatingMediaSourceTest { // Create all periods and assert period creation of child media sources has been called. testRunner.assertPrepareAndReleaseAllPeriods(); - mediaSourceContentOnly.assertMediaPeriodCreated(new MediaPeriodId(0)); - mediaSourceContentOnly.assertMediaPeriodCreated(new MediaPeriodId(1)); - mediaSourceWithAds.assertMediaPeriodCreated(new MediaPeriodId(0)); - mediaSourceWithAds.assertMediaPeriodCreated(new MediaPeriodId(1)); - mediaSourceWithAds.assertMediaPeriodCreated(new MediaPeriodId(0, 0, 0)); - mediaSourceWithAds.assertMediaPeriodCreated(new MediaPeriodId(1, 0, 0)); + mediaSourceContentOnly.assertMediaPeriodCreated( + new MediaPeriodId(/* periodIndex= */ 0, /* windowSequenceNumber= */ 0)); + mediaSourceContentOnly.assertMediaPeriodCreated( + new MediaPeriodId(/* periodIndex= */ 1, /* windowSequenceNumber= */ 0)); + mediaSourceWithAds.assertMediaPeriodCreated( + new MediaPeriodId(/* periodIndex= */ 0, /* windowSequenceNumber= */ 1)); + mediaSourceWithAds.assertMediaPeriodCreated( + new MediaPeriodId(/* periodIndex= */ 1, /* windowSequenceNumber= */ 1)); + mediaSourceWithAds.assertMediaPeriodCreated( + new MediaPeriodId( + /* periodIndex= */ 0, + /* adGroupIndex= */ 0, + /* adIndexInAdGroup= */ 0, + /* windowSequenceNumber= */ 1)); + mediaSourceWithAds.assertMediaPeriodCreated( + new MediaPeriodId( + /* periodIndex= */ 1, + /* adGroupIndex= */ 0, + /* adIndexInAdGroup= */ 0, + /* windowSequenceNumber= */ 1)); } @Test @@ -754,7 +772,9 @@ public final class DynamicConcatenatingMediaSourceTest { FakeMediaSource childSource = createFakeMediaSource(); mediaSource.addMediaSource(childSource); testRunner.prepareSource(); - MediaPeriod mediaPeriod = testRunner.createPeriod(new MediaPeriodId(/* periodIndex= */ 0)); + MediaPeriod mediaPeriod = + testRunner.createPeriod( + new MediaPeriodId(/* periodIndex= */ 0, /* windowSequenceNumber= */ 0)); mediaSource.removeMediaSource(/* index= */ 0); testRunner.assertTimelineChangeBlocking(); testRunner.releasePeriod(mediaPeriod); diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/MediaSourceTestRunner.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/MediaSourceTestRunner.java index cf0cc342f8..16389112ca 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/MediaSourceTestRunner.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/MediaSourceTestRunner.java @@ -244,16 +244,18 @@ public class MediaSourceTestRunner { /** * Creates and releases all periods (including ad periods) defined in the last timeline to be * returned from {@link #prepareSource()}, {@link #assertTimelineChange()} or {@link - * #assertTimelineChangeBlocking()}. + * #assertTimelineChangeBlocking()}. The {@link MediaPeriodId#windowSequenceNumber} is set to the + * index of the window. */ public void assertPrepareAndReleaseAllPeriods() throws InterruptedException { Timeline.Period period = new Timeline.Period(); for (int i = 0; i < timeline.getPeriodCount(); i++) { - assertPrepareAndReleasePeriod(new MediaPeriodId(i)); timeline.getPeriod(i, period); + assertPrepareAndReleasePeriod(new MediaPeriodId(i, 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)); + assertPrepareAndReleasePeriod( + new MediaPeriodId(i, adGroupIndex, adIndex, period.windowIndex)); } } }