Don't update the ad group count when releasing ImaAdsLoader

`ImaAdsLoader` clears its `AdPlaybackState` when it's released but this could
cause `AdsMediaSource` to look up information in the ad playback state that is
no longer in bounds.

Issue: #8693

#minor-release

PiperOrigin-RevId: 362556286
This commit is contained in:
andrewlewis 2021-03-12 18:53:46 +00:00 committed by Oliver Woodman
parent 7c8ab133e9
commit 93c9c7a072
4 changed files with 18 additions and 8 deletions

View File

@ -81,6 +81,9 @@
`DashMediaSource.Factory`.
* We don't currently support using platform extractors with
SmoothStreaming.
* IMA extension: fix error caused by `AdPlaybackState` ad group times being
cleared, which can occur if the `ImaAdsLoader` is released while an ad is
pending loading ([#8693](https://github.com/google/ExoPlayer/issues/8693)).
### 2.13.2 (2021-02-25)

View File

@ -411,7 +411,10 @@ import java.util.Map;
stopUpdatingAdProgress();
imaAdInfo = null;
pendingAdLoadError = null;
adPlaybackState = new AdPlaybackState(adsId);
// No more ads will play once the loader is released, so mark all ad groups as skipped.
for (int i = 0; i < adPlaybackState.adGroupCount; i++) {
adPlaybackState = adPlaybackState.withSkippedAdGroup(i);
}
updateAdPlaybackState();
}

View File

@ -56,7 +56,8 @@ public interface AdsLoader {
interface EventListener {
/**
* Called when the ad playback state has been updated.
* Called when the ad playback state has been updated. The number of {@link
* AdPlaybackState#adGroups ad groups} may not change after the first call.
*
* @param adPlaybackState The new ad playback state.
*/

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.source.ads;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import static com.google.android.exoplayer2.util.Assertions.checkState;
import android.net.Uri;
import android.os.Handler;
@ -290,6 +291,8 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
if (this.adPlaybackState == null) {
adMediaSourceHolders = new AdMediaSourceHolder[adPlaybackState.adGroupCount][];
Arrays.fill(adMediaSourceHolders, new AdMediaSourceHolder[0]);
} else {
checkState(adPlaybackState.adGroupCount == this.adPlaybackState.adGroupCount);
}
this.adPlaybackState = adPlaybackState;
maybeUpdateAdMediaSources();
@ -350,12 +353,12 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
private void maybeUpdateSourceInfo() {
@Nullable Timeline contentTimeline = this.contentTimeline;
if (adPlaybackState != null && contentTimeline != null) {
adPlaybackState = adPlaybackState.withAdDurationsUs(getAdDurationsUs());
Timeline timeline =
adPlaybackState.adGroupCount == 0
? contentTimeline
: new SinglePeriodAdTimeline(contentTimeline, adPlaybackState);
refreshSourceInfo(timeline);
if (adPlaybackState.adGroupCount == 0) {
refreshSourceInfo(contentTimeline);
} else {
adPlaybackState = adPlaybackState.withAdDurationsUs(getAdDurationsUs());
refreshSourceInfo(new SinglePeriodAdTimeline(contentTimeline, adPlaybackState));
}
}
}