diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapter.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapter.java index fe69f3f1247..33c36061965 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapter.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapter.java @@ -191,11 +191,13 @@ public void releaseOutputBuffer(int index, long renderTimeStampNs) { @Override public int dequeueInputBufferIndex() { + bufferEnqueuer.maybeThrowException(); return asynchronousMediaCodecCallback.dequeueInputBufferIndex(); } @Override public int dequeueOutputBufferIndex(MediaCodec.BufferInfo bufferInfo) { + bufferEnqueuer.maybeThrowException(); return asynchronousMediaCodecCallback.dequeueOutputBufferIndex(bufferInfo); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecBufferEnqueuer.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecBufferEnqueuer.java index 3e95c2a500c..cc6bfd33a9a 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecBufferEnqueuer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecBufferEnqueuer.java @@ -162,7 +162,8 @@ public void waitUntilQueueingComplete() throws InterruptedException { blockUntilHandlerThreadIsIdle(); } - private void maybeThrowException() { + /** Throw any exception that occurred on the enqueuer's background queueing thread. */ + public void maybeThrowException() { @Nullable RuntimeException exception = pendingRuntimeException.getAndSet(null); if (exception != null) { throw exception; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecCallback.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecCallback.java index a4a83c0deef..c1eeadfde73 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecCallback.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecCallback.java @@ -263,11 +263,12 @@ private void flushInternal() { // else, pendingOutputFormat may already be non-null following a previous flush, and remains // set in this case. + // mediaCodecException is not reset to null. If the codec has raised an error, then it remains + // in FAILED_STATE even after flushing. availableInputBuffers.clear(); availableOutputBuffers.clear(); bufferInfos.clear(); formats.clear(); - mediaCodecException = null; } @GuardedBy("lock") diff --git a/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapterTest.java b/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapterTest.java index 819ffd89bd4..439b4d9d9fa 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapterTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapterTest.java @@ -80,6 +80,20 @@ public void dequeueInputBufferIndex_withMediaCodecError_throwsException() throws assertThrows(IllegalStateException.class, () -> adapter.dequeueInputBufferIndex()); } + @Test + public void dequeueInputBufferIndex_withPendingQueueingError_throwsException() { + // Force MediaCodec to throw an error by attempting to queue input buffer -1. + adapter.queueInputBuffer( + /* index= */ -1, + /* offset= */ 0, + /* size= */ 0, + /* presentationTimeUs= */ 0, + /* flags= */ 0); + shadowOf(queueingThread.getLooper()).idle(); + + assertThrows(IllegalStateException.class, () -> adapter.dequeueInputBufferIndex()); + } + @Test public void dequeueInputBufferIndex_afterShutdown_returnsTryAgainLater() { adapter.release(); @@ -123,6 +137,20 @@ public void dequeueOutputBufferIndex_withMediaCodecError_throwsException() throw assertThrows(IllegalStateException.class, () -> adapter.dequeueOutputBufferIndex(bufferInfo)); } + @Test + public void dequeueOutputBufferIndex_withPendingQueueingError_throwsException() { + // Force MediaCodec to throw an error by attempting to queue input buffer -1. + adapter.queueInputBuffer( + /* index= */ -1, + /* offset= */ 0, + /* size= */ 0, + /* presentationTimeUs= */ 0, + /* flags= */ 0); + shadowOf(queueingThread.getLooper()).idle(); + + assertThrows(IllegalStateException.class, () -> adapter.dequeueOutputBufferIndex(bufferInfo)); + } + @Test public void dequeueOutputBufferIndex_afterShutdown_returnsTryAgainLater() { int index = adapter.dequeueInputBufferIndex();