mirror of
https://github.com/androidx/media.git
synced 2025-05-17 12:39:52 +08:00
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
8f81abee86
commit
165fce4c64
@ -887,7 +887,7 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
|
|||||||
private void stopAdInternal() {
|
private void stopAdInternal() {
|
||||||
Assertions.checkState(imaAdState != IMA_AD_STATE_NONE);
|
Assertions.checkState(imaAdState != IMA_AD_STATE_NONE);
|
||||||
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.
|
// TODO: Handle the skipped event so the ad can be marked as skipped rather than played.
|
||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
adPlaybackState.withPlayedAd(adGroupIndex, adIndexInAdGroup).withAdResumePositionUs(0);
|
adPlaybackState.withPlayedAd(adGroupIndex, adIndexInAdGroup).withAdResumePositionUs(0);
|
||||||
|
@ -372,7 +372,7 @@ import com.google.android.exoplayer2.util.Assertions;
|
|||||||
if (adGroupIndex == C.INDEX_UNSET) {
|
if (adGroupIndex == C.INDEX_UNSET) {
|
||||||
return new MediaPeriodId(periodIndex);
|
return new MediaPeriodId(periodIndex);
|
||||||
} else {
|
} else {
|
||||||
int adIndexInAdGroup = period.getNextAdIndexToPlay(adGroupIndex);
|
int adIndexInAdGroup = period.getFirstAdIndexToPlay(adGroupIndex);
|
||||||
return new MediaPeriodId(periodIndex, adGroupIndex, adIndexInAdGroup);
|
return new MediaPeriodId(periodIndex, adGroupIndex, adIndexInAdGroup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -496,19 +496,20 @@ import com.google.android.exoplayer2.util.Assertions;
|
|||||||
MediaPeriodId currentPeriodId = mediaPeriodInfo.id;
|
MediaPeriodId currentPeriodId = mediaPeriodInfo.id;
|
||||||
timeline.getPeriod(currentPeriodId.periodIndex, period);
|
timeline.getPeriod(currentPeriodId.periodIndex, period);
|
||||||
if (currentPeriodId.isAd()) {
|
if (currentPeriodId.isAd()) {
|
||||||
int currentAdGroupIndex = currentPeriodId.adGroupIndex;
|
int adGroupIndex = currentPeriodId.adGroupIndex;
|
||||||
int adCountInCurrentAdGroup = period.getAdCountInAdGroup(currentAdGroupIndex);
|
int adCountInCurrentAdGroup = period.getAdCountInAdGroup(adGroupIndex);
|
||||||
if (adCountInCurrentAdGroup == C.LENGTH_UNSET) {
|
if (adCountInCurrentAdGroup == C.LENGTH_UNSET) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
int nextAdIndexInAdGroup = currentPeriodId.adIndexInAdGroup + 1;
|
int nextAdIndexInAdGroup =
|
||||||
|
period.getNextAdIndexToPlay(adGroupIndex, currentPeriodId.adIndexInAdGroup);
|
||||||
if (nextAdIndexInAdGroup < adCountInCurrentAdGroup) {
|
if (nextAdIndexInAdGroup < adCountInCurrentAdGroup) {
|
||||||
// Play the next ad in the ad group if it's available.
|
// Play the next ad in the ad group if it's available.
|
||||||
return !period.isAdAvailable(currentAdGroupIndex, nextAdIndexInAdGroup)
|
return !period.isAdAvailable(adGroupIndex, nextAdIndexInAdGroup)
|
||||||
? null
|
? null
|
||||||
: getMediaPeriodInfoForAd(
|
: getMediaPeriodInfoForAd(
|
||||||
currentPeriodId.periodIndex,
|
currentPeriodId.periodIndex,
|
||||||
currentAdGroupIndex,
|
adGroupIndex,
|
||||||
nextAdIndexInAdGroup,
|
nextAdIndexInAdGroup,
|
||||||
mediaPeriodInfo.contentPositionUs);
|
mediaPeriodInfo.contentPositionUs);
|
||||||
} else {
|
} else {
|
||||||
@ -524,22 +525,32 @@ import com.google.android.exoplayer2.util.Assertions;
|
|||||||
return getMediaPeriodInfoForContent(
|
return getMediaPeriodInfoForContent(
|
||||||
currentPeriodId.periodIndex, mediaPeriodInfo.endPositionUs);
|
currentPeriodId.periodIndex, mediaPeriodInfo.endPositionUs);
|
||||||
}
|
}
|
||||||
return !period.isAdAvailable(nextAdGroupIndex, 0)
|
int adIndexInAdGroup = period.getFirstAdIndexToPlay(nextAdGroupIndex);
|
||||||
|
return !period.isAdAvailable(nextAdGroupIndex, adIndexInAdGroup)
|
||||||
? null
|
? null
|
||||||
: getMediaPeriodInfoForAd(
|
: getMediaPeriodInfoForAd(
|
||||||
currentPeriodId.periodIndex, nextAdGroupIndex, 0, mediaPeriodInfo.endPositionUs);
|
currentPeriodId.periodIndex,
|
||||||
|
nextAdGroupIndex,
|
||||||
|
adIndexInAdGroup,
|
||||||
|
mediaPeriodInfo.endPositionUs);
|
||||||
} 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();
|
||||||
if (adGroupCount == 0
|
if (adGroupCount == 0) {
|
||||||
|| period.getAdGroupTimeUs(adGroupCount - 1) != C.TIME_END_OF_SOURCE
|
return null;
|
||||||
|| period.hasPlayedAdGroup(adGroupCount - 1)
|
}
|
||||||
|| !period.isAdAvailable(adGroupCount - 1, 0)) {
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
long contentDurationUs = period.getDurationUs();
|
long contentDurationUs = period.getDurationUs();
|
||||||
return getMediaPeriodInfoForAd(
|
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)
|
.getPeriod(id.periodIndex, period)
|
||||||
.getAdDurationUs(id.adGroupIndex, id.adIndexInAdGroup);
|
.getAdDurationUs(id.adGroupIndex, id.adIndexInAdGroup);
|
||||||
long startPositionUs =
|
long startPositionUs =
|
||||||
adIndexInAdGroup == period.getNextAdIndexToPlay(adGroupIndex)
|
adIndexInAdGroup == period.getFirstAdIndexToPlay(adGroupIndex)
|
||||||
? period.getAdResumePositionUs()
|
? period.getAdResumePositionUs()
|
||||||
: 0;
|
: 0;
|
||||||
return new MediaPeriodInfo(
|
return new MediaPeriodInfo(
|
||||||
@ -636,7 +647,7 @@ import com.google.android.exoplayer2.util.Assertions;
|
|||||||
|
|
||||||
boolean isLastAd =
|
boolean isLastAd =
|
||||||
isAd && id.adGroupIndex == lastAdGroupIndex && id.adIndexInAdGroup == postrollAdCount - 1;
|
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) {
|
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
|
* Returns the index of the first ad in the specified ad group that should be played, or the
|
||||||
* the ad group if the ad group does not have any ads remaining to play.
|
* number of ads in the ad group if no ads should be played.
|
||||||
*
|
*
|
||||||
* @param adGroupIndex The ad group index.
|
* @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
|
* @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.
|
* if the ad group does not have any ads remaining to play.
|
||||||
*/
|
*/
|
||||||
public int getNextAdIndexToPlay(int adGroupIndex) {
|
public int getNextAdIndexToPlay(int adGroupIndex, int lastPlayedAdIndex) {
|
||||||
return adPlaybackState.adGroups[adGroupIndex].nextAdIndexToPlay;
|
return adPlaybackState.adGroups[adGroupIndex].getNextAdIndexToPlay(lastPlayedAdIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -400,7 +414,7 @@ public abstract class Timeline {
|
|||||||
*/
|
*/
|
||||||
public boolean hasPlayedAdGroup(int adGroupIndex) {
|
public boolean hasPlayedAdGroup(int adGroupIndex) {
|
||||||
AdPlaybackState.AdGroup adGroup = adPlaybackState.adGroups[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;
|
public final @AdState int[] states;
|
||||||
/** The durations of each ad in the ad group, in microseconds. */
|
/** The durations of each ad in the ad group, in microseconds. */
|
||||||
public final long[] durationsUs;
|
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. */
|
/** Creates a new ad group with an unspecified number of ads. */
|
||||||
public AdGroup() {
|
public AdGroup() {
|
||||||
@ -67,14 +65,30 @@ public final class AdPlaybackState {
|
|||||||
this.states = states;
|
this.states = states;
|
||||||
this.uris = uris;
|
this.uris = uris;
|
||||||
this.durationsUs = durationsUs;
|
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
|
if (states[nextAdIndexToPlay] == AD_STATE_UNAVAILABLE
|
||||||
|| states[nextAdIndexToPlay] == AD_STATE_AVAILABLE) {
|
|| states[nextAdIndexToPlay] == AD_STATE_AVAILABLE) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
nextAdIndexToPlay++;
|
||||||
}
|
}
|
||||||
this.nextAdIndexToPlay = nextAdIndexToPlay;
|
return nextAdIndexToPlay;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,29 +70,29 @@ public final class AdPlaybackStateTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInitialNextAdIndexToPlay() {
|
public void testGetFirstAdIndexToPlayIsZero() {
|
||||||
state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 3);
|
state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 3);
|
||||||
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, TEST_URI);
|
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, TEST_URI);
|
||||||
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 2, 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
|
@Test
|
||||||
public void testNextAdIndexToPlayWithPlayedAd() {
|
public void testGetFirstAdIndexToPlaySkipsPlayedAd() {
|
||||||
state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 3);
|
state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 3);
|
||||||
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, TEST_URI);
|
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, TEST_URI);
|
||||||
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 2, TEST_URI);
|
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 2, TEST_URI);
|
||||||
|
|
||||||
state = state.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0);
|
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[1]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE);
|
||||||
assertThat(state.adGroups[0].states[2]).isEqualTo(AdPlaybackState.AD_STATE_AVAILABLE);
|
assertThat(state.adGroups[0].states[2]).isEqualTo(AdPlaybackState.AD_STATE_AVAILABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNextAdIndexToPlaySkipsErrorAds() {
|
public void testGetFirstAdIndexToPlaySkipsErrorAds() {
|
||||||
state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 3);
|
state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 3);
|
||||||
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, TEST_URI);
|
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, TEST_URI);
|
||||||
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 2, 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.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0);
|
||||||
state = state.withAdLoadError(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1);
|
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
|
@Test
|
||||||
|
Loading…
x
Reference in New Issue
Block a user