Skip to content

Commit

Permalink
Integrate IMA SSAI samples in main demo app
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 429059793
  • Loading branch information
marcbaechinger authored and icbaker committed Feb 22, 2022
1 parent 899d458 commit 49bb768
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 30 deletions.
1 change: 1 addition & 0 deletions demos/main/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
<data android:scheme="content"/>
<data android:scheme="asset"/>
<data android:scheme="file"/>
<data android:scheme="ssai"/>
</intent-filter>
<intent-filter>
<action android:name="androidx.media3.demo.main.action.VIEW_LIST"/>
Expand Down
92 changes: 92 additions & 0 deletions demos/main/src/main/assets/media.exolist.json
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,98 @@
}
]
},
{
"name": "IMA DAI streams",
"samples": [
{
"name": "HLS VOD: Demo (skippable pre/post), single ads [30 s]",
"uri": "ssai://dai.google.com/?contentSourceId=2483977&videoId=ima-vod-skippable-test&format=2&adsId=1"
},
{
"name": "HLS VOD: Tears of Steel (pre/mid/mid/mid/post), single ads [10s]",
"uri": "ssai://dai.google.com/?contentSourceId=2528370&videoId=tears-of-steel&format=2&adsId=1"
},
{
"name": "HLS Live: Big Buck Bunny (mid), 3 ads each [10 s]",
"uri": "ssai://dai.google.com/?assetKey=sN_IYUG8STe1ZzhIIE_ksA&format=2&adsId=3"
},
{
"name": "DASH VOD: Tears of Steel (11 periods, pre/mid/post), 2/5/2 ads [5/10s]",
"uri": "ssai://dai.google.com/?contentSourceId=2559737&videoId=tos-dash&format=0&adsId=1"
},
{
"name": "Playlist: No ads - HLS VOD: Demo (skippable pre/post) - No ads",
"playlist": [
{
"uri": "https://html5demos.com/assets/dizzy.mp4"
},
{
"uri": "ssai://dai.google.com/?contentSourceId=2483977&videoId=ima-vod-skippable-test&format=2&adsId=1"
},
{
"uri": "https://html5demos.com/assets/dizzy.mp4"
}
]
},
{
"name": "Playlist: No ads - HLS VOD: Tears of steel (pre/mid/mid/mid/post) - No ads",
"playlist": [
{
"uri": "https://html5demos.com/assets/dizzy.mp4"
},
{
"uri": "ssai://dai.google.com/?contentSourceId=2528370&videoId=tears-of-steel&format=2&adsId=1"
},
{
"uri": "https://html5demos.com/assets/dizzy.mp4"
}
]
},
{
"name": "Playlist: No ads - HLS Live: Big Buck Bunny (mid) - No ads",
"playlist": [
{
"uri": "https://html5demos.com/assets/dizzy.mp4"
},
{
"uri": "ssai://dai.google.com/?assetKey=sN_IYUG8STe1ZzhIIE_ksA&format=2&adsId=3"
},
{
"uri": "https://html5demos.com/assets/dizzy.mp4"
}
]
},
{
"name": "Playlist: No ads - DASH VOD: Tears of Steel (11 periods, pre/mid/post) - No ads",
"playlist": [
{
"uri": "https://html5demos.com/assets/dizzy.mp4"
},
{
"uri": "ssai://dai.google.com/?contentSourceId=2559737&videoId=tos-dash&format=0&adsId=1"
},
{
"uri": "https://html5demos.com/assets/dizzy.mp4"
}
]
},
{
"name": "Playlist: Client-side Ads - DASH VOD: Tears of Steel (11 periods, pre/mid/post) - No ads",
"playlist": [
{
"uri": "https://storage.googleapis.com/exoplayer-test-media-1/mkv/android-screens-lavf-56.36.100-aac-avc-main-1280x720.mkv",
"ad_tag_uri": "https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/124319096/external/ad_rule_samples&ciu_szs=300x250&ad_rule=1&impl=s&gdfp_req=1&env=vp&output=vmap&unviewed_position_start=1&cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpost&cmsid=496&vid=short_onecue&correlator="
},
{
"uri": "ssai://dai.google.com/?contentSourceId=2559737&videoId=tos-dash&format=0&adsId=1"
},
{
"uri": "https://html5demos.com/assets/dizzy.mp4"
}
]
}
]
},
{
"name": "Playlists",
"samples": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
*/
package androidx.media3.demo.main;

import static androidx.media3.common.util.Assertions.checkNotNull;

import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
Expand All @@ -43,6 +41,7 @@
import androidx.media3.exoplayer.RenderersFactory;
import androidx.media3.exoplayer.drm.FrameworkMediaDrm;
import androidx.media3.exoplayer.ima.ImaAdsLoader;
import androidx.media3.exoplayer.ima.ImaServerSideAdInsertionMediaSource;
import androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.DecoderInitializationException;
import androidx.media3.exoplayer.mediacodec.MediaCodecUtil.DecoderQueryException;
import androidx.media3.exoplayer.offline.DownloadRequest;
Expand All @@ -57,6 +56,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;

/** An activity that plays media using {@link ExoPlayer}. */
public class PlayerActivity extends AppCompatActivity
Expand All @@ -65,6 +65,7 @@ public class PlayerActivity extends AppCompatActivity
// Saved instance state keys.

private static final String KEY_TRACK_SELECTION_PARAMETERS = "track_selection_parameters";
private static final String KEY_SERVER_SIDE_ADS_LOADER_STATE = "server_side_ads_loader_state";
private static final String KEY_ITEM_INDEX = "item_index";
private static final String KEY_POSITION = "position";
private static final String KEY_AUTO_PLAY = "auto_play";
Expand All @@ -88,7 +89,10 @@ public class PlayerActivity extends AppCompatActivity

// For ad playback only.

private AdsLoader adsLoader;
@Nullable private AdsLoader clientSideAdsLoader;
@Nullable private ImaServerSideAdInsertionMediaSource.AdsLoader serverSideAdsLoader;
private ImaServerSideAdInsertionMediaSource.AdsLoader.@MonotonicNonNull State
serverSideAdsLoaderState;

// Activity lifecycle.

Expand Down Expand Up @@ -116,6 +120,12 @@ public void onCreate(@Nullable Bundle savedInstanceState) {
startAutoPlay = savedInstanceState.getBoolean(KEY_AUTO_PLAY);
startItemIndex = savedInstanceState.getInt(KEY_ITEM_INDEX);
startPosition = savedInstanceState.getLong(KEY_POSITION);
Bundle adsLoaderStateBundle = savedInstanceState.getBundle(KEY_SERVER_SIDE_ADS_LOADER_STATE);
if (adsLoaderStateBundle != null) {
serverSideAdsLoaderState =
ImaServerSideAdInsertionMediaSource.AdsLoader.State.CREATOR.fromBundle(
adsLoaderStateBundle);
}
} else {
trackSelectionParameters =
new DefaultTrackSelector.ParametersBuilder(/* context= */ this).build();
Expand All @@ -127,7 +137,7 @@ public void onCreate(@Nullable Bundle savedInstanceState) {
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
releasePlayer();
releaseAdsLoader();
releaseClientSideAdsLoader();
clearStartPosition();
setIntent(intent);
}
Expand Down Expand Up @@ -179,7 +189,7 @@ public void onStop() {
@Override
public void onDestroy() {
super.onDestroy();
releaseAdsLoader();
releaseClientSideAdsLoader();
}

@Override
Expand Down Expand Up @@ -208,6 +218,9 @@ public void onSaveInstanceState(Bundle outState) {
outState.putBoolean(KEY_AUTO_PLAY, startAutoPlay);
outState.putInt(KEY_ITEM_INDEX, startItemIndex);
outState.putLong(KEY_POSITION, startPosition);
if (serverSideAdsLoaderState != null) {
outState.putBundle(KEY_SERVER_SIDE_ADS_LOADER_STATE, serverSideAdsLoaderState.toBundle());
}
}

// Activity input
Expand Down Expand Up @@ -261,17 +274,13 @@ protected boolean initializePlayer() {
intent.getBooleanExtra(IntentUtil.PREFER_EXTENSION_DECODERS_EXTRA, false);
RenderersFactory renderersFactory =
DemoUtil.buildRenderersFactory(/* context= */ this, preferExtensionDecoders);
MediaSource.Factory mediaSourceFactory =
new DefaultMediaSourceFactory(dataSourceFactory)
.setAdsLoaderProvider(this::getAdsLoader)
.setAdViewProvider(playerView);

trackSelector = new DefaultTrackSelector(/* context= */ this);
lastSeenTracksInfo = TracksInfo.EMPTY;
player =
new ExoPlayer.Builder(/* context= */ this)
.setRenderersFactory(renderersFactory)
.setMediaSourceFactory(mediaSourceFactory)
.setMediaSourceFactory(createMediaSourceFactory())
.setTrackSelector(trackSelector)
.build();
player.setTrackSelectionParameters(trackSelectionParameters);
Expand All @@ -280,6 +289,7 @@ protected boolean initializePlayer() {
player.setAudioAttributes(AudioAttributes.DEFAULT, /* handleAudioFocus= */ true);
player.setPlayWhenReady(startAutoPlay);
playerView.setPlayer(player);
serverSideAdsLoader.setPlayer(player);
debugViewHelper = new DebugTextViewHelper(player, debugTextView);
debugViewHelper.start();
}
Expand All @@ -293,6 +303,22 @@ protected boolean initializePlayer() {
return true;
}

private MediaSource.Factory createMediaSourceFactory() {
ImaServerSideAdInsertionMediaSource.AdsLoader.Builder serverSideAdLoaderBuilder =
new ImaServerSideAdInsertionMediaSource.AdsLoader.Builder(/* context= */ this, playerView);
if (serverSideAdsLoaderState != null) {
serverSideAdLoaderBuilder.setAdsLoaderState(serverSideAdsLoaderState);
}
serverSideAdsLoader = serverSideAdLoaderBuilder.build();
ImaServerSideAdInsertionMediaSource.Factory imaServerSideAdInsertionMediaSourceFactory =
new ImaServerSideAdInsertionMediaSource.Factory(
serverSideAdsLoader, new DefaultMediaSourceFactory(dataSourceFactory));
return new DefaultMediaSourceFactory(dataSourceFactory)
.setAdsLoaderProvider(this::getClientSideAdsLoader)
.setAdViewProvider(playerView)
.setServerSideAdInsertionMediaSourceFactory(imaServerSideAdInsertionMediaSourceFactory);
}

private List<MediaItem> createMediaItems(Intent intent) {
String action = intent.getAction();
boolean actionIsListView = IntentUtil.ACTION_VIEW_LIST.equals(action);
Expand All @@ -304,7 +330,6 @@ private List<MediaItem> createMediaItems(Intent intent) {

List<MediaItem> mediaItems =
createMediaItems(intent, DemoUtil.getDownloadTracker(/* context= */ this));
boolean hasAds = false;
for (int i = 0; i < mediaItems.size(); i++) {
MediaItem mediaItem = mediaItems.get(i);

Expand All @@ -318,8 +343,7 @@ private List<MediaItem> createMediaItems(Intent intent) {
return Collections.emptyList();
}

MediaItem.DrmConfiguration drmConfiguration =
checkNotNull(mediaItem.localConfiguration).drmConfiguration;
MediaItem.DrmConfiguration drmConfiguration = mediaItem.localConfiguration.drmConfiguration;
if (drmConfiguration != null) {
if (Util.SDK_INT < 18) {
showToast(R.string.error_drm_unsupported_before_api_18);
Expand All @@ -331,43 +355,44 @@ private List<MediaItem> createMediaItems(Intent intent) {
return Collections.emptyList();
}
}
hasAds |= mediaItem.localConfiguration.adsConfiguration != null;
}
if (!hasAds) {
releaseAdsLoader();
}
return mediaItems;
}

private AdsLoader getAdsLoader(MediaItem.AdsConfiguration adsConfiguration) {
private AdsLoader getClientSideAdsLoader(MediaItem.AdsConfiguration adsConfiguration) {
// The ads loader is reused for multiple playbacks, so that ad playback can resume.
if (adsLoader == null) {
adsLoader = new ImaAdsLoader.Builder(/* context= */ this).build();
if (clientSideAdsLoader == null) {
clientSideAdsLoader = new ImaAdsLoader.Builder(/* context= */ this).build();
}
adsLoader.setPlayer(player);
return adsLoader;
clientSideAdsLoader.setPlayer(player);
return clientSideAdsLoader;
}

protected void releasePlayer() {
if (player != null) {
updateTrackSelectorParameters();
updateStartPosition();
serverSideAdsLoaderState = serverSideAdsLoader.release();
serverSideAdsLoader = null;
debugViewHelper.stop();
debugViewHelper = null;
player.release();
player = null;
playerView.setPlayer(/* player= */ null);
mediaItems = Collections.emptyList();
}
if (adsLoader != null) {
adsLoader.setPlayer(null);
if (clientSideAdsLoader != null) {
clientSideAdsLoader.setPlayer(null);
} else {
playerView.getAdViewGroup().removeAllViews();
}
}

private void releaseAdsLoader() {
if (adsLoader != null) {
adsLoader.release();
adsLoader = null;
playerView.getOverlayFrameLayout().removeAllViews();
private void releaseClientSideAdsLoader() {
if (clientSideAdsLoader != null) {
clientSideAdsLoader.release();
clientSideAdsLoader = null;
playerView.getAdViewGroup().removeAllViews();
}
}

Expand Down Expand Up @@ -490,7 +515,7 @@ private static List<MediaItem> createMediaItems(Intent intent, DownloadTracker d
for (MediaItem item : IntentUtil.createMediaItemsFromIntent(intent)) {
@Nullable
DownloadRequest downloadRequest =
downloadTracker.getDownloadRequest(checkNotNull(item.localConfiguration).uri);
downloadTracker.getDownloadRequest(item.localConfiguration.uri);
if (downloadRequest != null) {
MediaItem.Builder builder = item.buildUpon();
builder
Expand Down

0 comments on commit 49bb768

Please sign in to comment.