WebAudioMediaCodecBridge.java revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)package org.chromium.media;
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.content.Context;
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.media.MediaCodec;
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.media.MediaCodec.BufferInfo;
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.media.MediaExtractor;
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.media.MediaFormat;
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)import android.os.ParcelFileDescriptor;
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.util.Log;
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import org.chromium.base.CalledByNative;
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import org.chromium.base.JNINamespace;
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)import java.io.File;
19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)import java.nio.ByteBuffer;
20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)@JNINamespace("media")
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class WebAudioMediaCodecBridge {
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static final String LOG_TAG = "WebAudioMediaCodec";
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // TODO(rtoy): What is the correct timeout value for reading
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // from a file in memory?
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static final long TIMEOUT_MICROSECONDS = 500;
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    @CalledByNative
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    private static String CreateTempFile(Context ctx) throws java.io.IOException {
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        File outputDirectory = ctx.getCacheDir();
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        File outputFile = File.createTempFile("webaudio", ".dat", outputDirectory);
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        return outputFile.getAbsolutePath();
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    @CalledByNative
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static boolean decodeAudioFile(Context ctx,
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                           long nativeMediaCodecBridge,
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           int inputFD,
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           long dataSize) {
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (dataSize < 0 || dataSize > 0x7fffffff)
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            return false;
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        MediaExtractor extractor = new MediaExtractor();
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        ParcelFileDescriptor encodedFD;
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        encodedFD = ParcelFileDescriptor.adoptFd(inputFD);
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        try {
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            extractor.setDataSource(encodedFD.getFileDescriptor(), 0, dataSize);
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        } catch (Exception e) {
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            e.printStackTrace();
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            encodedFD.detachFd();
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            return false;
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (extractor.getTrackCount() <= 0) {
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            encodedFD.detachFd();
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            return false;
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        MediaFormat format = extractor.getTrackFormat(0);
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
62ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        // Number of channels specified in the file
63ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        int inputChannelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
64ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
65ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        // Number of channels the decoder will provide. (Not
66ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        // necessarily the same as inputChannelCount.  See
67ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        // crbug.com/266006.)
68ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        int outputChannelCount = inputChannelCount;
69ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        String mime = format.getString(MediaFormat.KEY_MIME);
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        long durationMicroseconds = 0;
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (format.containsKey(MediaFormat.KEY_DURATION)) {
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            try {
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                durationMicroseconds = format.getLong(MediaFormat.KEY_DURATION);
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            } catch (Exception e) {
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                Log.d(LOG_TAG, "Cannot get duration");
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            }
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // If the duration is too long, set to 0 to force the caller
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // not to preallocate space.  See crbug.com/326856.
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // FIXME: What should be the limit? We're arbitrarily using
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // about 2148 sec (35.8 min).
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (durationMicroseconds > 0x7fffffff) {
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            durationMicroseconds = 0;
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        Log.d(LOG_TAG, "Initial: Tracks: " + extractor.getTrackCount() +
911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)              " Format: " + format);
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // Create decoder
94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        MediaCodec codec;
95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        try {
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            codec = MediaCodec.createDecoderByType(mime);
97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        } catch (Exception e) {
98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            Log.w(LOG_TAG, "Failed to create MediaCodec for mime type: " + mime);
99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            encodedFD.detachFd();
100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            return false;
101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        }
102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        codec.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        codec.start();
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        ByteBuffer[] codecInputBuffers = codec.getInputBuffers();
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        ByteBuffer[] codecOutputBuffers = codec.getOutputBuffers();
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // A track must be selected and will be used to read samples.
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        extractor.selectTrack(0);
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        boolean sawInputEOS = false;
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        boolean sawOutputEOS = false;
1141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        boolean destinationInitialized = false;
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // Keep processing until the output is done.
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        while (!sawOutputEOS) {
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            if (!sawInputEOS) {
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                // Input side
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                int inputBufIndex = codec.dequeueInputBuffer(TIMEOUT_MICROSECONDS);
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                if (inputBufIndex >= 0) {
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    int sampleSize = extractor.readSampleData(dstBuf, 0);
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    long presentationTimeMicroSec = 0;
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    if (sampleSize < 0) {
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        sawInputEOS = true;
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        sampleSize = 0;
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    } else {
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        presentationTimeMicroSec = extractor.getSampleTime();
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    }
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    codec.queueInputBuffer(inputBufIndex,
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           0, /* offset */
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           sampleSize,
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           presentationTimeMicroSec,
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    if (!sawInputEOS) {
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        extractor.advance();
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    }
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                }
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            }
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // Output side
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            MediaCodec.BufferInfo info = new BufferInfo();
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            final int outputBufIndex = codec.dequeueOutputBuffer(info, TIMEOUT_MICROSECONDS);
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            if (outputBufIndex >= 0) {
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                ByteBuffer buf = codecOutputBuffers[outputBufIndex];
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                if (!destinationInitialized) {
1541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    // Initialize the destination as late as possible to
1551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    // catch any changes in format. But be sure to
1561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    // initialize it BEFORE we send any decoded audio,
1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    // and only initialize once.
1581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    Log.d(LOG_TAG, "Final:  Rate: " + sampleRate +
1591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                          " Channels: " + inputChannelCount +
1601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                          " Mime: " + mime +
1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                          " Duration: " + durationMicroseconds + " microsec");
1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    nativeInitializeDestination(nativeMediaCodecBridge,
1641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                                inputChannelCount,
1651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                                sampleRate,
1661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                                durationMicroseconds);
1671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    destinationInitialized = true;
1681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                }
1691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                if (destinationInitialized && info.size > 0) {
171ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                    nativeOnChunkDecoded(nativeMediaCodecBridge, buf, info.size,
172ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                         inputChannelCount, outputChannelCount);
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                }
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                buf.clear();
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                codec.releaseOutputBuffer(outputBufIndex, false /* render */);
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    sawOutputEOS = true;
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                }
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                codecOutputBuffers = codec.getOutputBuffers();
183ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
184ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                MediaFormat newFormat = codec.getOutputFormat();
185ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                outputChannelCount = newFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
1861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                sampleRate = newFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
187ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                Log.d(LOG_TAG, "output format changed to " + newFormat);
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            }
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        encodedFD.detachFd();
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        codec.stop();
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        codec.release();
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        codec = null;
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static native void nativeOnChunkDecoded(
201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        long nativeWebAudioMediaCodecBridge, ByteBuffer buf, int size,
202ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        int inputChannelCount, int outputChannelCount);
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static native void nativeInitializeDestination(
205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        long nativeWebAudioMediaCodecBridge,
206ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        int inputChannelCount,
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        int sampleRate,
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        long durationMicroseconds);
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
210