Create an AdEventListener for each supported stream type
This is a refactoring to separate and simplify the logic of VOD and live streams when handling IMA ad events. An additional listener will be required for DASH live stream in a follow-up CL. PiperOrigin-RevId: 507435741
This commit is contained in:
parent
0eb11e269c
commit
afa3c628c1
@ -528,7 +528,6 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
|
|||||||
this.contentMediaSourceFactory = contentMediaSourceFactory;
|
this.contentMediaSourceFactory = contentMediaSourceFactory;
|
||||||
this.applicationAdEventListener = applicationAdEventListener;
|
this.applicationAdEventListener = applicationAdEventListener;
|
||||||
this.applicationAdErrorListener = applicationAdErrorListener;
|
this.applicationAdErrorListener = applicationAdErrorListener;
|
||||||
componentListener = new ComponentListener();
|
|
||||||
Assertions.checkArgument(player.getApplicationLooper() == Looper.getMainLooper());
|
Assertions.checkArgument(player.getApplicationLooper() == Looper.getMainLooper());
|
||||||
mainHandler = new Handler(Looper.getMainLooper());
|
mainHandler = new Handler(Looper.getMainLooper());
|
||||||
Uri streamRequestUri = checkNotNull(mediaItem.localConfiguration).uri;
|
Uri streamRequestUri = checkNotNull(mediaItem.localConfiguration).uri;
|
||||||
@ -536,6 +535,12 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
|
|||||||
adsId = ImaServerSideAdInsertionUriBuilder.getAdsId(streamRequestUri);
|
adsId = ImaServerSideAdInsertionUriBuilder.getAdsId(streamRequestUri);
|
||||||
loadVideoTimeoutMs = ImaServerSideAdInsertionUriBuilder.getLoadVideoTimeoutMs(streamRequestUri);
|
loadVideoTimeoutMs = ImaServerSideAdInsertionUriBuilder.getLoadVideoTimeoutMs(streamRequestUri);
|
||||||
streamRequest = ImaServerSideAdInsertionUriBuilder.createStreamRequest(streamRequestUri);
|
streamRequest = ImaServerSideAdInsertionUriBuilder.createStreamRequest(streamRequestUri);
|
||||||
|
boolean isDashStream = streamRequest.getFormat().equals(StreamRequest.StreamFormat.DASH);
|
||||||
|
componentListener =
|
||||||
|
new ComponentListener(
|
||||||
|
isLiveStream
|
||||||
|
? (isDashStream ? new NoopAdEventListener() : new SinglePeriodLiveAdEventListener())
|
||||||
|
: new VodAdEventListener());
|
||||||
adPlaybackState = adsLoader.getAdPlaybackState(adsId);
|
adPlaybackState = adsLoader.getAdPlaybackState(adsId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -773,6 +778,13 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
|
|||||||
private final class ComponentListener
|
private final class ComponentListener
|
||||||
implements AdEvent.AdEventListener, Player.Listener, AdPlaybackStateUpdater {
|
implements AdEvent.AdEventListener, Player.Listener, AdPlaybackStateUpdater {
|
||||||
|
|
||||||
|
private final AdEventListener adEventListener;
|
||||||
|
|
||||||
|
/** Creates an new instance. */
|
||||||
|
public ComponentListener(AdEventListener adEventListener) {
|
||||||
|
this.adEventListener = adEventListener;
|
||||||
|
}
|
||||||
|
|
||||||
// Implement Player.Listener.
|
// Implement Player.Listener.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -883,56 +895,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
|
|||||||
@MainThread
|
@MainThread
|
||||||
@Override
|
@Override
|
||||||
public void onAdEvent(AdEvent event) {
|
public void onAdEvent(AdEvent event) {
|
||||||
AdPlaybackState newAdPlaybackState = adPlaybackState;
|
adEventListener.onAdEvent(event);
|
||||||
switch (event.getType()) {
|
|
||||||
case CUEPOINTS_CHANGED:
|
|
||||||
// CUEPOINTS_CHANGED event is firing multiple times with the same queue points.
|
|
||||||
if (!isLiveStream && newAdPlaybackState.equals(AdPlaybackState.NONE)) {
|
|
||||||
newAdPlaybackState =
|
|
||||||
setVodAdGroupPlaceholders(
|
|
||||||
checkNotNull(streamManager).getCuePoints(), new AdPlaybackState(adsId));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case LOADED:
|
|
||||||
if (isLiveStream) {
|
|
||||||
Timeline timeline = player.getCurrentTimeline();
|
|
||||||
Timeline.Window window =
|
|
||||||
timeline.getWindow(player.getCurrentMediaItemIndex(), new Timeline.Window());
|
|
||||||
if (window.lastPeriodIndex > window.firstPeriodIndex) {
|
|
||||||
// multi-period live not integrated
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
long positionInWindowUs =
|
|
||||||
timeline.getPeriod(player.getCurrentPeriodIndex(), new Timeline.Period())
|
|
||||||
.positionInWindowUs;
|
|
||||||
long currentContentPeriodPositionUs =
|
|
||||||
msToUs(player.getContentPosition()) - positionInWindowUs;
|
|
||||||
Ad ad = event.getAd();
|
|
||||||
AdPodInfo adPodInfo = ad.getAdPodInfo();
|
|
||||||
newAdPlaybackState =
|
|
||||||
addLiveAdBreak(
|
|
||||||
currentContentPeriodPositionUs,
|
|
||||||
/* adDurationUs= */ secToUsRounded(ad.getDuration()),
|
|
||||||
/* adPositionInAdPod= */ adPodInfo.getAdPosition(),
|
|
||||||
/* totalAdDurationUs= */ secToUsRounded(adPodInfo.getMaxDuration()),
|
|
||||||
/* totalAdsInAdPod= */ adPodInfo.getTotalAds(),
|
|
||||||
/* adPlaybackState= */ newAdPlaybackState.equals(AdPlaybackState.NONE)
|
|
||||||
? new AdPlaybackState(adsId)
|
|
||||||
: newAdPlaybackState);
|
|
||||||
} else {
|
|
||||||
newAdPlaybackState = setVodAdInPlaceholder(event.getAd(), newAdPlaybackState);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SKIPPED:
|
|
||||||
if (!isLiveStream) {
|
|
||||||
newAdPlaybackState = skipAd(event.getAd(), newAdPlaybackState);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// Do nothing.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
setAdPlaybackState(newAdPlaybackState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implement AdPlaybackStateUpdater (called on the playback thread).
|
// Implement AdPlaybackStateUpdater (called on the playback thread).
|
||||||
@ -1356,4 +1319,70 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class VodAdEventListener implements AdEventListener {
|
||||||
|
@Override
|
||||||
|
public void onAdEvent(AdEvent event) {
|
||||||
|
AdPlaybackState newAdPlaybackState = adPlaybackState;
|
||||||
|
switch (event.getType()) {
|
||||||
|
case CUEPOINTS_CHANGED:
|
||||||
|
if (newAdPlaybackState.equals(AdPlaybackState.NONE)) {
|
||||||
|
newAdPlaybackState =
|
||||||
|
setVodAdGroupPlaceholders(
|
||||||
|
checkNotNull(streamManager).getCuePoints(), new AdPlaybackState(adsId));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LOADED:
|
||||||
|
newAdPlaybackState = setVodAdInPlaceholder(event.getAd(), newAdPlaybackState);
|
||||||
|
break;
|
||||||
|
case SKIPPED:
|
||||||
|
newAdPlaybackState = skipAd(event.getAd(), newAdPlaybackState);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Do nothing.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
setAdPlaybackState(newAdPlaybackState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SinglePeriodLiveAdEventListener implements AdEventListener {
|
||||||
|
@Override
|
||||||
|
public void onAdEvent(AdEvent event) {
|
||||||
|
if (event.getType() != AdEvent.AdEventType.LOADED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AdPlaybackState newAdPlaybackState = adPlaybackState;
|
||||||
|
Timeline timeline = player.getCurrentTimeline();
|
||||||
|
long positionInWindowUs =
|
||||||
|
timeline.getPeriod(player.getCurrentPeriodIndex(), new Timeline.Period())
|
||||||
|
.positionInWindowUs;
|
||||||
|
long currentContentPeriodPositionUs =
|
||||||
|
msToUs(player.getContentPosition()) - positionInWindowUs;
|
||||||
|
Ad ad = event.getAd();
|
||||||
|
AdPodInfo adPodInfo = ad.getAdPodInfo();
|
||||||
|
newAdPlaybackState =
|
||||||
|
addLiveAdBreak(
|
||||||
|
currentContentPeriodPositionUs,
|
||||||
|
/* adDurationUs= */ secToUsRounded(ad.getDuration()),
|
||||||
|
/* adPositionInAdPod= */ adPodInfo.getAdPosition(),
|
||||||
|
/* totalAdDurationUs= */ secToUsRounded(adPodInfo.getMaxDuration()),
|
||||||
|
/* totalAdsInAdPod= */ adPodInfo.getTotalAds(),
|
||||||
|
/* adPlaybackState= */ newAdPlaybackState.equals(AdPlaybackState.NONE)
|
||||||
|
? new AdPlaybackState(adsId)
|
||||||
|
: newAdPlaybackState);
|
||||||
|
setAdPlaybackState(newAdPlaybackState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class NoopAdEventListener implements AdEventListener {
|
||||||
|
@Override
|
||||||
|
public void onAdEvent(AdEvent event) {
|
||||||
|
Log.w(
|
||||||
|
"ImaSSAIMediaSource",
|
||||||
|
String.format(
|
||||||
|
"Ignoring IMA ad event %s because the current stream type is not supported.",
|
||||||
|
event.getType().name()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user