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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
DaleCurtis 2013/04/12 21:47:45 Leaving review to android/ folks.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.media;
6
7 import android.content.Context;
8 import android.media.AudioFormat;
9 import android.media.MediaCodec;
10 import android.media.MediaCodec.BufferInfo;
11 import android.media.MediaExtractor;
12 import android.media.MediaFormat;
13 import android.util.Log;
14
15 import java.nio.ByteBuffer;
16 import android.os.ParcelFileDescriptor;
17
18 import org.chromium.base.CalledByNative;
19 import org.chromium.base.JNINamespace;
20
21 @JNINamespace("media")
22 class WebAudioMediaCodecBridge {
23 private static final boolean DEBUG = true;
24 static final String LOG_TAG = "WebAudioMediaCodec";
25 // TODO(rtoy): What is the correct timeout value for reading
26 // from a file in memory?
27 static final long TIMEOUT_MICROSECONDS = 500;
28 @CalledByNative
29 private static boolean decodeAudioFile(Context ctx, int nativeMediaCodecBrid ge, int inputFD) {
30 MediaExtractor extractor = new MediaExtractor();
31
32 ParcelFileDescriptor encodedFD;
33 encodedFD = ParcelFileDescriptor.adoptFd(inputFD);
34 try {
35 extractor.setDataSource(encodedFD.getFileDescriptor());
36 } catch (Exception e) {
37 e.printStackTrace();
38 encodedFD.detachFd();
39 return false;
40 }
41
42 if (extractor.getTrackCount() <= 0) {
43 encodedFD.detachFd();
44 return false;
45 }
46
47 MediaFormat format = extractor.getTrackFormat(0);
48
49 int channelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
50 int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
51 String mime = format.getString(MediaFormat.KEY_MIME);
52
53 long duration_microseconds = 0;
54 if (format.containsKey(MediaFormat.KEY_DURATION)) {
55 try {
56 duration_microseconds = format.getLong(MediaFormat.KEY_DURATION) ;
57 } catch (Exception e) {
58 Log.d(LOG_TAG, "Cannot get duration");
59 }
60 }
61
62 if (DEBUG) {
63 Log.d(LOG_TAG, "Tracks: " + extractor.getTrackCount()
64 + " Rate: " + sampleRate
65 + " Channels: " + channelCount
66 + " Mime: " + mime
67 + " Duration: " + duration_microseconds + " microsec");
68 }
69
70 // For audio/vorbis files, MediaFormat returns a really huge
71 // (multi-year) duration value even for short files. Tell
72 // nativeInitializeDestination that this is a vorbis file so
73 // it can handle it properly.
74 //
75 // See b/8528051
76 nativeInitializeDestination(nativeMediaCodecBridge,
77 channelCount,
78 sampleRate,
79 duration_microseconds,
80 mime.equals("audio/vorbis"));
81
82 // Create decoder
83 MediaCodec codec = MediaCodec.createDecoderByType(mime);
84 codec.configure(format, null /* surface */, null /* crypto */, 0 /* flag s */);
85 codec.start();
86
87 ByteBuffer[] codecInputBuffers = codec.getInputBuffers();
88 ByteBuffer[] codecOutputBuffers = codec.getOutputBuffers();
89
90 // A track must be selected and will be used to read samples.
91 extractor.selectTrack(0);
92
93 boolean sawInputEOS = false;
94 boolean sawOutputEOS = false;
95
96 // Keep processing until the output is done.
97 while (!sawOutputEOS) {
98 if (!sawInputEOS) {
99 // Input side
100 int inputBufIndex = codec.dequeueInputBuffer(TIMEOUT_MICROSECOND S);
101
102 if (inputBufIndex >= 0) {
103 ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];
104 int sampleSize = extractor.readSampleData(dstBuf, 0);
105 long presentationTimeMicroSec = 0;
106
107 if (sampleSize < 0) {
108 sawInputEOS = true;
109 sampleSize = 0;
110 } else {
111 presentationTimeMicroSec = extractor.getSampleTime();
112 }
113
114 codec.queueInputBuffer(inputBufIndex,
115 0, /* offset */
116 sampleSize,
117 presentationTimeMicroSec,
118 sawInputEOS ? MediaCodec.BUFFER_FLAG_ END_OF_STREAM : 0);
119
120 if (!sawInputEOS) {
121 extractor.advance();
122 }
123 }
124 }
125
126 // Output side
127 MediaCodec.BufferInfo info = new BufferInfo();
128 final int outputBufIndex = codec.dequeueOutputBuffer(info, TIMEOUT_M ICROSECONDS);
129
130 if (outputBufIndex >= 0) {
131 ByteBuffer buf = codecOutputBuffers[outputBufIndex];
132
133 if (info.size > 0) {
134 nativeOnChunkDecoded(nativeMediaCodecBridge, buf, info.size) ;
135 }
136
137 buf.clear();
138 codec.releaseOutputBuffer(outputBufIndex, false /* render */);
139
140 if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
141 sawOutputEOS = true;
142 }
143 } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
144 codecOutputBuffers = codec.getOutputBuffers();
145 }
146 }
147
148 encodedFD.detachFd();
149
150 codec.stop();
151 codec.release();
152 codec = null;
153
154 return true;
155 }
156
157 private static native void nativeOnChunkDecoded(
158 int nativeWebAudioMediaCodecBridge, ByteBuffer buf, int size);
159
160 private static native void nativeInitializeDestination(
161 int nativeWebAudioMediaCodecBridge,
162 int channelCount,
163 int sampleRate,
164 long duration_microseconds,
165 boolean is_vorbis);
166 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698