Fix content progress updates and position faking
Occasionally the player could transition from playing content to playing an ad after IMA called playAd. The discontinuity triggered faking the content position, and the fake position was passed to IMA when content resumed causing the wrong ad group to be loaded. Fix this by only faking the position if the player transitions before playAd. Also fix the calculation of the expected ad group index for a postroll ad, and wait for the player to transition back from ad to content before passing a content progress update. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=185994229
This commit is contained in:
parent
6c3b677ddb
commit
56c9d023fa
@ -252,10 +252,9 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
|
|||||||
*/
|
*/
|
||||||
private boolean shouldNotifyAdPrepareError;
|
private boolean shouldNotifyAdPrepareError;
|
||||||
/**
|
/**
|
||||||
* If a content period has finished but IMA has not yet sent an ad event with {@link
|
* If a content period has finished but IMA has not yet called {@link #playAd()}, stores the value
|
||||||
* AdEvent.AdEventType#CONTENT_PAUSE_REQUESTED}, stores the value of {@link
|
* of {@link SystemClock#elapsedRealtime()} when the content stopped playing. This can be used to
|
||||||
* SystemClock#elapsedRealtime()} when the content stopped playing. This can be used to determine
|
* determine a fake, increasing content position. {@link C#TIME_UNSET} otherwise.
|
||||||
* a fake, increasing content position. {@link C#TIME_UNSET} otherwise.
|
|
||||||
*/
|
*/
|
||||||
private long fakeContentProgressElapsedRealtimeMs;
|
private long fakeContentProgressElapsedRealtimeMs;
|
||||||
/**
|
/**
|
||||||
@ -541,18 +540,21 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
|
|||||||
contentPositionMs = fakeContentProgressOffsetMs + elapsedSinceEndMs;
|
contentPositionMs = fakeContentProgressOffsetMs + elapsedSinceEndMs;
|
||||||
expectedAdGroupIndex =
|
expectedAdGroupIndex =
|
||||||
adPlaybackState.getAdGroupIndexForPositionUs(C.msToUs(contentPositionMs));
|
adPlaybackState.getAdGroupIndexForPositionUs(C.msToUs(contentPositionMs));
|
||||||
} else if (imaAdState == IMA_AD_STATE_NONE && hasContentDuration) {
|
} else if (imaAdState == IMA_AD_STATE_NONE && !playingAd && hasContentDuration) {
|
||||||
contentPositionMs = player.getCurrentPosition();
|
contentPositionMs = player.getCurrentPosition();
|
||||||
// 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.
|
||||||
int nextAdGroupIndex =
|
int nextAdGroupIndex =
|
||||||
adPlaybackState.getAdGroupIndexAfterPositionUs(C.msToUs(contentPositionMs));
|
adPlaybackState.getAdGroupIndexAfterPositionUs(C.msToUs(contentPositionMs));
|
||||||
if (nextAdGroupIndex != expectedAdGroupIndex
|
if (nextAdGroupIndex != expectedAdGroupIndex && nextAdGroupIndex != C.INDEX_UNSET) {
|
||||||
&& nextAdGroupIndex != C.INDEX_UNSET
|
long nextAdGroupTimeMs = C.usToMs(adPlaybackState.adGroupTimesUs[nextAdGroupIndex]);
|
||||||
&& C.usToMs(adPlaybackState.adGroupTimesUs[nextAdGroupIndex]) - contentPositionMs
|
if (nextAdGroupTimeMs == C.TIME_END_OF_SOURCE) {
|
||||||
< MAXIMUM_PRELOAD_DURATION_MS) {
|
nextAdGroupTimeMs = contentDurationMs;
|
||||||
expectedAdGroupIndex = nextAdGroupIndex;
|
}
|
||||||
|
if (nextAdGroupTimeMs - contentPositionMs < MAXIMUM_PRELOAD_DURATION_MS) {
|
||||||
|
expectedAdGroupIndex = nextAdGroupIndex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return VideoProgressUpdate.VIDEO_TIME_NOT_READY;
|
return VideoProgressUpdate.VIDEO_TIME_NOT_READY;
|
||||||
@ -567,12 +569,12 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
|
|||||||
public VideoProgressUpdate getAdProgress() {
|
public VideoProgressUpdate getAdProgress() {
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
return lastAdProgress;
|
return lastAdProgress;
|
||||||
} else if (imaAdState == IMA_AD_STATE_NONE) {
|
} else if (imaAdState != IMA_AD_STATE_NONE && playingAd) {
|
||||||
return VideoProgressUpdate.VIDEO_TIME_NOT_READY;
|
|
||||||
} else {
|
|
||||||
long adDuration = player.getDuration();
|
long adDuration = player.getDuration();
|
||||||
return adDuration == C.TIME_UNSET ? VideoProgressUpdate.VIDEO_TIME_NOT_READY
|
return adDuration == C.TIME_UNSET ? VideoProgressUpdate.VIDEO_TIME_NOT_READY
|
||||||
: new VideoProgressUpdate(player.getCurrentPosition(), adDuration);
|
: new VideoProgressUpdate(player.getCurrentPosition(), adDuration);
|
||||||
|
} else {
|
||||||
|
return VideoProgressUpdate.VIDEO_TIME_NOT_READY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,6 +627,9 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
|
|||||||
Log.w(TAG, "Unexpected playAd without stopAd");
|
Log.w(TAG, "Unexpected playAd without stopAd");
|
||||||
break;
|
break;
|
||||||
case IMA_AD_STATE_NONE:
|
case IMA_AD_STATE_NONE:
|
||||||
|
// IMA is requesting to play the ad, so stop faking the content position.
|
||||||
|
fakeContentProgressElapsedRealtimeMs = C.TIME_UNSET;
|
||||||
|
fakeContentProgressOffsetMs = C.TIME_UNSET;
|
||||||
imaAdState = IMA_AD_STATE_PLAYING;
|
imaAdState = IMA_AD_STATE_PLAYING;
|
||||||
for (int i = 0; i < adCallbacks.size(); i++) {
|
for (int i = 0; i < adCallbacks.size(); i++) {
|
||||||
adCallbacks.get(i).onPlay();
|
adCallbacks.get(i).onPlay();
|
||||||
@ -923,9 +928,9 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
|
|||||||
Log.d(TAG, "VideoAdPlayerCallback.onEnded in onTimelineChanged/onPositionDiscontinuity");
|
Log.d(TAG, "VideoAdPlayerCallback.onEnded in onTimelineChanged/onPositionDiscontinuity");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!wasPlayingAd && playingAd) {
|
if (!wasPlayingAd && playingAd && imaAdState == IMA_AD_STATE_NONE) {
|
||||||
int adGroupIndex = player.getCurrentAdGroupIndex();
|
int adGroupIndex = player.getCurrentAdGroupIndex();
|
||||||
// IMA hasn't sent CONTENT_PAUSE_REQUESTED yet, so fake the content position.
|
// IMA hasn't called playAd yet, so fake the content position.
|
||||||
fakeContentProgressElapsedRealtimeMs = SystemClock.elapsedRealtime();
|
fakeContentProgressElapsedRealtimeMs = SystemClock.elapsedRealtime();
|
||||||
fakeContentProgressOffsetMs = C.usToMs(adPlaybackState.adGroupTimesUs[adGroupIndex]);
|
fakeContentProgressOffsetMs = C.usToMs(adPlaybackState.adGroupTimesUs[adGroupIndex]);
|
||||||
if (fakeContentProgressOffsetMs == C.TIME_END_OF_SOURCE) {
|
if (fakeContentProgressOffsetMs == C.TIME_END_OF_SOURCE) {
|
||||||
@ -955,9 +960,6 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
|
|||||||
pendingContentPositionMs = C.TIME_UNSET;
|
pendingContentPositionMs = C.TIME_UNSET;
|
||||||
sentPendingContentPositionMs = false;
|
sentPendingContentPositionMs = false;
|
||||||
}
|
}
|
||||||
// IMA is requesting to pause content, so stop faking the content position.
|
|
||||||
fakeContentProgressElapsedRealtimeMs = C.TIME_UNSET;
|
|
||||||
fakeContentProgressOffsetMs = C.TIME_UNSET;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopAdInternal() {
|
private void stopAdInternal() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user