mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +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 positionSupplier;
|
||||||
private LivePositionSupplier bufferedPositionSupplier;
|
private LivePositionSupplier bufferedPositionSupplier;
|
||||||
private LivePositionSupplier totalBufferedDurationSupplier;
|
private LivePositionSupplier totalBufferedDurationSupplier;
|
||||||
private boolean isSeeking;
|
|
||||||
|
|
||||||
// "this" reference for position suppliers.
|
// "this" reference for position suppliers.
|
||||||
@SuppressWarnings("initialization:methodref.receiver.bound.invalid")
|
@SuppressWarnings("initialization:methodref.receiver.bound.invalid")
|
||||||
@ -506,9 +505,9 @@ public final class CompositionPlayer extends SimpleBasePlayer
|
|||||||
playWhenReadyChangeReason = PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST;
|
playWhenReadyChangeReason = PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST;
|
||||||
if (playbackState == STATE_READY) {
|
if (playbackState == STATE_READY) {
|
||||||
if (playWhenReady) {
|
if (playWhenReady) {
|
||||||
finalAudioSink.play();
|
checkStateNotNull(compositionPlayerInternal).startRendering();
|
||||||
} else {
|
} else {
|
||||||
finalAudioSink.pause();
|
checkStateNotNull(compositionPlayerInternal).stopRendering();
|
||||||
}
|
}
|
||||||
for (int i = 0; i < players.size(); i++) {
|
for (int i = 0; i < players.size(); i++) {
|
||||||
players.get(i).setPlayWhenReady(playWhenReady);
|
players.get(i).setPlayWhenReady(playWhenReady);
|
||||||
@ -587,7 +586,9 @@ public final class CompositionPlayer extends SimpleBasePlayer
|
|||||||
@Override
|
@Override
|
||||||
protected ListenableFuture<?> handleSetVolume(float volume) {
|
protected ListenableFuture<?> handleSetVolume(float volume) {
|
||||||
this.volume = Util.constrainValue(volume, /* min= */ 0.0f, /* max= */ 1.0f);
|
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();
|
return Futures.immediateVoidFuture();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -597,7 +598,6 @@ public final class CompositionPlayer extends SimpleBasePlayer
|
|||||||
resetLivePositionSuppliers();
|
resetLivePositionSuppliers();
|
||||||
CompositionPlayerInternal compositionPlayerInternal =
|
CompositionPlayerInternal compositionPlayerInternal =
|
||||||
checkStateNotNull(this.compositionPlayerInternal);
|
checkStateNotNull(this.compositionPlayerInternal);
|
||||||
isSeeking = true;
|
|
||||||
compositionPlayerInternal.startSeek(positionMs);
|
compositionPlayerInternal.startSeek(positionMs);
|
||||||
for (int i = 0; i < players.size(); i++) {
|
for (int i = 0; i < players.size(); i++) {
|
||||||
players.get(i).seekTo(positionMs);
|
players.get(i).seekTo(positionMs);
|
||||||
@ -683,22 +683,17 @@ public final class CompositionPlayer extends SimpleBasePlayer
|
|||||||
for (int i = 0; i < players.size(); i++) {
|
for (int i = 0; i < players.size(); i++) {
|
||||||
players.get(i).setPlayWhenReady(false);
|
players.get(i).setPlayWhenReady(false);
|
||||||
}
|
}
|
||||||
if (!isSeeking) {
|
checkStateNotNull(compositionPlayerInternal).stopRendering();
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (endedCount == players.size()) {
|
} else if (endedCount == players.size()) {
|
||||||
playbackState = STATE_ENDED;
|
playbackState = STATE_ENDED;
|
||||||
} else {
|
} else {
|
||||||
playbackState = STATE_READY;
|
playbackState = STATE_READY;
|
||||||
isSeeking = false;
|
|
||||||
if (oldPlaybackState != STATE_READY && playWhenReady) {
|
if (oldPlaybackState != STATE_READY && playWhenReady) {
|
||||||
for (int i = 0; i < players.size(); i++) {
|
for (int i = 0; i < players.size(); i++) {
|
||||||
players.get(i).setPlayWhenReady(true);
|
players.get(i).setPlayWhenReady(true);
|
||||||
}
|
}
|
||||||
finalAudioSink.play();
|
checkStateNotNull(compositionPlayerInternal).startRendering();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -799,6 +794,7 @@ public final class CompositionPlayer extends SimpleBasePlayer
|
|||||||
playbackVideoGraphWrapper,
|
playbackVideoGraphWrapper,
|
||||||
/* listener= */ this,
|
/* listener= */ this,
|
||||||
compositionInternalListenerHandler);
|
compositionInternalListenerHandler);
|
||||||
|
compositionPlayerInternal.setVolume(volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setPrimaryPlayerSequence(ExoPlayer player, EditedMediaItemSequence sequence) {
|
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 String TAG = "CompPlayerInternal";
|
||||||
private static final int MSG_SET_OUTPUT_SURFACE_INFO = 1;
|
private static final int MSG_START_RENDERING = 1;
|
||||||
private static final int MSG_CLEAR_OUTPUT_SURFACE = 2;
|
private static final int MSG_STOP_RENDERING = 2;
|
||||||
private static final int MSG_START_SEEK = 3;
|
private static final int MSG_SET_VOLUME = 3;
|
||||||
private static final int MSG_END_SEEK = 4;
|
private static final int MSG_SET_OUTPUT_SURFACE_INFO = 4;
|
||||||
private static final int MSG_RELEASE = 5;
|
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 Clock clock;
|
||||||
private final HandlerWrapper handler;
|
private final HandlerWrapper handler;
|
||||||
@ -94,6 +97,18 @@ import androidx.media3.exoplayer.video.PlaybackVideoGraphWrapper;
|
|||||||
|
|
||||||
// Public methods
|
// 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. */
|
/** Sets the output surface information on the video pipeline. */
|
||||||
public void setOutputSurfaceInfo(Surface surface, Size size) {
|
public void setOutputSurfaceInfo(Surface surface, Size size) {
|
||||||
handler
|
handler
|
||||||
@ -103,7 +118,7 @@ import androidx.media3.exoplayer.video.PlaybackVideoGraphWrapper;
|
|||||||
|
|
||||||
/** Clears the output surface from the video pipeline. */
|
/** Clears the output surface from the video pipeline. */
|
||||||
public void clearOutputSurface() {
|
public void clearOutputSurface() {
|
||||||
handler.obtainMessage(MSG_CLEAR_OUTPUT_SURFACE).sendToTarget();
|
handler.sendEmptyMessage(MSG_CLEAR_OUTPUT_SURFACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startSeek(long positionMs) {
|
public void startSeek(long positionMs) {
|
||||||
@ -111,7 +126,7 @@ import androidx.media3.exoplayer.video.PlaybackVideoGraphWrapper;
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void endSeek() {
|
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) {
|
public boolean handleMessage(Message message) {
|
||||||
try {
|
try {
|
||||||
switch (message.what) {
|
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:
|
case MSG_SET_OUTPUT_SURFACE_INFO:
|
||||||
setOutputSurfaceInfoOnInternalThread(
|
setOutputSurfaceInfoOnInternalThread(
|
||||||
/* outputSurfaceInfo= */ (OutputSurfaceInfo) message.obj);
|
/* outputSurfaceInfo= */ (OutputSurfaceInfo) message.obj);
|
||||||
|
@ -47,6 +47,7 @@ import java.util.Objects;
|
|||||||
private AudioFormat outputAudioFormat;
|
private AudioFormat outputAudioFormat;
|
||||||
private long outputFramesWritten;
|
private long outputFramesWritten;
|
||||||
private long seekPositionUs;
|
private long seekPositionUs;
|
||||||
|
private boolean isRenderingStarted;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance.
|
* Creates an instance.
|
||||||
@ -135,6 +136,24 @@ import java.util.Objects;
|
|||||||
+ sampleCountToDurationUs(outputFramesWritten, outputAudioFormat.sampleRate);
|
+ 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.
|
* 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) {
|
if (positionUs == C.TIME_UNSET) {
|
||||||
positionUs = 0;
|
positionUs = 0;
|
||||||
}
|
}
|
||||||
finalAudioSink.pause();
|
stopRendering();
|
||||||
audioGraph.blockInput();
|
audioGraph.blockInput();
|
||||||
audioGraph.setPendingStartTimeUs(positionUs);
|
audioGraph.setPendingStartTimeUs(positionUs);
|
||||||
audioGraph.flush();
|
audioGraph.flush();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user