Synchronize calls to queueSecureInpuffer()

Parallel asynchronous calls to MediaCodec.queueSecureInputBuffer() may
produce garbled video on some platforms. This workaround synchronizes
calls to MediaCodec.queueSecureInputBuffer() so that only one call is
in flight.

PiperOrigin-RevId: 297601037
This commit is contained in:
christosts 2020-02-27 16:17:27 +00:00 committed by kim-vde
parent 88e356f214
commit 4c0ba12c40

View file

@ -49,11 +49,14 @@ class AsynchronousMediaCodecBufferEnqueuer implements MediaCodecInputBufferEnque
@GuardedBy("MESSAGE_PARAMS_INSTANCE_POOL")
private static final ArrayDeque<MessageParams> MESSAGE_PARAMS_INSTANCE_POOL = new ArrayDeque<>();
private static final Object QUEUE_SECURE_LOCK = new Object();
private final MediaCodec codec;
private final HandlerThread handlerThread;
private @MonotonicNonNull Handler handler;
private final AtomicReference<@NullableType RuntimeException> pendingRuntimeException;
private final ConditionVariable conditionVariable;
private final boolean needsSynchronizationWorkaround;
private boolean started;
/**
@ -76,6 +79,7 @@ class AsynchronousMediaCodecBufferEnqueuer implements MediaCodecInputBufferEnque
this.handlerThread = handlerThread;
this.conditionVariable = conditionVariable;
pendingRuntimeException = new AtomicReference<>();
needsSynchronizationWorkaround = needsSynchronizationWorkaround();
}
@Override
@ -207,7 +211,13 @@ class AsynchronousMediaCodecBufferEnqueuer implements MediaCodecInputBufferEnque
private void doQueueSecureInputBuffer(
int index, int offset, MediaCodec.CryptoInfo info, long presentationTimeUs, int flags) {
try {
codec.queueSecureInputBuffer(index, offset, info, presentationTimeUs, flags);
if (needsSynchronizationWorkaround) {
synchronized (QUEUE_SECURE_LOCK) {
codec.queueSecureInputBuffer(index, offset, info, presentationTimeUs, flags);
}
} else {
codec.queueSecureInputBuffer(index, offset, info, presentationTimeUs, flags);
}
} catch (RuntimeException e) {
setPendingRuntimeException(e);
}
@ -260,6 +270,15 @@ class AsynchronousMediaCodecBufferEnqueuer implements MediaCodecInputBufferEnque
}
}
/**
* Returns whether this device needs the synchronization workaround when queueing secure input
* buffers (see [Internal: b/149908061]).
*/
private static boolean needsSynchronizationWorkaround() {
String manufacturer = Util.toLowerInvariant(Util.MANUFACTURER);
return manufacturer.contains("samsung") || manufacturer.contains("motorola");
}
private static String createThreadLabel(int trackType) {
StringBuilder labelBuilder = new StringBuilder("MediaCodecInputBufferEnqueuer:");
if (trackType == C.TRACK_TYPE_AUDIO) {