Get the next ad index to play in MediaPeriodQueue
The ad index in the ad group may need to skip over ads that failed to load, so it can't just be incremented any more. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=184812556
This commit is contained in:
parent
fea75f2e42
commit
84a105b031
@ -887,7 +887,7 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
|
||||
private void stopAdInternal() {
|
||||
Assertions.checkState(imaAdState != IMA_AD_STATE_NONE);
|
||||
imaAdState = IMA_AD_STATE_NONE;
|
||||
int adIndexInAdGroup = adPlaybackState.adGroups[adGroupIndex].nextAdIndexToPlay;
|
||||
int adIndexInAdGroup = adPlaybackState.adGroups[adGroupIndex].getFirstAdIndexToPlay();
|
||||
// TODO: Handle the skipped event so the ad can be marked as skipped rather than played.
|
||||
adPlaybackState =
|
||||
adPlaybackState.withPlayedAd(adGroupIndex, adIndexInAdGroup).withAdResumePositionUs(0);
|
||||
|
@ -372,7 +372,7 @@ import com.google.android.exoplayer2.util.Assertions;
|
||||
if (adGroupIndex == C.INDEX_UNSET) {
|
||||
return new MediaPeriodId(periodIndex);
|
||||
} else {
|
||||
int adIndexInAdGroup = period.getNextAdIndexToPlay(adGroupIndex);
|
||||
int adIndexInAdGroup = period.getFirstAdIndexToPlay(adGroupIndex);
|
||||
return new MediaPeriodId(periodIndex, adGroupIndex, adIndexInAdGroup);
|
||||
}
|
||||
}
|
||||
@ -496,19 +496,20 @@ import com.google.android.exoplayer2.util.Assertions;
|
||||
MediaPeriodId currentPeriodId = mediaPeriodInfo.id;
|
||||
timeline.getPeriod(currentPeriodId.periodIndex, period);
|
||||
if (currentPeriodId.isAd()) {
|
||||
int currentAdGroupIndex = currentPeriodId.adGroupIndex;
|
||||
int adCountInCurrentAdGroup = period.getAdCountInAdGroup(currentAdGroupIndex);
|
||||
int adGroupIndex = currentPeriodId.adGroupIndex;
|
||||
int adCountInCurrentAdGroup = period.getAdCountInAdGroup(adGroupIndex);
|
||||
if (adCountInCurrentAdGroup == C.LENGTH_UNSET) {
|
||||
return null;
|
||||
}
|
||||
int nextAdIndexInAdGroup = currentPeriodId.adIndexInAdGroup + 1;
|
||||
int nextAdIndexInAdGroup =
|
||||
period.getNextAdIndexToPlay(adGroupIndex, currentPeriodId.adIndexInAdGroup);
|
||||
if (nextAdIndexInAdGroup < adCountInCurrentAdGroup) {
|
||||
// Play the next ad in the ad group if it's available.
|
||||
return !period.isAdAvailable(currentAdGroupIndex, nextAdIndexInAdGroup)
|
||||
return !period.isAdAvailable(adGroupIndex, nextAdIndexInAdGroup)
|
||||
? null
|
||||
: getMediaPeriodInfoForAd(
|
||||
currentPeriodId.periodIndex,
|
||||
currentAdGroupIndex,
|
||||
adGroupIndex,
|
||||
nextAdIndexInAdGroup,
|
||||
mediaPeriodInfo.contentPositionUs);
|
||||
} else {
|
||||
@ -524,22 +525,32 @@ import com.google.android.exoplayer2.util.Assertions;
|
||||
return getMediaPeriodInfoForContent(
|
||||
currentPeriodId.periodIndex, mediaPeriodInfo.endPositionUs);
|
||||
}
|
||||
return !period.isAdAvailable(nextAdGroupIndex, 0)
|
||||
int adIndexInAdGroup = period.getFirstAdIndexToPlay(nextAdGroupIndex);
|
||||
return !period.isAdAvailable(nextAdGroupIndex, adIndexInAdGroup)
|
||||
? null
|
||||
: getMediaPeriodInfoForAd(
|
||||
currentPeriodId.periodIndex, nextAdGroupIndex, 0, mediaPeriodInfo.endPositionUs);
|
||||
currentPeriodId.periodIndex,
|
||||
nextAdGroupIndex,
|
||||
adIndexInAdGroup,
|
||||
mediaPeriodInfo.endPositionUs);
|
||||
} else {
|
||||
// Check if the postroll ad should be played.
|
||||
int adGroupCount = period.getAdGroupCount();
|
||||
if (adGroupCount == 0
|
||||
|| period.getAdGroupTimeUs(adGroupCount - 1) != C.TIME_END_OF_SOURCE
|
||||
|| period.hasPlayedAdGroup(adGroupCount - 1)
|
||||
|| !period.isAdAvailable(adGroupCount - 1, 0)) {
|
||||
if (adGroupCount == 0) {
|
||||
return null;
|
||||
}
|
||||
int adGroupIndex = adGroupCount - 1;
|
||||
if (period.getAdGroupTimeUs(adGroupIndex) != C.TIME_END_OF_SOURCE
|
||||
|| period.hasPlayedAdGroup(adGroupIndex)) {
|
||||
return null;
|
||||
}
|
||||
int adIndexInAdGroup = period.getFirstAdIndexToPlay(adGroupIndex);
|
||||
if (!period.isAdAvailable(adGroupIndex, adIndexInAdGroup)) {
|
||||
return null;
|
||||
}
|
||||
long contentDurationUs = period.getDurationUs();
|
||||
return getMediaPeriodInfoForAd(
|
||||
currentPeriodId.periodIndex, adGroupCount - 1, 0, contentDurationUs);
|
||||
currentPeriodId.periodIndex, adGroupIndex, adIndexInAdGroup, contentDurationUs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -587,7 +598,7 @@ import com.google.android.exoplayer2.util.Assertions;
|
||||
.getPeriod(id.periodIndex, period)
|
||||
.getAdDurationUs(id.adGroupIndex, id.adIndexInAdGroup);
|
||||
long startPositionUs =
|
||||
adIndexInAdGroup == period.getNextAdIndexToPlay(adGroupIndex)
|
||||
adIndexInAdGroup == period.getFirstAdIndexToPlay(adGroupIndex)
|
||||
? period.getAdResumePositionUs()
|
||||
: 0;
|
||||
return new MediaPeriodInfo(
|
||||
@ -636,7 +647,7 @@ import com.google.android.exoplayer2.util.Assertions;
|
||||
|
||||
boolean isLastAd =
|
||||
isAd && id.adGroupIndex == lastAdGroupIndex && id.adIndexInAdGroup == postrollAdCount - 1;
|
||||
return isLastAd || (!isAd && period.getNextAdIndexToPlay(lastAdGroupIndex) == postrollAdCount);
|
||||
return isLastAd || (!isAd && period.getFirstAdIndexToPlay(lastAdGroupIndex) == postrollAdCount);
|
||||
}
|
||||
|
||||
private boolean isLastInTimeline(MediaPeriodId id, boolean isLastMediaPeriodInPeriod) {
|
||||
|
@ -381,15 +381,29 @@ public abstract class Timeline {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the next ad to play in the specified ad group, or the number of ads in
|
||||
* the ad group if the ad group does not have any ads remaining to play.
|
||||
* Returns the index of the first ad in the specified ad group that should be played, or the
|
||||
* number of ads in the ad group if no ads should be played.
|
||||
*
|
||||
* @param adGroupIndex The ad group index.
|
||||
* @return The index of the first ad that should be played, or the number of ads in the ad group
|
||||
* if no ads should be played.
|
||||
*/
|
||||
public int getFirstAdIndexToPlay(int adGroupIndex) {
|
||||
return adPlaybackState.adGroups[adGroupIndex].getFirstAdIndexToPlay();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the next ad in the specified ad group that should be played after
|
||||
* playing {@code adIndexInAdGroup}, or the number of ads in the ad group if no later ads should
|
||||
* be played.
|
||||
*
|
||||
* @param adGroupIndex The ad group index.
|
||||
* @param lastPlayedAdIndex The last played ad index in the ad group.
|
||||
* @return The index of the next ad that should be played, or the number of ads in the ad group
|
||||
* if the ad group does not have any ads remaining to play.
|
||||
*/
|
||||
public int getNextAdIndexToPlay(int adGroupIndex) {
|
||||
return adPlaybackState.adGroups[adGroupIndex].nextAdIndexToPlay;
|
||||
public int getNextAdIndexToPlay(int adGroupIndex, int lastPlayedAdIndex) {
|
||||
return adPlaybackState.adGroups[adGroupIndex].getNextAdIndexToPlay(lastPlayedAdIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -400,7 +414,7 @@ public abstract class Timeline {
|
||||
*/
|
||||
public boolean hasPlayedAdGroup(int adGroupIndex) {
|
||||
AdPlaybackState.AdGroup adGroup = adPlaybackState.adGroups[adGroupIndex];
|
||||
return adGroup.nextAdIndexToPlay == adGroup.count;
|
||||
return adGroup.getFirstAdIndexToPlay() == adGroup.count;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,8 +49,6 @@ public final class AdPlaybackState {
|
||||
public final @AdState int[] states;
|
||||
/** The durations of each ad in the ad group, in microseconds. */
|
||||
public final long[] durationsUs;
|
||||
/** The index of the next ad that should be played, or {@link #count} if all ads were played. */
|
||||
public final int nextAdIndexToPlay;
|
||||
|
||||
/** Creates a new ad group with an unspecified number of ads. */
|
||||
public AdGroup() {
|
||||
@ -67,14 +65,30 @@ public final class AdPlaybackState {
|
||||
this.states = states;
|
||||
this.uris = uris;
|
||||
this.durationsUs = durationsUs;
|
||||
int nextAdIndexToPlay;
|
||||
for (nextAdIndexToPlay = 0; nextAdIndexToPlay < states.length; nextAdIndexToPlay++) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the first ad in the ad group that should be played, or {@link #count} if
|
||||
* no ads should be played.
|
||||
*/
|
||||
public int getFirstAdIndexToPlay() {
|
||||
return getNextAdIndexToPlay(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the next ad in the ad group that should be played after playing {@code
|
||||
* lastPlayedAdIndex}, or {@link #count} if no later ads should be played.
|
||||
*/
|
||||
public int getNextAdIndexToPlay(int lastPlayedAdIndex) {
|
||||
int nextAdIndexToPlay = lastPlayedAdIndex + 1;
|
||||
while (nextAdIndexToPlay < states.length) {
|
||||
if (states[nextAdIndexToPlay] == AD_STATE_UNAVAILABLE
|
||||
|| states[nextAdIndexToPlay] == AD_STATE_AVAILABLE) {
|
||||
break;
|
||||
}
|
||||
nextAdIndexToPlay++;
|
||||
}
|
||||
this.nextAdIndexToPlay = nextAdIndexToPlay;
|
||||
return nextAdIndexToPlay;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -70,29 +70,29 @@ public final class AdPlaybackStateTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitialNextAdIndexToPlay() {
|
||||
public void testGetFirstAdIndexToPlayIsZero() {
|
||||
state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 3);
|
||||
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, TEST_URI);
|
||||
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 2, TEST_URI);
|
||||
|
||||
assertThat(state.adGroups[0].nextAdIndexToPlay).isEqualTo(0);
|
||||
assertThat(state.adGroups[0].getFirstAdIndexToPlay()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNextAdIndexToPlayWithPlayedAd() {
|
||||
public void testGetFirstAdIndexToPlaySkipsPlayedAd() {
|
||||
state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 3);
|
||||
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, TEST_URI);
|
||||
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 2, TEST_URI);
|
||||
|
||||
state = state.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0);
|
||||
|
||||
assertThat(state.adGroups[0].nextAdIndexToPlay).isEqualTo(1);
|
||||
assertThat(state.adGroups[0].getFirstAdIndexToPlay()).isEqualTo(1);
|
||||
assertThat(state.adGroups[0].states[1]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE);
|
||||
assertThat(state.adGroups[0].states[2]).isEqualTo(AdPlaybackState.AD_STATE_AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNextAdIndexToPlaySkipsErrorAds() {
|
||||
public void testGetFirstAdIndexToPlaySkipsErrorAds() {
|
||||
state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 3);
|
||||
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, TEST_URI);
|
||||
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 2, TEST_URI);
|
||||
@ -100,7 +100,17 @@ public final class AdPlaybackStateTest {
|
||||
state = state.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0);
|
||||
state = state.withAdLoadError(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1);
|
||||
|
||||
assertThat(state.adGroups[0].nextAdIndexToPlay).isEqualTo(2);
|
||||
assertThat(state.adGroups[0].getFirstAdIndexToPlay()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNextAdIndexToPlaySkipsErrorAds() {
|
||||
state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 3);
|
||||
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1, TEST_URI);
|
||||
|
||||
state = state.withAdLoadError(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1);
|
||||
|
||||
assertThat(state.adGroups[0].getNextAdIndexToPlay(0)).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
x
Reference in New Issue
Block a user