summaryrefslogtreecommitdiffstats
path: root/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/decoder/TrackDecoder.java
diff options
context:
space:
mode:
Diffstat (limited to 'tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/decoder/TrackDecoder.java')
-rw-r--r--tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/decoder/TrackDecoder.java178
1 files changed, 178 insertions, 0 deletions
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/decoder/TrackDecoder.java b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/decoder/TrackDecoder.java
new file mode 100644
index 0000000..c81e8b4
--- /dev/null
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/decoder/TrackDecoder.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2012 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 androidx.media.filterfw.decoder;
+
+import android.annotation.TargetApi;
+import android.media.MediaCodec;
+import android.media.MediaCodec.BufferInfo;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.util.Log;
+
+import java.nio.ByteBuffer;
+
+@TargetApi(16)
+abstract class TrackDecoder {
+
+ interface Listener {
+ void onDecodedOutputAvailable(TrackDecoder decoder);
+
+ void onEndOfStream(TrackDecoder decoder);
+ }
+
+ private static final String LOG_TAG = "TrackDecoder";
+
+ private static final long TIMEOUT_US = 50; // Timeout for en-queueing and de-queueing buffers.
+
+ private static final int NO_INPUT_BUFFER = -1;
+
+ private final int mTrackIndex;
+ private final MediaFormat mMediaFormat;
+ private final Listener mListener;
+
+ private MediaCodec mMediaCodec;
+ private MediaFormat mOutputFormat;
+
+ private ByteBuffer[] mCodecInputBuffers;
+ private ByteBuffer[] mCodecOutputBuffers;
+
+ private boolean mShouldEnqueueEndOfStream;
+
+ /**
+ * @return a configured {@link MediaCodec}.
+ */
+ protected abstract MediaCodec initMediaCodec(MediaFormat format);
+
+ /**
+ * Called when decoded output is available. The implementer is responsible for releasing the
+ * assigned buffer.
+ *
+ * @return {@code true} if any further decoding should be attempted at the moment.
+ */
+ protected abstract boolean onDataAvailable(
+ MediaCodec codec, ByteBuffer[] buffers, int bufferIndex, BufferInfo info);
+
+ protected TrackDecoder(int trackIndex, MediaFormat mediaFormat, Listener listener) {
+ mTrackIndex = trackIndex;
+
+ if (mediaFormat == null) {
+ throw new NullPointerException("mediaFormat cannot be null");
+ }
+ mMediaFormat = mediaFormat;
+
+ if (listener == null) {
+ throw new NullPointerException("listener cannot be null");
+ }
+ mListener = listener;
+ }
+
+ public void init() {
+ mMediaCodec = initMediaCodec(mMediaFormat);
+ mMediaCodec.start();
+ mCodecInputBuffers = mMediaCodec.getInputBuffers();
+ mCodecOutputBuffers = mMediaCodec.getOutputBuffers();
+ }
+
+ public void signalEndOfInput() {
+ mShouldEnqueueEndOfStream = true;
+ tryEnqueueEndOfStream();
+ }
+
+ public void release() {
+ if (mMediaCodec != null) {
+ mMediaCodec.stop();
+ mMediaCodec.release();
+ }
+ }
+
+ protected MediaCodec getMediaCodec() {
+ return mMediaCodec;
+ }
+
+ protected void notifyListener() {
+ mListener.onDecodedOutputAvailable(this);
+ }
+
+ public boolean feedInput(MediaExtractor mediaExtractor) {
+ long presentationTimeUs = 0;
+
+ int inputBufferIndex = mMediaCodec.dequeueInputBuffer(TIMEOUT_US);
+ if (inputBufferIndex != NO_INPUT_BUFFER) {
+ ByteBuffer destinationBuffer = mCodecInputBuffers[inputBufferIndex];
+ int sampleSize = mediaExtractor.readSampleData(destinationBuffer, 0);
+ // We don't expect to get a sample without any data, so this should never happen.
+ if (sampleSize < 0) {
+ Log.w(LOG_TAG, "Media extractor had sample but no data.");
+
+ // Signal the end of the track immediately anyway, using the buffer.
+ mMediaCodec.queueInputBuffer(
+ inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
+ return false;
+ }
+
+ presentationTimeUs = mediaExtractor.getSampleTime();
+ mMediaCodec.queueInputBuffer(
+ inputBufferIndex,
+ 0,
+ sampleSize,
+ presentationTimeUs,
+ 0);
+
+ return mediaExtractor.advance()
+ && mediaExtractor.getSampleTrackIndex() == mTrackIndex;
+ }
+ return false;
+ }
+
+ private void tryEnqueueEndOfStream() {
+ int inputBufferIndex = mMediaCodec.dequeueInputBuffer(TIMEOUT_US);
+ // We will always eventually have an input buffer, because we keep trying until the last
+ // decoded frame is output.
+ // The EoS does not need to be signaled if the application stops decoding.
+ if (inputBufferIndex != NO_INPUT_BUFFER) {
+ mMediaCodec.queueInputBuffer(
+ inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
+ mShouldEnqueueEndOfStream = false;
+ }
+ }
+
+ public boolean drainOutputBuffer() {
+ BufferInfo outputInfo = new BufferInfo();
+ int outputBufferIndex = mMediaCodec.dequeueOutputBuffer(outputInfo, TIMEOUT_US);
+
+ if ((outputInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+ mListener.onEndOfStream(this);
+ return false;
+ }
+ if (mShouldEnqueueEndOfStream) {
+ tryEnqueueEndOfStream();
+ }
+ if (outputBufferIndex >= 0) {
+ return onDataAvailable(
+ mMediaCodec, mCodecOutputBuffers, outputBufferIndex, outputInfo);
+ } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+ mCodecOutputBuffers = mMediaCodec.getOutputBuffers();
+ return true;
+ } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+ mOutputFormat = mMediaCodec.getOutputFormat();
+ Log.d(LOG_TAG, "Output format has changed to " + mOutputFormat);
+ return true;
+ }
+ return false;
+ }
+
+}