Promote IMA DAI API to stable

PiperOrigin-RevId: 626064956
This commit is contained in:
bachinger 2024-04-18 09:47:26 -07:00 committed by Copybara-Service
parent 300e83414d
commit 09f2cda43c
6 changed files with 70 additions and 13 deletions

View File

@ -29,6 +29,9 @@
* Effect:
* Muxers:
* IMA extension:
* Promote API that is required for apps to play
[DAI ad streams](https://developers.google.com/ad-manager/dynamic-ad-insertion/full-service)
to stable.
* Session:
* Hide seekbar in the media notification for live streams by not setting
the duration into the platform session metadata

24
api.txt
View File

@ -1388,6 +1388,29 @@ package androidx.media3.exoplayer.ima {
method public androidx.media3.exoplayer.ima.ImaAdsLoader build();
}
public final class ImaServerSideAdInsertionMediaSource implements androidx.media3.exoplayer.source.MediaSource {
}
public static final class ImaServerSideAdInsertionMediaSource.AdsLoader {
method public androidx.media3.exoplayer.ima.ImaServerSideAdInsertionMediaSource.AdsLoader.State release();
method public void setPlayer(androidx.media3.common.Player);
}
public static final class ImaServerSideAdInsertionMediaSource.AdsLoader.Builder {
ctor public ImaServerSideAdInsertionMediaSource.AdsLoader.Builder(android.content.Context, androidx.media3.common.AdViewProvider);
method public androidx.media3.exoplayer.ima.ImaServerSideAdInsertionMediaSource.AdsLoader build();
method public androidx.media3.exoplayer.ima.ImaServerSideAdInsertionMediaSource.AdsLoader.Builder setAdsLoaderState(androidx.media3.exoplayer.ima.ImaServerSideAdInsertionMediaSource.AdsLoader.State);
}
public static class ImaServerSideAdInsertionMediaSource.AdsLoader.State {
method public static androidx.media3.exoplayer.ima.ImaServerSideAdInsertionMediaSource.AdsLoader.State fromBundle(android.os.Bundle);
method public android.os.Bundle toBundle();
}
public static final class ImaServerSideAdInsertionMediaSource.Factory implements androidx.media3.exoplayer.source.MediaSource.Factory {
ctor public ImaServerSideAdInsertionMediaSource.Factory(androidx.media3.exoplayer.ima.ImaServerSideAdInsertionMediaSource.AdsLoader, androidx.media3.exoplayer.source.MediaSource.Factory);
}
}
package androidx.media3.exoplayer.source {
@ -1397,6 +1420,7 @@ package androidx.media3.exoplayer.source {
method public androidx.media3.exoplayer.source.DefaultMediaSourceFactory clearLocalAdInsertionComponents();
method public androidx.media3.exoplayer.source.DefaultMediaSourceFactory setDataSourceFactory(androidx.media3.datasource.DataSource.Factory);
method public androidx.media3.exoplayer.source.DefaultMediaSourceFactory setLocalAdInsertionComponents(androidx.media3.exoplayer.source.ads.AdsLoader.Provider, androidx.media3.common.AdViewProvider);
method public androidx.media3.exoplayer.source.DefaultMediaSourceFactory setServerSideAdInsertionMediaSourceFactory(@Nullable androidx.media3.exoplayer.source.MediaSource.Factory);
}
public interface MediaSource {

View File

@ -93,11 +93,8 @@ public class PlayerActivity extends AppCompatActivity
@Nullable private AdsLoader clientSideAdsLoader;
@OptIn(markerClass = UnstableApi.class)
@Nullable
private ImaServerSideAdInsertionMediaSource.AdsLoader serverSideAdsLoader;
@Nullable private ImaServerSideAdInsertionMediaSource.AdsLoader serverSideAdsLoader;
@OptIn(markerClass = UnstableApi.class)
private ImaServerSideAdInsertionMediaSource.AdsLoader.@MonotonicNonNull State
serverSideAdsLoaderState;
@ -301,7 +298,7 @@ public class PlayerActivity extends AppCompatActivity
return true;
}
@OptIn(markerClass = UnstableApi.class) // SSAI configuration
@OptIn(markerClass = UnstableApi.class) // DRM configuration
private MediaSource.Factory createMediaSourceFactory() {
DefaultDrmSessionManagerProvider drmSessionManagerProvider =
new DefaultDrmSessionManagerProvider();
@ -334,7 +331,6 @@ public class PlayerActivity extends AppCompatActivity
playerBuilder.setRenderersFactory(renderersFactory);
}
@OptIn(markerClass = UnstableApi.class)
private void configurePlayerWithServerSideAdsLoader() {
serverSideAdsLoader.setPlayer(player);
}
@ -403,7 +399,6 @@ public class PlayerActivity extends AppCompatActivity
}
}
@OptIn(markerClass = UnstableApi.class)
private void releaseServerSideAdsLoader() {
serverSideAdsLoaderState = serverSideAdsLoader.release();
serverSideAdsLoader = null;
@ -417,14 +412,12 @@ public class PlayerActivity extends AppCompatActivity
}
}
@OptIn(markerClass = UnstableApi.class)
private void saveServerSideAdsLoaderState(Bundle outState) {
if (serverSideAdsLoaderState != null) {
outState.putBundle(KEY_SERVER_SIDE_ADS_LOADER_STATE, serverSideAdsLoaderState.toBundle());
}
}
@OptIn(markerClass = UnstableApi.class)
private void restoreServerSideAdsLoaderState(Bundle savedInstanceState) {
Bundle adsLoaderStateBundle = savedInstanceState.getBundle(KEY_SERVER_SIDE_ADS_LOADER_STATE);
if (adsLoaderStateBundle != null) {
@ -513,7 +506,7 @@ public class PlayerActivity extends AppCompatActivity
private class PlayerErrorMessageProvider implements ErrorMessageProvider<PlaybackException> {
@OptIn(markerClass = androidx.media3.common.util.UnstableApi.class)
@OptIn(markerClass = UnstableApi.class) // Using decoder exceptions
@Override
public Pair<Integer, String> getErrorMessage(PlaybackException e) {
String errorString = getString(R.string.error_generic);
@ -554,7 +547,7 @@ public class PlayerActivity extends AppCompatActivity
return mediaItems;
}
@OptIn(markerClass = androidx.media3.common.util.UnstableApi.class)
@OptIn(markerClass = UnstableApi.class) // Using Download API
private static MediaItem maybeSetDownloadProperties(
MediaItem item, @Nullable DownloadRequest downloadRequest) {
if (downloadRequest == null) {

View File

@ -202,6 +202,7 @@ public abstract class BaseMediaSource implements MediaSource {
return !mediaSourceCallers.isEmpty();
}
@UnstableApi
@Override
public final void addEventListener(Handler handler, MediaSourceEventListener eventListener) {
Assertions.checkNotNull(handler);
@ -209,11 +210,13 @@ public abstract class BaseMediaSource implements MediaSource {
eventDispatcher.addEventListener(handler, eventListener);
}
@UnstableApi
@Override
public final void removeEventListener(MediaSourceEventListener eventListener) {
eventDispatcher.removeEventListener(eventListener);
}
@UnstableApi
@Override
public final void addDrmEventListener(Handler handler, DrmSessionEventListener eventListener) {
Assertions.checkNotNull(handler);
@ -221,11 +224,13 @@ public abstract class BaseMediaSource implements MediaSource {
drmEventDispatcher.addEventListener(handler, eventListener);
}
@UnstableApi
@Override
public final void removeDrmEventListener(DrmSessionEventListener eventListener) {
drmEventDispatcher.removeEventListener(eventListener);
}
@UnstableApi
@SuppressWarnings("deprecation") // Overriding deprecated method to make it final.
@Override
public final void prepareSource(
@ -233,6 +238,7 @@ public abstract class BaseMediaSource implements MediaSource {
prepareSource(caller, mediaTransferListener, PlayerId.UNSET);
}
@UnstableApi
@Override
public final void prepareSource(
MediaSourceCaller caller,
@ -253,6 +259,7 @@ public abstract class BaseMediaSource implements MediaSource {
}
}
@UnstableApi
@Override
public final void enable(MediaSourceCaller caller) {
Assertions.checkNotNull(looper);
@ -263,6 +270,7 @@ public abstract class BaseMediaSource implements MediaSource {
}
}
@UnstableApi
@Override
public final void disable(MediaSourceCaller caller) {
boolean wasEnabled = !enabledMediaSourceCallers.isEmpty();
@ -272,6 +280,7 @@ public abstract class BaseMediaSource implements MediaSource {
}
}
@UnstableApi
@Override
public final void releaseSource(MediaSourceCaller caller) {
mediaSourceCallers.remove(caller);

View File

@ -313,7 +313,6 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
* @return This factory, for convenience.
*/
@CanIgnoreReturnValue
@UnstableApi
public DefaultMediaSourceFactory setServerSideAdInsertionMediaSourceFactory(
@Nullable MediaSource.Factory serverSideAdInsertionMediaSourceFactory) {
this.serverSideAdInsertionMediaSourceFactory = serverSideAdInsertionMediaSourceFactory;

View File

@ -112,10 +112,10 @@ import java.util.Map;
import java.util.Objects;
/** MediaSource for IMA server side inserted ad streams. */
@UnstableApi
public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSource<Void> {
/** A listener to be notified of stream events. */
@UnstableApi
public interface StreamEventListener {
/**
@ -154,6 +154,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
this.contentMediaSourceFactory = contentMediaSourceFactory;
}
@UnstableApi
@CanIgnoreReturnValue
@Override
public MediaSource.Factory setLoadErrorHandlingPolicy(
@ -162,6 +163,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
return this;
}
@UnstableApi
@CanIgnoreReturnValue
@Override
public MediaSource.Factory setDrmSessionManagerProvider(
@ -170,11 +172,13 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
return this;
}
@UnstableApi
@Override
public @C.ContentType int[] getSupportedTypes() {
return contentMediaSourceFactory.getSupportedTypes();
}
@UnstableApi
@Override
public MediaSource createMediaSource(MediaItem mediaItem) {
checkNotNull(mediaItem.localConfiguration);
@ -248,6 +252,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
* @param imaSdkSettings The {@link ImaSdkSettings}.
* @return This builder, for convenience.
*/
@UnstableApi
@CanIgnoreReturnValue
public AdsLoader.Builder setImaSdkSettings(ImaSdkSettings imaSdkSettings) {
this.imaSdkSettings = imaSdkSettings;
@ -260,6 +265,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
* @param streamEventListener The stream event listener.
* @return This builder, for convenience.
*/
@UnstableApi
@CanIgnoreReturnValue
public AdsLoader.Builder setStreamEventListener(StreamEventListener streamEventListener) {
this.streamEventListener = streamEventListener;
@ -271,9 +277,14 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
* StreamManager#addAdEventListener(AdEventListener)} when the stream manager becomes
* available.
*
* <p>Note: This method can be considered a stable API as long as the {@link AdEventListener}
* is provided by the IMA library. We can't declare this method stable because we don't have
* the same guarantee from the library we depend on.
*
* @param adEventListener The ad event listener.
* @return This builder, for convenience.
*/
@UnstableApi
@CanIgnoreReturnValue
public AdsLoader.Builder setAdEventListener(AdEventListener adEventListener) {
this.adEventListener = adEventListener;
@ -285,9 +296,14 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
* StreamManager#addAdErrorListener(AdErrorEvent.AdErrorListener)} when the stream manager
* becomes available.
*
* <p>Note: This method can be considered a stable API as long as the {@link
* AdErrorEvent.AdErrorListener} is provided by the IMA library. We can't declare this method
* stable because we don't have the same guarantee from the library we depend on.
*
* @param adErrorListener The {@link AdErrorEvent.AdErrorListener}.
* @return This builder, for convenience.
*/
@UnstableApi
@CanIgnoreReturnValue
public AdsLoader.Builder setAdErrorListener(AdErrorEvent.AdErrorListener adErrorListener) {
this.adErrorListener = adErrorListener;
@ -301,6 +317,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
* @return This builder, for convenience.
* @see AdDisplayContainer#setCompanionSlots(Collection)
*/
@UnstableApi
@CanIgnoreReturnValue
public AdsLoader.Builder setCompanionAdSlots(Collection<CompanionAdSlot> companionAdSlots) {
this.companionAdSlots = ImmutableList.copyOf(companionAdSlots);
@ -330,6 +347,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
* @return This builder, for convenience.
* @see AdsRenderingSettings#setFocusSkipButtonWhenAvailable(boolean)
*/
@UnstableApi
@CanIgnoreReturnValue
public AdsLoader.Builder setFocusSkipButtonWhenAvailable(
boolean focusSkipButtonWhenAvailable) {
@ -405,6 +423,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
*
* @deprecated Use {@link #fromBundle} instead.
*/
@UnstableApi
@Deprecated
@SuppressWarnings("deprecation") // Deprecated instance of deprecated class
public static final Bundleable.Creator<State> CREATOR = State::fromBundle;
@ -458,6 +477,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
*
* @see StreamManager#focus()
*/
@UnstableApi
public void focusSkipButton() {
if (player == null) {
return;
@ -600,11 +620,13 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
adPlaybackState = adsLoader.getAdPlaybackState(adsId);
}
@UnstableApi
@Override
public synchronized MediaItem getMediaItem() {
return mediaItem;
}
@UnstableApi
@Override
public boolean canUpdateMediaItem(MediaItem mediaItem) {
MediaItem existingMediaItem = getMediaItem();
@ -619,11 +641,13 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
&& existingMediaItem.liveConfiguration.equals(mediaItem.liveConfiguration);
}
@UnstableApi
@Override
public synchronized void updateMediaItem(MediaItem mediaItem) {
this.mediaItem = mediaItem;
}
@UnstableApi
@Override
public void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) {
mainHandler.post(() -> assertSingleInstanceInPlaylist(checkNotNull(player)));
@ -646,6 +670,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
}
}
@UnstableApi
@Override
protected void onChildSourceInfoRefreshed(
Void childSourceId, MediaSource mediaSource, Timeline newTimeline) {
@ -662,17 +687,20 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
});
}
@UnstableApi
@Override
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
return checkNotNull(serverSideAdInsertionMediaSource)
.createPeriod(id, allocator, startPositionUs);
}
@UnstableApi
@Override
public void releasePeriod(MediaPeriod mediaPeriod) {
checkNotNull(serverSideAdInsertionMediaSource).releasePeriod(mediaPeriod);
}
@UnstableApi
@Override
public void maybeThrowSourceInfoRefreshError() throws IOException {
super.maybeThrowSourceInfoRefreshError();
@ -683,6 +711,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
}
}
@UnstableApi
@Override
protected void releaseSourceInternal() {
super.releaseSourceInternal();