mirror of
https://github.com/androidx/media.git
synced 2025-04-29 22:36:54 +08:00
Access finalAudioSink from playback thread
The finalAudioSink was accessed from the main thread but it should only be accessed from the playback thread. PiperOrigin-RevId: 743548450
This commit is contained in:
parent
f755c7081f
commit
ee611a1ab8
@ -336,7 +336,6 @@ public final class CompositionPlayer extends SimpleBasePlayer
|
||||
private LivePositionSupplier positionSupplier;
|
||||
private LivePositionSupplier bufferedPositionSupplier;
|
||||
private LivePositionSupplier totalBufferedDurationSupplier;
|
||||
private boolean isSeeking;
|
||||
|
||||
// "this" reference for position suppliers.
|
||||
@SuppressWarnings("initialization:methodref.receiver.bound.invalid")
|
||||
@ -506,9 +505,9 @@ public final class CompositionPlayer extends SimpleBasePlayer
|
||||
playWhenReadyChangeReason = PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST;
|
||||
if (playbackState == STATE_READY) {
|
||||
if (playWhenReady) {
|
||||
finalAudioSink.play();
|
||||
checkStateNotNull(compositionPlayerInternal).startRendering();
|
||||
} else {
|
||||
finalAudioSink.pause();
|
||||
checkStateNotNull(compositionPlayerInternal).stopRendering();
|
||||
}
|
||||
for (int i = 0; i < players.size(); i++) {
|
||||
players.get(i).setPlayWhenReady(playWhenReady);
|
||||
@ -587,7 +586,9 @@ public final class CompositionPlayer extends SimpleBasePlayer
|
||||
@Override
|
||||
protected ListenableFuture<?> handleSetVolume(float volume) {
|
||||
this.volume = Util.constrainValue(volume, /* min= */ 0.0f, /* max= */ 1.0f);
|
||||
finalAudioSink.setVolume(this.volume);
|
||||
if (compositionPlayerInternal != null) {
|
||||
compositionPlayerInternal.setVolume(this.volume);
|
||||
}
|
||||
return Futures.immediateVoidFuture();
|
||||
}
|
||||
|
||||
@ -597,7 +598,6 @@ public final class CompositionPlayer extends SimpleBasePlayer
|
||||
resetLivePositionSuppliers();
|
||||
CompositionPlayerInternal compositionPlayerInternal =
|
||||
checkStateNotNull(this.compositionPlayerInternal);
|
||||
isSeeking = true;
|
||||
compositionPlayerInternal.startSeek(positionMs);
|
||||
for (int i = 0; i < players.size(); i++) {
|
||||
players.get(i).seekTo(positionMs);
|
||||
@ -683,22 +683,17 @@ public final class CompositionPlayer extends SimpleBasePlayer
|
||||
for (int i = 0; i < players.size(); i++) {
|
||||
players.get(i).setPlayWhenReady(false);
|
||||
}
|
||||
if (!isSeeking) {
|
||||
// The finalAudioSink cannot be paused more than once. The audio pipeline pauses it during
|
||||
// a seek, so don't pause here when seeking.
|
||||
finalAudioSink.pause();
|
||||
}
|
||||
checkStateNotNull(compositionPlayerInternal).stopRendering();
|
||||
}
|
||||
} else if (endedCount == players.size()) {
|
||||
playbackState = STATE_ENDED;
|
||||
} else {
|
||||
playbackState = STATE_READY;
|
||||
isSeeking = false;
|
||||
if (oldPlaybackState != STATE_READY && playWhenReady) {
|
||||
for (int i = 0; i < players.size(); i++) {
|
||||
players.get(i).setPlayWhenReady(true);
|
||||
}
|
||||
finalAudioSink.play();
|
||||
checkStateNotNull(compositionPlayerInternal).startRendering();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -799,6 +794,7 @@ public final class CompositionPlayer extends SimpleBasePlayer
|
||||
playbackVideoGraphWrapper,
|
||||
/* listener= */ this,
|
||||
compositionInternalListenerHandler);
|
||||
compositionPlayerInternal.setVolume(volume);
|
||||
}
|
||||
|
||||
private void setPrimaryPlayerSequence(ExoPlayer player, EditedMediaItemSequence sequence) {
|
||||
|
@ -47,11 +47,14 @@ import androidx.media3.exoplayer.video.PlaybackVideoGraphWrapper;
|
||||
}
|
||||
|
||||
private static final String TAG = "CompPlayerInternal";
|
||||
private static final int MSG_SET_OUTPUT_SURFACE_INFO = 1;
|
||||
private static final int MSG_CLEAR_OUTPUT_SURFACE = 2;
|
||||
private static final int MSG_START_SEEK = 3;
|
||||
private static final int MSG_END_SEEK = 4;
|
||||
private static final int MSG_RELEASE = 5;
|
||||
private static final int MSG_START_RENDERING = 1;
|
||||
private static final int MSG_STOP_RENDERING = 2;
|
||||
private static final int MSG_SET_VOLUME = 3;
|
||||
private static final int MSG_SET_OUTPUT_SURFACE_INFO = 4;
|
||||
private static final int MSG_CLEAR_OUTPUT_SURFACE = 5;
|
||||
private static final int MSG_START_SEEK = 6;
|
||||
private static final int MSG_END_SEEK = 7;
|
||||
private static final int MSG_RELEASE = 8;
|
||||
|
||||
private final Clock clock;
|
||||
private final HandlerWrapper handler;
|
||||
@ -94,6 +97,18 @@ import androidx.media3.exoplayer.video.PlaybackVideoGraphWrapper;
|
||||
|
||||
// Public methods
|
||||
|
||||
public void startRendering() {
|
||||
handler.sendEmptyMessage(MSG_START_RENDERING);
|
||||
}
|
||||
|
||||
public void stopRendering() {
|
||||
handler.sendEmptyMessage(MSG_STOP_RENDERING);
|
||||
}
|
||||
|
||||
public void setVolume(float volume) {
|
||||
handler.obtainMessage(MSG_SET_VOLUME, volume).sendToTarget();
|
||||
}
|
||||
|
||||
/** Sets the output surface information on the video pipeline. */
|
||||
public void setOutputSurfaceInfo(Surface surface, Size size) {
|
||||
handler
|
||||
@ -103,7 +118,7 @@ import androidx.media3.exoplayer.video.PlaybackVideoGraphWrapper;
|
||||
|
||||
/** Clears the output surface from the video pipeline. */
|
||||
public void clearOutputSurface() {
|
||||
handler.obtainMessage(MSG_CLEAR_OUTPUT_SURFACE).sendToTarget();
|
||||
handler.sendEmptyMessage(MSG_CLEAR_OUTPUT_SURFACE);
|
||||
}
|
||||
|
||||
public void startSeek(long positionMs) {
|
||||
@ -111,7 +126,7 @@ import androidx.media3.exoplayer.video.PlaybackVideoGraphWrapper;
|
||||
}
|
||||
|
||||
public void endSeek() {
|
||||
handler.obtainMessage(MSG_END_SEEK).sendToTarget();
|
||||
handler.sendEmptyMessage(MSG_END_SEEK);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -139,6 +154,15 @@ import androidx.media3.exoplayer.video.PlaybackVideoGraphWrapper;
|
||||
public boolean handleMessage(Message message) {
|
||||
try {
|
||||
switch (message.what) {
|
||||
case MSG_START_RENDERING:
|
||||
playbackAudioGraphWrapper.startRendering();
|
||||
break;
|
||||
case MSG_STOP_RENDERING:
|
||||
playbackAudioGraphWrapper.stopRendering();
|
||||
break;
|
||||
case MSG_SET_VOLUME:
|
||||
playbackAudioGraphWrapper.setVolume(/* volume= */ (float) message.obj);
|
||||
break;
|
||||
case MSG_SET_OUTPUT_SURFACE_INFO:
|
||||
setOutputSurfaceInfoOnInternalThread(
|
||||
/* outputSurfaceInfo= */ (OutputSurfaceInfo) message.obj);
|
||||
|
@ -47,6 +47,7 @@ import java.util.Objects;
|
||||
private AudioFormat outputAudioFormat;
|
||||
private long outputFramesWritten;
|
||||
private long seekPositionUs;
|
||||
private boolean isRenderingStarted;
|
||||
|
||||
/**
|
||||
* Creates an instance.
|
||||
@ -135,6 +136,24 @@ import java.util.Objects;
|
||||
+ sampleCountToDurationUs(outputFramesWritten, outputAudioFormat.sampleRate);
|
||||
}
|
||||
|
||||
public void startRendering() {
|
||||
finalAudioSink.play();
|
||||
isRenderingStarted = true;
|
||||
}
|
||||
|
||||
public void stopRendering() {
|
||||
if (!isRenderingStarted) {
|
||||
// The finalAudioSink cannot be paused more than once.
|
||||
return;
|
||||
}
|
||||
finalAudioSink.pause();
|
||||
isRenderingStarted = false;
|
||||
}
|
||||
|
||||
public void setVolume(float volume) {
|
||||
finalAudioSink.setVolume(volume);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the steps that need to be executed for a seek before seeking the upstream players.
|
||||
*
|
||||
@ -144,7 +163,7 @@ import java.util.Objects;
|
||||
if (positionUs == C.TIME_UNSET) {
|
||||
positionUs = 0;
|
||||
}
|
||||
finalAudioSink.pause();
|
||||
stopRendering();
|
||||
audioGraph.blockInput();
|
||||
audioGraph.setPendingStartTimeUs(positionUs);
|
||||
audioGraph.flush();
|
||||
|
Loading…
x
Reference in New Issue
Block a user