Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(119)

Unified Diff: media/base/android/java/src/org/chromium/media/WebAudioMediaCodecBridge.java

Issue 12457043: Android implementation of WebAudio audio file decoder (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/audio/android/audio_manager_android.cc ('k') | media/base/android/media_jni_registrar.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/base/android/java/src/org/chromium/media/WebAudioMediaCodecBridge.java
diff --git a/media/base/android/java/src/org/chromium/media/WebAudioMediaCodecBridge.java b/media/base/android/java/src/org/chromium/media/WebAudioMediaCodecBridge.java
new file mode 100644
index 0000000000000000000000000000000000000000..2802439149c759dc5598ad5bba27f0c9099d60a3
--- /dev/null
+++ b/media/base/android/java/src/org/chromium/media/WebAudioMediaCodecBridge.java
@@ -0,0 +1,166 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.media;
+
+import android.content.Context;
+import android.media.AudioFormat;
+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;
+import android.os.ParcelFileDescriptor;
+
+import org.chromium.base.CalledByNative;
+import org.chromium.base.JNINamespace;
+
+@JNINamespace("media")
+class WebAudioMediaCodecBridge {
+ private static final boolean DEBUG = true;
+ static final String LOG_TAG = "WebAudioMediaCodec";
+ // TODO(rtoy): What is the correct timeout value for reading
+ // from a file in memory?
+ static final long TIMEOUT_MICROSECONDS = 500;
+ @CalledByNative
+ private static boolean decodeAudioFile(Context ctx, int nativeMediaCodecBridge, int inputFD) {
+ MediaExtractor extractor = new MediaExtractor();
+
+ ParcelFileDescriptor encodedFD;
+ encodedFD = ParcelFileDescriptor.adoptFd(inputFD);
+ try {
+ extractor.setDataSource(encodedFD.getFileDescriptor());
+ } catch (Exception e) {
+ e.printStackTrace();
+ encodedFD.detachFd();
+ return false;
+ }
+
+ if (extractor.getTrackCount() <= 0) {
+ encodedFD.detachFd();
+ return false;
+ }
+
+ MediaFormat format = extractor.getTrackFormat(0);
+
+ int channelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
+ int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
+ String mime = format.getString(MediaFormat.KEY_MIME);
+
+ long duration_microseconds = 0;
+ if (format.containsKey(MediaFormat.KEY_DURATION)) {
+ try {
+ duration_microseconds = format.getLong(MediaFormat.KEY_DURATION);
+ } catch (Exception e) {
+ Log.d(LOG_TAG, "Cannot get duration");
+ }
+ }
+
+ if (DEBUG) {
+ Log.d(LOG_TAG, "Tracks: " + extractor.getTrackCount()
+ + " Rate: " + sampleRate
+ + " Channels: " + channelCount
+ + " Mime: " + mime
+ + " Duration: " + duration_microseconds + " microsec");
+ }
+
+ // For audio/vorbis files, MediaFormat returns a really huge
+ // (multi-year) duration value even for short files. Tell
+ // nativeInitializeDestination that this is a vorbis file so
+ // it can handle it properly.
+ //
+ // See b/8528051
+ nativeInitializeDestination(nativeMediaCodecBridge,
+ channelCount,
+ sampleRate,
+ duration_microseconds,
+ mime.equals("audio/vorbis"));
+
+ // Create decoder
+ MediaCodec codec = MediaCodec.createDecoderByType(mime);
+ codec.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);
+ codec.start();
+
+ ByteBuffer[] codecInputBuffers = codec.getInputBuffers();
+ ByteBuffer[] codecOutputBuffers = codec.getOutputBuffers();
+
+ // A track must be selected and will be used to read samples.
+ extractor.selectTrack(0);
+
+ boolean sawInputEOS = false;
+ boolean sawOutputEOS = false;
+
+ // Keep processing until the output is done.
+ while (!sawOutputEOS) {
+ if (!sawInputEOS) {
+ // Input side
+ int inputBufIndex = codec.dequeueInputBuffer(TIMEOUT_MICROSECONDS);
+
+ if (inputBufIndex >= 0) {
+ ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];
+ int sampleSize = extractor.readSampleData(dstBuf, 0);
+ long presentationTimeMicroSec = 0;
+
+ if (sampleSize < 0) {
+ sawInputEOS = true;
+ sampleSize = 0;
+ } else {
+ presentationTimeMicroSec = extractor.getSampleTime();
+ }
+
+ codec.queueInputBuffer(inputBufIndex,
+ 0, /* offset */
+ sampleSize,
+ presentationTimeMicroSec,
+ sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
+
+ if (!sawInputEOS) {
+ extractor.advance();
+ }
+ }
+ }
+
+ // Output side
+ MediaCodec.BufferInfo info = new BufferInfo();
+ final int outputBufIndex = codec.dequeueOutputBuffer(info, TIMEOUT_MICROSECONDS);
+
+ if (outputBufIndex >= 0) {
+ ByteBuffer buf = codecOutputBuffers[outputBufIndex];
+
+ if (info.size > 0) {
+ nativeOnChunkDecoded(nativeMediaCodecBridge, buf, info.size);
+ }
+
+ buf.clear();
+ codec.releaseOutputBuffer(outputBufIndex, false /* render */);
+
+ if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+ sawOutputEOS = true;
+ }
+ } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+ codecOutputBuffers = codec.getOutputBuffers();
+ }
+ }
+
+ encodedFD.detachFd();
+
+ codec.stop();
+ codec.release();
+ codec = null;
+
+ return true;
+ }
+
+ private static native void nativeOnChunkDecoded(
+ int nativeWebAudioMediaCodecBridge, ByteBuffer buf, int size);
+
+ private static native void nativeInitializeDestination(
+ int nativeWebAudioMediaCodecBridge,
+ int channelCount,
+ int sampleRate,
+ long duration_microseconds,
+ boolean is_vorbis);
+}
« no previous file with comments | « media/audio/android/audio_manager_android.cc ('k') | media/base/android/media_jni_registrar.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698