EMMA Coverage Report (generated Fri Aug 23 16:39:17 PDT 2013)
[all classes][org.chromium.media]

COVERAGE SUMMARY FOR SOURCE FILE [WebAudioMediaCodecBridge.java]

nameclass, %method, %block, %line, %
WebAudioMediaCodecBridge.java0%   (0/1)0%   (0/3)0%   (0/274)0%   (0/74)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class WebAudioMediaCodecBridge0%   (0/1)0%   (0/3)0%   (0/274)0%   (0/74)
CreateTempFile (Context): String 0%   (0/1)0%   (0/11)0%   (0/3)
WebAudioMediaCodecBridge (): void 0%   (0/1)0%   (0/3)0%   (0/1)
decodeAudioFile (Context, int, int, long): boolean 0%   (0/1)0%   (0/260)0%   (0/70)

1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4 
5package org.chromium.media;
6 
7import android.content.Context;
8import android.media.AudioFormat;
9import android.media.MediaCodec;
10import android.media.MediaCodec.BufferInfo;
11import android.media.MediaExtractor;
12import android.media.MediaFormat;
13import android.os.ParcelFileDescriptor;
14import android.util.Log;
15 
16import java.io.File;
17import java.nio.ByteBuffer;
18 
19import org.chromium.base.CalledByNative;
20import org.chromium.base.JNINamespace;
21 
22@JNINamespace("media")
23class WebAudioMediaCodecBridge {
24    private static final boolean DEBUG = true;
25    static final String LOG_TAG = "WebAudioMediaCodec";
26    // TODO(rtoy): What is the correct timeout value for reading
27    // from a file in memory?
28    static final long TIMEOUT_MICROSECONDS = 500;
29    @CalledByNative
30    private static String CreateTempFile(Context ctx) throws java.io.IOException {
31        File outputDirectory = ctx.getCacheDir();
32        File outputFile = File.createTempFile("webaudio", ".dat", outputDirectory);
33        return outputFile.getAbsolutePath();
34    }
35 
36    @CalledByNative
37    private static boolean decodeAudioFile(Context ctx,
38                                           int nativeMediaCodecBridge,
39                                           int inputFD,
40                                           long dataSize) {
41 
42        if (dataSize < 0 || dataSize > 0x7fffffff)
43            return false;
44 
45        MediaExtractor extractor = new MediaExtractor();
46 
47        ParcelFileDescriptor encodedFD;
48        encodedFD = ParcelFileDescriptor.adoptFd(inputFD);
49        try {
50            extractor.setDataSource(encodedFD.getFileDescriptor(), 0, dataSize);
51        } catch (Exception e) {
52            e.printStackTrace();
53            encodedFD.detachFd();
54            return false;
55        }
56 
57        if (extractor.getTrackCount() <= 0) {
58            encodedFD.detachFd();
59            return false;
60        }
61 
62        MediaFormat format = extractor.getTrackFormat(0);
63 
64        // Number of channels specified in the file
65        int inputChannelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
66 
67        // Number of channels the decoder will provide. (Not
68        // necessarily the same as inputChannelCount.  See
69        // crbug.com/266006.)
70        int outputChannelCount = inputChannelCount;
71 
72        int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
73        String mime = format.getString(MediaFormat.KEY_MIME);
74 
75        long durationMicroseconds = 0;
76        if (format.containsKey(MediaFormat.KEY_DURATION)) {
77            try {
78                durationMicroseconds = format.getLong(MediaFormat.KEY_DURATION);
79            } catch (Exception e) {
80                Log.d(LOG_TAG, "Cannot get duration");
81            }
82        }
83 
84        if (DEBUG) {
85            Log.d(LOG_TAG, "Tracks: " + extractor.getTrackCount()
86                  + " Rate: " + sampleRate
87                  + " Channels: " + inputChannelCount
88                  + " Mime: " + mime
89                  + " Duration: " + durationMicroseconds + " microsec");
90        }
91 
92        nativeInitializeDestination(nativeMediaCodecBridge,
93                                    inputChannelCount,
94                                    sampleRate,
95                                    durationMicroseconds);
96 
97        // Create decoder
98        MediaCodec codec = MediaCodec.createDecoderByType(mime);
99        codec.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);
100        codec.start();
101 
102        ByteBuffer[] codecInputBuffers = codec.getInputBuffers();
103        ByteBuffer[] codecOutputBuffers = codec.getOutputBuffers();
104 
105        // A track must be selected and will be used to read samples.
106        extractor.selectTrack(0);
107 
108        boolean sawInputEOS = false;
109        boolean sawOutputEOS = false;
110 
111        // Keep processing until the output is done.
112        while (!sawOutputEOS) {
113            if (!sawInputEOS) {
114                // Input side
115                int inputBufIndex = codec.dequeueInputBuffer(TIMEOUT_MICROSECONDS);
116 
117                if (inputBufIndex >= 0) {
118                    ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];
119                    int sampleSize = extractor.readSampleData(dstBuf, 0);
120                    long presentationTimeMicroSec = 0;
121 
122                    if (sampleSize < 0) {
123                        sawInputEOS = true;
124                        sampleSize = 0;
125                    } else {
126                        presentationTimeMicroSec = extractor.getSampleTime();
127                    }
128 
129                    codec.queueInputBuffer(inputBufIndex,
130                                           0, /* offset */
131                                           sampleSize,
132                                           presentationTimeMicroSec,
133                                           sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
134 
135                    if (!sawInputEOS) {
136                        extractor.advance();
137                    }
138                }
139            }
140 
141            // Output side
142            MediaCodec.BufferInfo info = new BufferInfo();
143            final int outputBufIndex = codec.dequeueOutputBuffer(info, TIMEOUT_MICROSECONDS);
144 
145            if (outputBufIndex >= 0) {
146                ByteBuffer buf = codecOutputBuffers[outputBufIndex];
147 
148                if (info.size > 0) {
149                    nativeOnChunkDecoded(nativeMediaCodecBridge, buf, info.size,
150                                         inputChannelCount, outputChannelCount);
151                }
152 
153                buf.clear();
154                codec.releaseOutputBuffer(outputBufIndex, false /* render */);
155 
156                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
157                    sawOutputEOS = true;
158                }
159            } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
160                codecOutputBuffers = codec.getOutputBuffers();
161            } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
162                MediaFormat newFormat = codec.getOutputFormat();
163                outputChannelCount = newFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
164                Log.d(LOG_TAG, "output format changed to " + newFormat);
165            }
166        }
167 
168        encodedFD.detachFd();
169 
170        codec.stop();
171        codec.release();
172        codec = null;
173 
174        return true;
175    }
176 
177    private static native void nativeOnChunkDecoded(
178        int nativeWebAudioMediaCodecBridge, ByteBuffer buf, int size,
179        int inputChannelCount, int outputChannelCount);
180 
181    private static native void nativeInitializeDestination(
182        int nativeWebAudioMediaCodecBridge,
183        int inputChannelCount,
184        int sampleRate,
185        long durationMicroseconds);
186}

[all classes][org.chromium.media]
EMMA 2.0.5312 (C) Vladimir Roubtsov