Fix seeking to a non-zero position in a preloaded ad item

`ImaAdsLoader` will preload the first ad of a subsequent media item, but the
preloaded ad might not actually play because the user could seek to a non-zero
position in that media item (which could trigger playback of a midroll, not the
preroll). In this case, playback would get stuck because the midroll ad
expected to play after the seek would never load, because the IMA SDK expected
the preroll to play first.

Fix this behavior by discarding the preloaded ad break. If there isn't a seek,
the transition to the next media item is still seamless.

#minor-release

PiperOrigin-RevId: 357682510
This commit is contained in:
andrewlewis 2021-02-16 11:25:48 +00:00 committed by kim-vde
parent 2326b56132
commit e009322edd
2 changed files with 22 additions and 5 deletions

View File

@ -21,6 +21,9 @@
* Remove `extension-jobdispatcher` module. Use the `extension-workmanager` * Remove `extension-jobdispatcher` module. Use the `extension-workmanager`
module instead. module instead.
* IMA extension: * IMA extension:
* Fix a bug where playback could get stuck when seeking into a playlist
item with ads, if the preroll ad had preloaded but the window position
of the seek should instead trigger playback of a midroll.
* Fix a bug with playback of ads in playlists, where the incorrect period * Fix a bug with playback of ads in playlists, where the incorrect period
index was used when deciding whether to trigger playback of an ad after index was used when deciding whether to trigger playback of an ad after
a seek. a seek.

View File

@ -341,13 +341,27 @@ import java.util.Map;
boolean playWhenReady = player.getPlayWhenReady(); boolean playWhenReady = player.getPlayWhenReady();
onTimelineChanged(player.getCurrentTimeline(), Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE); onTimelineChanged(player.getCurrentTimeline(), Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE);
if (!AdPlaybackState.NONE.equals(adPlaybackState) @Nullable AdsManager adsManager = this.adsManager;
&& adsManager != null if (!AdPlaybackState.NONE.equals(adPlaybackState) && adsManager != null && imaPausedContent) {
&& imaPausedContent // Check whether the current ad break matches the expected ad break based on the current
&& playWhenReady) { // position. If not, discard the current ad break so that the correct ad break can load.
long contentPositionMs = getContentPeriodPositionMs(player, timeline, period);
int adGroupForPositionIndex =
adPlaybackState.getAdGroupIndexForPositionUs(
C.msToUs(contentPositionMs), C.msToUs(contentDurationMs));
if (adGroupForPositionIndex != C.INDEX_UNSET
&& imaAdInfo != null
&& imaAdInfo.adGroupIndex != adGroupForPositionIndex) {
if (configuration.debugModeEnabled) {
Log.d(TAG, "Discarding preloaded ad " + imaAdInfo);
}
adsManager.discardAdBreak();
}
if (playWhenReady) {
adsManager.resume(); adsManager.resume();
} }
} }
}
/** Deactivates playback. */ /** Deactivates playback. */
public void deactivate() { public void deactivate() {