Move common init steps into SimpleExoPlayer builder.
Some player setup steps that are likely to be only done once should be moved into the Builder so that player setup can use a consistent style (builder vs setters). This also prevents some threading warning issues when the player is built on a background thread (e.g. for dependency injection frameworks) and setters can't be used due to threading restrictions. PiperOrigin-RevId: 311487224
This commit is contained in:
parent
ba5871dd0e
commit
7b552d7786
@ -7,6 +7,8 @@
|
|||||||
* Added `TextComponent.getCurrentCues` because the current cues are no
|
* Added `TextComponent.getCurrentCues` because the current cues are no
|
||||||
longer forwarded to a new `TextOutput` in `SimpleExoPlayer`
|
longer forwarded to a new `TextOutput` in `SimpleExoPlayer`
|
||||||
automatically.
|
automatically.
|
||||||
|
* Add additional options to `SimpleExoPlayer.Builder` that were previously
|
||||||
|
only accessible via setters.
|
||||||
* Add opt-in to verify correct thread usage with
|
* Add opt-in to verify correct thread usage with
|
||||||
`SimpleExoPlayer.setThrowsWhenUsingWrongThread(true)`
|
`SimpleExoPlayer.setThrowsWhenUsingWrongThread(true)`
|
||||||
([#4463](https://github.com/google/ExoPlayer/issues/4463)).
|
([#4463](https://github.com/google/ExoPlayer/issues/4463)).
|
||||||
|
@ -146,6 +146,8 @@ public interface ExoPlayer extends Player {
|
|||||||
private Looper looper;
|
private Looper looper;
|
||||||
@Nullable private AnalyticsCollector analyticsCollector;
|
@Nullable private AnalyticsCollector analyticsCollector;
|
||||||
private boolean useLazyPreparation;
|
private boolean useLazyPreparation;
|
||||||
|
private SeekParameters seekParameters;
|
||||||
|
private boolean pauseAtEndOfMediaItems;
|
||||||
private boolean buildCalled;
|
private boolean buildCalled;
|
||||||
|
|
||||||
private long releaseTimeoutMs;
|
private long releaseTimeoutMs;
|
||||||
@ -166,6 +168,8 @@ public interface ExoPlayer extends Player {
|
|||||||
* Looper}
|
* Looper}
|
||||||
* <li>{@link AnalyticsCollector}: {@link AnalyticsCollector} with {@link Clock#DEFAULT}
|
* <li>{@link AnalyticsCollector}: {@link AnalyticsCollector} with {@link Clock#DEFAULT}
|
||||||
* <li>{@code useLazyPreparation}: {@code true}
|
* <li>{@code useLazyPreparation}: {@code true}
|
||||||
|
* <li>{@link SeekParameters}: {@link SeekParameters#DEFAULT}
|
||||||
|
* <li>{@code pauseAtEndOfMediaItems}: {@code false}
|
||||||
* <li>{@link Clock}: {@link Clock#DEFAULT}
|
* <li>{@link Clock}: {@link Clock#DEFAULT}
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
@ -178,50 +182,37 @@ public interface ExoPlayer extends Player {
|
|||||||
new DefaultTrackSelector(context),
|
new DefaultTrackSelector(context),
|
||||||
DefaultMediaSourceFactory.newInstance(context),
|
DefaultMediaSourceFactory.newInstance(context),
|
||||||
new DefaultLoadControl(),
|
new DefaultLoadControl(),
|
||||||
DefaultBandwidthMeter.getSingletonInstance(context),
|
DefaultBandwidthMeter.getSingletonInstance(context));
|
||||||
Util.getLooper(),
|
|
||||||
/* analyticsCollector= */ null,
|
|
||||||
/* useLazyPreparation= */ true,
|
|
||||||
Clock.DEFAULT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a builder with the specified custom components.
|
* Creates a builder with the specified custom components.
|
||||||
*
|
*
|
||||||
* <p>Note that this constructor is only useful if you try to ensure that ExoPlayer's default
|
* <p>Note that this constructor is only useful to try and ensure that ExoPlayer's default
|
||||||
* components can be removed by ProGuard or R8. For most components except renderers, there is
|
* components can be removed by ProGuard or R8.
|
||||||
* only a marginal benefit of doing that.
|
|
||||||
*
|
*
|
||||||
* @param renderers The {@link Renderer Renderers} to be used by the player.
|
* @param renderers The {@link Renderer Renderers} to be used by the player.
|
||||||
* @param trackSelector A {@link TrackSelector}.
|
* @param trackSelector A {@link TrackSelector}.
|
||||||
* @param mediaSourceFactory A {@link MediaSourceFactory}.
|
* @param mediaSourceFactory A {@link MediaSourceFactory}.
|
||||||
* @param loadControl A {@link LoadControl}.
|
* @param loadControl A {@link LoadControl}.
|
||||||
* @param bandwidthMeter A {@link BandwidthMeter}.
|
* @param bandwidthMeter A {@link BandwidthMeter}.
|
||||||
* @param looper A {@link Looper} that must be used for all calls to the player.
|
|
||||||
* @param analyticsCollector An {@link AnalyticsCollector}.
|
|
||||||
* @param useLazyPreparation Whether media sources should be initialized lazily.
|
|
||||||
* @param clock A {@link Clock}. Should always be {@link Clock#DEFAULT}.
|
|
||||||
*/
|
*/
|
||||||
public Builder(
|
public Builder(
|
||||||
Renderer[] renderers,
|
Renderer[] renderers,
|
||||||
TrackSelector trackSelector,
|
TrackSelector trackSelector,
|
||||||
MediaSourceFactory mediaSourceFactory,
|
MediaSourceFactory mediaSourceFactory,
|
||||||
LoadControl loadControl,
|
LoadControl loadControl,
|
||||||
BandwidthMeter bandwidthMeter,
|
BandwidthMeter bandwidthMeter) {
|
||||||
Looper looper,
|
|
||||||
@Nullable AnalyticsCollector analyticsCollector,
|
|
||||||
boolean useLazyPreparation,
|
|
||||||
Clock clock) {
|
|
||||||
Assertions.checkArgument(renderers.length > 0);
|
Assertions.checkArgument(renderers.length > 0);
|
||||||
this.renderers = renderers;
|
this.renderers = renderers;
|
||||||
this.trackSelector = trackSelector;
|
this.trackSelector = trackSelector;
|
||||||
this.mediaSourceFactory = mediaSourceFactory;
|
this.mediaSourceFactory = mediaSourceFactory;
|
||||||
this.loadControl = loadControl;
|
this.loadControl = loadControl;
|
||||||
this.bandwidthMeter = bandwidthMeter;
|
this.bandwidthMeter = bandwidthMeter;
|
||||||
this.looper = looper;
|
looper = Util.getLooper();
|
||||||
this.analyticsCollector = analyticsCollector;
|
useLazyPreparation = true;
|
||||||
this.useLazyPreparation = useLazyPreparation;
|
seekParameters = SeekParameters.DEFAULT;
|
||||||
this.clock = clock;
|
clock = Clock.DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -347,6 +338,37 @@ public interface ExoPlayer extends Player {
|
|||||||
return this;
|
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.
|
||||||
|
*/
|
||||||
|
public Builder setSeekParameters(SeekParameters seekParameters) {
|
||||||
|
Assertions.checkState(!buildCalled);
|
||||||
|
this.seekParameters = seekParameters;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether to pause playback at the end of each media item.
|
||||||
|
*
|
||||||
|
* <p>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.EventListener#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.
|
||||||
|
*/
|
||||||
|
public Builder setPauseAtEndOfMediaItems(boolean pauseAtEndOfMediaItems) {
|
||||||
|
Assertions.checkState(!buildCalled);
|
||||||
|
this.pauseAtEndOfMediaItems = pauseAtEndOfMediaItems;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@link Clock} that will be used by the player. Should only be set for testing
|
* Sets the {@link Clock} that will be used by the player. Should only be set for testing
|
||||||
* purposes.
|
* purposes.
|
||||||
@ -379,6 +401,8 @@ public interface ExoPlayer extends Player {
|
|||||||
bandwidthMeter,
|
bandwidthMeter,
|
||||||
analyticsCollector,
|
analyticsCollector,
|
||||||
useLazyPreparation,
|
useLazyPreparation,
|
||||||
|
seekParameters,
|
||||||
|
pauseAtEndOfMediaItems,
|
||||||
clock,
|
clock,
|
||||||
looper);
|
looper);
|
||||||
|
|
||||||
|
@ -258,6 +258,8 @@ public final class ExoPlayerFactory {
|
|||||||
bandwidthMeter,
|
bandwidthMeter,
|
||||||
/* analyticsCollector= */ null,
|
/* analyticsCollector= */ null,
|
||||||
/* useLazyPreparation= */ true,
|
/* useLazyPreparation= */ true,
|
||||||
|
SeekParameters.DEFAULT,
|
||||||
|
/* pauseAtEndOfMediaItems= */ false,
|
||||||
Clock.DEFAULT,
|
Clock.DEFAULT,
|
||||||
applicationLooper);
|
applicationLooper);
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,8 @@ import java.util.concurrent.TimeoutException;
|
|||||||
* @param useLazyPreparation Whether playlist items are prepared lazily. If false, all manifest
|
* @param useLazyPreparation Whether playlist items are prepared lazily. If false, all manifest
|
||||||
* loads and other initial preparation steps happen immediately. If true, these initial
|
* loads and other initial preparation steps happen immediately. If true, these initial
|
||||||
* preparations are triggered only when the player starts buffering the media.
|
* preparations are triggered only when the player starts buffering the media.
|
||||||
|
* @param seekParameters The {@link SeekParameters}.
|
||||||
|
* @param pauseAtEndOfMediaItems Whether to pause playback at the end of each media item.
|
||||||
* @param clock The {@link Clock}.
|
* @param clock The {@link Clock}.
|
||||||
* @param applicationLooper The {@link Looper} that must be used for all calls to the player and
|
* @param applicationLooper The {@link Looper} that must be used for all calls to the player and
|
||||||
* which is used to call listeners on.
|
* which is used to call listeners on.
|
||||||
@ -122,6 +124,8 @@ import java.util.concurrent.TimeoutException;
|
|||||||
BandwidthMeter bandwidthMeter,
|
BandwidthMeter bandwidthMeter,
|
||||||
@Nullable AnalyticsCollector analyticsCollector,
|
@Nullable AnalyticsCollector analyticsCollector,
|
||||||
boolean useLazyPreparation,
|
boolean useLazyPreparation,
|
||||||
|
SeekParameters seekParameters,
|
||||||
|
boolean pauseAtEndOfMediaItems,
|
||||||
Clock clock,
|
Clock clock,
|
||||||
Looper applicationLooper) {
|
Looper applicationLooper) {
|
||||||
Log.i(TAG, "Init " + Integer.toHexString(System.identityHashCode(this)) + " ["
|
Log.i(TAG, "Init " + Integer.toHexString(System.identityHashCode(this)) + " ["
|
||||||
@ -131,6 +135,8 @@ import java.util.concurrent.TimeoutException;
|
|||||||
this.trackSelector = checkNotNull(trackSelector);
|
this.trackSelector = checkNotNull(trackSelector);
|
||||||
this.mediaSourceFactory = mediaSourceFactory;
|
this.mediaSourceFactory = mediaSourceFactory;
|
||||||
this.useLazyPreparation = useLazyPreparation;
|
this.useLazyPreparation = useLazyPreparation;
|
||||||
|
this.seekParameters = seekParameters;
|
||||||
|
this.pauseAtEndOfMediaItems = pauseAtEndOfMediaItems;
|
||||||
repeatMode = Player.REPEAT_MODE_OFF;
|
repeatMode = Player.REPEAT_MODE_OFF;
|
||||||
listeners = new CopyOnWriteArrayList<>();
|
listeners = new CopyOnWriteArrayList<>();
|
||||||
mediaSourceHolders = new ArrayList<>();
|
mediaSourceHolders = new ArrayList<>();
|
||||||
@ -142,7 +148,6 @@ import java.util.concurrent.TimeoutException;
|
|||||||
null);
|
null);
|
||||||
period = new Timeline.Period();
|
period = new Timeline.Period();
|
||||||
playbackSpeed = Player.DEFAULT_PLAYBACK_SPEED;
|
playbackSpeed = Player.DEFAULT_PLAYBACK_SPEED;
|
||||||
seekParameters = SeekParameters.DEFAULT;
|
|
||||||
maskingWindowIndex = C.INDEX_UNSET;
|
maskingWindowIndex = C.INDEX_UNSET;
|
||||||
applicationHandler =
|
applicationHandler =
|
||||||
new Handler(applicationLooper) {
|
new Handler(applicationLooper) {
|
||||||
@ -166,6 +171,8 @@ import java.util.concurrent.TimeoutException;
|
|||||||
repeatMode,
|
repeatMode,
|
||||||
shuffleModeEnabled,
|
shuffleModeEnabled,
|
||||||
analyticsCollector,
|
analyticsCollector,
|
||||||
|
seekParameters,
|
||||||
|
pauseAtEndOfMediaItems,
|
||||||
applicationHandler,
|
applicationHandler,
|
||||||
clock);
|
clock);
|
||||||
internalPlayerHandler = new Handler(internalPlayer.getPlaybackLooper());
|
internalPlayerHandler = new Handler(internalPlayer.getPlaybackLooper());
|
||||||
|
@ -146,6 +146,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
@Player.RepeatMode int repeatMode,
|
@Player.RepeatMode int repeatMode,
|
||||||
boolean shuffleModeEnabled,
|
boolean shuffleModeEnabled,
|
||||||
@Nullable AnalyticsCollector analyticsCollector,
|
@Nullable AnalyticsCollector analyticsCollector,
|
||||||
|
SeekParameters seekParameters,
|
||||||
|
boolean pauseAtEndOfWindow,
|
||||||
Handler eventHandler,
|
Handler eventHandler,
|
||||||
Clock clock) {
|
Clock clock) {
|
||||||
this.renderers = renderers;
|
this.renderers = renderers;
|
||||||
@ -155,6 +157,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
this.bandwidthMeter = bandwidthMeter;
|
this.bandwidthMeter = bandwidthMeter;
|
||||||
this.repeatMode = repeatMode;
|
this.repeatMode = repeatMode;
|
||||||
this.shuffleModeEnabled = shuffleModeEnabled;
|
this.shuffleModeEnabled = shuffleModeEnabled;
|
||||||
|
this.seekParameters = seekParameters;
|
||||||
|
this.pauseAtEndOfWindow = pauseAtEndOfWindow;
|
||||||
this.eventHandler = eventHandler;
|
this.eventHandler = eventHandler;
|
||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
this.queue = new MediaPeriodQueue();
|
this.queue = new MediaPeriodQueue();
|
||||||
@ -162,7 +166,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
backBufferDurationUs = loadControl.getBackBufferDurationUs();
|
backBufferDurationUs = loadControl.getBackBufferDurationUs();
|
||||||
retainBackBufferFromKeyframe = loadControl.retainBackBufferFromKeyframe();
|
retainBackBufferFromKeyframe = loadControl.retainBackBufferFromKeyframe();
|
||||||
|
|
||||||
seekParameters = SeekParameters.DEFAULT;
|
|
||||||
playbackInfo = PlaybackInfo.createDummy(emptyTrackSelectorResult);
|
playbackInfo = PlaybackInfo.createDummy(emptyTrackSelectorResult);
|
||||||
playbackInfoUpdate = new PlaybackInfoUpdate(playbackInfo);
|
playbackInfoUpdate = new PlaybackInfoUpdate(playbackInfo);
|
||||||
rendererCapabilities = new RendererCapabilities[renderers.length];
|
rendererCapabilities = new RendererCapabilities[renderers.length];
|
||||||
|
@ -99,7 +99,16 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
private BandwidthMeter bandwidthMeter;
|
private BandwidthMeter bandwidthMeter;
|
||||||
private AnalyticsCollector analyticsCollector;
|
private AnalyticsCollector analyticsCollector;
|
||||||
private Looper looper;
|
private Looper looper;
|
||||||
|
@Nullable private PriorityTaskManager priorityTaskManager;
|
||||||
|
private AudioAttributes audioAttributes;
|
||||||
|
private boolean handleAudioFocus;
|
||||||
|
@C.WakeMode private int wakeMode;
|
||||||
|
private boolean handleAudioBecomingNoisy;
|
||||||
|
private boolean skipSilenceEnabled;
|
||||||
|
@Renderer.VideoScalingMode private int videoScalingMode;
|
||||||
private boolean useLazyPreparation;
|
private boolean useLazyPreparation;
|
||||||
|
private SeekParameters seekParameters;
|
||||||
|
private boolean pauseAtEndOfMediaItems;
|
||||||
private boolean throwWhenStuckBuffering;
|
private boolean throwWhenStuckBuffering;
|
||||||
private boolean buildCalled;
|
private boolean buildCalled;
|
||||||
|
|
||||||
@ -122,7 +131,15 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
* Looper} of the application's main thread if the current thread doesn't have a {@link
|
* Looper} of the application's main thread if the current thread doesn't have a {@link
|
||||||
* Looper}
|
* Looper}
|
||||||
* <li>{@link AnalyticsCollector}: {@link AnalyticsCollector} with {@link Clock#DEFAULT}
|
* <li>{@link AnalyticsCollector}: {@link AnalyticsCollector} with {@link Clock#DEFAULT}
|
||||||
|
* <li>{@link PriorityTaskManager}: {@code null} (not used)
|
||||||
|
* <li>{@link AudioAttributes}: {@link AudioAttributes#DEFAULT}, not handling audio focus
|
||||||
|
* <li>{@link C.WakeMode}: {@link C#WAKE_MODE_NONE}
|
||||||
|
* <li>{@code handleAudioBecomingNoisy}: {@code true}
|
||||||
|
* <li>{@code skipSilenceEnabled}: {@code false}
|
||||||
|
* <li>{@link Renderer.VideoScalingMode}: {@link Renderer#VIDEO_SCALING_MODE_DEFAULT}
|
||||||
* <li>{@code useLazyPreparation}: {@code true}
|
* <li>{@code useLazyPreparation}: {@code true}
|
||||||
|
* <li>{@link SeekParameters}: {@link SeekParameters#DEFAULT}
|
||||||
|
* <li>{@code pauseAtEndOfMediaItems}: {@code false}
|
||||||
* <li>{@link Clock}: {@link Clock#DEFAULT}
|
* <li>{@link Clock}: {@link Clock#DEFAULT}
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
@ -149,18 +166,14 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
DefaultMediaSourceFactory.newInstance(context),
|
DefaultMediaSourceFactory.newInstance(context),
|
||||||
new DefaultLoadControl(),
|
new DefaultLoadControl(),
|
||||||
DefaultBandwidthMeter.getSingletonInstance(context),
|
DefaultBandwidthMeter.getSingletonInstance(context),
|
||||||
Util.getLooper(),
|
new AnalyticsCollector(Clock.DEFAULT));
|
||||||
new AnalyticsCollector(Clock.DEFAULT),
|
|
||||||
/* useLazyPreparation= */ true,
|
|
||||||
Clock.DEFAULT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a builder with the specified custom components.
|
* Creates a builder with the specified custom components.
|
||||||
*
|
*
|
||||||
* <p>Note that this constructor is only useful if you try to ensure that ExoPlayer's default
|
* <p>Note that this constructor is only useful to try and ensure that ExoPlayer's default
|
||||||
* components can be removed by ProGuard or R8. For most components except renderers, there is
|
* components can be removed by ProGuard or R8.
|
||||||
* only a marginal benefit of doing that.
|
|
||||||
*
|
*
|
||||||
* @param context A {@link Context}.
|
* @param context A {@link Context}.
|
||||||
* @param renderersFactory A factory for creating {@link Renderer Renderers} to be used by the
|
* @param renderersFactory A factory for creating {@link Renderer Renderers} to be used by the
|
||||||
@ -169,12 +182,7 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
* @param mediaSourceFactory A {@link MediaSourceFactory}.
|
* @param mediaSourceFactory A {@link MediaSourceFactory}.
|
||||||
* @param loadControl A {@link LoadControl}.
|
* @param loadControl A {@link LoadControl}.
|
||||||
* @param bandwidthMeter A {@link BandwidthMeter}.
|
* @param bandwidthMeter A {@link BandwidthMeter}.
|
||||||
* @param looper A {@link Looper} that must be used for all calls to the player.
|
|
||||||
* @param analyticsCollector An {@link AnalyticsCollector}.
|
* @param analyticsCollector An {@link AnalyticsCollector}.
|
||||||
* @param useLazyPreparation Whether playlist items should be prepared 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 clock A {@link Clock}. Should always be {@link Clock#DEFAULT}.
|
|
||||||
*/
|
*/
|
||||||
public Builder(
|
public Builder(
|
||||||
Context context,
|
Context context,
|
||||||
@ -183,20 +191,21 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
MediaSourceFactory mediaSourceFactory,
|
MediaSourceFactory mediaSourceFactory,
|
||||||
LoadControl loadControl,
|
LoadControl loadControl,
|
||||||
BandwidthMeter bandwidthMeter,
|
BandwidthMeter bandwidthMeter,
|
||||||
Looper looper,
|
AnalyticsCollector analyticsCollector) {
|
||||||
AnalyticsCollector analyticsCollector,
|
|
||||||
boolean useLazyPreparation,
|
|
||||||
Clock clock) {
|
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.renderersFactory = renderersFactory;
|
this.renderersFactory = renderersFactory;
|
||||||
this.trackSelector = trackSelector;
|
this.trackSelector = trackSelector;
|
||||||
this.mediaSourceFactory = mediaSourceFactory;
|
this.mediaSourceFactory = mediaSourceFactory;
|
||||||
this.loadControl = loadControl;
|
this.loadControl = loadControl;
|
||||||
this.bandwidthMeter = bandwidthMeter;
|
this.bandwidthMeter = bandwidthMeter;
|
||||||
this.looper = looper;
|
|
||||||
this.analyticsCollector = analyticsCollector;
|
this.analyticsCollector = analyticsCollector;
|
||||||
this.useLazyPreparation = useLazyPreparation;
|
looper = Util.getLooper();
|
||||||
this.clock = clock;
|
audioAttributes = AudioAttributes.DEFAULT;
|
||||||
|
wakeMode = C.WAKE_MODE_NONE;
|
||||||
|
videoScalingMode = Renderer.VIDEO_SCALING_MODE_DEFAULT;
|
||||||
|
useLazyPreparation = true;
|
||||||
|
seekParameters = SeekParameters.DEFAULT;
|
||||||
|
clock = Clock.DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -278,6 +287,111 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an {@link PriorityTaskManager} that will be used by the player.
|
||||||
|
*
|
||||||
|
* <p>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) {
|
||||||
|
Assertions.checkState(!buildCalled);
|
||||||
|
this.priorityTaskManager = priorityTaskManager;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets {@link AudioAttributes} that will be used by the player and whether to handle audio
|
||||||
|
* focus.
|
||||||
|
*
|
||||||
|
* <p>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 hanlde audio focus.
|
||||||
|
* @return This builder.
|
||||||
|
* @throws IllegalStateException If {@link #build()} has already been called.
|
||||||
|
*/
|
||||||
|
public Builder setAudioAttributes(AudioAttributes audioAttributes, boolean handleAudioFocus) {
|
||||||
|
Assertions.checkState(!buildCalled);
|
||||||
|
this.audioAttributes = audioAttributes;
|
||||||
|
this.handleAudioFocus = handleAudioFocus;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link C.WakeMode} that will be used by the player.
|
||||||
|
*
|
||||||
|
* <p>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).
|
||||||
|
*
|
||||||
|
* <p>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) {
|
||||||
|
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 <a
|
||||||
|
* href="https://developer.android.com/guide/topics/media-apps/volume-and-earphones#becoming-noisy">audio
|
||||||
|
* becoming noisy</a> 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) {
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
public Builder setSkipSilenceEnabled(boolean skipSilenceEnabled) {
|
||||||
|
Assertions.checkState(!buildCalled);
|
||||||
|
this.skipSilenceEnabled = skipSilenceEnabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link Renderer.VideoScalingMode} that will be used by the player.
|
||||||
|
*
|
||||||
|
* <p>Note that 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
|
||||||
|
* android.view.SurfaceView}.
|
||||||
|
*
|
||||||
|
* @param videoScalingMode A {@link Renderer.VideoScalingMode}.
|
||||||
|
* @return This builder.
|
||||||
|
* @throws IllegalStateException If {@link #build()} has already been called.
|
||||||
|
*/
|
||||||
|
public Builder setVideoScalingMode(@Renderer.VideoScalingMode int videoScalingMode) {
|
||||||
|
Assertions.checkState(!buildCalled);
|
||||||
|
this.videoScalingMode = videoScalingMode;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether media sources should be initialized lazily.
|
* Sets whether media sources should be initialized lazily.
|
||||||
*
|
*
|
||||||
@ -295,6 +409,37 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
return this;
|
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.
|
||||||
|
*/
|
||||||
|
public Builder setSeekParameters(SeekParameters seekParameters) {
|
||||||
|
Assertions.checkState(!buildCalled);
|
||||||
|
this.seekParameters = seekParameters;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether to pause playback at the end of each media item.
|
||||||
|
*
|
||||||
|
* <p>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.EventListener#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.
|
||||||
|
*/
|
||||||
|
public Builder setPauseAtEndOfMediaItems(boolean pauseAtEndOfMediaItems) {
|
||||||
|
Assertions.checkState(!buildCalled);
|
||||||
|
this.pauseAtEndOfMediaItems = pauseAtEndOfMediaItems;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether the player should throw when it detects it's stuck buffering.
|
* Sets whether the player should throw when it detects it's stuck buffering.
|
||||||
*
|
*
|
||||||
@ -326,7 +471,7 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
/**
|
/**
|
||||||
* Builds a {@link SimpleExoPlayer} instance.
|
* Builds a {@link SimpleExoPlayer} instance.
|
||||||
*
|
*
|
||||||
* @throws IllegalStateException If {@link #build()} has already been called.
|
* @throws IllegalStateException If this method has already been called.
|
||||||
*/
|
*/
|
||||||
public SimpleExoPlayer build() {
|
public SimpleExoPlayer build() {
|
||||||
Assertions.checkState(!buildCalled);
|
Assertions.checkState(!buildCalled);
|
||||||
@ -416,6 +561,10 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
protected SimpleExoPlayer(Builder builder) {
|
protected SimpleExoPlayer(Builder builder) {
|
||||||
bandwidthMeter = builder.bandwidthMeter;
|
bandwidthMeter = builder.bandwidthMeter;
|
||||||
analyticsCollector = builder.analyticsCollector;
|
analyticsCollector = builder.analyticsCollector;
|
||||||
|
priorityTaskManager = builder.priorityTaskManager;
|
||||||
|
audioAttributes = builder.audioAttributes;
|
||||||
|
videoScalingMode = builder.videoScalingMode;
|
||||||
|
skipSilenceEnabled = builder.skipSilenceEnabled;
|
||||||
componentListener = new ComponentListener();
|
componentListener = new ComponentListener();
|
||||||
videoListeners = new CopyOnWriteArraySet<>();
|
videoListeners = new CopyOnWriteArraySet<>();
|
||||||
audioListeners = new CopyOnWriteArraySet<>();
|
audioListeners = new CopyOnWriteArraySet<>();
|
||||||
@ -436,8 +585,6 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
// Set initial values.
|
// Set initial values.
|
||||||
audioVolume = 1;
|
audioVolume = 1;
|
||||||
audioSessionId = C.AUDIO_SESSION_ID_UNSET;
|
audioSessionId = C.AUDIO_SESSION_ID_UNSET;
|
||||||
audioAttributes = AudioAttributes.DEFAULT;
|
|
||||||
videoScalingMode = Renderer.VIDEO_SCALING_MODE_DEFAULT;
|
|
||||||
currentCues = Collections.emptyList();
|
currentCues = Collections.emptyList();
|
||||||
|
|
||||||
// Build the player and associated objects.
|
// Build the player and associated objects.
|
||||||
@ -450,6 +597,8 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
bandwidthMeter,
|
bandwidthMeter,
|
||||||
analyticsCollector,
|
analyticsCollector,
|
||||||
builder.useLazyPreparation,
|
builder.useLazyPreparation,
|
||||||
|
builder.seekParameters,
|
||||||
|
builder.pauseAtEndOfMediaItems,
|
||||||
builder.clock,
|
builder.clock,
|
||||||
builder.looper);
|
builder.looper);
|
||||||
analyticsCollector.setPlayer(player);
|
analyticsCollector.setPlayer(player);
|
||||||
@ -461,16 +610,27 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
audioListeners.add(analyticsCollector);
|
audioListeners.add(analyticsCollector);
|
||||||
addMetadataOutput(analyticsCollector);
|
addMetadataOutput(analyticsCollector);
|
||||||
bandwidthMeter.addEventListener(eventHandler, analyticsCollector);
|
bandwidthMeter.addEventListener(eventHandler, analyticsCollector);
|
||||||
|
|
||||||
audioBecomingNoisyManager =
|
audioBecomingNoisyManager =
|
||||||
new AudioBecomingNoisyManager(builder.context, eventHandler, componentListener);
|
new AudioBecomingNoisyManager(builder.context, eventHandler, componentListener);
|
||||||
|
audioBecomingNoisyManager.setEnabled(builder.handleAudioBecomingNoisy);
|
||||||
audioFocusManager = new AudioFocusManager(builder.context, eventHandler, componentListener);
|
audioFocusManager = new AudioFocusManager(builder.context, eventHandler, componentListener);
|
||||||
|
audioFocusManager.setAudioAttributes(builder.handleAudioFocus ? audioAttributes : null);
|
||||||
streamVolumeManager = new StreamVolumeManager(builder.context, eventHandler, componentListener);
|
streamVolumeManager = new StreamVolumeManager(builder.context, eventHandler, componentListener);
|
||||||
|
streamVolumeManager.setStreamType(Util.getStreamTypeForAudioUsage(audioAttributes.usage));
|
||||||
wakeLockManager = new WakeLockManager(builder.context);
|
wakeLockManager = new WakeLockManager(builder.context);
|
||||||
|
wakeLockManager.setEnabled(builder.wakeMode != C.WAKE_MODE_NONE);
|
||||||
wifiLockManager = new WifiLockManager(builder.context);
|
wifiLockManager = new WifiLockManager(builder.context);
|
||||||
|
wifiLockManager.setEnabled(builder.wakeMode == C.WAKE_MODE_NETWORK);
|
||||||
deviceInfo = createDeviceInfo(streamVolumeManager);
|
deviceInfo = createDeviceInfo(streamVolumeManager);
|
||||||
if (builder.throwWhenStuckBuffering) {
|
if (builder.throwWhenStuckBuffering) {
|
||||||
player.experimental_throwWhenStuckBuffering();
|
player.experimental_throwWhenStuckBuffering();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sendRendererMessage(C.TRACK_TYPE_AUDIO, Renderer.MSG_SET_AUDIO_ATTRIBUTES, audioAttributes);
|
||||||
|
sendRendererMessage(C.TRACK_TYPE_VIDEO, Renderer.MSG_SET_SCALING_MODE, videoScalingMode);
|
||||||
|
sendRendererMessage(
|
||||||
|
C.TRACK_TYPE_AUDIO, Renderer.MSG_SET_SKIP_SILENCE_ENABLED, skipSilenceEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1686,6 +1846,7 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
* @param wakeMode The {@link C.WakeMode} option to keep the device awake during playback.
|
* @param wakeMode The {@link C.WakeMode} option to keep the device awake during playback.
|
||||||
*/
|
*/
|
||||||
public void setWakeMode(@C.WakeMode int wakeMode) {
|
public void setWakeMode(@C.WakeMode int wakeMode) {
|
||||||
|
verifyApplicationThread();
|
||||||
switch (wakeMode) {
|
switch (wakeMode) {
|
||||||
case C.WAKE_MODE_NONE:
|
case C.WAKE_MODE_NONE:
|
||||||
wakeLockManager.setEnabled(false);
|
wakeLockManager.setEnabled(false);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user