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
123void *SoftMP3::memsetSafe(OMX_BUFFERHEADERTYPE *outHeader, int c, size_t len) {
124    if (len > outHeader->nAllocLen) {
125        ALOGE("memset buffer too small: got %u, expected %zu", outHeader->nAllocLen, len);
126        android_errorWriteLog(0x534e4554, "29422022");
127        notify(OMX_EventError, OMX_ErrorUndefined, OUTPUT_BUFFER_TOO_SMALL, NULL);
128        mSignalledError = true;
129        return NULL;
130    }
131    return memset(outHeader->pBuffer, c, len);
132}
133
134OMX_ERRORTYPE SoftMP3::internalGetParameter(
135        OMX_INDEXTYPE index, OMX_PTR params) {
136    switch (index) {
137        case OMX_IndexParamAudioPcm:
138        {
139            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
140                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
141
142            if (!isValidOMXParam(pcmParams)) {
143                return OMX_ErrorBadParameter;
144            }
145
146            if (pcmParams->nPortIndex > 1) {
147                return OMX_ErrorUndefined;
148            }
149
150            pcmParams->eNumData = OMX_NumericalDataSigned;
151            pcmParams->eEndian = OMX_EndianBig;
152            pcmParams->bInterleaved = OMX_TRUE;
153            pcmParams->nBitPerSample = 16;
154            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
155            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
156            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
157
158            pcmParams->nChannels = mNumChannels;
159            pcmParams->nSamplingRate = mSamplingRate;
160
161            return OMX_ErrorNone;
162        }
163
164        case OMX_IndexParamAudioMp3:
165        {
166            OMX_AUDIO_PARAM_MP3TYPE *mp3Params =
167                (OMX_AUDIO_PARAM_MP3TYPE *)params;
168
169            if (!isValidOMXParam(mp3Params)) {
170                return OMX_ErrorBadParameter;
171            }
172
173            if (mp3Params->nPortIndex > 1) {
174                return OMX_ErrorUndefined;
175            }
176
177            mp3Params->nChannels = mNumChannels;
178            mp3Params->nBitRate = 0 /* unknown */;
179            mp3Params->nSampleRate = mSamplingRate;
180            // other fields are encoder-only
181
182            return OMX_ErrorNone;
183        }
184
185        default:
186            return SimpleSoftOMXComponent::internalGetParameter(index, params);
187    }
188}
189
190OMX_ERRORTYPE SoftMP3::internalSetParameter(
191        OMX_INDEXTYPE index, const OMX_PTR params) {
192    switch (index) {
193        case OMX_IndexParamStandardComponentRole:
194        {
195            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
196                (const OMX_PARAM_COMPONENTROLETYPE *)params;
197
198            if (!isValidOMXParam(roleParams)) {
199                return OMX_ErrorBadParameter;
200            }
201
202            if (strncmp((const char *)roleParams->cRole,
203                        "audio_decoder.mp3",
204                        OMX_MAX_STRINGNAME_SIZE - 1)) {
205                return OMX_ErrorUndefined;
206            }
207
208            return OMX_ErrorNone;
209        }
210
211        case OMX_IndexParamAudioPcm:
212        {
213            const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
214                (const OMX_AUDIO_PARAM_PCMMODETYPE *)params;
215
216            if (!isValidOMXParam(pcmParams)) {
217                return OMX_ErrorBadParameter;
218            }
219
220            if (pcmParams->nPortIndex != 1) {
221                return OMX_ErrorUndefined;
222            }
223
224            mNumChannels = pcmParams->nChannels;
225            mSamplingRate = pcmParams->nSamplingRate;
226
227            return OMX_ErrorNone;
228        }
229
230        default:
231            return SimpleSoftOMXComponent::internalSetParameter(index, params);
232    }
233}
234
235void SoftMP3::onQueueFilled(OMX_U32 /* portIndex */) {
236    if (mSignalledError || mOutputPortSettingsChange != NONE) {
237        return;
238    }
239
240    List<BufferInfo *> &inQueue = getPortQueue(0);
241    List<BufferInfo *> &outQueue = getPortQueue(1);
242
243    while ((!inQueue.empty() || (mSawInputEos && !mSignalledOutputEos)) && !outQueue.empty()) {
244        BufferInfo *inInfo = NULL;
245        OMX_BUFFERHEADERTYPE *inHeader = NULL;
246        if (!inQueue.empty()) {
247            inInfo = *inQueue.begin();
248            inHeader = inInfo->mHeader;
249        }
250
251        BufferInfo *outInfo = *outQueue.begin();
252        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
253        outHeader->nFlags = 0;
254
255        if (inHeader) {
256            if (inHeader->nOffset == 0 && inHeader->nFilledLen) {
257                mAnchorTimeUs = inHeader->nTimeStamp;
258                mNumFramesOutput = 0;
259            }
260
261            if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
262                mSawInputEos = true;
263            }
264
265            mConfig->pInputBuffer =
266                inHeader->pBuffer + inHeader->nOffset;
267
268            mConfig->inputBufferCurrentLength = inHeader->nFilledLen;
269        } else {
270            mConfig->pInputBuffer = NULL;
271            mConfig->inputBufferCurrentLength = 0;
272        }
273        mConfig->inputBufferMaxLength = 0;
274        mConfig->inputBufferUsedLength = 0;
275
276        mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t);
277        if ((int32)outHeader->nAllocLen < mConfig->outputFrameSize) {
278            ALOGE("input buffer too small: got %u, expected %u",
279                outHeader->nAllocLen, mConfig->outputFrameSize);
280            android_errorWriteLog(0x534e4554, "27793371");
281            notify(OMX_EventError, OMX_ErrorUndefined, OUTPUT_BUFFER_TOO_SMALL, NULL);
282            mSignalledError = true;
283            return;
284        }
285
286        mConfig->pOutputBuffer =
287            reinterpret_cast<int16_t *>(outHeader->pBuffer);
288
289        ERROR_CODE decoderErr;
290        if ((decoderErr = pvmp3_framedecoder(mConfig, mDecoderBuf))
291                != NO_DECODING_ERROR) {
292            ALOGV("mp3 decoder returned error %d", decoderErr);
293
294            if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR
295                        && decoderErr != SIDE_INFO_ERROR) {
296                ALOGE("mp3 decoder returned error %d", decoderErr);
297
298                notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
299                mSignalledError = true;
300                return;
301            }
302
303            if (mConfig->outputFrameSize == 0) {
304                mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t);
305            }
306
307            if (decoderErr == NO_ENOUGH_MAIN_DATA_ERROR && mSawInputEos) {
308                if (!mIsFirst) {
309                    // pad the end of the stream with 529 samples, since that many samples
310                    // were trimmed off the beginning when decoding started
311                    outHeader->nOffset = 0;
312                    outHeader->nFilledLen = kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t);
313
314                    if (!memsetSafe(outHeader, 0, outHeader->nFilledLen)) {
315                        return;
316                    }
317
318                }
319                outHeader->nFlags = OMX_BUFFERFLAG_EOS;
320                mSignalledOutputEos = true;
321            } else {
322                // This is recoverable, just ignore the current frame and
323                // play silence instead.
324
325                // TODO: should we skip silence (and consume input data)
326                // if mIsFirst is true as we may not have a valid
327                // mConfig->samplingRate and mConfig->num_channels?
328                ALOGV_IF(mIsFirst, "insufficient data for first frame, sending silence");
329                if (!memsetSafe(outHeader, 0, mConfig->outputFrameSize * sizeof(int16_t))) {
330                    return;
331                }
332
333                if (inHeader) {
334                    mConfig->inputBufferUsedLength = inHeader->nFilledLen;
335                }
336            }
337        } else if (mConfig->samplingRate != mSamplingRate
338                || mConfig->num_channels != mNumChannels) {
339            mSamplingRate = mConfig->samplingRate;
340            mNumChannels = mConfig->num_channels;
341
342            notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
343            mOutputPortSettingsChange = AWAITING_DISABLED;
344            return;
345        }
346
347        if (mIsFirst) {
348            mIsFirst = false;
349            // The decoder delay is 529 samples, so trim that many samples off
350            // the start of the first output buffer. This essentially makes this
351            // decoder have zero delay, which the rest of the pipeline assumes.
352            outHeader->nOffset =
353                kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t);
354
355            outHeader->nFilledLen =
356                mConfig->outputFrameSize * sizeof(int16_t) - outHeader->nOffset;
357        } else if (!mSignalledOutputEos) {
358            outHeader->nOffset = 0;
359            outHeader->nFilledLen = mConfig->outputFrameSize * sizeof(int16_t);
360        }
361
362        outHeader->nTimeStamp =
363            mAnchorTimeUs + (mNumFramesOutput * 1000000ll) / mSamplingRate;
364
365        if (inHeader) {
366            CHECK_GE(inHeader->nFilledLen, mConfig->inputBufferUsedLength);
367
368            inHeader->nOffset += mConfig->inputBufferUsedLength;
369            inHeader->nFilledLen -= mConfig->inputBufferUsedLength;
370
371
372            if (inHeader->nFilledLen == 0) {
373                inInfo->mOwnedByUs = false;
374                inQueue.erase(inQueue.begin());
375                inInfo = NULL;
376                notifyEmptyBufferDone(inHeader);
377                inHeader = NULL;
378            }
379        }
380
381        mNumFramesOutput += mConfig->outputFrameSize / mNumChannels;
382
383        outInfo->mOwnedByUs = false;
384        outQueue.erase(outQueue.begin());
385        outInfo = NULL;
386        notifyFillBufferDone(outHeader);
387        outHeader = NULL;
388    }
389}
390
391void SoftMP3::onPortFlushCompleted(OMX_U32 portIndex) {
392    if (portIndex == 0) {
393        // Make sure that the next buffer output does not still
394        // depend on fragments from the last one decoded.
395        pvmp3_InitDecoder(mConfig, mDecoderBuf);
396        mIsFirst = true;
397        mSignalledError = false;
398        mSawInputEos = false;
399        mSignalledOutputEos = false;
400    }
401}
402
403void SoftMP3::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
404    if (portIndex != 1) {
405        return;
406    }
407
408    switch (mOutputPortSettingsChange) {
409        case NONE:
410            break;
411
412        case AWAITING_DISABLED:
413        {
414            CHECK(!enabled);
415            mOutputPortSettingsChange = AWAITING_ENABLED;
416            break;
417        }
418
419        default:
420        {
421            CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
422            CHECK(enabled);
423            mOutputPortSettingsChange = NONE;
424            break;
425        }
426    }
427}
428
429void SoftMP3::onReset() {
430    pvmp3_InitDecoder(mConfig, mDecoderBuf);
431    mIsFirst = true;
432    mSignalledError = false;
433    mSawInputEos = false;
434    mSignalledOutputEos = false;
435    mOutputPortSettingsChange = NONE;
436}
437
438}  // namespace android
439
440android::SoftOMXComponent *createSoftOMXComponent(
441        const char *name, const OMX_CALLBACKTYPE *callbacks,
442        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
443    return new android::SoftMP3(name, callbacks, appData, component);
444}
445