diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index 23201b9b91b..ca4891ad37b 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -16,16 +16,15 @@
* Fix NPE in `TextRenderer` when playing content with a single subtitle
buffer ([#8017](https://github.com/google/ExoPlayer/issues/8017)).
* UI:
- * Do not require subtitleButton in custom layouts of StyledPlayerView
+ * Show overflow button in `StyledPlayerControlView` only when there is not
+ enough space.
+ * Fix animation when `StyledPlayerView` first shows its playback controls.
+ * Allow subtitleButton to be omitted in custom `StyledPlayerView` layouts
([#7962](https://github.com/google/ExoPlayer/issues/7962)).
- * Add the option to sort tracks by `Format` in `TrackSelectionView` and
+ * Add an option to sort tracks by `Format` in `TrackSelectionView` and
`TrackSelectionDialogBuilder`
([#7709](https://github.com/google/ExoPlayer/issues/7709)).
- * Adjusted bottom buttons' heights and paddings in StyledPlayerView for
- easy tapping.
- * Show overflow button in `StyledPlayerControlView` only when there is no
- enough space.
- * Fix animation when `StyledPlayerView` first shows its playback controls.
+ * Improve touch targets in `StyledPlayerView` to make tapping easier.
* Audio:
* Fix the default audio sink position not advancing correctly when using
`AudioTrack`-based speed adjustment
@@ -58,6 +57,8 @@
ad tag via media item playback properties continues to be supported.
This is in preparation for supporting ads in playlists
([#3750](https://github.com/google/ExoPlayer/issues/3750)).
+ * Add a way to override ad media MIME types
+ ([#7961)(https://github.com/google/ExoPlayer/issues/7961)).
### 2.12.0 (2020-09-11) ###
diff --git a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java
index f782443619b..08662ea3305 100644
--- a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java
+++ b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java
@@ -59,7 +59,9 @@
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline;
+import com.google.android.exoplayer2.source.MediaSourceFactory;
import com.google.android.exoplayer2.source.ads.AdPlaybackState;
+import com.google.android.exoplayer2.source.ads.AdsMediaSource;
import com.google.android.exoplayer2.source.ads.AdsMediaSource.AdLoadException;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.upstream.DataSpec;
@@ -94,18 +96,17 @@
*
See https://developers.google.com/interactive-media-ads/docs/sdks/android/compatibility for
* information on compatible ad tag formats. Pass the ad tag URI when setting media item playback
* properties (if using the media item API) or as a {@link DataSpec} when constructing the {@link
- * com.google.android.exoplayer2.source.ads.AdsMediaSource} (if using media sources directly). For
- * the latter case, please note that this implementation delegates loading of the data spec to the
- * IMA SDK, so range and headers specifications will be ignored in ad tag URIs. Literal ads
- * responses can be encoded as data scheme data specs, for example, by constructing the data spec
- * using a URI generated via {@link Util#getDataUriForString(String, String)}.
+ * AdsMediaSource} (if using media sources directly). For the latter case, please note that this
+ * implementation delegates loading of the data spec to the IMA SDK, so range and headers
+ * specifications will be ignored in ad tag URIs. Literal ads responses can be encoded as data
+ * scheme data specs, for example, by constructing the data spec using a URI generated via {@link
+ * Util#getDataUriForString(String, String)}.
*
*
The IMA SDK can report obstructions to the ad view for accurate viewability measurement. This
* means that any overlay views that obstruct the ad overlay but are essential for playback need to
- * be registered via the {@link AdViewProvider} passed to the {@link
- * com.google.android.exoplayer2.source.ads.AdsMediaSource}. See the
- * IMA SDK Open Measurement documentation for more information.
+ * be registered via the {@link AdViewProvider} passed to the {@link AdsMediaSource}. See the IMA
+ * SDK Open Measurement documentation for more information.
*/
public final class ImaAdsLoader
implements Player.EventListener, com.google.android.exoplayer2.source.ads.AdsLoader {
@@ -134,6 +135,7 @@ public static final class Builder {
@Nullable private AdErrorListener adErrorListener;
@Nullable private AdEventListener adEventListener;
@Nullable private VideoAdPlayer.VideoAdPlayerCallback videoAdPlayerCallback;
+ @Nullable private List adMediaMimeTypes;
@Nullable private Set adUiElements;
@Nullable private Collection companionAdSlots;
private long adPreloadTimeoutMs;
@@ -239,6 +241,23 @@ public Builder setCompanionAdSlots(Collection companionAdSlots)
return this;
}
+ /**
+ * Sets the MIME types to prioritize for linear ad media. If not specified, MIME types supported
+ * by the {@link MediaSourceFactory adMediaSourceFactory} used to construct the {@link
+ * AdsMediaSource} will be used.
+ *
+ * @param adMediaMimeTypes The MIME types to prioritize for linear ad media. May contain {@link
+ * MimeTypes#APPLICATION_MPD}, {@link MimeTypes#APPLICATION_M3U8}, {@link
+ * MimeTypes#VIDEO_MP4}, {@link MimeTypes#VIDEO_WEBM}, {@link MimeTypes#VIDEO_H263}, {@link
+ * MimeTypes#AUDIO_MP4} and {@link MimeTypes#AUDIO_MPEG}.
+ * @return This builder, for convenience.
+ * @see AdsRenderingSettings#setMimeTypes(List)
+ */
+ public Builder setAdMediaMimeTypes(List adMediaMimeTypes) {
+ this.adMediaMimeTypes = ImmutableList.copyOf(checkNotNull(adMediaMimeTypes));
+ return this;
+ }
+
/**
* Sets the duration in milliseconds for which the player must buffer while preloading an ad
* group before that ad group is skipped and marked as having failed to load. Pass {@link
@@ -340,9 +359,8 @@ public Builder setPlayAdBeforeStartPosition(boolean playAdBeforeStartPosition) {
* information on compatible ad tags.
* @return The new {@link ImaAdsLoader}.
* @deprecated Pass the ad tag URI when setting media item playback properties (if using the
- * media item API) or as a {@link DataSpec} when constructing the {@link
- * com.google.android.exoplayer2.source.ads.AdsMediaSource} (if using media sources
- * directly).
+ * media item API) or as a {@link DataSpec} when constructing the {@link AdsMediaSource} (if
+ * using media sources directly).
*/
@Deprecated
public ImaAdsLoader buildForAdTag(Uri adTagUri) {
@@ -362,9 +380,9 @@ public ImaAdsLoader buildForAdTag(Uri adTagUri) {
* @return The new {@link ImaAdsLoader}.
* @deprecated Pass the ads response as a data URI when setting media item playback properties
* (if using the media item API) or as a {@link DataSpec} when constructing the {@link
- * com.google.android.exoplayer2.source.ads.AdsMediaSource} (if using media sources
- * directly). {@link Util#getDataUriForString(String, String)} can be used to construct a
- * data URI from literal string ads response (with MIME type text/xml).
+ * AdsMediaSource} (if using media sources directly). {@link
+ * Util#getDataUriForString(String, String)} can be used to construct a data URI from
+ * literal string ads response (with MIME type text/xml).
*/
@Deprecated
public ImaAdsLoader buildForAdsResponse(String adsResponse) {
@@ -387,6 +405,7 @@ public ImaAdsLoader build() {
focusSkipButtonWhenAvailable,
playAdBeforeStartPosition,
mediaBitrate,
+ adMediaMimeTypes,
adUiElements,
companionAdSlots,
adErrorListener,
@@ -548,8 +567,7 @@ public ImaAdsLoader build() {
* more information.
* @deprecated Use {@link Builder} to create an instance. Pass the ad tag URI when setting media
* item playback properties (if using the media item API) or as a {@link DataSpec} when
- * constructing the {@link com.google.android.exoplayer2.source.ads.AdsMediaSource} (if using
- * media sources directly).
+ * constructing the {@link AdsMediaSource} (if using media sources directly).
*/
@Deprecated
public ImaAdsLoader(Context context, Uri adTagUri) {
@@ -988,7 +1006,10 @@ public void onPlayerError(ExoPlaybackException error) {
private AdsRenderingSettings setupAdsRendering() {
AdsRenderingSettings adsRenderingSettings = imaFactory.createAdsRenderingSettings();
adsRenderingSettings.setEnablePreloading(true);
- adsRenderingSettings.setMimeTypes(supportedMimeTypes);
+ adsRenderingSettings.setMimeTypes(
+ configuration.adMediaMimeTypes != null
+ ? configuration.adMediaMimeTypes
+ : supportedMimeTypes);
if (configuration.mediaLoadTimeoutMs != TIMEOUT_UNSET) {
adsRenderingSettings.setLoadVideoTimeout(configuration.mediaLoadTimeoutMs);
}
diff --git a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaUtil.java b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaUtil.java
index caaf6ae4bf0..2c7813bfd66 100644
--- a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaUtil.java
+++ b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaUtil.java
@@ -88,6 +88,7 @@ public static final class Configuration {
public final boolean focusSkipButtonWhenAvailable;
public final boolean playAdBeforeStartPosition;
public final int mediaBitrate;
+ @Nullable public final List adMediaMimeTypes;
@Nullable public final Set adUiElements;
@Nullable public final Collection companionAdSlots;
@Nullable public final AdErrorEvent.AdErrorListener applicationAdErrorListener;
@@ -102,6 +103,7 @@ public Configuration(
boolean focusSkipButtonWhenAvailable,
boolean playAdBeforeStartPosition,
int mediaBitrate,
+ @Nullable List adMediaMimeTypes,
@Nullable Set adUiElements,
@Nullable Collection companionAdSlots,
@Nullable AdErrorEvent.AdErrorListener applicationAdErrorListener,
@@ -114,6 +116,7 @@ public Configuration(
this.focusSkipButtonWhenAvailable = focusSkipButtonWhenAvailable;
this.playAdBeforeStartPosition = playAdBeforeStartPosition;
this.mediaBitrate = mediaBitrate;
+ this.adMediaMimeTypes = adMediaMimeTypes;
this.adUiElements = adUiElements;
this.companionAdSlots = companionAdSlots;
this.applicationAdErrorListener = applicationAdErrorListener;
diff --git a/extensions/ima/src/test/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoaderTest.java b/extensions/ima/src/test/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoaderTest.java
index dc6f5b517c6..d894466091e 100644
--- a/extensions/ima/src/test/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoaderTest.java
+++ b/extensions/ima/src/test/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoaderTest.java
@@ -64,6 +64,7 @@
import com.google.android.exoplayer2.testutil.FakeTimeline;
import com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition;
import com.google.android.exoplayer2.upstream.DataSpec;
+import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -754,6 +755,40 @@ public void requestAdTagWithUri_requestsWithAdTagUrl() throws Exception {
verify(mockAdsRequest).setAdTagUrl(TEST_DATA_SPEC.uri.toString());
}
+ @Test
+ public void setsDefaultMimeTypes() throws Exception {
+ setupPlayback(CONTENT_TIMELINE, ImmutableList.of(0f));
+ imaAdsLoader.setSupportedContentTypes(C.TYPE_DASH, C.TYPE_OTHER);
+ imaAdsLoader.start(adsLoaderListener, adViewProvider);
+
+ verify(mockAdsRenderingSettings)
+ .setMimeTypes(
+ ImmutableList.of(
+ MimeTypes.APPLICATION_MPD,
+ MimeTypes.VIDEO_MP4,
+ MimeTypes.VIDEO_WEBM,
+ MimeTypes.VIDEO_H263,
+ MimeTypes.AUDIO_MP4,
+ MimeTypes.AUDIO_MPEG));
+ }
+
+ @Test
+ public void buildWithAdMediaMimeTypes_setsMimeTypes() throws Exception {
+ setupPlayback(
+ CONTENT_TIMELINE,
+ ImmutableList.of(0f),
+ new ImaAdsLoader.Builder(getApplicationContext())
+ .setImaFactory(mockImaFactory)
+ .setImaSdkSettings(mockImaSdkSettings)
+ .setAdMediaMimeTypes(ImmutableList.of(MimeTypes.AUDIO_MPEG))
+ .build(),
+ TEST_DATA_SPEC);
+ imaAdsLoader.setSupportedContentTypes(C.TYPE_OTHER);
+ imaAdsLoader.start(adsLoaderListener, adViewProvider);
+
+ verify(mockAdsRenderingSettings).setMimeTypes(ImmutableList.of(MimeTypes.AUDIO_MPEG));
+ }
+
@Test
public void stop_unregistersAllVideoControlOverlays() {
setupPlayback(CONTENT_TIMELINE, PREROLL_CUE_POINTS_SECONDS);