mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Enable nullness checking for the IMA extension
adPlaybackState is now non-null, and the uninitialized case is covered by a new boolean hasAdPlaybackState. Position progress updates are now non-null and initialized with IMA's VIDEO_TIME_NOT_READY constant. Also fix some misc code issues: - Remove empty branch for SmoothStreaming (Android Studio warns about this). - Tidy onTimelineChanged and onPositionDiscontinuity and the methods they call to improve naming. - Remove logging for IMA events after release, as these methods are expected to be called in the current IMA SDK behavior. PiperOrigin-RevId: 308977116
This commit is contained in:
parent
dcbdbe5341
commit
625c734726
2 changed files with 68 additions and 56 deletions
|
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.ext.ima;
|
package com.google.android.exoplayer2.ext.ima;
|
||||||
|
|
||||||
|
import static com.google.android.exoplayer2.util.Util.castNonNull;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
|
@ -282,7 +284,7 @@ public final class ImaAdsLoader
|
||||||
* Threshold before the end of content at which IMA is notified that content is complete if the
|
* Threshold before the end of content at which IMA is notified that content is complete if the
|
||||||
* player buffers, in milliseconds.
|
* player buffers, in milliseconds.
|
||||||
*/
|
*/
|
||||||
private static final long END_OF_CONTENT_POSITION_THRESHOLD_MS = 5000;
|
private static final long END_OF_CONTENT_THRESHOLD_MS = 5000;
|
||||||
|
|
||||||
/** The maximum duration before an ad break that IMA may start preloading the next ad. */
|
/** The maximum duration before an ad break that IMA may start preloading the next ad. */
|
||||||
private static final long MAXIMUM_PRELOAD_DURATION_MS = 8000;
|
private static final long MAXIMUM_PRELOAD_DURATION_MS = 8000;
|
||||||
|
|
@ -324,7 +326,7 @@ public final class ImaAdsLoader
|
||||||
|
|
||||||
private boolean wasSetPlayerCalled;
|
private boolean wasSetPlayerCalled;
|
||||||
@Nullable private Player nextPlayer;
|
@Nullable private Player nextPlayer;
|
||||||
private Object pendingAdRequestContext;
|
@Nullable private Object pendingAdRequestContext;
|
||||||
private List<String> supportedMimeTypes;
|
private List<String> supportedMimeTypes;
|
||||||
@Nullable private EventListener eventListener;
|
@Nullable private EventListener eventListener;
|
||||||
@Nullable private Player player;
|
@Nullable private Player player;
|
||||||
|
|
@ -334,7 +336,8 @@ public final class ImaAdsLoader
|
||||||
|
|
||||||
@Nullable private AdsManager adsManager;
|
@Nullable private AdsManager adsManager;
|
||||||
private boolean initializedAdsManager;
|
private boolean initializedAdsManager;
|
||||||
private AdLoadException pendingAdLoadError;
|
private boolean hasAdPlaybackState;
|
||||||
|
@Nullable private AdLoadException pendingAdLoadError;
|
||||||
private Timeline timeline;
|
private Timeline timeline;
|
||||||
private long contentDurationMs;
|
private long contentDurationMs;
|
||||||
private int podIndexOffset;
|
private int podIndexOffset;
|
||||||
|
|
@ -438,6 +441,7 @@ public final class ImaAdsLoader
|
||||||
/* imaFactory= */ new DefaultImaFactory());
|
/* imaFactory= */ new DefaultImaFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("nullness:argument.type.incompatible")
|
||||||
private ImaAdsLoader(
|
private ImaAdsLoader(
|
||||||
Context context,
|
Context context,
|
||||||
@Nullable Uri adTagUri,
|
@Nullable Uri adTagUri,
|
||||||
|
|
@ -477,12 +481,16 @@ public final class ImaAdsLoader
|
||||||
context.getApplicationContext(), imaSdkSettings, adDisplayContainer);
|
context.getApplicationContext(), imaSdkSettings, adDisplayContainer);
|
||||||
adsLoader.addAdErrorListener(/* adErrorListener= */ this);
|
adsLoader.addAdErrorListener(/* adErrorListener= */ this);
|
||||||
adsLoader.addAdsLoadedListener(/* adsLoadedListener= */ this);
|
adsLoader.addAdsLoadedListener(/* adsLoadedListener= */ this);
|
||||||
|
supportedMimeTypes = Collections.emptyList();
|
||||||
|
lastContentProgress = VideoProgressUpdate.VIDEO_TIME_NOT_READY;
|
||||||
|
lastAdProgress = VideoProgressUpdate.VIDEO_TIME_NOT_READY;
|
||||||
fakeContentProgressElapsedRealtimeMs = C.TIME_UNSET;
|
fakeContentProgressElapsedRealtimeMs = C.TIME_UNSET;
|
||||||
fakeContentProgressOffsetMs = C.TIME_UNSET;
|
fakeContentProgressOffsetMs = C.TIME_UNSET;
|
||||||
pendingContentPositionMs = C.TIME_UNSET;
|
pendingContentPositionMs = C.TIME_UNSET;
|
||||||
adGroupIndex = C.INDEX_UNSET;
|
adGroupIndex = C.INDEX_UNSET;
|
||||||
contentDurationMs = C.TIME_UNSET;
|
contentDurationMs = C.TIME_UNSET;
|
||||||
timeline = Timeline.EMPTY;
|
timeline = Timeline.EMPTY;
|
||||||
|
adPlaybackState = AdPlaybackState.NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -530,22 +538,22 @@ public final class ImaAdsLoader
|
||||||
* @param adViewGroup A {@link ViewGroup} on top of the player that will show any ad UI.
|
* @param adViewGroup A {@link ViewGroup} on top of the player that will show any ad UI.
|
||||||
*/
|
*/
|
||||||
public void requestAds(ViewGroup adViewGroup) {
|
public void requestAds(ViewGroup adViewGroup) {
|
||||||
if (adPlaybackState != null || adsManager != null || pendingAdRequestContext != null) {
|
if (hasAdPlaybackState || adsManager != null || pendingAdRequestContext != null) {
|
||||||
// Ads have already been requested.
|
// Ads have already been requested.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
adDisplayContainer.setAdContainer(adViewGroup);
|
adDisplayContainer.setAdContainer(adViewGroup);
|
||||||
pendingAdRequestContext = new Object();
|
|
||||||
AdsRequest request = imaFactory.createAdsRequest();
|
AdsRequest request = imaFactory.createAdsRequest();
|
||||||
if (adTagUri != null) {
|
if (adTagUri != null) {
|
||||||
request.setAdTagUrl(adTagUri.toString());
|
request.setAdTagUrl(adTagUri.toString());
|
||||||
} else /* adsResponse != null */ {
|
} else {
|
||||||
request.setAdsResponse(adsResponse);
|
request.setAdsResponse(castNonNull(adsResponse));
|
||||||
}
|
}
|
||||||
if (vastLoadTimeoutMs != TIMEOUT_UNSET) {
|
if (vastLoadTimeoutMs != TIMEOUT_UNSET) {
|
||||||
request.setVastLoadTimeout(vastLoadTimeoutMs);
|
request.setVastLoadTimeout(vastLoadTimeoutMs);
|
||||||
}
|
}
|
||||||
request.setContentProgressProvider(this);
|
request.setContentProgressProvider(this);
|
||||||
|
pendingAdRequestContext = new Object();
|
||||||
request.setUserRequestContext(pendingAdRequestContext);
|
request.setUserRequestContext(pendingAdRequestContext);
|
||||||
adsLoader.requestAds(request);
|
adsLoader.requestAds(request);
|
||||||
}
|
}
|
||||||
|
|
@ -565,6 +573,7 @@ public final class ImaAdsLoader
|
||||||
public void setSupportedContentTypes(@C.ContentType int... contentTypes) {
|
public void setSupportedContentTypes(@C.ContentType int... contentTypes) {
|
||||||
List<String> supportedMimeTypes = new ArrayList<>();
|
List<String> supportedMimeTypes = new ArrayList<>();
|
||||||
for (@C.ContentType int contentType : contentTypes) {
|
for (@C.ContentType int contentType : contentTypes) {
|
||||||
|
// IMA does not support Smooth Streaming ad media.
|
||||||
if (contentType == C.TYPE_DASH) {
|
if (contentType == C.TYPE_DASH) {
|
||||||
supportedMimeTypes.add(MimeTypes.APPLICATION_MPD);
|
supportedMimeTypes.add(MimeTypes.APPLICATION_MPD);
|
||||||
} else if (contentType == C.TYPE_HLS) {
|
} else if (contentType == C.TYPE_HLS) {
|
||||||
|
|
@ -577,8 +586,6 @@ public final class ImaAdsLoader
|
||||||
MimeTypes.VIDEO_H263,
|
MimeTypes.VIDEO_H263,
|
||||||
MimeTypes.AUDIO_MP4,
|
MimeTypes.AUDIO_MP4,
|
||||||
MimeTypes.AUDIO_MPEG));
|
MimeTypes.AUDIO_MPEG));
|
||||||
} else if (contentType == C.TYPE_SS) {
|
|
||||||
// IMA does not support Smooth Streaming ad media.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.supportedMimeTypes = Collections.unmodifiableList(supportedMimeTypes);
|
this.supportedMimeTypes = Collections.unmodifiableList(supportedMimeTypes);
|
||||||
|
|
@ -592,22 +599,23 @@ public final class ImaAdsLoader
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
player.addListener(this);
|
||||||
|
boolean playWhenReady = player.getPlayWhenReady();
|
||||||
this.eventListener = eventListener;
|
this.eventListener = eventListener;
|
||||||
lastVolumePercentage = 0;
|
lastVolumePercentage = 0;
|
||||||
lastAdProgress = null;
|
lastAdProgress = VideoProgressUpdate.VIDEO_TIME_NOT_READY;
|
||||||
lastContentProgress = null;
|
lastContentProgress = VideoProgressUpdate.VIDEO_TIME_NOT_READY;
|
||||||
ViewGroup adViewGroup = adViewProvider.getAdViewGroup();
|
ViewGroup adViewGroup = adViewProvider.getAdViewGroup();
|
||||||
adDisplayContainer.setAdContainer(adViewGroup);
|
adDisplayContainer.setAdContainer(adViewGroup);
|
||||||
View[] adOverlayViews = adViewProvider.getAdOverlayViews();
|
View[] adOverlayViews = adViewProvider.getAdOverlayViews();
|
||||||
for (View view : adOverlayViews) {
|
for (View view : adOverlayViews) {
|
||||||
adDisplayContainer.registerVideoControlsOverlay(view);
|
adDisplayContainer.registerVideoControlsOverlay(view);
|
||||||
}
|
}
|
||||||
player.addListener(this);
|
|
||||||
maybeNotifyPendingAdLoadError();
|
maybeNotifyPendingAdLoadError();
|
||||||
if (adPlaybackState != null) {
|
if (hasAdPlaybackState) {
|
||||||
// Pass the ad playback state to the player, and resume ads if necessary.
|
// Pass the ad playback state to the player, and resume ads if necessary.
|
||||||
eventListener.onAdPlaybackState(adPlaybackState);
|
eventListener.onAdPlaybackState(adPlaybackState);
|
||||||
if (imaPausedContent && player.getPlayWhenReady()) {
|
if (adsManager != null && imaPausedContent && playWhenReady) {
|
||||||
adsManager.resume();
|
adsManager.resume();
|
||||||
}
|
}
|
||||||
} else if (adsManager != null) {
|
} else if (adsManager != null) {
|
||||||
|
|
@ -621,21 +629,22 @@ public final class ImaAdsLoader
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
|
@Nullable Player player = this.player;
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (adsManager != null && imaPausedContent) {
|
if (adsManager != null && imaPausedContent) {
|
||||||
|
adsManager.pause();
|
||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
adPlaybackState.withAdResumePositionUs(
|
adPlaybackState.withAdResumePositionUs(
|
||||||
playingAd ? C.msToUs(player.getCurrentPosition()) : 0);
|
playingAd ? C.msToUs(player.getCurrentPosition()) : 0);
|
||||||
adsManager.pause();
|
|
||||||
}
|
}
|
||||||
lastVolumePercentage = getVolume();
|
lastVolumePercentage = getVolume();
|
||||||
lastAdProgress = getAdProgress();
|
lastAdProgress = getAdProgress();
|
||||||
lastContentProgress = getContentProgress();
|
lastContentProgress = getContentProgress();
|
||||||
adDisplayContainer.unregisterAllVideoControlsOverlays();
|
adDisplayContainer.unregisterAllVideoControlsOverlays();
|
||||||
player.removeListener(this);
|
player.removeListener(this);
|
||||||
player = null;
|
this.player = null;
|
||||||
eventListener = null;
|
eventListener = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -657,6 +666,7 @@ public final class ImaAdsLoader
|
||||||
imaAdState = IMA_AD_STATE_NONE;
|
imaAdState = IMA_AD_STATE_NONE;
|
||||||
pendingAdLoadError = null;
|
pendingAdLoadError = null;
|
||||||
adPlaybackState = AdPlaybackState.NONE;
|
adPlaybackState = AdPlaybackState.NONE;
|
||||||
|
hasAdPlaybackState = false;
|
||||||
updateAdPlaybackState();
|
updateAdPlaybackState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -692,6 +702,7 @@ public final class ImaAdsLoader
|
||||||
// If a player is attached already, start playback immediately.
|
// If a player is attached already, start playback immediately.
|
||||||
try {
|
try {
|
||||||
adPlaybackState = new AdPlaybackState(getAdGroupTimesUs(adsManager.getAdCuePoints()));
|
adPlaybackState = new AdPlaybackState(getAdGroupTimesUs(adsManager.getAdCuePoints()));
|
||||||
|
hasAdPlaybackState = true;
|
||||||
updateAdPlaybackState();
|
updateAdPlaybackState();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
maybeNotifyInternalError("onAdsManagerLoaded", e);
|
maybeNotifyInternalError("onAdsManagerLoaded", e);
|
||||||
|
|
@ -708,7 +719,7 @@ public final class ImaAdsLoader
|
||||||
Log.d(TAG, "onAdEvent: " + adEventType);
|
Log.d(TAG, "onAdEvent: " + adEventType);
|
||||||
}
|
}
|
||||||
if (adsManager == null) {
|
if (adsManager == null) {
|
||||||
Log.w(TAG, "Ignoring AdEvent after release: " + adEvent);
|
// Drop events after release.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
@ -729,7 +740,8 @@ public final class ImaAdsLoader
|
||||||
if (adsManager == null) {
|
if (adsManager == null) {
|
||||||
// No ads were loaded, so allow playback to start without any ads.
|
// No ads were loaded, so allow playback to start without any ads.
|
||||||
pendingAdRequestContext = null;
|
pendingAdRequestContext = null;
|
||||||
adPlaybackState = new AdPlaybackState();
|
adPlaybackState = AdPlaybackState.NONE;
|
||||||
|
hasAdPlaybackState = true;
|
||||||
updateAdPlaybackState();
|
updateAdPlaybackState();
|
||||||
} else if (isAdGroupLoadError(error)) {
|
} else if (isAdGroupLoadError(error)) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -766,7 +778,7 @@ public final class ImaAdsLoader
|
||||||
adPlaybackState.getAdGroupIndexForPositionUs(
|
adPlaybackState.getAdGroupIndexForPositionUs(
|
||||||
C.msToUs(contentPositionMs), C.msToUs(contentDurationMs));
|
C.msToUs(contentPositionMs), C.msToUs(contentDurationMs));
|
||||||
} else if (imaAdState == IMA_AD_STATE_NONE && !playingAd && hasContentDuration) {
|
} else if (imaAdState == IMA_AD_STATE_NONE && !playingAd && hasContentDuration) {
|
||||||
contentPositionMs = getContentPeriodPositionMs();
|
contentPositionMs = getContentPeriodPositionMs(player, timeline, period);
|
||||||
// Update the expected ad group index for the current content position. The update is delayed
|
// Update the expected ad group index for the current content position. The update is delayed
|
||||||
// until MAXIMUM_PRELOAD_DURATION_MS before the ad so that an ad group load error delivered
|
// until MAXIMUM_PRELOAD_DURATION_MS before the ad so that an ad group load error delivered
|
||||||
// just after an ad group isn't incorrectly attributed to the next ad group.
|
// just after an ad group isn't incorrectly attributed to the next ad group.
|
||||||
|
|
@ -806,11 +818,12 @@ public final class ImaAdsLoader
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getVolume() {
|
public int getVolume() {
|
||||||
|
@Nullable Player player = this.player;
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
return lastVolumePercentage;
|
return lastVolumePercentage;
|
||||||
}
|
}
|
||||||
|
|
||||||
Player.AudioComponent audioComponent = player.getAudioComponent();
|
@Nullable Player.AudioComponent audioComponent = player.getAudioComponent();
|
||||||
if (audioComponent != null) {
|
if (audioComponent != null) {
|
||||||
return (int) (audioComponent.getVolume() * 100);
|
return (int) (audioComponent.getVolume() * 100);
|
||||||
}
|
}
|
||||||
|
|
@ -832,16 +845,16 @@ public final class ImaAdsLoader
|
||||||
Log.d(TAG, "loadAd in ad group " + adGroupIndex);
|
Log.d(TAG, "loadAd in ad group " + adGroupIndex);
|
||||||
}
|
}
|
||||||
if (adsManager == null) {
|
if (adsManager == null) {
|
||||||
Log.w(TAG, "Ignoring loadAd after release");
|
// Drop events after release.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (adGroupIndex == C.INDEX_UNSET) {
|
if (adGroupIndex == C.INDEX_UNSET) {
|
||||||
|
adGroupIndex = expectedAdGroupIndex;
|
||||||
|
adsManager.start();
|
||||||
Log.w(
|
Log.w(
|
||||||
TAG,
|
TAG,
|
||||||
"Unexpected loadAd without LOADED event; assuming ad group index is actually "
|
"Unexpected loadAd without LOADED event; assuming ad group index is actually "
|
||||||
+ expectedAdGroupIndex);
|
+ expectedAdGroupIndex);
|
||||||
adGroupIndex = expectedAdGroupIndex;
|
|
||||||
adsManager.start();
|
|
||||||
}
|
}
|
||||||
int adIndexInAdGroup = getAdIndexInAdGroupToLoad(adGroupIndex);
|
int adIndexInAdGroup = getAdIndexInAdGroupToLoad(adGroupIndex);
|
||||||
if (adIndexInAdGroup == C.INDEX_UNSET) {
|
if (adIndexInAdGroup == C.INDEX_UNSET) {
|
||||||
|
|
@ -872,7 +885,7 @@ public final class ImaAdsLoader
|
||||||
Log.d(TAG, "playAd");
|
Log.d(TAG, "playAd");
|
||||||
}
|
}
|
||||||
if (adsManager == null) {
|
if (adsManager == null) {
|
||||||
Log.w(TAG, "Ignoring playAd after release");
|
// Drop events after release.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (imaAdState) {
|
switch (imaAdState) {
|
||||||
|
|
@ -909,7 +922,7 @@ public final class ImaAdsLoader
|
||||||
// Sometimes messages from IMA arrive after detaching the player. See [Internal: b/63801642].
|
// Sometimes messages from IMA arrive after detaching the player. See [Internal: b/63801642].
|
||||||
Log.w(TAG, "Unexpected playAd while detached");
|
Log.w(TAG, "Unexpected playAd while detached");
|
||||||
} else if (!player.getPlayWhenReady()) {
|
} else if (!player.getPlayWhenReady()) {
|
||||||
adsManager.pause();
|
Assertions.checkNotNull(adsManager).pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -919,7 +932,7 @@ public final class ImaAdsLoader
|
||||||
Log.d(TAG, "stopAd");
|
Log.d(TAG, "stopAd");
|
||||||
}
|
}
|
||||||
if (adsManager == null) {
|
if (adsManager == null) {
|
||||||
Log.w(TAG, "Ignoring stopAd after release");
|
// Drop event after release.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
|
|
@ -975,9 +988,14 @@ public final class ImaAdsLoader
|
||||||
}
|
}
|
||||||
if (!initializedAdsManager && adsManager != null) {
|
if (!initializedAdsManager && adsManager != null) {
|
||||||
initializedAdsManager = true;
|
initializedAdsManager = true;
|
||||||
initializeAdsManager();
|
initializeAdsManager(adsManager);
|
||||||
}
|
}
|
||||||
checkForContentCompleteOrNewAdGroup();
|
handleTimelineOrPositionChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPositionDiscontinuity(@Player.DiscontinuityReason int reason) {
|
||||||
|
handleTimelineOrPositionChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -1016,14 +1034,9 @@ public final class ImaAdsLoader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPositionDiscontinuity(@Player.DiscontinuityReason int reason) {
|
|
||||||
checkForContentCompleteOrNewAdGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Internal methods.
|
// Internal methods.
|
||||||
|
|
||||||
private void initializeAdsManager() {
|
private void initializeAdsManager(AdsManager adsManager) {
|
||||||
AdsRenderingSettings adsRenderingSettings = imaFactory.createAdsRenderingSettings();
|
AdsRenderingSettings adsRenderingSettings = imaFactory.createAdsRenderingSettings();
|
||||||
adsRenderingSettings.setEnablePreloading(true);
|
adsRenderingSettings.setEnablePreloading(true);
|
||||||
adsRenderingSettings.setMimeTypes(supportedMimeTypes);
|
adsRenderingSettings.setMimeTypes(supportedMimeTypes);
|
||||||
|
|
@ -1040,7 +1053,8 @@ public final class ImaAdsLoader
|
||||||
|
|
||||||
// Skip ads based on the start position as required.
|
// Skip ads based on the start position as required.
|
||||||
long[] adGroupTimesUs = getAdGroupTimesUs(adsManager.getAdCuePoints());
|
long[] adGroupTimesUs = getAdGroupTimesUs(adsManager.getAdCuePoints());
|
||||||
long contentPositionMs = getContentPeriodPositionMs();
|
long contentPositionMs =
|
||||||
|
getContentPeriodPositionMs(Assertions.checkNotNull(player), timeline, period);
|
||||||
int adGroupIndexForPosition =
|
int adGroupIndexForPosition =
|
||||||
adPlaybackState.getAdGroupIndexForPositionUs(
|
adPlaybackState.getAdGroupIndexForPositionUs(
|
||||||
C.msToUs(contentPositionMs), C.msToUs(contentDurationMs));
|
C.msToUs(contentPositionMs), C.msToUs(contentDurationMs));
|
||||||
|
|
@ -1093,7 +1107,7 @@ public final class ImaAdsLoader
|
||||||
podIndex == -1 ? (adPlaybackState.adGroupCount - 1) : (podIndex + podIndexOffset);
|
podIndex == -1 ? (adPlaybackState.adGroupCount - 1) : (podIndex + podIndexOffset);
|
||||||
int adPosition = adPodInfo.getAdPosition();
|
int adPosition = adPodInfo.getAdPosition();
|
||||||
int adCount = adPodInfo.getTotalAds();
|
int adCount = adPodInfo.getTotalAds();
|
||||||
adsManager.start();
|
Assertions.checkNotNull(adsManager).start();
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "Loaded ad " + adPosition + " of " + adCount + " in group " + adGroupIndex);
|
Log.d(TAG, "Loaded ad " + adPosition + " of " + adCount + " in group " + adGroupIndex);
|
||||||
}
|
}
|
||||||
|
|
@ -1145,8 +1159,6 @@ public final class ImaAdsLoader
|
||||||
handleAdGroupLoadError(new IOException(message));
|
handleAdGroupLoadError(new IOException(message));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case STARTED:
|
|
||||||
case ALL_ADS_COMPLETED:
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1167,7 +1179,8 @@ public final class ImaAdsLoader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkForContentCompleteOrNewAdGroup() {
|
private void handleTimelineOrPositionChanged() {
|
||||||
|
@Nullable Player player = this.player;
|
||||||
if (adsManager == null || player == null) {
|
if (adsManager == null || player == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1181,7 +1194,7 @@ public final class ImaAdsLoader
|
||||||
}
|
}
|
||||||
updateAdPlaybackState();
|
updateAdPlaybackState();
|
||||||
} else if (!timeline.isEmpty()) {
|
} else if (!timeline.isEmpty()) {
|
||||||
long positionMs = getContentPeriodPositionMs();
|
long positionMs = getContentPeriodPositionMs(player, timeline, period);
|
||||||
timeline.getPeriod(/* periodIndex= */ 0, period);
|
timeline.getPeriod(/* periodIndex= */ 0, period);
|
||||||
int newAdGroupIndex = period.getAdGroupIndexForPositionUs(C.msToUs(positionMs));
|
int newAdGroupIndex = period.getAdGroupIndexForPositionUs(C.msToUs(positionMs));
|
||||||
if (newAdGroupIndex != C.INDEX_UNSET) {
|
if (newAdGroupIndex != C.INDEX_UNSET) {
|
||||||
|
|
@ -1193,10 +1206,7 @@ public final class ImaAdsLoader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateImaStateForPlayerState();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateImaStateForPlayerState() {
|
|
||||||
boolean wasPlayingAd = playingAd;
|
boolean wasPlayingAd = playingAd;
|
||||||
int oldPlayingAdIndexInAdGroup = playingAdIndexInAdGroup;
|
int oldPlayingAdIndexInAdGroup = playingAdIndexInAdGroup;
|
||||||
playingAd = player.isPlayingAd();
|
playingAd = player.isPlayingAd();
|
||||||
|
|
@ -1323,10 +1333,11 @@ public final class ImaAdsLoader
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkForContentComplete() {
|
private void checkForContentComplete() {
|
||||||
if (contentDurationMs != C.TIME_UNSET
|
long positionMs = getContentPeriodPositionMs(Assertions.checkNotNull(player), timeline, period);
|
||||||
|
if (!sentContentComplete
|
||||||
|
&& contentDurationMs != C.TIME_UNSET
|
||||||
&& pendingContentPositionMs == C.TIME_UNSET
|
&& pendingContentPositionMs == C.TIME_UNSET
|
||||||
&& getContentPeriodPositionMs() + END_OF_CONTENT_POSITION_THRESHOLD_MS >= contentDurationMs
|
&& positionMs + END_OF_CONTENT_THRESHOLD_MS >= contentDurationMs) {
|
||||||
&& !sentContentComplete) {
|
|
||||||
adsLoader.contentComplete();
|
adsLoader.contentComplete();
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "adsLoader.contentComplete");
|
Log.d(TAG, "adsLoader.contentComplete");
|
||||||
|
|
@ -1364,7 +1375,7 @@ public final class ImaAdsLoader
|
||||||
|
|
||||||
private void maybeNotifyPendingAdLoadError() {
|
private void maybeNotifyPendingAdLoadError() {
|
||||||
if (pendingAdLoadError != null && eventListener != null) {
|
if (pendingAdLoadError != null && eventListener != null) {
|
||||||
eventListener.onAdLoadError(pendingAdLoadError, new DataSpec(adTagUri));
|
eventListener.onAdLoadError(pendingAdLoadError, getAdsDataSpec(adTagUri));
|
||||||
pendingAdLoadError = null;
|
pendingAdLoadError = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1373,22 +1384,23 @@ public final class ImaAdsLoader
|
||||||
String message = "Internal error in " + name;
|
String message = "Internal error in " + name;
|
||||||
Log.e(TAG, message, cause);
|
Log.e(TAG, message, cause);
|
||||||
// We can't recover from an unexpected error in general, so skip all remaining ads.
|
// We can't recover from an unexpected error in general, so skip all remaining ads.
|
||||||
if (adPlaybackState == null) {
|
for (int i = 0; i < adPlaybackState.adGroupCount; i++) {
|
||||||
adPlaybackState = AdPlaybackState.NONE;
|
adPlaybackState = adPlaybackState.withSkippedAdGroup(i);
|
||||||
} else {
|
|
||||||
for (int i = 0; i < adPlaybackState.adGroupCount; i++) {
|
|
||||||
adPlaybackState = adPlaybackState.withSkippedAdGroup(i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
updateAdPlaybackState();
|
updateAdPlaybackState();
|
||||||
if (eventListener != null) {
|
if (eventListener != null) {
|
||||||
eventListener.onAdLoadError(
|
eventListener.onAdLoadError(
|
||||||
AdLoadException.createForUnexpected(new RuntimeException(message, cause)),
|
AdLoadException.createForUnexpected(new RuntimeException(message, cause)),
|
||||||
new DataSpec(adTagUri));
|
getAdsDataSpec(adTagUri));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getContentPeriodPositionMs() {
|
private static DataSpec getAdsDataSpec(@Nullable Uri adTagUri) {
|
||||||
|
return new DataSpec(adTagUri != null ? adTagUri : Uri.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long getContentPeriodPositionMs(
|
||||||
|
Player player, Timeline timeline, Timeline.Period period) {
|
||||||
long contentWindowPositionMs = player.getContentPosition();
|
long contentWindowPositionMs = player.getContentPosition();
|
||||||
return contentWindowPositionMs
|
return contentWindowPositionMs
|
||||||
- timeline.getPeriod(/* periodIndex= */ 0, period).getPositionInWindowMs();
|
- timeline.getPeriod(/* periodIndex= */ 0, period).getPositionInWindowMs();
|
||||||
|
|
|
||||||
|
|
@ -271,7 +271,7 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected @Nullable MediaPeriodId getMediaPeriodIdForChildMediaPeriodId(
|
protected MediaPeriodId getMediaPeriodIdForChildMediaPeriodId(
|
||||||
MediaPeriodId childId, MediaPeriodId mediaPeriodId) {
|
MediaPeriodId childId, MediaPeriodId mediaPeriodId) {
|
||||||
// The child id for the content period is just DUMMY_CONTENT_MEDIA_PERIOD_ID. That's why we need
|
// The child id for the content period is just DUMMY_CONTENT_MEDIA_PERIOD_ID. That's why we need
|
||||||
// to forward the reported mediaPeriodId in this case.
|
// to forward the reported mediaPeriodId in this case.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue