mirror of
https://github.com/samsonjs/media.git
synced 2026-03-26 09:35:47 +00:00
Add setPlaybackLooper ExoPlayer builder method
The method allows clients to specify a pre-existing thread to use for playback. This can be used to run multiple ExoPlayer instances on the same playback thread. PiperOrigin-RevId: 488980749
This commit is contained in:
parent
f52bb274b8
commit
79b809b556
3 changed files with 43 additions and 13 deletions
|
|
@ -24,6 +24,7 @@ import android.media.AudioDeviceInfo;
|
|||
import android.media.AudioTrack;
|
||||
import android.media.MediaCodec;
|
||||
import android.os.Looper;
|
||||
import android.os.Process;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
|
|
@ -473,6 +474,7 @@ public interface ExoPlayer extends Player {
|
|||
/* package */ long detachSurfaceTimeoutMs;
|
||||
/* package */ boolean pauseAtEndOfMediaItems;
|
||||
/* package */ boolean usePlatformDiagnostics;
|
||||
@Nullable /* package */ Looper playbackLooper;
|
||||
/* package */ boolean buildCalled;
|
||||
|
||||
/**
|
||||
|
|
@ -515,6 +517,7 @@ public interface ExoPlayer extends Player {
|
|||
* <li>{@code pauseAtEndOfMediaItems}: {@code false}
|
||||
* <li>{@code usePlatformDiagnostics}: {@code true}
|
||||
* <li>{@link Clock}: {@link Clock#DEFAULT}
|
||||
* <li>{@code playbackLooper}: {@code null} (create new thread)
|
||||
* </ul>
|
||||
*
|
||||
* @param context A {@link Context}.
|
||||
|
|
@ -1097,6 +1100,23 @@ public interface ExoPlayer extends Player {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link Looper} that will be used for playback.
|
||||
*
|
||||
* <p>The backing thread should run with priority {@link Process#THREAD_PRIORITY_AUDIO} and
|
||||
* should handle messages within 10ms.
|
||||
*
|
||||
* @param playbackLooper A {@link looper}.
|
||||
* @return This builder.
|
||||
* @throws IllegalStateException If {@link #build()} has already been called.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setPlaybackLooper(Looper playbackLooper) {
|
||||
checkState(!buildCalled);
|
||||
this.playbackLooper = playbackLooper;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an {@link ExoPlayer} instance.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -334,7 +334,8 @@ import java.util.concurrent.TimeoutException;
|
|||
applicationLooper,
|
||||
clock,
|
||||
playbackInfoUpdateListener,
|
||||
playerId);
|
||||
playerId,
|
||||
builder.playbackLooper);
|
||||
|
||||
volume = 1;
|
||||
repeatMode = Player.REPEAT_MODE_OFF;
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
private final LoadControl loadControl;
|
||||
private final BandwidthMeter bandwidthMeter;
|
||||
private final HandlerWrapper handler;
|
||||
private final HandlerThread internalPlaybackThread;
|
||||
@Nullable private final HandlerThread internalPlaybackThread;
|
||||
private final Looper playbackLooper;
|
||||
private final Timeline.Window window;
|
||||
private final Timeline.Period period;
|
||||
|
|
@ -236,7 +236,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
Looper applicationLooper,
|
||||
Clock clock,
|
||||
PlaybackInfoUpdateListener playbackInfoUpdateListener,
|
||||
PlayerId playerId) {
|
||||
PlayerId playerId,
|
||||
Looper playbackLooper) {
|
||||
this.playbackInfoUpdateListener = playbackInfoUpdateListener;
|
||||
this.renderers = renderers;
|
||||
this.trackSelector = trackSelector;
|
||||
|
|
@ -277,12 +278,18 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
mediaSourceList =
|
||||
new MediaSourceList(/* listener= */ this, analyticsCollector, eventHandler, playerId);
|
||||
|
||||
// Note: The documentation for Process.THREAD_PRIORITY_AUDIO that states "Applications can
|
||||
// not normally change to this priority" is incorrect.
|
||||
internalPlaybackThread = new HandlerThread("ExoPlayer:Playback", Process.THREAD_PRIORITY_AUDIO);
|
||||
internalPlaybackThread.start();
|
||||
playbackLooper = internalPlaybackThread.getLooper();
|
||||
handler = clock.createHandler(playbackLooper, this);
|
||||
if (playbackLooper != null) {
|
||||
internalPlaybackThread = null;
|
||||
this.playbackLooper = playbackLooper;
|
||||
} else {
|
||||
// Note: The documentation for Process.THREAD_PRIORITY_AUDIO that states "Applications can
|
||||
// not normally change to this priority" is incorrect.
|
||||
internalPlaybackThread =
|
||||
new HandlerThread("ExoPlayer:Playback", Process.THREAD_PRIORITY_AUDIO);
|
||||
internalPlaybackThread.start();
|
||||
this.playbackLooper = internalPlaybackThread.getLooper();
|
||||
}
|
||||
handler = clock.createHandler(this.playbackLooper, this);
|
||||
}
|
||||
|
||||
public void experimentalSetForegroundModeTimeoutMs(long setForegroundModeTimeoutMs) {
|
||||
|
|
@ -385,7 +392,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
|
||||
@Override
|
||||
public synchronized void sendMessage(PlayerMessage message) {
|
||||
if (released || !internalPlaybackThread.isAlive()) {
|
||||
if (released || !playbackLooper.getThread().isAlive()) {
|
||||
Log.w(TAG, "Ignoring messages sent after release.");
|
||||
message.markAsProcessed(/* isDelivered= */ false);
|
||||
return;
|
||||
|
|
@ -400,7 +407,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
* @return Whether the operations succeeded. If false, the operation timed out.
|
||||
*/
|
||||
public synchronized boolean setForegroundMode(boolean foregroundMode) {
|
||||
if (released || !internalPlaybackThread.isAlive()) {
|
||||
if (released || !playbackLooper.getThread().isAlive()) {
|
||||
return true;
|
||||
}
|
||||
if (foregroundMode) {
|
||||
|
|
@ -422,7 +429,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
* @return Whether the release succeeded. If false, the release timed out.
|
||||
*/
|
||||
public synchronized boolean release() {
|
||||
if (released || !internalPlaybackThread.isAlive()) {
|
||||
if (released || !playbackLooper.getThread().isAlive()) {
|
||||
return true;
|
||||
}
|
||||
handler.sendEmptyMessage(MSG_RELEASE);
|
||||
|
|
@ -1374,7 +1381,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
/* resetError= */ false);
|
||||
loadControl.onReleased();
|
||||
setState(Player.STATE_IDLE);
|
||||
internalPlaybackThread.quit();
|
||||
if (internalPlaybackThread != null) {
|
||||
internalPlaybackThread.quit();
|
||||
}
|
||||
synchronized (this) {
|
||||
released = true;
|
||||
notifyAll();
|
||||
|
|
|
|||
Loading…
Reference in a new issue