This source file includes following definitions.
- JNINamespace
- CreateTempFile
- decodeAudioFile
- nativeOnChunkDecoded
- nativeInitializeDestination
package org.chromium.media;
import android.content.Context;
import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import java.io.File;
import java.nio.ByteBuffer;
@JNINamespace("media")
class WebAudioMediaCodecBridge {
    static final String LOG_TAG = "WebAudioMediaCodec";
    
    
    static final long TIMEOUT_MICROSECONDS = 500;
    @CalledByNative
    private static String CreateTempFile(Context ctx) throws java.io.IOException {
        File outputDirectory = ctx.getCacheDir();
        File outputFile = File.createTempFile("webaudio", ".dat", outputDirectory);
        return outputFile.getAbsolutePath();
    }
    @CalledByNative
    private static boolean decodeAudioFile(Context ctx,
                                           long nativeMediaCodecBridge,
                                           int inputFD,
                                           long dataSize) {
        if (dataSize < 0 || dataSize > 0x7fffffff)
            return false;
        MediaExtractor extractor = new MediaExtractor();
        ParcelFileDescriptor encodedFD;
        encodedFD = ParcelFileDescriptor.adoptFd(inputFD);
        try {
            extractor.setDataSource(encodedFD.getFileDescriptor(), 0, dataSize);
        } catch (Exception e) {
            e.printStackTrace();
            encodedFD.detachFd();
            return false;
        }
        if (extractor.getTrackCount() <= 0) {
            encodedFD.detachFd();
            return false;
        }
        MediaFormat format = extractor.getTrackFormat(0);
        
        int inputChannelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
        
        
        
        int outputChannelCount = inputChannelCount;
        int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
        String mime = format.getString(MediaFormat.KEY_MIME);
        long durationMicroseconds = 0;
        if (format.containsKey(MediaFormat.KEY_DURATION)) {
            try {
                durationMicroseconds = format.getLong(MediaFormat.KEY_DURATION);
            } catch (Exception e) {
                Log.d(LOG_TAG, "Cannot get duration");
            }
        }
        
        
        
        
        if (durationMicroseconds > 0x7fffffff) {
            durationMicroseconds = 0;
        }
        Log.d(LOG_TAG, "Initial: Tracks: " + extractor.getTrackCount() +
              " Format: " + format);
        
        MediaCodec codec;
        try {
            codec = MediaCodec.createDecoderByType(mime);
        } catch (Exception e) {
            Log.w(LOG_TAG, "Failed to create MediaCodec for mime type: " + mime);
            encodedFD.detachFd();
            return false;
        }
        codec.configure(format, null , null , 0 );
        codec.start();
        ByteBuffer[] codecInputBuffers = codec.getInputBuffers();
        ByteBuffer[] codecOutputBuffers = codec.getOutputBuffers();
        
        extractor.selectTrack(0);
        boolean sawInputEOS = false;
        boolean sawOutputEOS = false;
        boolean destinationInitialized = false;
        
        while (!sawOutputEOS) {
            if (!sawInputEOS) {
                
                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, 
                                           sampleSize,
                                           presentationTimeMicroSec,
                                           sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
                    if (!sawInputEOS) {
                        extractor.advance();
                    }
                }
            }
            
            MediaCodec.BufferInfo info = new BufferInfo();
            final int outputBufIndex = codec.dequeueOutputBuffer(info, TIMEOUT_MICROSECONDS);
            if (outputBufIndex >= 0) {
                ByteBuffer buf = codecOutputBuffers[outputBufIndex];
                if (!destinationInitialized) {
                    
                    
                    
                    
                    Log.d(LOG_TAG, "Final:  Rate: " + sampleRate +
                          " Channels: " + inputChannelCount +
                          " Mime: " + mime +
                          " Duration: " + durationMicroseconds + " microsec");
                    nativeInitializeDestination(nativeMediaCodecBridge,
                                                inputChannelCount,
                                                sampleRate,
                                                durationMicroseconds);
                    destinationInitialized = true;
                }
                if (destinationInitialized && info.size > 0) {
                    nativeOnChunkDecoded(nativeMediaCodecBridge, buf, info.size,
                                         inputChannelCount, outputChannelCount);
                }
                buf.clear();
                codec.releaseOutputBuffer(outputBufIndex, false );
                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                    sawOutputEOS = true;
                }
            } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
                codecOutputBuffers = codec.getOutputBuffers();
            } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                MediaFormat newFormat = codec.getOutputFormat();
                outputChannelCount = newFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
                sampleRate = newFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
                Log.d(LOG_TAG, "output format changed to " + newFormat);
            }
        }
        encodedFD.detachFd();
        codec.stop();
        codec.release();
        codec = null;
        return true;
    }
    private static native void nativeOnChunkDecoded(
        long nativeWebAudioMediaCodecBridge, ByteBuffer buf, int size,
        int inputChannelCount, int outputChannelCount);
    private static native void nativeInitializeDestination(
        long nativeWebAudioMediaCodecBridge,
        int inputChannelCount,
        int sampleRate,
        long durationMicroseconds);
}