Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
9ea6be21
authored
Feb 16, 2022
by
bachinger
Committed by
Ian Baker
Feb 22, 2022
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Integrate IMA SSAI samples in main demo app
PiperOrigin-RevId: 429059793
parent
3db1d1f4
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
148 additions
and
30 deletions
demos/main/src/main/AndroidManifest.xml
demos/main/src/main/assets/media.exolist.json
demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java
demos/main/src/main/AndroidManifest.xml
View file @
9ea6be21
...
...
@@ -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=
"com.google.android.exoplayer.demo.action.VIEW_LIST"
/>
...
...
demos/main/src/main/assets/media.exolist.json
View file @
9ea6be21
...
...
@@ -388,6 +388,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"
:
[
{
...
...
demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java
View file @
9ea6be21
...
...
@@ -15,8 +15,6 @@
*/
package
com
.
google
.
android
.
exoplayer2
.
demo
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Assertions
.
checkNotNull
;
import
android.content.Intent
;
import
android.content.pm.PackageManager
;
import
android.os.Bundle
;
...
...
@@ -40,6 +38,7 @@ import com.google.android.exoplayer2.TracksInfo;
import
com.google.android.exoplayer2.audio.AudioAttributes
;
import
com.google.android.exoplayer2.drm.FrameworkMediaDrm
;
import
com.google.android.exoplayer2.ext.ima.ImaAdsLoader
;
import
com.google.android.exoplayer2.ext.ima.ImaServerSideAdInsertionMediaSource
;
import
com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.DecoderInitializationException
;
import
com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException
;
import
com.google.android.exoplayer2.offline.DownloadRequest
;
...
...
@@ -57,6 +56,7 @@ import com.google.android.exoplayer2.util.Util;
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
...
...
@@ -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"
;
...
...
@@ -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.
...
...
@@ -116,6 +120,12 @@ public class PlayerActivity extends AppCompatActivity
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
();
...
...
@@ -127,7 +137,7 @@ public class PlayerActivity extends AppCompatActivity
public
void
onNewIntent
(
Intent
intent
)
{
super
.
onNewIntent
(
intent
);
releasePlayer
();
releaseAdsLoader
();
release
ClientSide
AdsLoader
();
clearStartPosition
();
setIntent
(
intent
);
}
...
...
@@ -179,7 +189,7 @@ public class PlayerActivity extends AppCompatActivity
@Override
public
void
onDestroy
()
{
super
.
onDestroy
();
releaseAdsLoader
();
release
ClientSide
AdsLoader
();
}
@Override
...
...
@@ -208,6 +218,9 @@ public class PlayerActivity extends AppCompatActivity
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
...
...
@@ -261,17 +274,13 @@ public class PlayerActivity extends AppCompatActivity
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
);
...
...
@@ -280,6 +289,7 @@ public class PlayerActivity extends AppCompatActivity
player
.
setAudioAttributes
(
AudioAttributes
.
DEFAULT
,
/* handleAudioFocus= */
true
);
player
.
setPlayWhenReady
(
startAutoPlay
);
playerView
.
setPlayer
(
player
);
serverSideAdsLoader
.
setPlayer
(
player
);
debugViewHelper
=
new
DebugTextViewHelper
(
player
,
debugTextView
);
debugViewHelper
.
start
();
}
...
...
@@ -293,6 +303,22 @@ public class PlayerActivity extends AppCompatActivity
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
);
...
...
@@ -304,7 +330,6 @@ public class PlayerActivity extends AppCompatActivity
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
);
...
...
@@ -318,8 +343,7 @@ public class PlayerActivity extends AppCompatActivity
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
);
...
...
@@ -331,43 +355,44 @@ public class PlayerActivity extends AppCompatActivity
return
Collections
.
emptyList
();
}
}
hasAds
|=
mediaItem
.
localConfiguration
.
adsConfiguration
!=
null
;
}
if
(!
hasAds
)
{
releaseAdsLoader
();
}
return
mediaItems
;
}
private
AdsLoader
getAdsLoader
(
MediaItem
.
AdsConfiguration
adsConfiguration
)
{
private
AdsLoader
get
ClientSide
AdsLoader
(
MediaItem
.
AdsConfiguration
adsConfiguration
)
{
// The ads loader is reused for multiple playbacks, so that ad playback can resume.
if
(
a
dsLoader
==
null
)
{
a
dsLoader
=
new
ImaAdsLoader
.
Builder
(
/* context= */
this
).
build
();
if
(
clientSideA
dsLoader
==
null
)
{
clientSideA
dsLoader
=
new
ImaAdsLoader
.
Builder
(
/* context= */
this
).
build
();
}
a
dsLoader
.
setPlayer
(
player
);
return
a
dsLoader
;
clientSideA
dsLoader
.
setPlayer
(
player
);
return
clientSideA
dsLoader
;
}
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
(
a
dsLoader
!=
null
)
{
a
dsLoader
.
release
();
a
dsLoader
=
null
;
playerView
.
get
OverlayFrameLayout
().
removeAllViews
();
private
void
release
ClientSide
AdsLoader
()
{
if
(
clientSideA
dsLoader
!=
null
)
{
clientSideA
dsLoader
.
release
();
clientSideA
dsLoader
=
null
;
playerView
.
get
AdViewGroup
().
removeAllViews
();
}
}
...
...
@@ -490,7 +515,7 @@ public class PlayerActivity extends AppCompatActivity
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
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment