mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Add flag to force synchronization in async queueing
Add experiment flag to force synchronization between queueing threads in AsynchronousMediaCodecAdapter. PiperOrigin-RevId: 341431481
This commit is contained in:
parent
9473fda056
commit
9e98a680da
6 changed files with 71 additions and 8 deletions
|
|
@ -92,6 +92,7 @@ public class DefaultRenderersFactory implements RenderersFactory {
|
||||||
private boolean enableDecoderFallback;
|
private boolean enableDecoderFallback;
|
||||||
private MediaCodecSelector mediaCodecSelector;
|
private MediaCodecSelector mediaCodecSelector;
|
||||||
private boolean enableAsyncQueueing;
|
private boolean enableAsyncQueueing;
|
||||||
|
private boolean forceAsyncQueueingSynchronizationWorkaround;
|
||||||
private boolean enableSynchronizeCodecInteractionsWithQueueing;
|
private boolean enableSynchronizeCodecInteractionsWithQueueing;
|
||||||
private boolean enableFloatOutput;
|
private boolean enableFloatOutput;
|
||||||
private boolean enableAudioTrackPlaybackParams;
|
private boolean enableAudioTrackPlaybackParams;
|
||||||
|
|
@ -161,6 +162,24 @@ public class DefaultRenderersFactory implements RenderersFactory {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable the asynchronous queueing synchronization workaround.
|
||||||
|
*
|
||||||
|
* <p>When enabled, the queueing threads for {@link MediaCodec} instances will synchronize on a
|
||||||
|
* shared lock when submitting buffers to the respective {@link MediaCodec}.
|
||||||
|
*
|
||||||
|
* <p>This method is experimental, and will be renamed or removed in a future release.
|
||||||
|
*
|
||||||
|
* @param enabled Whether the asynchronous queueing synchronization workaround is enabled by
|
||||||
|
* default.
|
||||||
|
* @return This factory, for convenience.
|
||||||
|
*/
|
||||||
|
public DefaultRenderersFactory experimentalSetForceAsyncQueueingSynchronizationWorkaround(
|
||||||
|
boolean enabled) {
|
||||||
|
this.forceAsyncQueueingSynchronizationWorkaround = enabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable synchronizing codec interactions with asynchronous buffer queueing.
|
* Enable synchronizing codec interactions with asynchronous buffer queueing.
|
||||||
*
|
*
|
||||||
|
|
@ -353,6 +372,8 @@ public class DefaultRenderersFactory implements RenderersFactory {
|
||||||
eventListener,
|
eventListener,
|
||||||
MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY);
|
MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY);
|
||||||
videoRenderer.experimentalSetAsynchronousBufferQueueingEnabled(enableAsyncQueueing);
|
videoRenderer.experimentalSetAsynchronousBufferQueueingEnabled(enableAsyncQueueing);
|
||||||
|
videoRenderer.experimentalSetForceAsyncQueueingSynchronizationWorkaround(
|
||||||
|
forceAsyncQueueingSynchronizationWorkaround);
|
||||||
videoRenderer.experimentalSetSynchronizeCodecInteractionsWithQueueingEnabled(
|
videoRenderer.experimentalSetSynchronizeCodecInteractionsWithQueueingEnabled(
|
||||||
enableSynchronizeCodecInteractionsWithQueueing);
|
enableSynchronizeCodecInteractionsWithQueueing);
|
||||||
out.add(videoRenderer);
|
out.add(videoRenderer);
|
||||||
|
|
@ -480,6 +501,8 @@ public class DefaultRenderersFactory implements RenderersFactory {
|
||||||
eventListener,
|
eventListener,
|
||||||
audioSink);
|
audioSink);
|
||||||
audioRenderer.experimentalSetAsynchronousBufferQueueingEnabled(enableAsyncQueueing);
|
audioRenderer.experimentalSetAsynchronousBufferQueueingEnabled(enableAsyncQueueing);
|
||||||
|
audioRenderer.experimentalSetForceAsyncQueueingSynchronizationWorkaround(
|
||||||
|
forceAsyncQueueingSynchronizationWorkaround);
|
||||||
audioRenderer.experimentalSetSynchronizeCodecInteractionsWithQueueingEnabled(
|
audioRenderer.experimentalSetSynchronizeCodecInteractionsWithQueueingEnabled(
|
||||||
enableSynchronizeCodecInteractionsWithQueueing);
|
enableSynchronizeCodecInteractionsWithQueueing);
|
||||||
out.add(audioRenderer);
|
out.add(audioRenderer);
|
||||||
|
|
|
||||||
|
|
@ -72,11 +72,15 @@ import java.nio.ByteBuffer;
|
||||||
* {@link MediaCodec}.
|
* {@link MediaCodec}.
|
||||||
*/
|
*/
|
||||||
/* package */ AsynchronousMediaCodecAdapter(
|
/* package */ AsynchronousMediaCodecAdapter(
|
||||||
MediaCodec codec, int trackType, boolean synchronizeCodecInteractionsWithQueueing) {
|
MediaCodec codec,
|
||||||
|
int trackType,
|
||||||
|
boolean forceQueueingSynchronizationWorkaround,
|
||||||
|
boolean synchronizeCodecInteractionsWithQueueing) {
|
||||||
this(
|
this(
|
||||||
codec,
|
codec,
|
||||||
new HandlerThread(createCallbackThreadLabel(trackType)),
|
new HandlerThread(createCallbackThreadLabel(trackType)),
|
||||||
new HandlerThread(createQueueingThreadLabel(trackType)),
|
new HandlerThread(createQueueingThreadLabel(trackType)),
|
||||||
|
forceQueueingSynchronizationWorkaround,
|
||||||
synchronizeCodecInteractionsWithQueueing);
|
synchronizeCodecInteractionsWithQueueing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,10 +89,13 @@ import java.nio.ByteBuffer;
|
||||||
MediaCodec codec,
|
MediaCodec codec,
|
||||||
HandlerThread callbackThread,
|
HandlerThread callbackThread,
|
||||||
HandlerThread enqueueingThread,
|
HandlerThread enqueueingThread,
|
||||||
|
boolean forceQueueingSynchronizationWorkaround,
|
||||||
boolean synchronizeCodecInteractionsWithQueueing) {
|
boolean synchronizeCodecInteractionsWithQueueing) {
|
||||||
this.codec = codec;
|
this.codec = codec;
|
||||||
this.asynchronousMediaCodecCallback = new AsynchronousMediaCodecCallback(callbackThread);
|
this.asynchronousMediaCodecCallback = new AsynchronousMediaCodecCallback(callbackThread);
|
||||||
this.bufferEnqueuer = new AsynchronousMediaCodecBufferEnqueuer(codec, enqueueingThread);
|
this.bufferEnqueuer =
|
||||||
|
new AsynchronousMediaCodecBufferEnqueuer(
|
||||||
|
codec, enqueueingThread, forceQueueingSynchronizationWorkaround);
|
||||||
this.synchronizeCodecInteractionsWithQueueing = synchronizeCodecInteractionsWithQueueing;
|
this.synchronizeCodecInteractionsWithQueueing = synchronizeCodecInteractionsWithQueueing;
|
||||||
this.state = STATE_CREATED;
|
this.state = STATE_CREATED;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,18 +68,29 @@ class AsynchronousMediaCodecBufferEnqueuer {
|
||||||
* @param codec The {@link MediaCodec} to submit input buffers to.
|
* @param codec The {@link MediaCodec} to submit input buffers to.
|
||||||
* @param queueingThread The {@link HandlerThread} to use for queueing buffers.
|
* @param queueingThread The {@link HandlerThread} to use for queueing buffers.
|
||||||
*/
|
*/
|
||||||
public AsynchronousMediaCodecBufferEnqueuer(MediaCodec codec, HandlerThread queueingThread) {
|
public AsynchronousMediaCodecBufferEnqueuer(
|
||||||
this(codec, queueingThread, /* conditionVariable= */ new ConditionVariable());
|
MediaCodec codec,
|
||||||
|
HandlerThread queueingThread,
|
||||||
|
boolean forceQueueingSynchronizationWorkaround) {
|
||||||
|
this(
|
||||||
|
codec,
|
||||||
|
queueingThread,
|
||||||
|
forceQueueingSynchronizationWorkaround,
|
||||||
|
/* conditionVariable= */ new ConditionVariable());
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
/* package */ AsynchronousMediaCodecBufferEnqueuer(
|
/* package */ AsynchronousMediaCodecBufferEnqueuer(
|
||||||
MediaCodec codec, HandlerThread handlerThread, ConditionVariable conditionVariable) {
|
MediaCodec codec,
|
||||||
|
HandlerThread handlerThread,
|
||||||
|
boolean forceQueueingSynchronizationWorkaround,
|
||||||
|
ConditionVariable conditionVariable) {
|
||||||
this.codec = codec;
|
this.codec = codec;
|
||||||
this.handlerThread = handlerThread;
|
this.handlerThread = handlerThread;
|
||||||
this.conditionVariable = conditionVariable;
|
this.conditionVariable = conditionVariable;
|
||||||
pendingRuntimeException = new AtomicReference<>();
|
pendingRuntimeException = new AtomicReference<>();
|
||||||
needsSynchronizationWorkaround = needsSynchronizationWorkaround();
|
needsSynchronizationWorkaround =
|
||||||
|
forceQueueingSynchronizationWorkaround || needsSynchronizationWorkaround();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -348,6 +348,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
private boolean waitingForFirstSampleInFormat;
|
private boolean waitingForFirstSampleInFormat;
|
||||||
private boolean pendingOutputEndOfStream;
|
private boolean pendingOutputEndOfStream;
|
||||||
private boolean enableAsynchronousBufferQueueing;
|
private boolean enableAsynchronousBufferQueueing;
|
||||||
|
private boolean forceAsyncQueueingSynchronizationWorkaround;
|
||||||
private boolean enableSynchronizeCodecInteractionsWithQueueing;
|
private boolean enableSynchronizeCodecInteractionsWithQueueing;
|
||||||
@Nullable private ExoPlaybackException pendingPlaybackException;
|
@Nullable private ExoPlaybackException pendingPlaybackException;
|
||||||
protected DecoderCounters decoderCounters;
|
protected DecoderCounters decoderCounters;
|
||||||
|
|
@ -417,6 +418,19 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
enableAsynchronousBufferQueueing = enabled;
|
enableAsynchronousBufferQueueing = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable the asynchronous queueing synchronization workaround.
|
||||||
|
*
|
||||||
|
* <p>When enabled, the queueing threads for {@link MediaCodec} instance will synchronize on a
|
||||||
|
* shared lock when submitting buffers to the respective {@link MediaCodec}.
|
||||||
|
*
|
||||||
|
* <p>This method is experimental, and will be renamed or removed in a future release. It should
|
||||||
|
* only be called before the renderer is used.
|
||||||
|
*/
|
||||||
|
public void experimentalSetForceAsyncQueueingSynchronizationWorkaround(boolean enabled) {
|
||||||
|
this.forceAsyncQueueingSynchronizationWorkaround = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable synchronizing codec interactions with asynchronous buffer queueing.
|
* Enable synchronizing codec interactions with asynchronous buffer queueing.
|
||||||
*
|
*
|
||||||
|
|
@ -1068,7 +1082,10 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
if (enableAsynchronousBufferQueueing && Util.SDK_INT >= 23) {
|
if (enableAsynchronousBufferQueueing && Util.SDK_INT >= 23) {
|
||||||
codecAdapter =
|
codecAdapter =
|
||||||
new AsynchronousMediaCodecAdapter(
|
new AsynchronousMediaCodecAdapter(
|
||||||
codec, getTrackType(), enableSynchronizeCodecInteractionsWithQueueing);
|
codec,
|
||||||
|
getTrackType(),
|
||||||
|
forceAsyncQueueingSynchronizationWorkaround,
|
||||||
|
enableSynchronizeCodecInteractionsWithQueueing);
|
||||||
} else {
|
} else {
|
||||||
codecAdapter = new SynchronousMediaCodecAdapter(codec);
|
codecAdapter = new SynchronousMediaCodecAdapter(codec);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ public class AsynchronousMediaCodecAdapterTest {
|
||||||
codec,
|
codec,
|
||||||
callbackThread,
|
callbackThread,
|
||||||
queueingThread,
|
queueingThread,
|
||||||
|
/* forceQueueingSynchronizationWorkaround= */ false,
|
||||||
/* synchronizeCodecInteractionsWithQueueing= */ false);
|
/* synchronizeCodecInteractionsWithQueueing= */ false);
|
||||||
bufferInfo = new MediaCodec.BufferInfo();
|
bufferInfo = new MediaCodec.BufferInfo();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,11 @@ public class AsynchronousMediaCodecBufferEnqueuerTest {
|
||||||
codec.start();
|
codec.start();
|
||||||
handlerThread = new TestHandlerThread("TestHandlerThread");
|
handlerThread = new TestHandlerThread("TestHandlerThread");
|
||||||
enqueuer =
|
enqueuer =
|
||||||
new AsynchronousMediaCodecBufferEnqueuer(codec, handlerThread, mockConditionVariable);
|
new AsynchronousMediaCodecBufferEnqueuer(
|
||||||
|
codec,
|
||||||
|
handlerThread,
|
||||||
|
/* forceQueueingSynchronizationWorkaround= */ false,
|
||||||
|
mockConditionVariable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue