Commit 57282f61 by tonihei Committed by Ian Baker

Simplify StreamRequest.Builder to an Uri Builder and make it public

Right now, the option to build an IMA DAI URI programmatically is still
package-private. To simplify the process, we can remove the StreamRequest
wrapper and directly provide an URI builder.

The same class can provide some package-private helper methods to parse the
created URI.

#minor-release

PiperOrigin-RevId: 427445326
parent 8554cf5a
......@@ -321,7 +321,10 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
private final com.google.ads.interactivemedia.v3.api.AdsLoader adsLoader;
@Nullable private final AdEventListener applicationAdEventListener;
@Nullable private final AdErrorListener applicationAdErrorListener;
private final ServerSideAdInsertionStreamRequest streamRequest;
private final boolean isLiveStream;
private final String adsId;
private final StreamRequest streamRequest;
private final int loadVideoTimeoutMs;
private final StreamPlayer streamPlayer;
private final Handler mainHandler;
private final ComponentListener componentListener;
......@@ -352,7 +355,10 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
adPlaybackState = AdPlaybackState.NONE;
mainHandler = Util.createHandlerForCurrentLooper();
Uri streamRequestUri = checkNotNull(mediaItem.localConfiguration).uri;
streamRequest = ServerSideAdInsertionStreamRequest.fromUri(streamRequestUri);
isLiveStream = ImaServerSideAdInsertionUriBuilder.isLiveStream(streamRequestUri);
adsId = ImaServerSideAdInsertionUriBuilder.getAdsId(streamRequestUri);
loadVideoTimeoutMs = ImaServerSideAdInsertionUriBuilder.getLoadVideoTimeoutMs(streamRequestUri);
streamRequest = ImaServerSideAdInsertionUriBuilder.createStreamRequest(streamRequestUri);
}
@Override
......@@ -369,10 +375,10 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
StreamManagerLoadable streamManagerLoadable =
new StreamManagerLoadable(
adsLoader,
streamRequest.getStreamRequest(),
streamRequest,
streamPlayer,
applicationAdErrorListener,
streamRequest.loadVideoTimeoutMs);
loadVideoTimeoutMs);
loader.startLoading(
streamManagerLoadable,
new StreamManagerLoadableCallback(),
......@@ -481,7 +487,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
if (!adPlaybackState.equals(AdPlaybackState.NONE) && contentTimeline != null) {
ImmutableMap<Object, AdPlaybackState> splitAdPlaybackStates =
splitAdPlaybackStateForPeriods(adPlaybackState, contentTimeline);
streamPlayer.setAdPlaybackStates(streamRequest.adsId, splitAdPlaybackStates, contentTimeline);
streamPlayer.setAdPlaybackStates(adsId, splitAdPlaybackStates, contentTimeline);
checkNotNull(serverSideAdInsertionMediaSource).setAdPlaybackStates(splitAdPlaybackStates);
}
}
......@@ -497,9 +503,9 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
contentMediaSourceFactory.createMediaSource(MediaItem.fromUri(contentUri)),
componentListener);
this.serverSideAdInsertionMediaSource = serverSideAdInsertionMediaSource;
if (streamRequest.isLiveStream()) {
if (isLiveStream) {
AdPlaybackState liveAdPlaybackState =
new AdPlaybackState(streamRequest.adsId)
new AdPlaybackState(adsId)
.withNewAdGroup(/* adGroupIndex= */ 0, /* adGroupTimeUs= */ C.TIME_END_OF_SOURCE)
.withIsServerSideInserted(/* adGroupIndex= */ 0, true);
mainHandler.post(() -> setAdPlaybackState(liveAdPlaybackState));
......@@ -612,7 +618,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
if (!mediaItem.equals(oldPosition.mediaItem)
|| !mediaItem.equals(newPosition.mediaItem)
|| !streamRequest.adsId.equals(
|| !adsId.equals(
player
.getCurrentTimeline()
.getPeriodByUid(checkNotNull(newPosition.periodUid), new Timeline.Period())
......@@ -646,7 +652,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
@Override
public void onMetadata(Metadata metadata) {
if (!isCurrentAdPlaying(player, mediaItem, streamRequest.adsId)) {
if (!isCurrentAdPlaying(player, mediaItem, adsId)) {
return;
}
for (int i = 0; i < metadata.length(); i++) {
......@@ -666,15 +672,14 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
@Override
public void onPlaybackStateChanged(@Player.State int state) {
if (state == Player.STATE_ENDED
&& isCurrentAdPlaying(player, mediaItem, streamRequest.adsId)) {
if (state == Player.STATE_ENDED && isCurrentAdPlaying(player, mediaItem, adsId)) {
streamPlayer.onContentCompleted();
}
}
@Override
public void onVolumeChanged(float volume) {
if (!isCurrentAdPlaying(player, mediaItem, streamRequest.adsId)) {
if (!isCurrentAdPlaying(player, mediaItem, adsId)) {
return;
}
int volumePct = (int) Math.floor(volume * 100);
......@@ -690,15 +695,14 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
switch (event.getType()) {
case CUEPOINTS_CHANGED:
// CUEPOINTS_CHANGED event is firing multiple times with the same queue points.
if (!streamRequest.isLiveStream() && newAdPlaybackState.equals(AdPlaybackState.NONE)) {
if (!isLiveStream && newAdPlaybackState.equals(AdPlaybackState.NONE)) {
newAdPlaybackState =
setVodAdGroupPlaceholders(
checkNotNull(streamManager).getCuePoints(),
new AdPlaybackState(streamRequest.adsId));
checkNotNull(streamManager).getCuePoints(), new AdPlaybackState(adsId));
}
break;
case LOADED:
if (streamRequest.isLiveStream()) {
if (isLiveStream) {
Timeline timeline = player.getCurrentTimeline();
Timeline.Window window =
timeline.getWindow(player.getCurrentMediaItemIndex(), new Timeline.Window());
......@@ -715,14 +719,14 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
event.getAd(),
currentPeriodPosition,
newAdPlaybackState.equals(AdPlaybackState.NONE)
? new AdPlaybackState(streamRequest.adsId)
? new AdPlaybackState(adsId)
: newAdPlaybackState);
} else {
newAdPlaybackState = setVodAdInPlaceholder(event.getAd(), newAdPlaybackState);
}
break;
case SKIPPED:
if (!streamRequest.isLiveStream()) {
if (!isLiveStream) {
newAdPlaybackState = skipAd(event.getAd(), newAdPlaybackState);
}
break;
......@@ -740,7 +744,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
mainHandler.post(() -> setContentTimeline(contentTimeline));
// Defer source refresh to ad playback state update for VOD. Refresh immediately when live
// with single period.
return !streamRequest.isLiveStream() || contentTimeline.getPeriodCount() > 1;
return !isLiveStream || contentTimeline.getPeriodCount() > 1;
}
}
......
......@@ -17,16 +17,20 @@ package com.google.android.exoplayer2.ext.ima;
import static com.google.common.truth.Truth.assertThat;
import android.net.Uri;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.ads.interactivemedia.v3.api.StreamRequest;
import com.google.ads.interactivemedia.v3.api.StreamRequest.StreamFormat;
import com.google.android.exoplayer2.C;
import java.util.HashMap;
import java.util.Map;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
/** Unit tests for {@link ServerSideAdInsertionStreamRequest}. */
/** Unit tests for {@link ImaServerSideAdInsertionUriBuilder}. */
@RunWith(AndroidJUnit4.class)
public final class ServerSideAdInsertionStreamRequestTest {
public final class ImaServerSideAdInsertionUriBuilderTest {
private static final String ADS_ID = "testAdsId";
private static final String ASSET_KEY = "testAssetKey";
......@@ -39,8 +43,6 @@ public final class ServerSideAdInsertionStreamRequestTest {
private static final String AUTH_TOKEN = "testAuthToken";
private static final String STREAM_ACTIVITY_MONITOR_ID = "testStreamActivityMonitorId";
private static final int ADS_LOADER_TIMEOUT_MS = 2;
private static final int FORMAT_DASH = 0;
private static final int FORMAT_HLS = 2;
private static final Map<String, String> adTagParameters = new HashMap<>();
static {
......@@ -49,9 +51,8 @@ public final class ServerSideAdInsertionStreamRequestTest {
}
@Test
public void build_live_correctUriAndParsing() {
ServerSideAdInsertionStreamRequest.Builder builder =
new ServerSideAdInsertionStreamRequest.Builder();
public void build_live_correctUriParsing() {
ImaServerSideAdInsertionUriBuilder builder = new ImaServerSideAdInsertionUriBuilder();
builder.setAdsId(ADS_ID);
builder.setAssetKey(ASSET_KEY);
builder.setApiKey(API_KEY);
......@@ -59,21 +60,34 @@ public final class ServerSideAdInsertionStreamRequestTest {
builder.setContentUrl(CONTENT_URL);
builder.setAuthToken(AUTH_TOKEN);
builder.setStreamActivityMonitorId(STREAM_ACTIVITY_MONITOR_ID);
builder.setFormat(FORMAT_HLS);
builder.setFormat(C.TYPE_HLS);
builder.setAdTagParameters(adTagParameters);
builder.setLoadVideoTimeoutMs(ADS_LOADER_TIMEOUT_MS);
ServerSideAdInsertionStreamRequest streamRequest = builder.build();
ServerSideAdInsertionStreamRequest requestAfterConversions =
ServerSideAdInsertionStreamRequest.fromUri(streamRequest.toUri());
assertThat(streamRequest).isEqualTo(requestAfterConversions);
Uri uri = builder.build();
StreamRequest streamRequest = ImaServerSideAdInsertionUriBuilder.createStreamRequest(uri);
assertThat(streamRequest.getAssetKey()).isEqualTo(ASSET_KEY);
assertThat(streamRequest.getApiKey()).isEqualTo(API_KEY);
assertThat(streamRequest.getManifestSuffix()).isEqualTo(MANIFEST_SUFFIX);
assertThat(streamRequest.getContentUrl()).isEqualTo(CONTENT_URL);
assertThat(streamRequest.getAuthToken()).isEqualTo(AUTH_TOKEN);
assertThat(streamRequest.getStreamActivityMonitorId()).isEqualTo(STREAM_ACTIVITY_MONITOR_ID);
assertThat(streamRequest.getFormat()).isEqualTo(StreamFormat.HLS);
assertThat(streamRequest.getAdTagParameters()).isEqualTo(adTagParameters);
boolean isLive = ImaServerSideAdInsertionUriBuilder.isLiveStream(uri);
assertThat(isLive).isTrue();
String adsId = ImaServerSideAdInsertionUriBuilder.getAdsId(uri);
assertThat(adsId).isEqualTo(ADS_ID);
int loadVideoTimeoutMs = ImaServerSideAdInsertionUriBuilder.getLoadVideoTimeoutMs(uri);
assertThat(loadVideoTimeoutMs).isEqualTo(ADS_LOADER_TIMEOUT_MS);
}
@Test
public void build_vod_correctUriAndParsing() {
ServerSideAdInsertionStreamRequest.Builder builder =
new ServerSideAdInsertionStreamRequest.Builder();
public void build_vod_correctUriParsing() {
ImaServerSideAdInsertionUriBuilder builder = new ImaServerSideAdInsertionUriBuilder();
builder.setAdsId(ADS_ID);
builder.setApiKey(API_KEY);
builder.setContentSourceId(CONTENT_SOURCE_ID);
......@@ -82,46 +96,60 @@ public final class ServerSideAdInsertionStreamRequestTest {
builder.setContentUrl(CONTENT_URL);
builder.setAuthToken(AUTH_TOKEN);
builder.setStreamActivityMonitorId(STREAM_ACTIVITY_MONITOR_ID);
builder.setFormat(FORMAT_DASH);
builder.setFormat(C.TYPE_DASH);
builder.setAdTagParameters(adTagParameters);
builder.setLoadVideoTimeoutMs(ADS_LOADER_TIMEOUT_MS);
ServerSideAdInsertionStreamRequest streamRequest = builder.build();
ServerSideAdInsertionStreamRequest requestAfterConversions =
ServerSideAdInsertionStreamRequest.fromUri(streamRequest.toUri());
assertThat(requestAfterConversions).isEqualTo(streamRequest);
Uri uri = builder.build();
StreamRequest streamRequest = ImaServerSideAdInsertionUriBuilder.createStreamRequest(uri);
assertThat(streamRequest.getApiKey()).isEqualTo(API_KEY);
assertThat(streamRequest.getContentSourceId()).isEqualTo(CONTENT_SOURCE_ID);
assertThat(streamRequest.getVideoId()).isEqualTo(VIDEO_ID);
assertThat(streamRequest.getManifestSuffix()).isEqualTo(MANIFEST_SUFFIX);
assertThat(streamRequest.getContentUrl()).isEqualTo(CONTENT_URL);
assertThat(streamRequest.getAuthToken()).isEqualTo(AUTH_TOKEN);
assertThat(streamRequest.getStreamActivityMonitorId()).isEqualTo(STREAM_ACTIVITY_MONITOR_ID);
assertThat(streamRequest.getFormat()).isEqualTo(StreamFormat.DASH);
assertThat(streamRequest.getAdTagParameters()).isEqualTo(adTagParameters);
boolean isLive = ImaServerSideAdInsertionUriBuilder.isLiveStream(uri);
assertThat(isLive).isFalse();
String adsId = ImaServerSideAdInsertionUriBuilder.getAdsId(uri);
assertThat(adsId).isEqualTo(ADS_ID);
int loadVideoTimeoutMs = ImaServerSideAdInsertionUriBuilder.getLoadVideoTimeoutMs(uri);
assertThat(loadVideoTimeoutMs).isEqualTo(ADS_LOADER_TIMEOUT_MS);
}
@Test
public void build_vodWithNoAdsId_usesVideoIdAsDefault() {
ServerSideAdInsertionStreamRequest.Builder builder =
new ServerSideAdInsertionStreamRequest.Builder();
ImaServerSideAdInsertionUriBuilder builder = new ImaServerSideAdInsertionUriBuilder();
builder.setContentSourceId(CONTENT_SOURCE_ID);
builder.setVideoId(VIDEO_ID);
builder.setFormat(C.TYPE_DASH);
ServerSideAdInsertionStreamRequest streamRequest = builder.build();
Uri streamRequest = builder.build();
assertThat(streamRequest.adsId).isEqualTo(VIDEO_ID);
assertThat(streamRequest.toUri().getQueryParameter("adsId")).isEqualTo(VIDEO_ID);
assertThat(ImaServerSideAdInsertionUriBuilder.getAdsId(streamRequest)).isEqualTo(VIDEO_ID);
assertThat(streamRequest.getQueryParameter("adsId")).isEqualTo(VIDEO_ID);
}
@Test
public void build_liveWithNoAdsId_usesAssetKeyAsDefault() {
ServerSideAdInsertionStreamRequest.Builder builder =
new ServerSideAdInsertionStreamRequest.Builder();
ImaServerSideAdInsertionUriBuilder builder = new ImaServerSideAdInsertionUriBuilder();
builder.setAssetKey(ASSET_KEY);
builder.setFormat(C.TYPE_DASH);
ServerSideAdInsertionStreamRequest streamRequest = builder.build();
Uri streamRequest = builder.build();
assertThat(streamRequest.adsId).isEqualTo(ASSET_KEY);
assertThat(streamRequest.toUri().getQueryParameter("adsId")).isEqualTo(ASSET_KEY);
assertThat(ImaServerSideAdInsertionUriBuilder.getAdsId(streamRequest)).isEqualTo(ASSET_KEY);
assertThat(streamRequest.getQueryParameter("adsId")).isEqualTo(ASSET_KEY);
}
@Test
public void build_assetKeyWithVideoId_throwsIllegalStateException() {
ServerSideAdInsertionStreamRequest.Builder requestBuilder =
new ServerSideAdInsertionStreamRequest.Builder();
ImaServerSideAdInsertionUriBuilder requestBuilder = new ImaServerSideAdInsertionUriBuilder();
requestBuilder.setAssetKey(ASSET_KEY);
requestBuilder.setVideoId(VIDEO_ID);
......@@ -130,8 +158,7 @@ public final class ServerSideAdInsertionStreamRequestTest {
@Test
public void build_assetKeyWithContentSource_throwsIllegalStateException() {
ServerSideAdInsertionStreamRequest.Builder requestBuilder =
new ServerSideAdInsertionStreamRequest.Builder();
ImaServerSideAdInsertionUriBuilder requestBuilder = new ImaServerSideAdInsertionUriBuilder();
requestBuilder.setAssetKey(ASSET_KEY);
requestBuilder.setContentSourceId(CONTENT_SOURCE_ID);
......@@ -140,9 +167,21 @@ public final class ServerSideAdInsertionStreamRequestTest {
@Test
public void build_withoutContentSourceAndVideoIdOrAssetKey_throwsIllegalStateException() {
ServerSideAdInsertionStreamRequest.Builder requestBuilder =
new ServerSideAdInsertionStreamRequest.Builder();
ImaServerSideAdInsertionUriBuilder requestBuilder = new ImaServerSideAdInsertionUriBuilder();
Assert.assertThrows(IllegalStateException.class, requestBuilder::build);
}
@Test
public void build_withoutLoadVideoTimeoutMs_usesDefaultTimeout() {
Uri uri =
new ImaServerSideAdInsertionUriBuilder()
.setAssetKey(ASSET_KEY)
.setFormat(C.TYPE_DASH)
.build();
int loadVideoTimeoutMs = ImaServerSideAdInsertionUriBuilder.getLoadVideoTimeoutMs(uri);
assertThat(loadVideoTimeoutMs)
.isEqualTo(ImaServerSideAdInsertionUriBuilder.DEFAULT_LOAD_VIDEO_TIMEOUT_MS);
}
}
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