diff --git a/RELEASENOTES.md b/RELEASENOTES.md index e268181b66..7b002474ff 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -218,6 +218,8 @@ * Fix a bug that caused playback to be stuck buffering on resuming from the background after all ads had played to the end ([#7508](https://github.com/google/ExoPlayer/issues/7508)). + * Fix a bug where the number of ads in an ad group couldn't change + ([#7477](https://github.com/google/ExoPlayer/issues/7477)). * Demo app: Retain previous position in list of samples. * Add Guava dependency. diff --git a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java index 98718752bf..454f9513e9 100644 --- a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java +++ b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java @@ -1485,6 +1485,7 @@ public final class ImaAdsLoader implements Player.EventListener, AdsLoader { // Drop events after release. return; } + int adGroupIndex = getAdGroupIndexForAdPod(adPodInfo); int adIndexInAdGroup = adPodInfo.getAdPosition() - 1; AdInfo adInfo = new AdInfo(adGroupIndex, adIndexInAdGroup); @@ -1494,21 +1495,23 @@ public final class ImaAdsLoader implements Player.EventListener, AdsLoader { // will timeout after its media load timeout. return; } + + // The ad count may increase on successive loads of ads in the same ad pod, for example, due + // to separate requests for ad tags with multiple ads within the ad pod completing after an + // earlier ad has loaded. See also https://github.com/google/ExoPlayer/issues/7477. AdPlaybackState.AdGroup adGroup = adPlaybackState.adGroups[adInfo.adGroupIndex]; - if (adGroup.count == C.LENGTH_UNSET) { - adPlaybackState = - adPlaybackState.withAdCount( - adInfo.adGroupIndex, Math.max(adPodInfo.getTotalAds(), adGroup.states.length)); - adGroup = adPlaybackState.adGroups[adInfo.adGroupIndex]; - } + adPlaybackState = + adPlaybackState.withAdCount( + adInfo.adGroupIndex, Math.max(adPodInfo.getTotalAds(), adGroup.states.length)); + adGroup = adPlaybackState.adGroups[adInfo.adGroupIndex]; for (int i = 0; i < adIndexInAdGroup; i++) { // Any preceding ads that haven't loaded are not going to load. if (adGroup.states[i] == AdPlaybackState.AD_STATE_UNAVAILABLE) { adPlaybackState = - adPlaybackState.withAdLoadError( - /* adGroupIndex= */ adGroupIndex, /* adIndexInAdGroup= */ i); + adPlaybackState.withAdLoadError(adGroupIndex, /* adIndexInAdGroup= */ i); } } + Uri adUri = Uri.parse(adMediaInfo.getUrl()); adPlaybackState = adPlaybackState.withAdUri(adInfo.adGroupIndex, adInfo.adIndexInAdGroup, adUri); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdPlaybackState.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdPlaybackState.java index d56c4eefac..70128c78bf 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdPlaybackState.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdPlaybackState.java @@ -124,13 +124,9 @@ public final class AdPlaybackState { return result; } - /** - * Returns a new instance with the ad count set to {@code count}. This method may only be called - * if this instance's ad count has not yet been specified. - */ + /** Returns a new instance with the ad count set to {@code count}. */ @CheckResult public AdGroup withAdCount(int count) { - Assertions.checkArgument(this.count == C.LENGTH_UNSET && states.length <= count); @AdState int[] states = copyStatesWithSpaceForAdCount(this.states, count); long[] durationsUs = copyDurationsUsWithSpaceForAdCount(this.durationsUs, count); @NullableType Uri[] uris = Arrays.copyOf(this.uris, count); @@ -139,17 +135,11 @@ public final class AdPlaybackState { /** * Returns a new instance with the specified {@code uri} set for the specified ad, and the ad - * marked as {@link #AD_STATE_AVAILABLE}. The specified ad must currently be in {@link - * #AD_STATE_UNAVAILABLE}, which is the default state. - * - *
This instance's ad count may be unknown, in which case {@code index} must be less than the - * ad count specified later. Otherwise, {@code index} must be less than the current ad count. + * marked as {@link #AD_STATE_AVAILABLE}. */ @CheckResult public AdGroup withAdUri(Uri uri, int index) { - Assertions.checkArgument(count == C.LENGTH_UNSET || index < count); @AdState int[] states = copyStatesWithSpaceForAdCount(this.states, index + 1); - Assertions.checkArgument(states[index] == AD_STATE_UNAVAILABLE); long[] durationsUs = this.durationsUs.length == states.length ? this.durationsUs