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
This commit is contained in:
tonihei 2018-02-15 06:29:45 -08:00 committed by Oliver Woodman
parent 0291bc5e2d
commit 67780bfbc2
8 changed files with 200 additions and 55 deletions

View File

@ -44,6 +44,7 @@ import com.google.android.exoplayer2.util.Assertions;
private final Timeline.Period period; private final Timeline.Period period;
private final Timeline.Window window; private final Timeline.Window window;
private long nextWindowSequenceNumber;
private Timeline timeline; private Timeline timeline;
private @RepeatMode int repeatMode; private @RepeatMode int repeatMode;
private boolean shuffleModeEnabled; 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. * @return The identifier for the first media period to play, taking into account unplayed ads.
*/ */
public MediaPeriodId resolveMediaPeriodIdForAds(int periodIndex, long positionUs) { public MediaPeriodId resolveMediaPeriodIdForAds(int periodIndex, long positionUs) {
timeline.getPeriod(periodIndex, period); long windowSequenceNumber = resolvePeriodIndexToWindowSequenceNumber(periodIndex);
int adGroupIndex = period.getAdGroupIndexForPositionUs(positionUs); return resolveMediaPeriodIdForAds(periodIndex, positionUs, windowSequenceNumber);
if (adGroupIndex == C.INDEX_UNSET) {
return new MediaPeriodId(periodIndex);
} else {
int adIndexInAdGroup = period.getFirstAdIndexToPlay(adGroupIndex);
return new MediaPeriodId(periodIndex, adGroupIndex, adIndexInAdGroup);
}
} }
// Internal methods. // 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 * Returns whether {@code periodHolder} can be kept for playing the media period described by
* {@code info}. * {@code info}.
@ -466,7 +519,10 @@ import com.google.android.exoplayer2.util.Assertions;
} }
long startPositionUs; 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) { if (timeline.getWindow(nextWindowIndex, window).firstPeriodIndex == nextPeriodIndex) {
// We're starting to buffer a new window. When playback transitions to this window we'll // 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 // 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; nextPeriodIndex = defaultPosition.first;
startPositionUs = defaultPosition.second; startPositionUs = defaultPosition.second;
if (mediaPeriodHolder.next != null && mediaPeriodHolder.next.uid.equals(nextPeriodUid)) {
windowSequenceNumber = mediaPeriodHolder.next.info.id.windowSequenceNumber;
} else {
windowSequenceNumber = nextWindowSequenceNumber++;
}
} else { } else {
startPositionUs = 0; startPositionUs = 0;
} }
MediaPeriodId periodId = resolveMediaPeriodIdForAds(nextPeriodIndex, startPositionUs); MediaPeriodId periodId =
resolveMediaPeriodIdForAds(nextPeriodIndex, startPositionUs, windowSequenceNumber);
return getMediaPeriodInfo(periodId, startPositionUs, startPositionUs); return getMediaPeriodInfo(periodId, startPositionUs, startPositionUs);
} }
@ -512,11 +574,14 @@ import com.google.android.exoplayer2.util.Assertions;
currentPeriodId.periodIndex, currentPeriodId.periodIndex,
adGroupIndex, adGroupIndex,
nextAdIndexInAdGroup, nextAdIndexInAdGroup,
mediaPeriodInfo.contentPositionUs); mediaPeriodInfo.contentPositionUs,
currentPeriodId.windowSequenceNumber);
} else { } else {
// Play content from the ad group position. // Play content from the ad group position.
return getMediaPeriodInfoForContent( return getMediaPeriodInfoForContent(
currentPeriodId.periodIndex, mediaPeriodInfo.contentPositionUs); currentPeriodId.periodIndex,
mediaPeriodInfo.contentPositionUs,
currentPeriodId.windowSequenceNumber);
} }
} else if (mediaPeriodInfo.endPositionUs != C.TIME_END_OF_SOURCE) { } else if (mediaPeriodInfo.endPositionUs != C.TIME_END_OF_SOURCE) {
// Play the next ad group if it's available. // 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) { if (nextAdGroupIndex == C.INDEX_UNSET) {
// The next ad group can't be played. Play content from the ad group position instead. // The next ad group can't be played. Play content from the ad group position instead.
return getMediaPeriodInfoForContent( return getMediaPeriodInfoForContent(
currentPeriodId.periodIndex, mediaPeriodInfo.endPositionUs); currentPeriodId.periodIndex,
mediaPeriodInfo.endPositionUs,
currentPeriodId.windowSequenceNumber);
} }
int adIndexInAdGroup = period.getFirstAdIndexToPlay(nextAdGroupIndex); int adIndexInAdGroup = period.getFirstAdIndexToPlay(nextAdGroupIndex);
return !period.isAdAvailable(nextAdGroupIndex, adIndexInAdGroup) return !period.isAdAvailable(nextAdGroupIndex, adIndexInAdGroup)
@ -533,7 +600,8 @@ import com.google.android.exoplayer2.util.Assertions;
currentPeriodId.periodIndex, currentPeriodId.periodIndex,
nextAdGroupIndex, nextAdGroupIndex,
adIndexInAdGroup, adIndexInAdGroup,
mediaPeriodInfo.endPositionUs); mediaPeriodInfo.endPositionUs,
currentPeriodId.windowSequenceNumber);
} else { } else {
// Check if the postroll ad should be played. // Check if the postroll ad should be played.
int adGroupCount = period.getAdGroupCount(); int adGroupCount = period.getAdGroupCount();
@ -551,7 +619,11 @@ import com.google.android.exoplayer2.util.Assertions;
} }
long contentDurationUs = period.getDurationUs(); long contentDurationUs = period.getDurationUs();
return getMediaPeriodInfoForAd( 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 null;
} }
return getMediaPeriodInfoForAd( return getMediaPeriodInfoForAd(
id.periodIndex, id.adGroupIndex, id.adIndexInAdGroup, contentPositionUs); id.periodIndex,
id.adGroupIndex,
id.adIndexInAdGroup,
contentPositionUs,
id.windowSequenceNumber);
} else { } else {
return getMediaPeriodInfoForContent(id.periodIndex, startPositionUs); return getMediaPeriodInfoForContent(id.periodIndex, startPositionUs, id.windowSequenceNumber);
} }
} }
private MediaPeriodInfo getMediaPeriodInfoForAd( private MediaPeriodInfo getMediaPeriodInfoForAd(
int periodIndex, int adGroupIndex, int adIndexInAdGroup, long contentPositionUs) { int periodIndex,
MediaPeriodId id = new MediaPeriodId(periodIndex, adGroupIndex, adIndexInAdGroup); 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 isLastInPeriod = isLastInPeriod(id, C.TIME_END_OF_SOURCE);
boolean isLastInTimeline = isLastInTimeline(id, isLastInPeriod); boolean isLastInTimeline = isLastInTimeline(id, isLastInPeriod);
long durationUs = long durationUs =
@ -612,8 +693,9 @@ import com.google.android.exoplayer2.util.Assertions;
isLastInTimeline); isLastInTimeline);
} }
private MediaPeriodInfo getMediaPeriodInfoForContent(int periodIndex, long startPositionUs) { private MediaPeriodInfo getMediaPeriodInfoForContent(
MediaPeriodId id = new MediaPeriodId(periodIndex); int periodIndex, long startPositionUs, long windowSequenceNumber) {
MediaPeriodId id = new MediaPeriodId(periodIndex, windowSequenceNumber);
timeline.getPeriod(id.periodIndex, period); timeline.getPeriod(id.periodIndex, period);
int nextAdGroupIndex = period.getAdGroupIndexAfterPositionUs(startPositionUs); int nextAdGroupIndex = period.getAdGroupIndexAfterPositionUs(startPositionUs);
long endUs = long endUs =

View File

@ -41,7 +41,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
this( this(
timeline, timeline,
/* manifest= */ null, /* manifest= */ null,
new MediaPeriodId(0), new MediaPeriodId(/* periodIndex= */ 0),
startPositionUs, startPositionUs,
/* contentPositionUs =*/ C.TIME_UNSET, /* contentPositionUs =*/ C.TIME_UNSET,
Player.STATE_IDLE, Player.STATE_IDLE,

View File

@ -63,12 +63,6 @@ public interface MediaSource {
*/ */
final class MediaPeriodId { 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. * The timeline period index.
*/ */
@ -86,13 +80,32 @@ public interface MediaSource {
*/ */
public final int adIndexInAdGroup; 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. * Creates a media period identifier for the specified period in the timeline.
* *
* @param periodIndex The timeline period index. * @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) { public MediaPeriodId(int periodIndex, long windowSequenceNumber) {
this(periodIndex, C.INDEX_UNSET, C.INDEX_UNSET); 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 periodIndex The index 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
* 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.periodIndex = periodIndex;
this.adGroupIndex = adGroupIndex; this.adGroupIndex = adGroupIndex;
this.adIndexInAdGroup = adIndexInAdGroup; this.adIndexInAdGroup = adIndexInAdGroup;
this.windowSequenceNumber = windowSequenceNumber;
} }
/** /**
* Returns a copy of this period identifier but with {@code newPeriodIndex} as its period index. * Returns a copy of this period identifier but with {@code newPeriodIndex} as its period index.
*/ */
public MediaPeriodId copyWithPeriodIndex(int newPeriodIndex) { public MediaPeriodId copyWithPeriodIndex(int newPeriodIndex) {
return periodIndex == newPeriodIndex ? this return periodIndex == newPeriodIndex
: new MediaPeriodId(newPeriodIndex, adGroupIndex, adIndexInAdGroup); ? this
: new MediaPeriodId(newPeriodIndex, adGroupIndex, adIndexInAdGroup, windowSequenceNumber);
} }
/** /**
@ -134,8 +152,10 @@ public interface MediaSource {
} }
MediaPeriodId periodId = (MediaPeriodId) obj; MediaPeriodId periodId = (MediaPeriodId) obj;
return periodIndex == periodId.periodIndex && adGroupIndex == periodId.adGroupIndex return periodIndex == periodId.periodIndex
&& adIndexInAdGroup == periodId.adIndexInAdGroup; && adGroupIndex == periodId.adGroupIndex
&& adIndexInAdGroup == periodId.adIndexInAdGroup
&& windowSequenceNumber == periodId.windowSequenceNumber;
} }
@Override @Override
@ -144,6 +164,7 @@ public interface MediaSource {
result = 31 * result + periodIndex; result = 31 * result + periodIndex;
result = 31 * result + adGroupIndex; result = 31 * result + adGroupIndex;
result = 31 * result + adIndexInAdGroup; result = 31 * result + adIndexInAdGroup;
result = 31 * result + (int) windowSequenceNumber;
return result; return result;
} }

View File

@ -235,7 +235,10 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
} }
MediaSource mediaSource = adGroupMediaSources[adGroupIndex][adIndexInAdGroup]; MediaSource mediaSource = adGroupMediaSources[adGroupIndex][adIndexInAdGroup];
DeferredMediaPeriod deferredMediaPeriod = DeferredMediaPeriod deferredMediaPeriod =
new DeferredMediaPeriod(mediaSource, new MediaPeriodId(0), allocator); new DeferredMediaPeriod(
mediaSource,
new MediaPeriodId(/* periodIndex= */ 0, id.windowSequenceNumber),
allocator);
deferredMediaPeriod.setPrepareErrorListener( deferredMediaPeriod.setPrepareErrorListener(
new AdPrepareErrorListener(adGroupIndex, adIndexInAdGroup)); new AdPrepareErrorListener(adGroupIndex, adIndexInAdGroup));
List<DeferredMediaPeriod> mediaPeriods = deferredMediaPeriodByAdMediaSource.get(mediaSource); List<DeferredMediaPeriod> mediaPeriods = deferredMediaPeriodByAdMediaSource.get(mediaSource);

View File

@ -1802,7 +1802,10 @@ public final class ExoPlayerTest {
testRunner.assertPlayedPeriodIndices(0, 1); testRunner.assertPlayedPeriodIndices(0, 1);
// 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(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(); .inOrder();
} }

View File

@ -245,12 +245,26 @@ public final class ConcatenatingMediaSourceTest {
// Create all periods and assert period creation of child media sources has been called. // Create all periods and assert period creation of child media sources has been called.
testRunner.assertPrepareAndReleaseAllPeriods(); testRunner.assertPrepareAndReleaseAllPeriods();
mediaSourceContentOnly.assertMediaPeriodCreated(new MediaPeriodId(0)); mediaSourceContentOnly.assertMediaPeriodCreated(
mediaSourceContentOnly.assertMediaPeriodCreated(new MediaPeriodId(1)); new MediaPeriodId(/* periodIndex= */ 0, /* windowSequenceNumber= */ 0));
mediaSourceWithAds.assertMediaPeriodCreated(new MediaPeriodId(0)); mediaSourceContentOnly.assertMediaPeriodCreated(
mediaSourceWithAds.assertMediaPeriodCreated(new MediaPeriodId(1)); new MediaPeriodId(/* periodIndex= */ 1, /* windowSequenceNumber= */ 0));
mediaSourceWithAds.assertMediaPeriodCreated(new MediaPeriodId(0, 0, 0)); mediaSourceWithAds.assertMediaPeriodCreated(
mediaSourceWithAds.assertMediaPeriodCreated(new MediaPeriodId(1, 0, 0)); 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 { } finally {
testRunner.release(); testRunner.release();
} }

View File

@ -267,12 +267,16 @@ public final class DynamicConcatenatingMediaSourceTest {
// Create a period from an unprepared lazy media source and assert Callback.onPrepared is not // Create a period from an unprepared lazy media source and assert Callback.onPrepared is not
// called yet. // 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); CountDownLatch preparedCondition = testRunner.preparePeriod(lazyPeriod, 0);
assertThat(preparedCondition.getCount()).isEqualTo(1); assertThat(preparedCondition.getCount()).isEqualTo(1);
// Assert that a second period can also be created and released without problems. // 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); testRunner.releasePeriod(secondLazyPeriod);
// Trigger source info refresh for lazy media source. Assert that now all information is // 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. // Create all periods and assert period creation of child media sources has been called.
testRunner.assertPrepareAndReleaseAllPeriods(); testRunner.assertPrepareAndReleaseAllPeriods();
mediaSourceContentOnly.assertMediaPeriodCreated(new MediaPeriodId(0)); mediaSourceContentOnly.assertMediaPeriodCreated(
mediaSourceContentOnly.assertMediaPeriodCreated(new MediaPeriodId(1)); new MediaPeriodId(/* periodIndex= */ 0, /* windowSequenceNumber= */ 0));
mediaSourceWithAds.assertMediaPeriodCreated(new MediaPeriodId(0)); mediaSourceContentOnly.assertMediaPeriodCreated(
mediaSourceWithAds.assertMediaPeriodCreated(new MediaPeriodId(1)); new MediaPeriodId(/* periodIndex= */ 1, /* windowSequenceNumber= */ 0));
mediaSourceWithAds.assertMediaPeriodCreated(new MediaPeriodId(0, 0, 0)); mediaSourceWithAds.assertMediaPeriodCreated(
mediaSourceWithAds.assertMediaPeriodCreated(new MediaPeriodId(1, 0, 0)); 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 @Test
@ -754,7 +772,9 @@ public final class DynamicConcatenatingMediaSourceTest {
FakeMediaSource childSource = createFakeMediaSource(); FakeMediaSource childSource = createFakeMediaSource();
mediaSource.addMediaSource(childSource); mediaSource.addMediaSource(childSource);
testRunner.prepareSource(); testRunner.prepareSource();
MediaPeriod mediaPeriod = testRunner.createPeriod(new MediaPeriodId(/* periodIndex= */ 0)); MediaPeriod mediaPeriod =
testRunner.createPeriod(
new MediaPeriodId(/* periodIndex= */ 0, /* windowSequenceNumber= */ 0));
mediaSource.removeMediaSource(/* index= */ 0); mediaSource.removeMediaSource(/* index= */ 0);
testRunner.assertTimelineChangeBlocking(); testRunner.assertTimelineChangeBlocking();
testRunner.releasePeriod(mediaPeriod); testRunner.releasePeriod(mediaPeriod);

View File

@ -244,16 +244,18 @@ public class MediaSourceTestRunner {
/** /**
* Creates and releases all periods (including ad periods) defined in the last timeline to be * Creates and releases all periods (including ad periods) defined in the last timeline to be
* returned from {@link #prepareSource()}, {@link #assertTimelineChange()} or {@link * 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 { 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++) {
assertPrepareAndReleasePeriod(new MediaPeriodId(i));
timeline.getPeriod(i, period); timeline.getPeriod(i, period);
assertPrepareAndReleasePeriod(new MediaPeriodId(i, 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(new MediaPeriodId(i, adGroupIndex, adIndex)); assertPrepareAndReleasePeriod(
new MediaPeriodId(i, adGroupIndex, adIndex, period.windowIndex));
} }
} }
} }