From 6197a712ff87e844d6374a82d43e63ef9723acd1 Mon Sep 17 00:00:00 2001 From: bachinger Date: Mon, 14 Feb 2022 11:47:20 +0000 Subject: [PATCH] Use content timeline to get ad group index and ad index in ad group The timeline used to map ad groups to periods needs to report the original content period duration without subtracting the serverside inserted ad duration. When marking played ads in onPositionDiscontinuity, the public timeline has been used which crashed the app when the ads media source is playing on a window index different to zero (in a playlist). #minor-release PiperOrigin-RevId: 428465833 --- .../ima/ImaServerSideAdInsertionMediaSource.java | 6 +++++- .../main/java/androidx/media3/exoplayer/ima/ImaUtil.java | 8 ++++---- 2 files changed, 9 insertions(+), 5 deletions(-) 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 c9c90372c2..a2421ecbca 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 @@ -93,6 +93,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.checkerframework.checker.nullness.qual.EnsuresNonNull; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** @@ -476,6 +477,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou } @MainThread + @EnsuresNonNull("contentTimeline") private void setContentTimeline(Timeline contentTimeline) { if (contentTimeline.equals(this.contentTimeline)) { return; @@ -640,7 +642,9 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou // Map adGroupIndex and adIndexInAdGroup to multi-period window. Pair adGroupIndexAndAdIndexInAdGroup = getAdGroupAndIndexInMultiPeriodWindow( - oldPosition.periodIndex, adPlaybackState, timeline); + oldPosition.periodIndex - window.firstPeriodIndex, + adPlaybackState, + checkNotNull(contentTimeline)); adGroupIndex = adGroupIndexAndAdIndexInAdGroup.first; adIndexInAdGroup = adGroupIndexAndAdIndexInAdGroup.second; } diff --git a/libraries/exoplayer_ima/src/main/java/androidx/media3/exoplayer/ima/ImaUtil.java b/libraries/exoplayer_ima/src/main/java/androidx/media3/exoplayer/ima/ImaUtil.java index 5304fa637f..cede70d9cb 100644 --- a/libraries/exoplayer_ima/src/main/java/androidx/media3/exoplayer/ima/ImaUtil.java +++ b/libraries/exoplayer_ima/src/main/java/androidx/media3/exoplayer/ima/ImaUtil.java @@ -475,11 +475,11 @@ import java.util.Set; * * @param adPeriodIndex The period index of the ad period. * @param adPlaybackState The ad playback state that holds the ad group and ad information. - * @param timeline The timeline that contains the ad period. + * @param contentTimeline The timeline that contains the ad period. * @return A pair with the ad group index (first) and the ad index in that ad group (second). */ public static Pair getAdGroupAndIndexInMultiPeriodWindow( - int adPeriodIndex, AdPlaybackState adPlaybackState, Timeline timeline) { + int adPeriodIndex, AdPlaybackState adPlaybackState, Timeline contentTimeline) { Timeline.Period period = new Timeline.Period(); int periodIndex = 0; long totalElapsedContentDurationUs = 0; @@ -488,8 +488,8 @@ import java.util.Set; AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(/* adGroupIndex= */ i); long adGroupDurationUs = sum(adGroup.durationsUs); long elapsedAdGroupAdDurationUs = 0; - for (int j = periodIndex; j < timeline.getPeriodCount(); j++) { - timeline.getPeriod(j, period, /* setIds= */ true); + for (int j = periodIndex; j < contentTimeline.getPeriodCount(); j++) { + contentTimeline.getPeriod(j, period, /* setIds= */ true); // TODO(b/192231683) Remove subtracted US from ad group time when we can upgrade the SDK. // Subtract one microsecond to work around rounding errors with adGroup.timeUs. if (totalElapsedContentDurationUs < adGroup.timeUs - 1) {