SoftMP3.cpp revision 423766ca07beb7e3e9cd301385708ca13fcce3e1
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "SoftMP3"
19#include <utils/Log.h>
20
21#include "SoftMP3.h"
22
23#include <media/stagefright/foundation/ADebug.h>
24#include <media/stagefright/MediaDefs.h>
25
26#include "include/pvmp3decoder_api.h"
27
28namespace android {
29
30template<class T>
31static void InitOMXParams(T *params) {
32    params->nSize = sizeof(T);
33    params->nVersion.s.nVersionMajor = 1;
34    params->nVersion.s.nVersionMinor = 0;
35    params->nVersion.s.nRevision = 0;
36    params->nVersion.s.nStep = 0;
37}
38
39SoftMP3::SoftMP3(
40        const char *name,
41        const OMX_CALLBACKTYPE *callbacks,
42        OMX_PTR appData,
43        OMX_COMPONENTTYPE **component)
44    : SimpleSoftOMXComponent(name, callbacks, appData, component),
45      mConfig(new tPVMP3DecoderExternal),
46      mDecoderBuf(NULL),
47      mAnchorTimeUs(0),
48      mNumFramesOutput(0),
49      mNumChannels(2),
50      mSamplingRate(44100),
51      mSignalledError(false),
52      mSawInputEos(false),
53      mSignalledOutputEos(false),
54      mOutputPortSettingsChange(NONE) {
55    initPorts();
56    initDecoder();
57}
58
59SoftMP3::~SoftMP3() {
60    if (mDecoderBuf != NULL) {
61        free(mDecoderBuf);
62        mDecoderBuf = NULL;
63    }
64
65    delete mConfig;
66    mConfig = NULL;
67}
68
69void SoftMP3::initPorts() {
70    OMX_PARAM_PORTDEFINITIONTYPE def;
71    InitOMXParams(&def);
72
73    def.nPortIndex = 0;
74    def.eDir = OMX_DirInput;
75    def.nBufferCountMin = kNumBuffers;
76    def.nBufferCountActual = def.nBufferCountMin;
77    def.nBufferSize = 8192;
78    def.bEnabled = OMX_TRUE;
79    def.bPopulated = OMX_FALSE;
80    def.eDomain = OMX_PortDomainAudio;
81    def.bBuffersContiguous = OMX_FALSE;
82    def.nBufferAlignment = 1;
83
84    def.format.audio.cMIMEType =
85        const_cast<char *>(MEDIA_MIMETYPE_AUDIO_MPEG);
86
87    def.format.audio.pNativeRender = NULL;
88    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
89    def.format.audio.eEncoding = OMX_AUDIO_CodingMP3;
90
91    addPort(def);
92
93    def.nPortIndex = 1;
94    def.eDir = OMX_DirOutput;
95    def.nBufferCountMin = kNumBuffers;
96    def.nBufferCountActual = def.nBufferCountMin;
97    def.nBufferSize = kOutputBufferSize;
98    def.bEnabled = OMX_TRUE;
99    def.bPopulated = OMX_FALSE;
100    def.eDomain = OMX_PortDomainAudio;
101    def.bBuffersContiguous = OMX_FALSE;
102    def.nBufferAlignment = 2;
103
104    def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
105    def.format.audio.pNativeRender = NULL;
106    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
107    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
108
109    addPort(def);
110}
111
112void SoftMP3::initDecoder() {
113    mConfig->equalizerType = flat;
114    mConfig->crcEnabled = false;
115
116    uint32_t memRequirements = pvmp3_decoderMemRequirements();
117    mDecoderBuf = malloc(memRequirements);
118
119    pvmp3_InitDecoder(mConfig, mDecoderBuf);
120    mIsFirst = true;
121}
122
123OMX_ERRORTYPE SoftMP3::internalGetParameter(
124        OMX_INDEXTYPE index, OMX_PTR params) {
125    switch (index) {
126        case OMX_IndexParamAudioPcm:
127        {
128            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
129                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
130
131            if (!isValidOMXParam(pcmParams)) {
132                return OMX_ErrorBadParameter;
133            }
134
135            if (pcmParams->nPortIndex > 1) {
136                return OMX_ErrorUndefined;
137            }
138
139            pcmParams->eNumData = OMX_NumericalDataSigned;
140            pcmParams->eEndian = OMX_EndianBig;
141            pcmParams->bInterleaved = OMX_TRUE;
142            pcmParams->nBitPerSample = 16;
143            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
144            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
145            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
146
147            pcmParams->nChannels = mNumChannels;
148            pcmParams->nSamplingRate = mSamplingRate;
149
150            return OMX_ErrorNone;
151        }
152
153        case OMX_IndexParamAudioMp3:
154        {
155            OMX_AUDIO_PARAM_MP3TYPE *mp3Params =
156                (OMX_AUDIO_PARAM_MP3TYPE *)params;
157
158            if (!isValidOMXParam(mp3Params)) {
159                return OMX_ErrorBadParameter;
160            }
161
162            if (mp3Params->nPortIndex > 1) {
163                return OMX_ErrorUndefined;
164            }
165
166            mp3Params->nChannels = mNumChannels;
167            mp3Params->nBitRate = 0 /* unknown */;
168            mp3Params->nSampleRate = mSamplingRate;
169            // other fields are encoder-only
170
171            return OMX_ErrorNone;
172        }
173
174        default:
175            return SimpleSoftOMXComponent::internalGetParameter(index, params);
176    }
177}
178
179OMX_ERRORTYPE SoftMP3::internalSetParameter(
180        OMX_INDEXTYPE index, const OMX_PTR params) {
181    switch (index) {
182        case OMX_IndexParamStandardComponentRole:
183        {
184            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
185                (const OMX_PARAM_COMPONENTROLETYPE *)params;
186
187            if (!isValidOMXParam(roleParams)) {
188                return OMX_ErrorBadParameter;
189            }
190
191            if (strncmp((const char *)roleParams->cRole,
192                        "audio_decoder.mp3",
193                        OMX_MAX_STRINGNAME_SIZE - 1)) {
194                return OMX_ErrorUndefined;
195            }
196
197            return OMX_ErrorNone;
198        }
199
200        case OMX_IndexParamAudioPcm:
201        {
202            const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
203                (const OMX_AUDIO_PARAM_PCMMODETYPE *)params;
204
205            if (!isValidOMXParam(pcmParams)) {
206                return OMX_ErrorBadParameter;
207            }
208
209            if (pcmParams->nPortIndex != 1) {
210                return OMX_ErrorUndefined;
211            }
212
213            mNumChannels = pcmParams->nChannels;
214            mSamplingRate = pcmParams->nSamplingRate;
215
216            return OMX_ErrorNone;
217        }
218
219        default:
220            return SimpleSoftOMXComponent::internalSetParameter(index, params);
221    }
222}
223
224void SoftMP3::onQueueFilled(OMX_U32 /* portIndex */) {
225    if (mSignalledError || mOutputPortSettingsChange != NONE) {
226        return;
227    }
228
229    List<BufferInfo *> &inQueue = getPortQueue(0);
230    List<BufferInfo *> &outQueue = getPortQueue(1);
231
232    while ((!inQueue.empty() || (mSawInputEos && !mSignalledOutputEos)) && !outQueue.empty()) {
233        BufferInfo *inInfo = NULL;
234        OMX_BUFFERHEADERTYPE *inHeader = NULL;
235        if (!inQueue.empty()) {
236            inInfo = *inQueue.begin();
237            inHeader = inInfo->mHeader;
238        }
239
240        BufferInfo *outInfo = *outQueue.begin();
241        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
242        outHeader->nFlags = 0;
243
244        if (inHeader) {
245            if (inHeader->nOffset == 0 && inHeader->nFilledLen) {
246                mAnchorTimeUs = inHeader->nTimeStamp;
247                mNumFramesOutput = 0;
248            }
249
250            if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
251                mSawInputEos = true;
252            }
253
254            mConfig->pInputBuffer =
255                inHeader->pBuffer + inHeader->nOffset;
256
257            mConfig->inputBufferCurrentLength = inHeader->nFilledLen;
258        } else {
259            mConfig->pInputBuffer = NULL;
260            mConfig->inputBufferCurrentLength = 0;
261        }
262        mConfig->inputBufferMaxLength = 0;
263        mConfig->inputBufferUsedLength = 0;
264
265        mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t);
266
267        mConfig->pOutputBuffer =
268            reinterpret_cast<int16_t *>(outHeader->pBuffer);
269
270        ERROR_CODE decoderErr;
271        if ((decoderErr = pvmp3_framedecoder(mConfig, mDecoderBuf))
272                != NO_DECODING_ERROR) {
273            ALOGV("mp3 decoder returned error %d", decoderErr);
274
275            if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR
276                        && decoderErr != SIDE_INFO_ERROR) {
277                ALOGE("mp3 decoder returned error %d", decoderErr);
278
279                notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
280                mSignalledError = true;
281                return;
282            }
283
284            if (mConfig->outputFrameSize == 0) {
285                mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t);
286            }
287
288            if (decoderErr == NO_ENOUGH_MAIN_DATA_ERROR && mSawInputEos) {
289                if (!mIsFirst) {
290                    // pad the end of the stream with 529 samples, since that many samples
291                    // were trimmed off the beginning when decoding started
292                    outHeader->nOffset = 0;
293                    outHeader->nFilledLen = kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t);
294
295                    memset(outHeader->pBuffer, 0, outHeader->nFilledLen);
296                }
297                outHeader->nFlags = OMX_BUFFERFLAG_EOS;
298                mSignalledOutputEos = true;
299            } else {
300                // This is recoverable, just ignore the current frame and
301                // play silence instead.
302                memset(outHeader->pBuffer,
303                       0,
304                       mConfig->outputFrameSize * sizeof(int16_t));
305
306                if (inHeader) {
307                    mConfig->inputBufferUsedLength = inHeader->nFilledLen;
308                }
309            }
310        } else if (mConfig->samplingRate != mSamplingRate
311                || mConfig->num_channels != mNumChannels) {
312            mSamplingRate = mConfig->samplingRate;
313            mNumChannels = mConfig->num_channels;
314
315            notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
316            mOutputPortSettingsChange = AWAITING_DISABLED;
317            return;
318        }
319
320        if (mIsFirst) {
321            mIsFirst = false;
322            // The decoder delay is 529 samples, so trim that many samples off
323            // the start of the first output buffer. This essentially makes this
324            // decoder have zero delay, which the rest of the pipeline assumes.
325            outHeader->nOffset =
326                kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t);
327
328            outHeader->nFilledLen =
329                mConfig->outputFrameSize * sizeof(int16_t) - outHeader->nOffset;
330        } else if (!mSignalledOutputEos) {
331            outHeader->nOffset = 0;
332            outHeader->nFilledLen = mConfig->outputFrameSize * sizeof(int16_t);
333        }
334
335        outHeader->nTimeStamp =
336            mAnchorTimeUs
337                + (mNumFramesOutput * 1000000ll) / mConfig->samplingRate;
338
339        if (inHeader) {
340            CHECK_GE(inHeader->nFilledLen, mConfig->inputBufferUsedLength);
341
342            inHeader->nOffset += mConfig->inputBufferUsedLength;
343            inHeader->nFilledLen -= mConfig->inputBufferUsedLength;
344
345
346            if (inHeader->nFilledLen == 0) {
347                inInfo->mOwnedByUs = false;
348                inQueue.erase(inQueue.begin());
349                inInfo = NULL;
350                notifyEmptyBufferDone(inHeader);
351                inHeader = NULL;
352            }
353        }
354
355        mNumFramesOutput += mConfig->outputFrameSize / mNumChannels;
356
357        outInfo->mOwnedByUs = false;
358        outQueue.erase(outQueue.begin());
359        outInfo = NULL;
360        notifyFillBufferDone(outHeader);
361        outHeader = NULL;
362    }
363}
364
365void SoftMP3::onPortFlushCompleted(OMX_U32 portIndex) {
366    if (portIndex == 0) {
367        // Make sure that the next buffer output does not still
368        // depend on fragments from the last one decoded.
369        pvmp3_InitDecoder(mConfig, mDecoderBuf);
370        mIsFirst = true;
371        mSignalledError = false;
372        mSawInputEos = false;
373        mSignalledOutputEos = false;
374    }
375}
376
377void SoftMP3::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
378    if (portIndex != 1) {
379        return;
380    }
381
382    switch (mOutputPortSettingsChange) {
383        case NONE:
384            break;
385
386        case AWAITING_DISABLED:
387        {
388            CHECK(!enabled);
389            mOutputPortSettingsChange = AWAITING_ENABLED;
390            break;
391        }
392
393        default:
394        {
395            CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
396            CHECK(enabled);
397            mOutputPortSettingsChange = NONE;
398            break;
399        }
400    }
401}
402
403void SoftMP3::onReset() {
404    pvmp3_InitDecoder(mConfig, mDecoderBuf);
405    mIsFirst = true;
406    mSignalledError = false;
407    mSawInputEos = false;
408    mSignalledOutputEos = false;
409    mOutputPortSettingsChange = NONE;
410}
411
412}  // namespace android
413
414android::SoftOMXComponent *createSoftOMXComponent(
415        const char *name, const OMX_CALLBACKTYPE *callbacks,
416        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
417    return new android::SoftMP3(name, callbacks, appData, component);
418}
419