From d8802df62e4ef7026cd14f1f90a173b817ad7326 Mon Sep 17 00:00:00 2001 From: christosts Date: Mon, 10 Feb 2020 10:56:34 +0000 Subject: [PATCH] Add interface MediaCodecInputBufferEnqueuer MediaCodecInputBufferEnqueuer wraps MediaCodec queue operations. PiperOrigin-RevId: 294182717 --- ...DedicatedThreadAsyncMediaCodecAdapter.java | 10 +++- .../MediaCodecInputBufferEnqueuer.java | 51 +++++++++++++++++ .../SynchronousMediaCodecBufferEnqueuer.java | 57 +++++++++++++++++++ 3 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInputBufferEnqueuer.java create mode 100644 library/core/src/main/java/com/google/android/exoplayer2/mediacodec/SynchronousMediaCodecBufferEnqueuer.java diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/DedicatedThreadAsyncMediaCodecAdapter.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/DedicatedThreadAsyncMediaCodecAdapter.java index d231a247de..4a4ff01091 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/DedicatedThreadAsyncMediaCodecAdapter.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/DedicatedThreadAsyncMediaCodecAdapter.java @@ -52,6 +52,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private long pendingFlushCount; private @State int state; private Runnable codecStartRunnable; + private final MediaCodecInputBufferEnqueuer bufferEnqueuer; @Nullable private IllegalStateException internalException; /** @@ -75,6 +76,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; this.handlerThread = handlerThread; state = STATE_CREATED; codecStartRunnable = codec::start; + bufferEnqueuer = new SynchronousMediaCodecBufferEnqueuer(this.codec); } @Override @@ -82,6 +84,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; handlerThread.start(); handler = new Handler(handlerThread.getLooper()); codec.setCallback(this, handler); + bufferEnqueuer.start(); codecStartRunnable.run(); state = STATE_STARTED; } @@ -91,7 +94,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; int index, int offset, int size, long presentationTimeUs, int flags) { // This method does not need to be synchronized because it does not interact with the // mediaCodecAsyncCallback. - codec.queueInputBuffer(index, offset, size, presentationTimeUs, flags); + bufferEnqueuer.queueInputBuffer(index, offset, size, presentationTimeUs, flags); } @Override @@ -99,7 +102,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; int index, int offset, MediaCodec.CryptoInfo info, long presentationTimeUs, int flags) { // This method does not need to be synchronized because it does not interact with the // mediaCodecAsyncCallback. - codec.queueSecureInputBuffer(index, offset, info, presentationTimeUs, flags); + bufferEnqueuer.queueSecureInputBuffer(index, offset, info, presentationTimeUs, flags); } @Override @@ -129,6 +132,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @Override public synchronized void flush() { + bufferEnqueuer.flush(); codec.flush(); ++pendingFlushCount; Util.castNonNull(handler).post(this::onFlushCompleted); @@ -137,10 +141,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @Override public synchronized void shutdown() { if (state == STATE_STARTED) { + bufferEnqueuer.shutdown(); handlerThread.quit(); mediaCodecAsyncCallback.flush(); } - state = STATE_SHUT_DOWN; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInputBufferEnqueuer.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInputBufferEnqueuer.java new file mode 100644 index 0000000000..43376d42e9 --- /dev/null +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInputBufferEnqueuer.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.exoplayer2.mediacodec; + +import android.media.MediaCodec; + +/** Abstracts operations to enqueue input buffer on a {@link android.media.MediaCodec}. */ +interface MediaCodecInputBufferEnqueuer { + + /** + * Starts this instance. + * + *

Call this method after creating an instance. + */ + void start(); + + /** + * Submits an input buffer for decoding. + * + * @see android.media.MediaCodec#queueInputBuffer + */ + void queueInputBuffer(int index, int offset, int size, long presentationTimeUs, int flags); + + /** + * Submits an input buffer that potentially contains encrypted data for decoding. + * + * @see MediaCodec#queueSecureInputBuffer + */ + void queueSecureInputBuffer( + int index, int offset, MediaCodec.CryptoInfo info, long presentationTimeUs, int flags); + + /** Flushes the instance. */ + void flush(); + + /** Shut down the instance. Make sure to call this method to release its internal resources. */ + void shutdown(); +} diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/SynchronousMediaCodecBufferEnqueuer.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/SynchronousMediaCodecBufferEnqueuer.java new file mode 100644 index 0000000000..3507b675bf --- /dev/null +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/SynchronousMediaCodecBufferEnqueuer.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.exoplayer2.mediacodec; + +import android.media.MediaCodec; + +/** + * A {@link MediaCodecInputBufferEnqueuer} that forwards queueing methods directly to {@link + * MediaCodec}. + */ +class SynchronousMediaCodecBufferEnqueuer implements MediaCodecInputBufferEnqueuer { + private final MediaCodec codec; + + /** + * Creates an instance that queues input buffers on the specified {@link MediaCodec}. + * + * @param codec The {@link MediaCodec} to submit input buffers to. + */ + SynchronousMediaCodecBufferEnqueuer(MediaCodec codec) { + this.codec = codec; + } + + @Override + public void start() {} + + @Override + public void queueInputBuffer( + int index, int offset, int size, long presentationTimeUs, int flags) { + codec.queueInputBuffer(index, offset, size, presentationTimeUs, flags); + } + + @Override + public void queueSecureInputBuffer( + int index, int offset, MediaCodec.CryptoInfo info, long presentationTimeUs, int flags) { + codec.queueSecureInputBuffer(index, offset, info, presentationTimeUs, flags); + } + + @Override + public void flush() {} + + @Override + public void shutdown() {} +}