From a92e48e5f88360deb0f331326ff0f75ecf7d78d2 Mon Sep 17 00:00:00 2001 From: bachinger Date: Tue, 7 Dec 2021 21:02:24 +0000 Subject: [PATCH] Support IMA DAI streams for HLS PiperOrigin-RevId: 414804513 --- .../android/exoplayer2/ext/ima/ImaUtil.java | 36 +++++++++---------- .../google/android/exoplayer2/util/Util.java | 12 +++++++ .../source/ads/ServerSideAdInsertionUtil.java | 29 +++++++++------ 3 files changed, 48 insertions(+), 29 deletions(-) diff --git a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaUtil.java b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaUtil.java index 9a40ba74de..b750df3625 100644 --- a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaUtil.java +++ b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaUtil.java @@ -37,6 +37,7 @@ import com.google.ads.interactivemedia.v3.api.player.VideoAdPlayer; import com.google.ads.interactivemedia.v3.api.player.VideoProgressUpdate; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ui.AdOverlayInfo; +import com.google.android.exoplayer2.ui.AdViewProvider; import com.google.android.exoplayer2.upstream.DataSchemeDataSource; import com.google.android.exoplayer2.upstream.DataSourceUtil; import com.google.android.exoplayer2.upstream.DataSpec; @@ -135,31 +136,28 @@ import java.util.Set; } } - /** Stores configuration for DAI ad playback. */ - static final class DaiConfiguration { + /** Stores configuration for playing server side ad insertion content. */ + public static final class ServerSideAdInsertionConfiguration { - public final AdErrorEvent.AdErrorListener applicationAdErrorListener; + public final AdViewProvider adViewProvider; + public final ImaSdkSettings imaSdkSettings; + @Nullable public final AdEvent.AdEventListener applicationAdEventListener; + @Nullable public final AdErrorEvent.AdErrorListener applicationAdErrorListener; + public final ImmutableList companionAdSlots; public final boolean debugModeEnabled; - @Nullable public final List companionAdSlots; - @Nullable public final AdEvent.AdEventListener applicationAdEventListener; - @Nullable public final VideoAdPlayer.VideoAdPlayerCallback applicationVideoAdPlayerCallback; - @Nullable public final ImaSdkSettings imaSdkSettings; - - public DaiConfiguration( - AdErrorEvent.AdErrorListener applicationAdErrorListener, - @Nullable List companionAdSlots, + public ServerSideAdInsertionConfiguration( + AdViewProvider adViewProvider, + ImaSdkSettings imaSdkSettings, @Nullable AdEvent.AdEventListener applicationAdEventListener, - @Nullable VideoAdPlayer.VideoAdPlayerCallback applicationVideoAdPlayerCallback, - @Nullable ImaSdkSettings imaSdkSettings, + @Nullable AdErrorEvent.AdErrorListener applicationAdErrorListener, + List companionAdSlots, boolean debugModeEnabled) { - - this.applicationAdErrorListener = applicationAdErrorListener; - this.companionAdSlots = - companionAdSlots != null ? ImmutableList.copyOf(companionAdSlots) : null; - this.applicationAdEventListener = applicationAdEventListener; - this.applicationVideoAdPlayerCallback = applicationVideoAdPlayerCallback; this.imaSdkSettings = imaSdkSettings; + this.adViewProvider = adViewProvider; + this.applicationAdEventListener = applicationAdEventListener; + this.applicationAdErrorListener = applicationAdErrorListener; + this.companionAdSlots = ImmutableList.copyOf(companionAdSlots); this.debugModeEnabled = debugModeEnabled; } } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java b/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java index b7678d35e0..9dad181b91 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java @@ -1141,6 +1141,18 @@ public final class Util { return (timeMs == C.TIME_UNSET || timeMs == C.TIME_END_OF_SOURCE) ? timeMs : (timeMs * 1000); } + /** + * Converts a time in seconds to the corresponding time in microseconds. + * + * @param timeSec The time in seconds. + * @return The corresponding time in microseconds. + */ + public static long secToUs(double timeSec) { + return BigDecimal.valueOf(timeSec) + .multiply(BigDecimal.valueOf(C.MICROS_PER_SECOND)) + .longValue(); + } + /** * Parses an xs:duration attribute value, returning the parsed duration in milliseconds. * diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/ServerSideAdInsertionUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/ServerSideAdInsertionUtil.java index 9b4d4710f9..d7609848af 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/ServerSideAdInsertionUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/ServerSideAdInsertionUtil.java @@ -67,16 +67,8 @@ public final class ServerSideAdInsertionUtil { .withAdCount(insertionIndex, /* adCount= */ 1) .withAdDurationsUs(insertionIndex, adDurationUs) .withContentResumeOffsetUs(insertionIndex, contentResumeOffsetUs); - long followingAdGroupTimeUsOffset = -adDurationUs + contentResumeOffsetUs; - for (int i = insertionIndex + 1; i < adPlaybackState.adGroupCount; i++) { - long adGroupTimeUs = adPlaybackState.getAdGroup(i).timeUs; - if (adGroupTimeUs != C.TIME_END_OF_SOURCE) { - adPlaybackState = - adPlaybackState.withAdGroupTimeUs( - /* adGroupIndex= */ i, adGroupTimeUs + followingAdGroupTimeUsOffset); - } - } - return adPlaybackState; + return correctFollowingAdGroupTimes( + adPlaybackState, insertionIndex, adDurationUs, contentResumeOffsetUs); } /** @@ -314,4 +306,21 @@ public final class ServerSideAdInsertionUtil { AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(adGroupIndex); return adGroup.count == C.LENGTH_UNSET ? 0 : adGroup.count; } + + private static AdPlaybackState correctFollowingAdGroupTimes( + AdPlaybackState adPlaybackState, + int adGroupInsertionIndex, + long insertedAdDurationUs, + long addedContentResumeOffsetUs) { + long followingAdGroupTimeUsOffset = -insertedAdDurationUs + addedContentResumeOffsetUs; + for (int i = adGroupInsertionIndex + 1; i < adPlaybackState.adGroupCount; i++) { + long adGroupTimeUs = adPlaybackState.getAdGroup(i).timeUs; + if (adGroupTimeUs != C.TIME_END_OF_SOURCE) { + adPlaybackState = + adPlaybackState.withAdGroupTimeUs( + /* adGroupIndex= */ i, adGroupTimeUs + followingAdGroupTimeUsOffset); + } + } + return adPlaybackState; + } }