Defer adsManager.init until the timeline has loaded

If the app seeks after we get an ads manager but before the player exposes the
timeline with ads, we would end up expecting to play a preroll even after the
seek request arrived. This caused the player to get stuck.

Wait until a non-empty timeline has been exposed via onTimelineChanged before
initializing IMA (at which point it can start polling the player position). Seek
requests are not handled while an ad is playing.

PiperOrigin-RevId: 265058325
This commit is contained in:
andrewlewis 2019-08-23 16:16:07 +01:00 committed by Oliver Woodman
parent 7cefb56eda
commit 0085a7e761
2 changed files with 14 additions and 9 deletions

View File

@ -338,6 +338,7 @@ public final class ImaAdsLoader
private int lastVolumePercentage;
private AdsManager adsManager;
private boolean initializedAdsManager;
private AdLoadException pendingAdLoadError;
private Timeline timeline;
private long contentDurationMs;
@ -613,8 +614,8 @@ public final class ImaAdsLoader
adsManager.resume();
}
} else if (adsManager != null) {
// Ads have loaded but the ads manager is not initialized.
startAdPlayback();
adPlaybackState = new AdPlaybackState(getAdGroupTimesUs(adsManager.getAdCuePoints()));
updateAdPlaybackState();
} else {
// Ads haven't loaded yet, so request them.
requestAds(adViewGroup);
@ -688,7 +689,8 @@ public final class ImaAdsLoader
if (player != null) {
// If a player is attached already, start playback immediately.
try {
startAdPlayback();
adPlaybackState = new AdPlaybackState(getAdGroupTimesUs(adsManager.getAdCuePoints()));
updateAdPlaybackState();
} catch (Exception e) {
maybeNotifyInternalError("onAdsManagerLoaded", e);
}
@ -968,6 +970,10 @@ public final class ImaAdsLoader
if (contentDurationUs != C.TIME_UNSET) {
adPlaybackState = adPlaybackState.withContentDurationUs(contentDurationUs);
}
if (!initializedAdsManager && adsManager != null) {
initializedAdsManager = true;
initializeAdsManager();
}
onPositionDiscontinuity(Player.DISCONTINUITY_REASON_INTERNAL);
}
@ -1041,7 +1047,7 @@ public final class ImaAdsLoader
// Internal methods.
private void startAdPlayback() {
private void initializeAdsManager() {
AdsRenderingSettings adsRenderingSettings = imaFactory.createAdsRenderingSettings();
adsRenderingSettings.setEnablePreloading(ENABLE_PRELOADING);
adsRenderingSettings.setMimeTypes(supportedMimeTypes);
@ -1056,10 +1062,9 @@ public final class ImaAdsLoader
adsRenderingSettings.setUiElements(adUiElements);
}
// Set up the ad playback state, skipping ads based on the start position as required.
// Skip ads based on the start position as required.
long[] adGroupTimesUs = getAdGroupTimesUs(adsManager.getAdCuePoints());
adPlaybackState = new AdPlaybackState(adGroupTimesUs);
long contentPositionMs = player.getCurrentPosition();
long contentPositionMs = player.getContentPosition();
int adGroupIndexForPosition =
adPlaybackState.getAdGroupIndexForPositionUs(C.msToUs(contentPositionMs));
if (adGroupIndexForPosition > 0 && adGroupIndexForPosition != C.INDEX_UNSET) {
@ -1093,7 +1098,6 @@ public final class ImaAdsLoader
pendingContentPositionMs = contentPositionMs;
}
// Start ad playback.
adsManager.init(adsRenderingSettings);
updateAdPlaybackState();
if (DEBUG) {

View File

@ -143,7 +143,8 @@ public class ImaAdsLoaderTest {
assertThat(adsLoaderListener.adPlaybackState)
.isEqualTo(
new AdPlaybackState(/* adGroupTimesUs= */ 0)
.withAdDurationsUs(PREROLL_ADS_DURATIONS_US));
.withAdDurationsUs(PREROLL_ADS_DURATIONS_US)
.withContentDurationUs(CONTENT_DURATION_US));
}
@Test