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