Commit de03e389 by andrewlewis Committed by Andrew Lewis

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
parent 6e66dc02
...@@ -15,6 +15,8 @@ ...@@ -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 ...@@ -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;
...@@ -325,7 +327,7 @@ public final class ImaAdsLoader ...@@ -325,7 +327,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;
...@@ -335,7 +337,8 @@ public final class ImaAdsLoader ...@@ -335,7 +337,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;
...@@ -439,6 +442,7 @@ public final class ImaAdsLoader ...@@ -439,6 +442,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,
...@@ -479,12 +483,16 @@ public final class ImaAdsLoader ...@@ -479,12 +483,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;
} }
/** /**
...@@ -532,22 +540,22 @@ public final class ImaAdsLoader ...@@ -532,22 +540,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);
} }
...@@ -567,6 +575,7 @@ public final class ImaAdsLoader ...@@ -567,6 +575,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) {
...@@ -579,8 +588,6 @@ public final class ImaAdsLoader ...@@ -579,8 +588,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);
...@@ -594,22 +601,23 @@ public final class ImaAdsLoader ...@@ -594,22 +601,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) {
...@@ -623,21 +631,22 @@ public final class ImaAdsLoader ...@@ -623,21 +631,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;
} }
...@@ -659,6 +668,7 @@ public final class ImaAdsLoader ...@@ -659,6 +668,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();
} }
...@@ -694,6 +704,7 @@ public final class ImaAdsLoader ...@@ -694,6 +704,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);
...@@ -710,7 +721,7 @@ public final class ImaAdsLoader ...@@ -710,7 +721,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 {
...@@ -731,7 +742,8 @@ public final class ImaAdsLoader ...@@ -731,7 +742,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 {
...@@ -768,7 +780,7 @@ public final class ImaAdsLoader ...@@ -768,7 +780,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.
...@@ -808,11 +820,12 @@ public final class ImaAdsLoader ...@@ -808,11 +820,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);
} }
...@@ -834,16 +847,16 @@ public final class ImaAdsLoader ...@@ -834,16 +847,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) {
...@@ -874,7 +887,7 @@ public final class ImaAdsLoader ...@@ -874,7 +887,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) {
...@@ -911,7 +924,7 @@ public final class ImaAdsLoader ...@@ -911,7 +924,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();
} }
} }
...@@ -921,7 +934,7 @@ public final class ImaAdsLoader ...@@ -921,7 +934,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) {
...@@ -977,9 +990,14 @@ public final class ImaAdsLoader ...@@ -977,9 +990,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
...@@ -1009,14 +1027,9 @@ public final class ImaAdsLoader ...@@ -1009,14 +1027,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);
...@@ -1033,7 +1046,8 @@ public final class ImaAdsLoader ...@@ -1033,7 +1046,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));
...@@ -1086,7 +1100,7 @@ public final class ImaAdsLoader ...@@ -1086,7 +1100,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);
} }
...@@ -1138,8 +1152,6 @@ public final class ImaAdsLoader ...@@ -1138,8 +1152,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;
} }
...@@ -1160,7 +1172,8 @@ public final class ImaAdsLoader ...@@ -1160,7 +1172,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;
} }
...@@ -1174,7 +1187,7 @@ public final class ImaAdsLoader ...@@ -1174,7 +1187,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) {
...@@ -1186,10 +1199,7 @@ public final class ImaAdsLoader ...@@ -1186,10 +1199,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();
...@@ -1316,10 +1326,11 @@ public final class ImaAdsLoader ...@@ -1316,10 +1326,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");
...@@ -1357,7 +1368,7 @@ public final class ImaAdsLoader ...@@ -1357,7 +1368,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;
} }
} }
...@@ -1366,22 +1377,23 @@ public final class ImaAdsLoader ...@@ -1366,22 +1377,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> { ...@@ -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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment