diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 2f6b60f65d4..b20946d0003 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -97,6 +97,8 @@ ([#3676](https://github.com/google/ExoPlayer/issues/3676)). * Fix handling of ad tags where ad groups are out of order ([#3716](https://github.com/google/ExoPlayer/issues/3716)). + * Fix handling of ad tags with only preroll/postroll ad groups + ([#3715](https://github.com/google/ExoPlayer/issues/3715)). * Propagate ad media preparation errors to IMA so that the ads can be skipped. * `EventLogger` moved from the demo app into the core library. 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 d11bc920e18..0a79acb6179 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 @@ -851,15 +851,14 @@ private void startAdPlayback() { adsRenderingSettings.setMimeTypes(supportedMimeTypes); // Set up the ad playback state, skipping ads based on the start position as required. - pendingContentPositionMs = player.getCurrentPosition(); long[] adGroupTimesUs = getAdGroupTimesUs(adsManager.getAdCuePoints()); adPlaybackState = new AdPlaybackState(adGroupTimesUs); + long contentPositionMs = player.getCurrentPosition(); int adGroupIndexForPosition = - adPlaybackState.getAdGroupIndexForPositionUs(C.msToUs(pendingContentPositionMs)); + adPlaybackState.getAdGroupIndexForPositionUs(C.msToUs(contentPositionMs)); if (adGroupIndexForPosition == 0) { podIndexOffset = 0; } else if (adGroupIndexForPosition == C.INDEX_UNSET) { - pendingContentPositionMs = C.TIME_UNSET; // There is no preroll and midroll pod indices start at 1. podIndexOffset = -1; } else /* adGroupIndexForPosition > 0 */ { @@ -879,6 +878,11 @@ private void startAdPlayback() { podIndexOffset = adGroupIndexForPosition - 1; } + if (hasMidrollAdGroups(adGroupTimesUs)) { + // IMA will poll the content position, so provide the player's initial position like a seek. + pendingContentPositionMs = contentPositionMs; + } + // Start ad playback. adsManager.init(adsRenderingSettings); updateAdPlaybackState(); @@ -1051,4 +1055,16 @@ private static boolean isAdGroupLoadError(AdError adError) { // a single ad, ad group or the whole timeline. return adError.getErrorCode() == AdErrorCode.VAST_LINEAR_ASSET_MISMATCH; } + + private static boolean hasMidrollAdGroups(long[] adGroupTimesUs) { + int count = adGroupTimesUs.length; + if (count == 1) { + return adGroupTimesUs[0] != 0 && adGroupTimesUs[0] != C.TIME_END_OF_SOURCE; + } else if (count == 2) { + return adGroupTimesUs[0] != 0 || adGroupTimesUs[1] != C.TIME_END_OF_SOURCE; + } else { + // There's at least one midroll ad group, as adGroupTimesUs is never empty. + return true; + } + } }