diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 99783b63e3..98ac2c62e7 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -4,6 +4,8 @@ * Core Library: * Move `com.google.android.exoplayer2.device.DeviceInfo` to `com.google.android.exoplayer2.DeviceInfo`. + * Make `ExoPlayer.Builder` return a `SimpleExoPlayer` instance. + * Deprecate `SimpleExoPlayer.Builder`. Use `ExoPlayer.Builder` instead. * Android 12 compatibility: * Disable platform transcoding when playing content URIs on Android 12. * Add `ExoPlayer.setVideoChangeFrameRateStrategy` to allow disabling of diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java index b4a9ab2980..fff434fb99 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java @@ -23,6 +23,7 @@ import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.TextureView; +import androidx.annotation.IntRange; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.google.android.exoplayer2.analytics.AnalyticsCollector; @@ -33,6 +34,8 @@ import com.google.android.exoplayer2.audio.AudioSink; import com.google.android.exoplayer2.audio.AuxEffectInfo; import com.google.android.exoplayer2.audio.DefaultAudioSink; import com.google.android.exoplayer2.audio.MediaCodecAudioRenderer; +import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory; +import com.google.android.exoplayer2.extractor.ExtractorsFactory; import com.google.android.exoplayer2.metadata.MetadataOutput; import com.google.android.exoplayer2.metadata.MetadataRenderer; import com.google.android.exoplayer2.source.DefaultMediaSourceFactory; @@ -47,8 +50,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelector; import com.google.android.exoplayer2.upstream.BandwidthMeter; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; -import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Clock; +import com.google.android.exoplayer2.util.PriorityTaskManager; import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.video.MediaCodecVideoRenderer; import com.google.android.exoplayer2.video.VideoFrameMetadataListener; @@ -59,7 +62,7 @@ import java.util.List; /** * An extensible media player that plays {@link MediaSource}s. Instances can be obtained from {@link - * SimpleExoPlayer.Builder}. + * Builder}. * *

Player components

* @@ -73,10 +76,10 @@ import java.util.List; *
  • {@link MediaSource MediaSources} that define the media to be played, load the media, * and from which the loaded media can be read. MediaSources are created from {@link MediaItem * MediaItems} by the {@link MediaSourceFactory} injected into the player {@link - * SimpleExoPlayer.Builder#setMediaSourceFactory Builder}, or can be added directly by methods - * like {@link #setMediaSource(MediaSource)}. The library provides a {@link - * DefaultMediaSourceFactory} for progressive media files, DASH, SmoothStreaming and HLS, - * which also includes functionality for side-loading subtitle files and clipping media. + * Builder#setMediaSourceFactory Builder}, or can be added directly by methods like {@link + * #setMediaSource(MediaSource)}. The library provides a {@link DefaultMediaSourceFactory} for + * progressive media files, DASH, SmoothStreaming and HLS, which also includes functionality + * for side-loading subtitle files and clipping media. *
  • {@link Renderer}s that render individual components of the media. The library * provides default implementations for common media types ({@link MediaCodecVideoRenderer}, * {@link MediaCodecAudioRenderer}, {@link TextRenderer} and {@link MetadataRenderer}). A @@ -505,12 +508,6 @@ public interface ExoPlayer extends Player { void setDeviceMuted(boolean muted); } - /** - * The default timeout for calls to {@link #release} and {@link #setForegroundMode}, in - * milliseconds. - */ - long DEFAULT_RELEASE_TIMEOUT_MS = 500; - /** * A listener for audio offload events. * @@ -519,7 +516,7 @@ public interface ExoPlayer extends Player { interface AudioOffloadListener { /** * Called when the player has started or stopped offload scheduling using {@link - * ExoPlayer#experimentalSetOffloadSchedulingEnabled(boolean)}. + * #experimentalSetOffloadSchedulingEnabled(boolean)}. * *

    This method is experimental, and will be renamed or removed in a future release. */ @@ -534,39 +531,28 @@ public interface ExoPlayer extends Player { } /** - * A builder for {@link ExoPlayer} instances. + * A builder for {@link SimpleExoPlayer} instances. * - *

    See {@link #Builder(Context, Renderer...)} for the list of default values. - * - * @deprecated Use {@link SimpleExoPlayer.Builder} instead. + *

    See {@link #Builder(Context)} for the list of default values. */ - @Deprecated + @SuppressWarnings("deprecation") final class Builder { - private final Renderer[] renderers; - - private Clock clock; - private TrackSelector trackSelector; - private MediaSourceFactory mediaSourceFactory; - private LoadControl loadControl; - private BandwidthMeter bandwidthMeter; - private Looper looper; - @Nullable private AnalyticsCollector analyticsCollector; - private boolean useLazyPreparation; - private SeekParameters seekParameters; - private boolean pauseAtEndOfMediaItems; - private long releaseTimeoutMs; - private LivePlaybackSpeedControl livePlaybackSpeedControl; - private boolean buildCalled; - - private long setForegroundModeTimeoutMs; + private final SimpleExoPlayer.Builder wrappedBuilder; /** - * Creates a builder with a list of {@link Renderer Renderers}. + * Creates a builder. + * + *

    Use {@link #Builder(Context, RenderersFactory)}, {@link #Builder(Context, + * RenderersFactory)} or {@link #Builder(Context, RenderersFactory, ExtractorsFactory)} instead, + * if you intend to provide a custom {@link RenderersFactory} or a custom {@link + * ExtractorsFactory}. This is to ensure that ProGuard or R8 can remove ExoPlayer's {@link + * DefaultRenderersFactory} and {@link DefaultExtractorsFactory} from the APK. * *

    The builder uses the following default values: * *

    * * @param context A {@link Context}. - * @param renderers The {@link Renderer Renderers} to be used by the player. */ - public Builder(Context context, Renderer... renderers) { - this( - renderers, - new DefaultTrackSelector(context), - new DefaultMediaSourceFactory(context), - new DefaultLoadControl(), - DefaultBandwidthMeter.getSingletonInstance(context)); + public Builder(Context context) { + wrappedBuilder = new SimpleExoPlayer.Builder(context); + } + + /** + * Creates a builder with a custom {@link RenderersFactory}. + * + *

    See {@link #Builder(Context)} for a list of default values. + * + * @param context A {@link Context}. + * @param renderersFactory A factory for creating {@link Renderer Renderers} to be used by the + * player. + */ + public Builder(Context context, RenderersFactory renderersFactory) { + wrappedBuilder = new SimpleExoPlayer.Builder(context, renderersFactory); + } + + /** + * Creates a builder with a custom {@link ExtractorsFactory}. + * + *

    See {@link #Builder(Context)} for a list of default values. + * + * @param context A {@link Context}. + * @param extractorsFactory An {@link ExtractorsFactory} used to extract progressive media from + * its container. + */ + public Builder(Context context, ExtractorsFactory extractorsFactory) { + wrappedBuilder = new SimpleExoPlayer.Builder(context, extractorsFactory); + } + + /** + * Creates a builder with a custom {@link RenderersFactory} and {@link ExtractorsFactory}. + * + *

    See {@link #Builder(Context)} for a list of default values. + * + * @param context A {@link Context}. + * @param renderersFactory A factory for creating {@link Renderer Renderers} to be used by the + * player. + * @param extractorsFactory An {@link ExtractorsFactory} used to extract progressive media from + * its container. + */ + public Builder( + Context context, RenderersFactory renderersFactory, ExtractorsFactory extractorsFactory) { + wrappedBuilder = new SimpleExoPlayer.Builder(context, renderersFactory, extractorsFactory); } /** @@ -601,44 +634,45 @@ public interface ExoPlayer extends Player { *

    Note that this constructor is only useful to try and ensure that ExoPlayer's default * components can be removed by ProGuard or R8. * - * @param renderers The {@link Renderer Renderers} to be used by the player. + * @param context A {@link Context}. + * @param renderersFactory A factory for creating {@link Renderer Renderers} to be used by the + * player. * @param trackSelector A {@link TrackSelector}. * @param mediaSourceFactory A {@link MediaSourceFactory}. * @param loadControl A {@link LoadControl}. * @param bandwidthMeter A {@link BandwidthMeter}. + * @param analyticsCollector An {@link AnalyticsCollector}. */ public Builder( - Renderer[] renderers, + Context context, + RenderersFactory renderersFactory, TrackSelector trackSelector, MediaSourceFactory mediaSourceFactory, LoadControl loadControl, - BandwidthMeter bandwidthMeter) { - Assertions.checkArgument(renderers.length > 0); - this.renderers = renderers; - this.trackSelector = trackSelector; - this.mediaSourceFactory = mediaSourceFactory; - this.loadControl = loadControl; - this.bandwidthMeter = bandwidthMeter; - looper = Util.getCurrentOrMainLooper(); - useLazyPreparation = true; - seekParameters = SeekParameters.DEFAULT; - livePlaybackSpeedControl = new DefaultLivePlaybackSpeedControl.Builder().build(); - clock = Clock.DEFAULT; - releaseTimeoutMs = DEFAULT_RELEASE_TIMEOUT_MS; + BandwidthMeter bandwidthMeter, + AnalyticsCollector analyticsCollector) { + wrappedBuilder = + new SimpleExoPlayer.Builder( + context, + renderersFactory, + trackSelector, + mediaSourceFactory, + loadControl, + bandwidthMeter, + analyticsCollector); } /** - * Set a limit on the time a call to {@link ExoPlayer#setForegroundMode} can spend. If a call to - * {@link ExoPlayer#setForegroundMode} takes more than {@code timeoutMs} milliseconds to - * complete, the player will raise an error via {@link Player.Listener#onPlayerError}. + * Set a limit on the time a call to {@link #setForegroundMode} can spend. If a call to {@link + * #setForegroundMode} takes more than {@code timeoutMs} milliseconds to complete, the player + * will raise an error via {@link Player.Listener#onPlayerError}. * *

    This method is experimental, and will be renamed or removed in a future release. * * @param timeoutMs The time limit in milliseconds. */ public Builder experimentalSetForegroundModeTimeoutMs(long timeoutMs) { - Assertions.checkState(!buildCalled); - setForegroundModeTimeoutMs = timeoutMs; + wrappedBuilder.experimentalSetForegroundModeTimeoutMs(timeoutMs); return this; } @@ -650,8 +684,7 @@ public interface ExoPlayer extends Player { * @throws IllegalStateException If {@link #build()} has already been called. */ public Builder setTrackSelector(TrackSelector trackSelector) { - Assertions.checkState(!buildCalled); - this.trackSelector = trackSelector; + wrappedBuilder.setTrackSelector(trackSelector); return this; } @@ -663,8 +696,7 @@ public interface ExoPlayer extends Player { * @throws IllegalStateException If {@link #build()} has already been called. */ public Builder setMediaSourceFactory(MediaSourceFactory mediaSourceFactory) { - Assertions.checkState(!buildCalled); - this.mediaSourceFactory = mediaSourceFactory; + wrappedBuilder.setMediaSourceFactory(mediaSourceFactory); return this; } @@ -676,8 +708,7 @@ public interface ExoPlayer extends Player { * @throws IllegalStateException If {@link #build()} has already been called. */ public Builder setLoadControl(LoadControl loadControl) { - Assertions.checkState(!buildCalled); - this.loadControl = loadControl; + wrappedBuilder.setLoadControl(loadControl); return this; } @@ -689,8 +720,7 @@ public interface ExoPlayer extends Player { * @throws IllegalStateException If {@link #build()} has already been called. */ public Builder setBandwidthMeter(BandwidthMeter bandwidthMeter) { - Assertions.checkState(!buildCalled); - this.bandwidthMeter = bandwidthMeter; + wrappedBuilder.setBandwidthMeter(bandwidthMeter); return this; } @@ -703,8 +733,7 @@ public interface ExoPlayer extends Player { * @throws IllegalStateException If {@link #build()} has already been called. */ public Builder setLooper(Looper looper) { - Assertions.checkState(!buildCalled); - this.looper = looper; + wrappedBuilder.setLooper(looper); return this; } @@ -716,8 +745,124 @@ public interface ExoPlayer extends Player { * @throws IllegalStateException If {@link #build()} has already been called. */ public Builder setAnalyticsCollector(AnalyticsCollector analyticsCollector) { - Assertions.checkState(!buildCalled); - this.analyticsCollector = analyticsCollector; + wrappedBuilder.setAnalyticsCollector(analyticsCollector); + return this; + } + + /** + * Sets an {@link PriorityTaskManager} that will be used by the player. + * + *

    The priority {@link C#PRIORITY_PLAYBACK} will be set while the player is loading. + * + * @param priorityTaskManager A {@link PriorityTaskManager}, or null to not use one. + * @return This builder. + * @throws IllegalStateException If {@link #build()} has already been called. + */ + public Builder setPriorityTaskManager(@Nullable PriorityTaskManager priorityTaskManager) { + wrappedBuilder.setPriorityTaskManager(priorityTaskManager); + return this; + } + + /** + * Sets {@link AudioAttributes} that will be used by the player and whether to handle audio + * focus. + * + *

    If audio focus should be handled, the {@link AudioAttributes#usage} must be {@link + * C#USAGE_MEDIA} or {@link C#USAGE_GAME}. Other usages will throw an {@link + * IllegalArgumentException}. + * + * @param audioAttributes {@link AudioAttributes}. + * @param handleAudioFocus Whether the player should handle audio focus. + * @return This builder. + * @throws IllegalStateException If {@link #build()} has already been called. + */ + public Builder setAudioAttributes(AudioAttributes audioAttributes, boolean handleAudioFocus) { + wrappedBuilder.setAudioAttributes(audioAttributes, handleAudioFocus); + return this; + } + + /** + * Sets the {@link C.WakeMode} that will be used by the player. + * + *

    Enabling this feature requires the {@link android.Manifest.permission#WAKE_LOCK} + * permission. It should be used together with a foreground {@link android.app.Service} for use + * cases where playback occurs and the screen is off (e.g. background audio playback). It is not + * useful when the screen will be kept on during playback (e.g. foreground video playback). + * + *

    When enabled, the locks ({@link android.os.PowerManager.WakeLock} / {@link + * android.net.wifi.WifiManager.WifiLock}) will be held whenever the player is in the {@link + * #STATE_READY} or {@link #STATE_BUFFERING} states with {@code playWhenReady = true}. The locks + * held depend on the specified {@link C.WakeMode}. + * + * @param wakeMode A {@link C.WakeMode}. + * @return This builder. + * @throws IllegalStateException If {@link #build()} has already been called. + */ + public Builder setWakeMode(@C.WakeMode int wakeMode) { + wrappedBuilder.setWakeMode(wakeMode); + return this; + } + + /** + * Sets whether the player should pause automatically when audio is rerouted from a headset to + * device speakers. See the + * audio becoming noisy documentation for more information. + * + * @param handleAudioBecomingNoisy Whether the player should pause automatically when audio is + * rerouted from a headset to device speakers. + * @return This builder. + * @throws IllegalStateException If {@link #build()} has already been called. + */ + public Builder setHandleAudioBecomingNoisy(boolean handleAudioBecomingNoisy) { + wrappedBuilder.setHandleAudioBecomingNoisy(handleAudioBecomingNoisy); + return this; + } + + /** + * Sets whether silences silences in the audio stream is enabled. + * + * @param skipSilenceEnabled Whether skipping silences is enabled. + * @return This builder. + * @throws IllegalStateException If {@link #build()} has already been called. + */ + public Builder setSkipSilenceEnabled(boolean skipSilenceEnabled) { + wrappedBuilder.setSkipSilenceEnabled(skipSilenceEnabled); + return this; + } + + /** + * Sets the {@link C.VideoScalingMode} that will be used by the player. + * + *

    The scaling mode only applies if a {@link MediaCodec}-based video {@link Renderer} is + * enabled and if the output surface is owned by a {@link SurfaceView}. + * + * @param videoScalingMode A {@link C.VideoScalingMode}. + * @return This builder. + * @throws IllegalStateException If {@link #build()} has already been called. + */ + public Builder setVideoScalingMode(@C.VideoScalingMode int videoScalingMode) { + wrappedBuilder.setVideoScalingMode(videoScalingMode); + return this; + } + + /** + * Sets a {@link C.VideoChangeFrameRateStrategy} that will be used by the player when provided + * with a video output {@link Surface}. + * + *

    The strategy only applies if a {@link MediaCodec}-based video {@link Renderer} is enabled. + * Applications wishing to use {@link Surface#CHANGE_FRAME_RATE_ALWAYS} should set the mode to + * {@link C#VIDEO_CHANGE_FRAME_RATE_STRATEGY_OFF} to disable calls to {@link + * Surface#setFrameRate} from ExoPlayer, and should then call {@link Surface#setFrameRate} + * directly from application code. + * + * @param videoChangeFrameRateStrategy A {@link C.VideoChangeFrameRateStrategy}. + * @return This builder. + * @throws IllegalStateException If {@link #build()} has already been called. + */ + public Builder setVideoChangeFrameRateStrategy( + @C.VideoChangeFrameRateStrategy int videoChangeFrameRateStrategy) { + wrappedBuilder.setVideoChangeFrameRateStrategy(videoChangeFrameRateStrategy); return this; } @@ -733,8 +878,7 @@ public interface ExoPlayer extends Player { * @throws IllegalStateException If {@link #build()} has already been called. */ public Builder setUseLazyPreparation(boolean useLazyPreparation) { - Assertions.checkState(!buildCalled); - this.useLazyPreparation = useLazyPreparation; + wrappedBuilder.setUseLazyPreparation(useLazyPreparation); return this; } @@ -746,8 +890,33 @@ public interface ExoPlayer extends Player { * @throws IllegalStateException If {@link #build()} has already been called. */ public Builder setSeekParameters(SeekParameters seekParameters) { - Assertions.checkState(!buildCalled); - this.seekParameters = seekParameters; + wrappedBuilder.setSeekParameters(seekParameters); + return this; + } + + /** + * Sets the {@link #seekBack()} increment. + * + * @param seekBackIncrementMs The seek back increment, in milliseconds. + * @return This builder. + * @throws IllegalArgumentException If {@code seekBackIncrementMs} is non-positive. + * @throws IllegalStateException If {@link #build()} has already been called. + */ + public Builder setSeekBackIncrementMs(@IntRange(from = 1) long seekBackIncrementMs) { + wrappedBuilder.setSeekBackIncrementMs(seekBackIncrementMs); + return this; + } + + /** + * Sets the {@link #seekForward()} increment. + * + * @param seekForwardIncrementMs The seek forward increment, in milliseconds. + * @return This builder. + * @throws IllegalArgumentException If {@code seekForwardIncrementMs} is non-positive. + * @throws IllegalStateException If {@link #build()} has already been called. + */ + public Builder setSeekForwardIncrementMs(@IntRange(from = 1) long seekForwardIncrementMs) { + wrappedBuilder.setSeekForwardIncrementMs(seekForwardIncrementMs); return this; } @@ -763,8 +932,23 @@ public interface ExoPlayer extends Player { * @throws IllegalStateException If {@link #build()} has already been called. */ public Builder setReleaseTimeoutMs(long releaseTimeoutMs) { - Assertions.checkState(!buildCalled); - this.releaseTimeoutMs = releaseTimeoutMs; + wrappedBuilder.setReleaseTimeoutMs(releaseTimeoutMs); + return this; + } + + /** + * Sets a timeout for detaching a surface from the player. + * + *

    If detaching a surface or replacing a surface takes more than {@code + * detachSurfaceTimeoutMs} to complete, the player will report an error via {@link + * Player.Listener#onPlayerError}. + * + * @param detachSurfaceTimeoutMs The timeout for detaching a surface, in milliseconds. + * @return This builder. + * @throws IllegalStateException If {@link #build()} has already been called. + */ + public Builder setDetachSurfaceTimeoutMs(long detachSurfaceTimeoutMs) { + wrappedBuilder.setDetachSurfaceTimeoutMs(detachSurfaceTimeoutMs); return this; } @@ -781,8 +965,7 @@ public interface ExoPlayer extends Player { * @throws IllegalStateException If {@link #build()} has already been called. */ public Builder setPauseAtEndOfMediaItems(boolean pauseAtEndOfMediaItems) { - Assertions.checkState(!buildCalled); - this.pauseAtEndOfMediaItems = pauseAtEndOfMediaItems; + wrappedBuilder.setPauseAtEndOfMediaItems(pauseAtEndOfMediaItems); return this; } @@ -795,8 +978,7 @@ public interface ExoPlayer extends Player { * @throws IllegalStateException If {@link #build()} has already been called. */ public Builder setLivePlaybackSpeedControl(LivePlaybackSpeedControl livePlaybackSpeedControl) { - Assertions.checkState(!buildCalled); - this.livePlaybackSpeedControl = livePlaybackSpeedControl; + wrappedBuilder.setLivePlaybackSpeedControl(livePlaybackSpeedControl); return this; } @@ -810,46 +992,29 @@ public interface ExoPlayer extends Player { */ @VisibleForTesting public Builder setClock(Clock clock) { - Assertions.checkState(!buildCalled); - this.clock = clock; + wrappedBuilder.setClock(clock); return this; } /** - * Builds an {@link ExoPlayer} instance. + * Builds a {@link SimpleExoPlayer} instance. * - * @throws IllegalStateException If {@code build} has already been called. + * @throws IllegalStateException If this method has already been called. */ - public ExoPlayer build() { - Assertions.checkState(!buildCalled); - buildCalled = true; - ExoPlayerImpl player = - new ExoPlayerImpl( - renderers, - trackSelector, - mediaSourceFactory, - loadControl, - bandwidthMeter, - analyticsCollector, - useLazyPreparation, - seekParameters, - C.DEFAULT_SEEK_BACK_INCREMENT_MS, - C.DEFAULT_SEEK_FORWARD_INCREMENT_MS, - livePlaybackSpeedControl, - releaseTimeoutMs, - pauseAtEndOfMediaItems, - clock, - looper, - /* wrappingPlayer= */ null, - /* additionalPermanentAvailableCommands= */ Commands.EMPTY); - - if (setForegroundModeTimeoutMs > 0) { - player.experimentalSetForegroundModeTimeoutMs(setForegroundModeTimeoutMs); - } - return player; + public SimpleExoPlayer build() { + return wrappedBuilder.build(); } } + /** + * The default timeout for calls to {@link #release} and {@link #setForegroundMode}, in + * milliseconds. + */ + long DEFAULT_RELEASE_TIMEOUT_MS = 500; + + /** The default timeout for detaching a surface from the player, in milliseconds. */ + long DEFAULT_DETACH_SURFACE_TIMEOUT_MS = 2_000; + /** * Equivalent to {@link Player#getPlayerError()}, except the exception is guaranteed to be an * {@link ExoPlaybackException}. diff --git a/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java b/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java index a8d4cce101..6f10613cfa 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java @@ -35,7 +35,6 @@ import android.graphics.Rect; import android.graphics.SurfaceTexture; import android.media.AudioFormat; import android.media.AudioTrack; -import android.media.MediaCodec; import android.media.MediaFormat; import android.os.Handler; import android.os.Looper; @@ -91,7 +90,7 @@ import java.util.concurrent.TimeoutException; /** * An {@link ExoPlayer} implementation that uses default {@link Renderer} components. Instances can - * be obtained from {@link SimpleExoPlayer.Builder}. + * be obtained from {@link ExoPlayer.Builder}. */ public class SimpleExoPlayer extends BasePlayer implements ExoPlayer, @@ -101,14 +100,9 @@ public class SimpleExoPlayer extends BasePlayer ExoPlayer.MetadataComponent, ExoPlayer.DeviceComponent { - /** The default timeout for detaching a surface from the player, in milliseconds. */ - public static final long DEFAULT_DETACH_SURFACE_TIMEOUT_MS = 2_000; - - /** - * A builder for {@link SimpleExoPlayer} instances. - * - *

    See {@link #Builder(Context)} for the list of default values. - */ + /** @deprecated Use {@link ExoPlayer.Builder} instead. */ + @Deprecated + @SuppressWarnings("deprecation") public static final class Builder { private final Context context; @@ -140,89 +134,29 @@ public class SimpleExoPlayer extends BasePlayer private boolean pauseAtEndOfMediaItems; private boolean buildCalled; - /** - * Creates a builder. - * - *

    Use {@link #Builder(Context, RenderersFactory)}, {@link #Builder(Context, - * RenderersFactory)} or {@link #Builder(Context, RenderersFactory, ExtractorsFactory)} instead, - * if you intend to provide a custom {@link RenderersFactory} or a custom {@link - * ExtractorsFactory}. This is to ensure that ProGuard or R8 can remove ExoPlayer's {@link - * DefaultRenderersFactory} and {@link DefaultExtractorsFactory} from the APK. - * - *

    The builder uses the following default values: - * - *

    - * - * @param context A {@link Context}. - */ + /** @deprecated Use {@link ExoPlayer.Builder#Builder(Context)} instead. */ + @Deprecated public Builder(Context context) { this(context, new DefaultRenderersFactory(context), new DefaultExtractorsFactory()); } - /** - * Creates a builder with a custom {@link RenderersFactory}. - * - *

    See {@link #Builder(Context)} for a list of default values. - * - * @param context A {@link Context}. - * @param renderersFactory A factory for creating {@link Renderer Renderers} to be used by the - * player. - */ + /** @deprecated Use {@link ExoPlayer.Builder#Builder(Context, RenderersFactory)} instead. */ + @Deprecated public Builder(Context context, RenderersFactory renderersFactory) { this(context, renderersFactory, new DefaultExtractorsFactory()); } - /** - * Creates a builder with a custom {@link ExtractorsFactory}. - * - *

    See {@link #Builder(Context)} for a list of default values. - * - * @param context A {@link Context}. - * @param extractorsFactory An {@link ExtractorsFactory} used to extract progressive media from - * its container. - */ + /** @deprecated Use {@link ExoPlayer.Builder#Builder(Context, ExtractorsFactory)} instead. */ + @Deprecated public Builder(Context context, ExtractorsFactory extractorsFactory) { this(context, new DefaultRenderersFactory(context), extractorsFactory); } /** - * Creates a builder with a custom {@link RenderersFactory} and {@link ExtractorsFactory}. - * - *

    See {@link #Builder(Context)} for a list of default values. - * - * @param context A {@link Context}. - * @param renderersFactory A factory for creating {@link Renderer Renderers} to be used by the - * player. - * @param extractorsFactory An {@link ExtractorsFactory} used to extract progressive media from - * its container. + * @deprecated Use {@link ExoPlayer.Builder#Builder(Context, RenderersFactory, + * ExtractorsFactory)} instead. */ + @Deprecated public Builder( Context context, RenderersFactory renderersFactory, ExtractorsFactory extractorsFactory) { this( @@ -236,20 +170,10 @@ public class SimpleExoPlayer extends BasePlayer } /** - * Creates a builder with the specified custom components. - * - *

    Note that this constructor is only useful to try and ensure that ExoPlayer's default - * components can be removed by ProGuard or R8. - * - * @param context A {@link Context}. - * @param renderersFactory A factory for creating {@link Renderer Renderers} to be used by the - * player. - * @param trackSelector A {@link TrackSelector}. - * @param mediaSourceFactory A {@link MediaSourceFactory}. - * @param loadControl A {@link LoadControl}. - * @param bandwidthMeter A {@link BandwidthMeter}. - * @param analyticsCollector An {@link AnalyticsCollector}. + * @deprecated Use {@link ExoPlayer.Builder#Builder(Context, RenderersFactory, TrackSelector, + * MediaSourceFactory, LoadControl, BandwidthMeter, AnalyticsCollector)} instead. */ + @Deprecated public Builder( Context context, RenderersFactory renderersFactory, @@ -276,32 +200,23 @@ public class SimpleExoPlayer extends BasePlayer seekForwardIncrementMs = C.DEFAULT_SEEK_FORWARD_INCREMENT_MS; livePlaybackSpeedControl = new DefaultLivePlaybackSpeedControl.Builder().build(); clock = Clock.DEFAULT; - releaseTimeoutMs = ExoPlayer.DEFAULT_RELEASE_TIMEOUT_MS; + releaseTimeoutMs = DEFAULT_RELEASE_TIMEOUT_MS; detachSurfaceTimeoutMs = DEFAULT_DETACH_SURFACE_TIMEOUT_MS; } /** - * Set a limit on the time a call to {@link #setForegroundMode} can spend. If a call to {@link - * #setForegroundMode} takes more than {@code timeoutMs} milliseconds to complete, the player - * will raise an error via {@link Player.Listener#onPlayerError}. - * - *

    This method is experimental, and will be renamed or removed in a future release. - * - * @param timeoutMs The time limit in milliseconds. + * @deprecated Use {@link ExoPlayer.Builder#experimentalSetForegroundModeTimeoutMs(long)} + * instead. */ + @Deprecated public Builder experimentalSetForegroundModeTimeoutMs(long timeoutMs) { Assertions.checkState(!buildCalled); foregroundModeTimeoutMs = timeoutMs; return this; } - /** - * Sets the {@link TrackSelector} that will be used by the player. - * - * @param trackSelector A {@link TrackSelector}. - * @return This builder. - * @throws IllegalStateException If {@link #build()} has already been called. - */ + /** @deprecated Use {@link ExoPlayer.Builder#setTrackSelector(TrackSelector)} instead. */ + @Deprecated public Builder setTrackSelector(TrackSelector trackSelector) { Assertions.checkState(!buildCalled); this.trackSelector = trackSelector; @@ -309,52 +224,33 @@ public class SimpleExoPlayer extends BasePlayer } /** - * Sets the {@link MediaSourceFactory} that will be used by the player. - * - * @param mediaSourceFactory A {@link MediaSourceFactory}. - * @return This builder. - * @throws IllegalStateException If {@link #build()} has already been called. + * @deprecated Use {@link ExoPlayer.Builder#setMediaSourceFactory(MediaSourceFactory)} instead. */ + @Deprecated public Builder setMediaSourceFactory(MediaSourceFactory mediaSourceFactory) { Assertions.checkState(!buildCalled); this.mediaSourceFactory = mediaSourceFactory; return this; } - /** - * Sets the {@link LoadControl} that will be used by the player. - * - * @param loadControl A {@link LoadControl}. - * @return This builder. - * @throws IllegalStateException If {@link #build()} has already been called. - */ + /** @deprecated Use {@link ExoPlayer.Builder#setLoadControl(LoadControl)} instead. */ + @Deprecated public Builder setLoadControl(LoadControl loadControl) { Assertions.checkState(!buildCalled); this.loadControl = loadControl; return this; } - /** - * Sets the {@link BandwidthMeter} that will be used by the player. - * - * @param bandwidthMeter A {@link BandwidthMeter}. - * @return This builder. - * @throws IllegalStateException If {@link #build()} has already been called. - */ + /** @deprecated Use {@link ExoPlayer.Builder#setBandwidthMeter(BandwidthMeter)} instead. */ + @Deprecated public Builder setBandwidthMeter(BandwidthMeter bandwidthMeter) { Assertions.checkState(!buildCalled); this.bandwidthMeter = bandwidthMeter; return this; } - /** - * Sets the {@link Looper} that must be used for all calls to the player and that is used to - * call listeners on. - * - * @param looper A {@link Looper}. - * @return This builder. - * @throws IllegalStateException If {@link #build()} has already been called. - */ + /** @deprecated Use {@link ExoPlayer.Builder#setLooper(Looper)} instead. */ + @Deprecated public Builder setLooper(Looper looper) { Assertions.checkState(!buildCalled); this.looper = looper; @@ -362,12 +258,9 @@ public class SimpleExoPlayer extends BasePlayer } /** - * Sets the {@link AnalyticsCollector} that will collect and forward all player events. - * - * @param analyticsCollector An {@link AnalyticsCollector}. - * @return This builder. - * @throws IllegalStateException If {@link #build()} has already been called. + * @deprecated Use {@link ExoPlayer.Builder#setAnalyticsCollector(AnalyticsCollector)} instead. */ + @Deprecated public Builder setAnalyticsCollector(AnalyticsCollector analyticsCollector) { Assertions.checkState(!buildCalled); this.analyticsCollector = analyticsCollector; @@ -375,14 +268,10 @@ public class SimpleExoPlayer extends BasePlayer } /** - * Sets an {@link PriorityTaskManager} that will be used by the player. - * - *

    The priority {@link C#PRIORITY_PLAYBACK} will be set while the player is loading. - * - * @param priorityTaskManager A {@link PriorityTaskManager}, or null to not use one. - * @return This builder. - * @throws IllegalStateException If {@link #build()} has already been called. + * @deprecated Use {@link ExoPlayer.Builder#setPriorityTaskManager(PriorityTaskManager)} + * instead. */ + @Deprecated public Builder setPriorityTaskManager(@Nullable PriorityTaskManager priorityTaskManager) { Assertions.checkState(!buildCalled); this.priorityTaskManager = priorityTaskManager; @@ -390,18 +279,10 @@ public class SimpleExoPlayer extends BasePlayer } /** - * Sets {@link AudioAttributes} that will be used by the player and whether to handle audio - * focus. - * - *

    If audio focus should be handled, the {@link AudioAttributes#usage} must be {@link - * C#USAGE_MEDIA} or {@link C#USAGE_GAME}. Other usages will throw an {@link - * IllegalArgumentException}. - * - * @param audioAttributes {@link AudioAttributes}. - * @param handleAudioFocus Whether the player should handle audio focus. - * @return This builder. - * @throws IllegalStateException If {@link #build()} has already been called. + * @deprecated Use {@link ExoPlayer.Builder#setAudioAttributes(AudioAttributes, boolean)} + * instead. */ + @Deprecated public Builder setAudioAttributes(AudioAttributes audioAttributes, boolean handleAudioFocus) { Assertions.checkState(!buildCalled); this.audioAttributes = audioAttributes; @@ -409,89 +290,40 @@ public class SimpleExoPlayer extends BasePlayer return this; } - /** - * Sets the {@link C.WakeMode} that will be used by the player. - * - *

    Enabling this feature requires the {@link android.Manifest.permission#WAKE_LOCK} - * permission. It should be used together with a foreground {@link android.app.Service} for use - * cases where playback occurs and the screen is off (e.g. background audio playback). It is not - * useful when the screen will be kept on during playback (e.g. foreground video playback). - * - *

    When enabled, the locks ({@link android.os.PowerManager.WakeLock} / {@link - * android.net.wifi.WifiManager.WifiLock}) will be held whenever the player is in the {@link - * #STATE_READY} or {@link #STATE_BUFFERING} states with {@code playWhenReady = true}. The locks - * held depend on the specified {@link C.WakeMode}. - * - * @param wakeMode A {@link C.WakeMode}. - * @return This builder. - * @throws IllegalStateException If {@link #build()} has already been called. - */ + /** @deprecated Use {@link ExoPlayer.Builder#setWakeMode(int)} instead. */ + @Deprecated public Builder setWakeMode(@C.WakeMode int wakeMode) { Assertions.checkState(!buildCalled); this.wakeMode = wakeMode; return this; } - /** - * Sets whether the player should pause automatically when audio is rerouted from a headset to - * device speakers. See the audio - * becoming noisy documentation for more information. - * - * @param handleAudioBecomingNoisy Whether the player should pause automatically when audio is - * rerouted from a headset to device speakers. - * @return This builder. - * @throws IllegalStateException If {@link #build()} has already been called. - */ + /** @deprecated Use {@link ExoPlayer.Builder#setHandleAudioBecomingNoisy(boolean)} instead. */ + @Deprecated public Builder setHandleAudioBecomingNoisy(boolean handleAudioBecomingNoisy) { Assertions.checkState(!buildCalled); this.handleAudioBecomingNoisy = handleAudioBecomingNoisy; return this; } - /** - * Sets whether silences silences in the audio stream is enabled. - * - * @param skipSilenceEnabled Whether skipping silences is enabled. - * @return This builder. - * @throws IllegalStateException If {@link #build()} has already been called. - */ + /** @deprecated Use {@link ExoPlayer.Builder#setSkipSilenceEnabled(boolean)} instead. */ + @Deprecated public Builder setSkipSilenceEnabled(boolean skipSilenceEnabled) { Assertions.checkState(!buildCalled); this.skipSilenceEnabled = skipSilenceEnabled; return this; } - /** - * Sets the {@link C.VideoScalingMode} that will be used by the player. - * - *

    The scaling mode only applies if a {@link MediaCodec}-based video {@link Renderer} is - * enabled and if the output surface is owned by a {@link SurfaceView}. - * - * @param videoScalingMode A {@link C.VideoScalingMode}. - * @return This builder. - * @throws IllegalStateException If {@link #build()} has already been called. - */ + /** @deprecated Use {@link ExoPlayer.Builder#setVideoScalingMode(int)} instead. */ + @Deprecated public Builder setVideoScalingMode(@C.VideoScalingMode int videoScalingMode) { Assertions.checkState(!buildCalled); this.videoScalingMode = videoScalingMode; return this; } - /** - * Sets a {@link C.VideoChangeFrameRateStrategy} that will be used by the player when provided - * with a video output {@link Surface}. - * - *

    The strategy only applies if a {@link MediaCodec}-based video {@link Renderer} is enabled. - * Applications wishing to use {@link Surface#CHANGE_FRAME_RATE_ALWAYS} should set the mode to - * {@link C#VIDEO_CHANGE_FRAME_RATE_STRATEGY_OFF} to disable calls to {@link - * Surface#setFrameRate} from ExoPlayer, and should then call {@link Surface#setFrameRate} - * directly from application code. - * - * @param videoChangeFrameRateStrategy A {@link C.VideoChangeFrameRateStrategy}. - * @return This builder. - * @throws IllegalStateException If {@link #build()} has already been called. - */ + /** @deprecated Use {@link ExoPlayer.Builder#setVideoChangeFrameRateStrategy(int)} instead. */ + @Deprecated public Builder setVideoChangeFrameRateStrategy( @C.VideoChangeFrameRateStrategy int videoChangeFrameRateStrategy) { Assertions.checkState(!buildCalled); @@ -499,44 +331,24 @@ public class SimpleExoPlayer extends BasePlayer return this; } - /** - * Sets whether media sources should be initialized lazily. - * - *

    If false, all initial preparation steps (e.g., manifest loads) happen immediately. If - * true, these initial preparations are triggered only when the player starts buffering the - * media. - * - * @param useLazyPreparation Whether to use lazy preparation. - * @return This builder. - * @throws IllegalStateException If {@link #build()} has already been called. - */ + /** @deprecated Use {@link ExoPlayer.Builder#setUseLazyPreparation(boolean)} instead. */ + @Deprecated public Builder setUseLazyPreparation(boolean useLazyPreparation) { Assertions.checkState(!buildCalled); this.useLazyPreparation = useLazyPreparation; return this; } - /** - * Sets the parameters that control how seek operations are performed. - * - * @param seekParameters The {@link SeekParameters}. - * @return This builder. - * @throws IllegalStateException If {@link #build()} has already been called. - */ + /** @deprecated Use {@link ExoPlayer.Builder#setSeekParameters(SeekParameters)} instead. */ + @Deprecated public Builder setSeekParameters(SeekParameters seekParameters) { Assertions.checkState(!buildCalled); this.seekParameters = seekParameters; return this; } - /** - * Sets the {@link #seekBack()} increment. - * - * @param seekBackIncrementMs The seek back increment, in milliseconds. - * @return This builder. - * @throws IllegalArgumentException If {@code seekBackIncrementMs} is non-positive. - * @throws IllegalStateException If {@link #build()} has already been called. - */ + /** @deprecated Use {@link ExoPlayer.Builder#setSeekBackIncrementMs(long)} instead. */ + @Deprecated public Builder setSeekBackIncrementMs(@IntRange(from = 1) long seekBackIncrementMs) { checkArgument(seekBackIncrementMs > 0); Assertions.checkState(!buildCalled); @@ -544,14 +356,8 @@ public class SimpleExoPlayer extends BasePlayer return this; } - /** - * Sets the {@link #seekForward()} increment. - * - * @param seekForwardIncrementMs The seek forward increment, in milliseconds. - * @return This builder. - * @throws IllegalArgumentException If {@code seekForwardIncrementMs} is non-positive. - * @throws IllegalStateException If {@link #build()} has already been called. - */ + /** @deprecated Use {@link ExoPlayer.Builder#setSeekForwardIncrementMs(long)} instead. */ + @Deprecated public Builder setSeekForwardIncrementMs(@IntRange(from = 1) long seekForwardIncrementMs) { checkArgument(seekForwardIncrementMs > 0); Assertions.checkState(!buildCalled); @@ -559,52 +365,24 @@ public class SimpleExoPlayer extends BasePlayer return this; } - /** - * Sets a timeout for calls to {@link #release} and {@link #setForegroundMode}. - * - *

    If a call to {@link #release} or {@link #setForegroundMode} takes more than {@code - * timeoutMs} to complete, the player will report an error via {@link - * Player.Listener#onPlayerError}. - * - * @param releaseTimeoutMs The release timeout, in milliseconds. - * @return This builder. - * @throws IllegalStateException If {@link #build()} has already been called. - */ + /** @deprecated Use {@link ExoPlayer.Builder#setReleaseTimeoutMs(long)} instead. */ + @Deprecated public Builder setReleaseTimeoutMs(long releaseTimeoutMs) { Assertions.checkState(!buildCalled); this.releaseTimeoutMs = releaseTimeoutMs; return this; } - /** - * Sets a timeout for detaching a surface from the player. - * - *

    If detaching a surface or replacing a surface takes more than {@code - * detachSurfaceTimeoutMs} to complete, the player will report an error via {@link - * Player.Listener#onPlayerError}. - * - * @param detachSurfaceTimeoutMs The timeout for detaching a surface, in milliseconds. - * @return This builder. - * @throws IllegalStateException If {@link #build()} has already been called. - */ + /** @deprecated Use {@link ExoPlayer.Builder#setDetachSurfaceTimeoutMs(long)} instead. */ + @Deprecated public Builder setDetachSurfaceTimeoutMs(long detachSurfaceTimeoutMs) { Assertions.checkState(!buildCalled); this.detachSurfaceTimeoutMs = detachSurfaceTimeoutMs; return this; } - /** - * Sets whether to pause playback at the end of each media item. - * - *

    This means the player will pause at the end of each window in the current {@link - * #getCurrentTimeline() timeline}. Listeners will be informed by a call to {@link - * Player.Listener#onPlayWhenReadyChanged(boolean, int)} with the reason {@link - * Player#PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM} when this happens. - * - * @param pauseAtEndOfMediaItems Whether to pause playback at the end of each media item. - * @return This builder. - * @throws IllegalStateException If {@link #build()} has already been called. - */ + /** @deprecated Use {@link ExoPlayer.Builder#setPauseAtEndOfMediaItems(boolean)} instead. */ + @Deprecated public Builder setPauseAtEndOfMediaItems(boolean pauseAtEndOfMediaItems) { Assertions.checkState(!buildCalled); this.pauseAtEndOfMediaItems = pauseAtEndOfMediaItems; @@ -612,27 +390,18 @@ public class SimpleExoPlayer extends BasePlayer } /** - * Sets the {@link LivePlaybackSpeedControl} that will control the playback speed when playing - * live streams, in order to maintain a steady target offset from the live stream edge. - * - * @param livePlaybackSpeedControl The {@link LivePlaybackSpeedControl}. - * @return This builder. - * @throws IllegalStateException If {@link #build()} has already been called. + * @deprecated Use {@link + * ExoPlayer.Builder#setLivePlaybackSpeedControl(LivePlaybackSpeedControl)} instead. */ + @Deprecated public Builder setLivePlaybackSpeedControl(LivePlaybackSpeedControl livePlaybackSpeedControl) { Assertions.checkState(!buildCalled); this.livePlaybackSpeedControl = livePlaybackSpeedControl; return this; } - /** - * Sets the {@link Clock} that will be used by the player. Should only be set for testing - * purposes. - * - * @param clock A {@link Clock}. - * @return This builder. - * @throws IllegalStateException If {@link #build()} has already been called. - */ + /** @deprecated Use {@link ExoPlayer.Builder#setClock(Clock)} instead. */ + @Deprecated @VisibleForTesting public Builder setClock(Clock clock) { Assertions.checkState(!buildCalled); @@ -640,11 +409,8 @@ public class SimpleExoPlayer extends BasePlayer return this; } - /** - * Builds a {@link SimpleExoPlayer} instance. - * - * @throws IllegalStateException If this method has already been called. - */ + /** @deprecated Use {@link ExoPlayer.Builder#build()} instead. */ + @Deprecated public SimpleExoPlayer build() { Assertions.checkState(!buildCalled); buildCalled = true; @@ -706,6 +472,7 @@ public class SimpleExoPlayer extends BasePlayer /** @deprecated Use the {@link Builder} and pass it to {@link #SimpleExoPlayer(Builder)}. */ @Deprecated + @SuppressWarnings("deprecation") protected SimpleExoPlayer( Context context, RenderersFactory renderersFactory, @@ -730,6 +497,7 @@ public class SimpleExoPlayer extends BasePlayer } /** @param builder The {@link Builder} to obtain all construction parameters. */ + @SuppressWarnings("deprecation") protected SimpleExoPlayer(Builder builder) { constructorFinished = new ConditionVariable(); try {