use of com.google.android.exoplayer2.source.ads.AdPlaybackState in project ExoPlayer by google.
the class ServerSideAdInsertionMediaSourceTest method playbackWithSeek_isHandledCorrectly.
@Test
public void playbackWithSeek_isHandledCorrectly() throws Exception {
Context context = ApplicationProvider.getApplicationContext();
ExoPlayer player = new ExoPlayer.Builder(context).setClock(new FakeClock(/* isAutoAdvancing= */
true)).build();
player.setVideoSurface(new Surface(new SurfaceTexture(/* texName= */
1)));
AdPlaybackState adPlaybackState = new AdPlaybackState(/* adsId= */
new Object());
adPlaybackState = addAdGroupToAdPlaybackState(adPlaybackState, /* fromPositionUs= */
0, /* contentResumeOffsetUs= */
0, /* adDurationsUs...= */
100_000);
adPlaybackState = addAdGroupToAdPlaybackState(adPlaybackState, /* fromPositionUs= */
600_000, /* contentResumeOffsetUs= */
1_000_000, /* adDurationsUs...= */
100_000);
AdPlaybackState firstAdPlaybackState = addAdGroupToAdPlaybackState(adPlaybackState, /* fromPositionUs= */
900_000, /* contentResumeOffsetUs= */
0, /* adDurationsUs...= */
100_000);
AtomicReference<ServerSideAdInsertionMediaSource> mediaSourceRef = new AtomicReference<>();
mediaSourceRef.set(new ServerSideAdInsertionMediaSource(new DefaultMediaSourceFactory(context).createMediaSource(MediaItem.fromUri(TEST_ASSET)), /* adPlaybackStateUpdater= */
contentTimeline -> {
Object periodUid = checkNotNull(contentTimeline.getPeriod(/* periodIndex= */
0, new Timeline.Period(), /* setIds= */
true).uid);
mediaSourceRef.get().setAdPlaybackStates(ImmutableMap.of(periodUid, firstAdPlaybackState));
return true;
}));
AnalyticsListener listener = mock(AnalyticsListener.class);
player.addAnalyticsListener(listener);
player.setMediaSource(mediaSourceRef.get());
player.prepare();
// Play to the first content part, then seek past the midroll.
playUntilPosition(player, /* mediaItemIndex= */
0, /* positionMs= */
100);
player.seekTo(/* positionMs= */
1_600);
runUntilPendingCommandsAreFullyHandled(player);
long positionAfterSeekMs = player.getCurrentPosition();
long contentPositionAfterSeekMs = player.getContentPosition();
player.play();
runUntilPlaybackState(player, Player.STATE_ENDED);
player.release();
// Assert playback has been reported with ads: [ad0][content] seek [ad1][content][ad2][content]
// 6*2(audio+video) format changes, 4 auto-transitions between parts, 1 seek with adjustment.
verify(listener, times(4)).onPositionDiscontinuity(any(), any(), any(), eq(Player.DISCONTINUITY_REASON_AUTO_TRANSITION));
verify(listener, times(1)).onPositionDiscontinuity(any(), any(), any(), eq(Player.DISCONTINUITY_REASON_SEEK));
verify(listener, times(1)).onPositionDiscontinuity(any(), any(), any(), eq(Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT));
verify(listener, times(12)).onDownstreamFormatChanged(any(), any());
assertThat(contentPositionAfterSeekMs).isEqualTo(1_600);
// Beginning of second ad.
assertThat(positionAfterSeekMs).isEqualTo(0);
// Assert renderers played through without reset, except for the seek.
verify(listener, times(2)).onVideoEnabled(any(), any());
verify(listener, times(2)).onAudioEnabled(any(), any());
// Assert playback progression was smooth (=no unexpected delays that cause audio to underrun)
verify(listener, never()).onAudioUnderrun(any(), anyInt(), anyLong(), anyLong());
}
use of com.google.android.exoplayer2.source.ads.AdPlaybackState in project ExoPlayer by google.
the class ServerSideAdInsertionMediaSourceTest method playbackWithPredefinedAds_playsSuccessfulWithoutRendererResets.
@Test
public void playbackWithPredefinedAds_playsSuccessfulWithoutRendererResets() throws Exception {
Context context = ApplicationProvider.getApplicationContext();
CapturingRenderersFactory renderersFactory = new CapturingRenderersFactory(context);
ExoPlayer player = new ExoPlayer.Builder(context, renderersFactory).setClock(new FakeClock(/* isAutoAdvancing= */
true)).build();
player.setVideoSurface(new Surface(new SurfaceTexture(/* texName= */
1)));
PlaybackOutput playbackOutput = PlaybackOutput.register(player, renderersFactory);
AdPlaybackState adPlaybackState = new AdPlaybackState(/* adsId= */
new Object());
adPlaybackState = addAdGroupToAdPlaybackState(adPlaybackState, /* fromPositionUs= */
0, /* contentResumeOffsetUs= */
0, /* adDurationsUs...= */
200_000);
adPlaybackState = addAdGroupToAdPlaybackState(adPlaybackState, /* fromPositionUs= */
400_000, /* contentResumeOffsetUs= */
1_000_000, /* adDurationsUs...= */
300_000);
AdPlaybackState firstAdPlaybackState = addAdGroupToAdPlaybackState(adPlaybackState, /* fromPositionUs= */
900_000, /* contentResumeOffsetUs= */
0, /* adDurationsUs...= */
100_000);
AtomicReference<ServerSideAdInsertionMediaSource> mediaSourceRef = new AtomicReference<>();
mediaSourceRef.set(new ServerSideAdInsertionMediaSource(new DefaultMediaSourceFactory(context).createMediaSource(MediaItem.fromUri(TEST_ASSET)), contentTimeline -> {
Object periodUid = checkNotNull(contentTimeline.getPeriod(/* periodIndex= */
0, new Timeline.Period(), /* setIds= */
true).uid);
mediaSourceRef.get().setAdPlaybackStates(ImmutableMap.of(periodUid, firstAdPlaybackState));
return true;
}));
AnalyticsListener listener = mock(AnalyticsListener.class);
player.addAnalyticsListener(listener);
player.setMediaSource(mediaSourceRef.get());
player.prepare();
player.play();
runUntilPlaybackState(player, Player.STATE_ENDED);
player.release();
// Assert all samples have been played.
DumpFileAsserts.assertOutput(context, playbackOutput, TEST_ASSET_DUMP);
// Assert playback has been reported with ads: [ad0][content][ad1][content][ad2][content]
// 6*2(audio+video) format changes, 5 discontinuities between parts.
verify(listener, times(5)).onPositionDiscontinuity(any(), any(), any(), eq(Player.DISCONTINUITY_REASON_AUTO_TRANSITION));
verify(listener, times(12)).onDownstreamFormatChanged(any(), any());
// Assert renderers played through without reset (=decoders have been enabled only once).
verify(listener).onVideoEnabled(any(), any());
verify(listener).onAudioEnabled(any(), any());
// Assert playback progression was smooth (=no unexpected delays that cause audio to underrun)
verify(listener, never()).onAudioUnderrun(any(), anyInt(), anyLong(), anyLong());
}
use of com.google.android.exoplayer2.source.ads.AdPlaybackState in project ExoPlayer by google.
the class ServerSideAdInsertionUtilTest method getStreamPositionUsForContent_returnsCorrectPositions.
@Test
public void getStreamPositionUsForContent_returnsCorrectPositions() {
// stream: 0-- ad1 --200-- content --2100-- ad2 --2300-- content --4300-- ad3 --4500-- content
// content timeline: 0 - [ad1] - 100-2000 -[ad2] - 2000-4000 - [ad3] - 4400-end
AdPlaybackState state = new AdPlaybackState(ADS_ID, /* adGroupTimesUs...= */
0, 0, 0, 2000, 4000).withRemovedAdGroupCount(2).withAdCount(/* adGroupIndex= */
2, /* adCount= */
2).withAdCount(/* adGroupIndex= */
3, /* adCount= */
1).withAdCount(/* adGroupIndex= */
4, /* adCount= */
3).withContentResumeOffsetUs(/* adGroupIndex= */
2, /* contentResumeOffsetUs= */
100).withContentResumeOffsetUs(/* adGroupIndex= */
3, /* contentResumeOffsetUs= */
0).withContentResumeOffsetUs(/* adGroupIndex= */
4, /* contentResumeOffsetUs= */
400).withAdDurationsUs(/* adGroupIndex= */
2, /* adDurationsUs...= */
150, 50).withAdDurationsUs(/* adGroupIndex= */
3, /* adDurationsUs...= */
200).withAdDurationsUs(/* adGroupIndex= */
4, /* adDurationsUs...= */
50, 50, 100);
assertThat(getStreamPositionUsForContent(/* positionUs= */
0, /* nextAdGroupIndex= */
2, state)).isEqualTo(0);
assertThat(getStreamPositionUsForContent(/* positionUs= */
0, /* nextAdGroupIndex= */
3, state)).isEqualTo(100);
assertThat(getStreamPositionUsForContent(/* positionUs= */
0, /* nextAdGroupIndex= */
C.INDEX_UNSET, state)).isEqualTo(100);
assertThat(getStreamPositionUsForContent(/* positionUs= */
50, /* nextAdGroupIndex= */
2, state)).isEqualTo(50);
assertThat(getStreamPositionUsForContent(/* positionUs= */
50, /* nextAdGroupIndex= */
3, state)).isEqualTo(150);
assertThat(getStreamPositionUsForContent(/* positionUs= */
50, /* nextAdGroupIndex= */
C.INDEX_UNSET, state)).isEqualTo(150);
assertThat(getStreamPositionUsForContent(/* positionUs= */
100, /* nextAdGroupIndex= */
3, state)).isEqualTo(200);
assertThat(getStreamPositionUsForContent(/* positionUs= */
100, /* nextAdGroupIndex= */
C.INDEX_UNSET, state)).isEqualTo(200);
assertThat(getStreamPositionUsForContent(/* positionUs= */
1999, /* nextAdGroupIndex= */
3, state)).isEqualTo(2099);
assertThat(getStreamPositionUsForContent(/* positionUs= */
1999, /* nextAdGroupIndex= */
C.INDEX_UNSET, state)).isEqualTo(2099);
assertThat(getStreamPositionUsForContent(/* positionUs= */
2000, /* nextAdGroupIndex= */
3, state)).isEqualTo(2100);
assertThat(getStreamPositionUsForContent(/* positionUs= */
2000, /* nextAdGroupIndex= */
4, state)).isEqualTo(2300);
assertThat(getStreamPositionUsForContent(/* positionUs= */
2000, /* nextAdGroupIndex= */
C.INDEX_UNSET, state)).isEqualTo(2300);
assertThat(getStreamPositionUsForContent(/* positionUs= */
3999, /* nextAdGroupIndex= */
4, state)).isEqualTo(4299);
assertThat(getStreamPositionUsForContent(/* positionUs= */
3999, /* nextAdGroupIndex= */
C.INDEX_UNSET, state)).isEqualTo(4299);
assertThat(getStreamPositionUsForContent(/* positionUs= */
4000, /* nextAdGroupIndex= */
4, state)).isEqualTo(4300);
assertThat(getStreamPositionUsForContent(/* positionUs= */
4000, /* nextAdGroupIndex= */
C.INDEX_UNSET, state)).isEqualTo(4300);
assertThat(getStreamPositionUsForContent(/* positionUs= */
4200, /* nextAdGroupIndex= */
C.INDEX_UNSET, state)).isEqualTo(4300);
assertThat(getStreamPositionUsForContent(/* positionUs= */
4300, /* nextAdGroupIndex= */
C.INDEX_UNSET, state)).isEqualTo(4400);
assertThat(getStreamPositionUsForContent(/* positionUs= */
4400, /* nextAdGroupIndex= */
C.INDEX_UNSET, state)).isEqualTo(4500);
}
use of com.google.android.exoplayer2.source.ads.AdPlaybackState in project ExoPlayer by google.
the class ServerSideAdInsertionUtilTest method getAdCountInGroup_withSetCount_returnsCount.
@Test
public void getAdCountInGroup_withSetCount_returnsCount() {
AdPlaybackState state = new AdPlaybackState(ADS_ID, /* adGroupTimesUs...= */
0, 2000).withAdCount(/* adGroupIndex= */
0, /* adCount= */
4).withAdCount(/* adGroupIndex= */
1, /* adCount= */
6);
assertThat(getAdCountInGroup(state, /* adGroupIndex= */
0)).isEqualTo(4);
assertThat(getAdCountInGroup(state, /* adGroupIndex= */
1)).isEqualTo(6);
}
use of com.google.android.exoplayer2.source.ads.AdPlaybackState in project ExoPlayer by google.
the class ServerSideAdInsertionUtilTest method getStreamPositionUsForAd_returnsCorrectPositions.
@Test
public void getStreamPositionUsForAd_returnsCorrectPositions() {
// stream: 0-- ad1 --200-- content --2100-- ad2 --2300-- content --4300-- ad3 --4500-- content
// content timeline: 0 - [ad1] - 100-2000 -[ad2] - 2000-4000 - [ad3] - 4400-end
AdPlaybackState state = new AdPlaybackState(ADS_ID, /* adGroupTimesUs...= */
0, 0, 0, 2000, 4000).withRemovedAdGroupCount(2).withAdCount(/* adGroupIndex= */
2, /* adCount= */
2).withAdCount(/* adGroupIndex= */
3, /* adCount= */
1).withAdCount(/* adGroupIndex= */
4, /* adCount= */
3).withContentResumeOffsetUs(/* adGroupIndex= */
2, /* contentResumeOffsetUs= */
100).withContentResumeOffsetUs(/* adGroupIndex= */
3, /* contentResumeOffsetUs= */
0).withContentResumeOffsetUs(/* adGroupIndex= */
4, /* contentResumeOffsetUs= */
400).withAdDurationsUs(/* adGroupIndex= */
2, /* adDurationsUs...= */
150, 50).withAdDurationsUs(/* adGroupIndex= */
3, /* adDurationsUs...= */
200).withAdDurationsUs(/* adGroupIndex= */
4, /* adDurationsUs...= */
50, 50, 100);
assertThat(getStreamPositionUsForAd(/* positionUs= */
0, /* adGroupIndex= */
2, /* adIndexInAdGroup= */
0, state)).isEqualTo(0);
assertThat(getStreamPositionUsForAd(/* positionUs= */
100, /* adGroupIndex= */
2, /* adIndexInAdGroup= */
0, state)).isEqualTo(100);
assertThat(getStreamPositionUsForAd(/* positionUs= */
200, /* adGroupIndex= */
2, /* adIndexInAdGroup= */
0, state)).isEqualTo(200);
assertThat(getStreamPositionUsForAd(/* positionUs= */
-50, /* adGroupIndex= */
2, /* adIndexInAdGroup= */
1, state)).isEqualTo(100);
assertThat(getStreamPositionUsForAd(/* positionUs= */
0, /* adGroupIndex= */
2, /* adIndexInAdGroup= */
1, state)).isEqualTo(150);
assertThat(getStreamPositionUsForAd(/* positionUs= */
100, /* adGroupIndex= */
2, /* adIndexInAdGroup= */
1, state)).isEqualTo(250);
assertThat(getStreamPositionUsForAd(/* positionUs= */
-50, /* adGroupIndex= */
3, /* adIndexInAdGroup= */
0, state)).isEqualTo(2050);
assertThat(getStreamPositionUsForAd(/* positionUs= */
0, /* adGroupIndex= */
3, /* adIndexInAdGroup= */
0, state)).isEqualTo(2100);
assertThat(getStreamPositionUsForAd(/* positionUs= */
200, /* adGroupIndex= */
3, /* adIndexInAdGroup= */
0, state)).isEqualTo(2300);
assertThat(getStreamPositionUsForAd(/* positionUs= */
300, /* adGroupIndex= */
3, /* adIndexInAdGroup= */
0, state)).isEqualTo(2400);
assertThat(getStreamPositionUsForAd(/* positionUs= */
-50, /* adGroupIndex= */
4, /* adIndexInAdGroup= */
0, state)).isEqualTo(4250);
assertThat(getStreamPositionUsForAd(/* positionUs= */
0, /* adGroupIndex= */
4, /* adIndexInAdGroup= */
0, state)).isEqualTo(4300);
assertThat(getStreamPositionUsForAd(/* positionUs= */
100, /* adGroupIndex= */
4, /* adIndexInAdGroup= */
0, state)).isEqualTo(4400);
assertThat(getStreamPositionUsForAd(/* positionUs= */
-50, /* adGroupIndex= */
4, /* adIndexInAdGroup= */
1, state)).isEqualTo(4300);
assertThat(getStreamPositionUsForAd(/* positionUs= */
0, /* adGroupIndex= */
4, /* adIndexInAdGroup= */
1, state)).isEqualTo(4350);
assertThat(getStreamPositionUsForAd(/* positionUs= */
100, /* adGroupIndex= */
4, /* adIndexInAdGroup= */
1, state)).isEqualTo(4450);
assertThat(getStreamPositionUsForAd(/* positionUs= */
-50, /* adGroupIndex= */
4, /* adIndexInAdGroup= */
2, state)).isEqualTo(4350);
assertThat(getStreamPositionUsForAd(/* positionUs= */
50, /* adGroupIndex= */
4, /* adIndexInAdGroup= */
2, state)).isEqualTo(4450);
assertThat(getStreamPositionUsForAd(/* positionUs= */
150, /* adGroupIndex= */
4, /* adIndexInAdGroup= */
2, state)).isEqualTo(4550);
}
Aggregations