diff --git a/RELEASENOTES.md b/RELEASENOTES.md index e281a7d987..0d7c8057f5 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -82,6 +82,9 @@ * Effect: * Muxers: * IMA extension: + * Fix bug where server-side inserted DAI streams without a preroll can + result in an `ArrayIndexOutOfBoundsException` when playing past the last + midroll ([#1741](https://github.com/androidx/media/issues/1741)). * Session: * Fix bug that caused custom commands sent from a `MediaBrowser` being dispatched to the `MediaSessionCompat.Callback` instead of the diff --git a/libraries/exoplayer_ima/src/main/java/androidx/media3/exoplayer/ima/ImaServerSideAdInsertionMediaSource.java b/libraries/exoplayer_ima/src/main/java/androidx/media3/exoplayer/ima/ImaServerSideAdInsertionMediaSource.java index f823a8e78e..facbc90f27 100644 --- a/libraries/exoplayer_ima/src/main/java/androidx/media3/exoplayer/ima/ImaServerSideAdInsertionMediaSource.java +++ b/libraries/exoplayer_ima/src/main/java/androidx/media3/exoplayer/ima/ImaServerSideAdInsertionMediaSource.java @@ -897,9 +897,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou private static AdPlaybackState setVodAdInPlaceholder(Ad ad, AdPlaybackState adPlaybackState) { AdPodInfo adPodInfo = ad.getAdPodInfo(); - // Handle post rolls that have a podIndex of -1. - int adGroupIndex = - adPodInfo.getPodIndex() == -1 ? adPlaybackState.adGroupCount - 1 : adPodInfo.getPodIndex(); + int adGroupIndex = getAdGroupIndexFromAdPodInfo(adPodInfo, adPlaybackState); AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(adGroupIndex); int adIndexInAdGroup = adPodInfo.getAdPosition() - 1; if (adGroup.count < adPodInfo.getTotalAds()) { @@ -924,12 +922,27 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou private static AdPlaybackState skipAd(Ad ad, AdPlaybackState adPlaybackState) { AdPodInfo adPodInfo = ad.getAdPodInfo(); - int adGroupIndex = adPodInfo.getPodIndex(); + int adGroupIndex = getAdGroupIndexFromAdPodInfo(adPodInfo, adPlaybackState); // IMA SDK always returns index starting at 1. int adIndexInAdGroup = adPodInfo.getAdPosition() - 1; return adPlaybackState.withSkippedAd(adGroupIndex, adIndexInAdGroup); } + private static int getAdGroupIndexFromAdPodInfo( + AdPodInfo adPodInfo, AdPlaybackState adPlaybackState) { + int adPodIndex = adPodInfo.getPodIndex(); + if (adPodIndex == -1) { + // Post-roll + return adPlaybackState.adGroupCount - 1; + } + if (adPlaybackState.getAdGroup(0).timeUs == 0) { + // When a pre-roll exists, the index starts at zero. + return adPodIndex; + } + // Mid-rolls always start at 1. + return adPodIndex - 1; + } + private final class ComponentListener implements AdEvent.AdEventListener, Player.Listener, AdPlaybackStateUpdater {