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
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    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)
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    @SuppressWarnings("deprecation")
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    @CalledByNative
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static boolean decodeAudioFile(Context ctx,
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                           long nativeMediaCodecBridge,
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           int inputFD,
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           long dataSize) {
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (dataSize < 0 || dataSize > 0x7fffffff)
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            return false;
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        MediaExtractor extractor = new MediaExtractor();
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        ParcelFileDescriptor encodedFD;
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        encodedFD = ParcelFileDescriptor.adoptFd(inputFD);
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        try {
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            extractor.setDataSource(encodedFD.getFileDescriptor(), 0, dataSize);
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        } catch (Exception e) {
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            e.printStackTrace();
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            encodedFD.detachFd();
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            return false;
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (extractor.getTrackCount() <= 0) {
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            encodedFD.detachFd();
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            return false;
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        MediaFormat format = extractor.getTrackFormat(0);
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
63ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        // Number of channels specified in the file
64ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        int inputChannelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
65ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
66ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        // Number of channels the decoder will provide. (Not
67ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        // necessarily the same as inputChannelCount.  See
68ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        // crbug.com/266006.)
69ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        int outputChannelCount = inputChannelCount;
70ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        String mime = format.getString(MediaFormat.KEY_MIME);
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        long durationMicroseconds = 0;
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (format.containsKey(MediaFormat.KEY_DURATION)) {
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            try {
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                durationMicroseconds = format.getLong(MediaFormat.KEY_DURATION);
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            } catch (Exception e) {
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                Log.d(LOG_TAG, "Cannot get duration");
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            }
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // If the duration is too long, set to 0 to force the caller
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // not to preallocate space.  See crbug.com/326856.
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // FIXME: What should be the limit? We're arbitrarily using
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // about 2148 sec (35.8 min).
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (durationMicroseconds > 0x7fffffff) {
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            durationMicroseconds = 0;
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        Log.d(LOG_TAG, "Initial: Tracks: " + extractor.getTrackCount() +
921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)              " Format: " + format);
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // Create decoder
95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        MediaCodec codec;
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        try {
97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            codec = MediaCodec.createDecoderByType(mime);
98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        } catch (Exception e) {
99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            Log.w(LOG_TAG, "Failed to create MediaCodec for mime type: " + mime);
100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            encodedFD.detachFd();
101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            return false;
102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        }
103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        codec.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        codec.start();
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        ByteBuffer[] codecInputBuffers = codec.getInputBuffers();
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        ByteBuffer[] codecOutputBuffers = codec.getOutputBuffers();
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // A track must be selected and will be used to read samples.
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        extractor.selectTrack(0);
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        boolean sawInputEOS = false;
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        boolean sawOutputEOS = false;
1151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        boolean destinationInitialized = false;
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // Keep processing until the output is done.
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        while (!sawOutputEOS) {
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            if (!sawInputEOS) {
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                // Input side
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                int inputBufIndex = codec.dequeueInputBuffer(TIMEOUT_MICROSECONDS);
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                if (inputBufIndex >= 0) {
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    int sampleSize = extractor.readSampleData(dstBuf, 0);
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    long presentationTimeMicroSec = 0;
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    if (sampleSize < 0) {
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        sawInputEOS = true;
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        sampleSize = 0;
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    } else {
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        presentationTimeMicroSec = extractor.getSampleTime();
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    }
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    codec.queueInputBuffer(inputBufIndex,
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           0, /* offset */
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           sampleSize,
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           presentationTimeMicroSec,
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    if (!sawInputEOS) {
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        extractor.advance();
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    }
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                }
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            }
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // Output side
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            MediaCodec.BufferInfo info = new BufferInfo();
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            final int outputBufIndex = codec.dequeueOutputBuffer(info, TIMEOUT_MICROSECONDS);
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            if (outputBufIndex >= 0) {
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                ByteBuffer buf = codecOutputBuffers[outputBufIndex];
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                if (!destinationInitialized) {
1551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    // Initialize the destination as late as possible to
1561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    // catch any changes in format. But be sure to
1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    // initialize it BEFORE we send any decoded audio,
1581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    // and only initialize once.
1591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    Log.d(LOG_TAG, "Final:  Rate: " + sampleRate +
1601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                          " Channels: " + inputChannelCount +
1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                          " Mime: " + mime +
1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                          " Duration: " + durationMicroseconds + " microsec");
1631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    nativeInitializeDestination(nativeMediaCodecBridge,
1651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                                inputChannelCount,
1661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                                sampleRate,
1671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                                durationMicroseconds);
1681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    destinationInitialized = true;
1691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                }
1701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                if (destinationInitialized && info.size > 0) {
172ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                    nativeOnChunkDecoded(nativeMediaCodecBridge, buf, info.size,
173ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                         inputChannelCount, outputChannelCount);
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                }
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                buf.clear();
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                codec.releaseOutputBuffer(outputBufIndex, false /* render */);
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    sawOutputEOS = true;
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                }
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                codecOutputBuffers = codec.getOutputBuffers();
184ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
185ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                MediaFormat newFormat = codec.getOutputFormat();
186ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                outputChannelCount = newFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
1871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                sampleRate = newFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
188ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                Log.d(LOG_TAG, "output format changed to " + newFormat);
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            }
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        encodedFD.detachFd();
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        codec.stop();
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        codec.release();
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        codec = null;
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static native void nativeOnChunkDecoded(
202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        long nativeWebAudioMediaCodecBridge, ByteBuffer buf, int size,
203ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        int inputChannelCount, int outputChannelCount);
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static native void nativeInitializeDestination(
206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        long nativeWebAudioMediaCodecBridge,
207ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        int inputChannelCount,
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        int sampleRate,
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        long durationMicroseconds);
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
211