Home | History | Annotate | Download | only in dec
      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 "SoftAMR"
     19 #include <utils/Log.h>
     20 
     21 #include "SoftAMR.h"
     22 
     23 #include "gsmamr_dec.h"
     24 #include "pvamrwbdecoder.h"
     25 
     26 #include <media/stagefright/foundation/ADebug.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 SoftAMR::SoftAMR(
     40         const char *name,
     41         const OMX_CALLBACKTYPE *callbacks,
     42         OMX_PTR appData,
     43         OMX_COMPONENTTYPE **component)
     44     : SimpleSoftOMXComponent(name, callbacks, appData, component),
     45       mMode(MODE_NARROW),
     46       mState(NULL),
     47       mDecoderBuf(NULL),
     48       mDecoderCookie(NULL),
     49       mInputBufferCount(0),
     50       mAnchorTimeUs(0),
     51       mNumSamplesOutput(0),
     52       mSignalledError(false),
     53       mOutputPortSettingsChange(NONE) {
     54     if (!strcmp(name, "OMX.google.amrwb.decoder")) {
     55         mMode = MODE_WIDE;
     56     } else {
     57         CHECK(!strcmp(name, "OMX.google.amrnb.decoder"));
     58     }
     59 
     60     initPorts();
     61     CHECK_EQ(initDecoder(), (status_t)OK);
     62 }
     63 
     64 SoftAMR::~SoftAMR() {
     65     if (mMode == MODE_NARROW) {
     66         GSMDecodeFrameExit(&mState);
     67         mState = NULL;
     68     } else {
     69         free(mDecoderBuf);
     70         mDecoderBuf = NULL;
     71 
     72         mState = NULL;
     73         mDecoderCookie = NULL;
     74     }
     75 }
     76 
     77 void SoftAMR::initPorts() {
     78     OMX_PARAM_PORTDEFINITIONTYPE def;
     79     InitOMXParams(&def);
     80 
     81     def.nPortIndex = 0;
     82     def.eDir = OMX_DirInput;
     83     def.nBufferCountMin = kNumBuffers;
     84     def.nBufferCountActual = def.nBufferCountMin;
     85     def.nBufferSize = 8192;
     86     def.bEnabled = OMX_TRUE;
     87     def.bPopulated = OMX_FALSE;
     88     def.eDomain = OMX_PortDomainAudio;
     89     def.bBuffersContiguous = OMX_FALSE;
     90     def.nBufferAlignment = 1;
     91 
     92     def.format.audio.cMIMEType =
     93         mMode == MODE_NARROW
     94             ? const_cast<char *>("audio/amr")
     95             : const_cast<char *>("audio/amrwb");
     96 
     97     def.format.audio.pNativeRender = NULL;
     98     def.format.audio.bFlagErrorConcealment = OMX_FALSE;
     99     def.format.audio.eEncoding = OMX_AUDIO_CodingAMR;
    100 
    101     addPort(def);
    102 
    103     def.nPortIndex = 1;
    104     def.eDir = OMX_DirOutput;
    105     def.nBufferCountMin = kNumBuffers;
    106     def.nBufferCountActual = def.nBufferCountMin;
    107 
    108     def.nBufferSize =
    109         (mMode == MODE_NARROW ? kNumSamplesPerFrameNB : kNumSamplesPerFrameWB)
    110             * sizeof(int16_t);
    111 
    112     def.bEnabled = OMX_TRUE;
    113     def.bPopulated = OMX_FALSE;
    114     def.eDomain = OMX_PortDomainAudio;
    115     def.bBuffersContiguous = OMX_FALSE;
    116     def.nBufferAlignment = 2;
    117 
    118     def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
    119     def.format.audio.pNativeRender = NULL;
    120     def.format.audio.bFlagErrorConcealment = OMX_FALSE;
    121     def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
    122 
    123     addPort(def);
    124 }
    125 
    126 status_t SoftAMR::initDecoder() {
    127     if (mMode == MODE_NARROW) {
    128         Word16 err = GSMInitDecode(&mState, (Word8 *)"AMRNBDecoder");
    129 
    130         if (err != 0) {
    131             return UNKNOWN_ERROR;
    132         }
    133     } else {
    134         int32_t memReq = pvDecoder_AmrWbMemRequirements();
    135         mDecoderBuf = malloc(memReq);
    136 
    137         pvDecoder_AmrWb_Init(&mState, mDecoderBuf, &mDecoderCookie);
    138     }
    139 
    140     return OK;
    141 }
    142 
    143 OMX_ERRORTYPE SoftAMR::internalGetParameter(
    144         OMX_INDEXTYPE index, OMX_PTR params) {
    145     switch (index) {
    146         case OMX_IndexParamAudioAmr:
    147         {
    148             OMX_AUDIO_PARAM_AMRTYPE *amrParams =
    149                 (OMX_AUDIO_PARAM_AMRTYPE *)params;
    150 
    151             if (amrParams->nPortIndex != 0) {
    152                 return OMX_ErrorUndefined;
    153             }
    154 
    155             amrParams->nChannels = 1;
    156             amrParams->eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff;
    157             amrParams->eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
    158 
    159             if (!isConfigured()) {
    160                 amrParams->nBitRate = 0;
    161                 amrParams->eAMRBandMode = OMX_AUDIO_AMRBandModeUnused;
    162             } else {
    163                 amrParams->nBitRate = 0;
    164                 amrParams->eAMRBandMode =
    165                     mMode == MODE_NARROW
    166                         ? OMX_AUDIO_AMRBandModeNB0 : OMX_AUDIO_AMRBandModeWB0;
    167             }
    168 
    169             return OMX_ErrorNone;
    170         }
    171 
    172         case OMX_IndexParamAudioPcm:
    173         {
    174             OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
    175                 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
    176 
    177             if (pcmParams->nPortIndex != 1) {
    178                 return OMX_ErrorUndefined;
    179             }
    180 
    181             pcmParams->nChannels = 1;
    182             pcmParams->eNumData = OMX_NumericalDataSigned;
    183             pcmParams->eEndian = OMX_EndianBig;
    184             pcmParams->bInterleaved = OMX_TRUE;
    185             pcmParams->nBitPerSample = 16;
    186 
    187             pcmParams->nSamplingRate =
    188                 (mMode == MODE_NARROW) ? kSampleRateNB : kSampleRateWB;
    189 
    190             pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
    191             pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
    192             pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
    193 
    194             return OMX_ErrorNone;
    195         }
    196 
    197         default:
    198             return SimpleSoftOMXComponent::internalGetParameter(index, params);
    199     }
    200 }
    201 
    202 OMX_ERRORTYPE SoftAMR::internalSetParameter(
    203         OMX_INDEXTYPE index, const OMX_PTR params) {
    204     switch (index) {
    205         case OMX_IndexParamStandardComponentRole:
    206         {
    207             const OMX_PARAM_COMPONENTROLETYPE *roleParams =
    208                 (const OMX_PARAM_COMPONENTROLETYPE *)params;
    209 
    210             if (mMode == MODE_NARROW) {
    211                 if (strncmp((const char *)roleParams->cRole,
    212                             "audio_decoder.amrnb",
    213                             OMX_MAX_STRINGNAME_SIZE - 1)) {
    214                     return OMX_ErrorUndefined;
    215                 }
    216             } else {
    217                 if (strncmp((const char *)roleParams->cRole,
    218                             "audio_decoder.amrwb",
    219                             OMX_MAX_STRINGNAME_SIZE - 1)) {
    220                     return OMX_ErrorUndefined;
    221                 }
    222             }
    223 
    224             return OMX_ErrorNone;
    225         }
    226 
    227         case OMX_IndexParamAudioAmr:
    228         {
    229             const OMX_AUDIO_PARAM_AMRTYPE *aacParams =
    230                 (const OMX_AUDIO_PARAM_AMRTYPE *)params;
    231 
    232             if (aacParams->nPortIndex != 0) {
    233                 return OMX_ErrorUndefined;
    234             }
    235 
    236             return OMX_ErrorNone;
    237         }
    238 
    239         case OMX_IndexParamAudioPcm:
    240         {
    241             const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
    242                 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
    243 
    244             if (pcmParams->nPortIndex != 1) {
    245                 return OMX_ErrorUndefined;
    246             }
    247 
    248             return OMX_ErrorNone;
    249         }
    250 
    251         default:
    252             return SimpleSoftOMXComponent::internalSetParameter(index, params);
    253     }
    254 }
    255 
    256 bool SoftAMR::isConfigured() const {
    257     return mInputBufferCount > 0;
    258 }
    259 
    260 static size_t getFrameSize(unsigned FT) {
    261     static const size_t kFrameSizeWB[10] = {
    262         132, 177, 253, 285, 317, 365, 397, 461, 477, 40
    263     };
    264 
    265     if (FT >= 10) {
    266         return 1;
    267     }
    268 
    269     size_t frameSize = kFrameSizeWB[FT];
    270 
    271     // Round up bits to bytes and add 1 for the header byte.
    272     frameSize = (frameSize + 7) / 8 + 1;
    273 
    274     return frameSize;
    275 }
    276 
    277 void SoftAMR::onQueueFilled(OMX_U32 portIndex) {
    278     List<BufferInfo *> &inQueue = getPortQueue(0);
    279     List<BufferInfo *> &outQueue = getPortQueue(1);
    280 
    281     if (mSignalledError || mOutputPortSettingsChange != NONE) {
    282         return;
    283     }
    284 
    285     while (!inQueue.empty() && !outQueue.empty()) {
    286         BufferInfo *inInfo = *inQueue.begin();
    287         OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
    288 
    289         BufferInfo *outInfo = *outQueue.begin();
    290         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
    291 
    292         if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
    293             inQueue.erase(inQueue.begin());
    294             inInfo->mOwnedByUs = false;
    295             notifyEmptyBufferDone(inHeader);
    296 
    297             outHeader->nFilledLen = 0;
    298             outHeader->nFlags = OMX_BUFFERFLAG_EOS;
    299 
    300             outQueue.erase(outQueue.begin());
    301             outInfo->mOwnedByUs = false;
    302             notifyFillBufferDone(outHeader);
    303             return;
    304         }
    305 
    306         if (inHeader->nOffset == 0) {
    307             mAnchorTimeUs = inHeader->nTimeStamp;
    308             mNumSamplesOutput = 0;
    309         }
    310 
    311         const uint8_t *inputPtr = inHeader->pBuffer + inHeader->nOffset;
    312         int32_t numBytesRead;
    313 
    314         if (mMode == MODE_NARROW) {
    315             numBytesRead =
    316                 AMRDecode(mState,
    317                   (Frame_Type_3GPP)((inputPtr[0] >> 3) & 0x0f),
    318                   (UWord8 *)&inputPtr[1],
    319                   reinterpret_cast<int16_t *>(outHeader->pBuffer),
    320                   MIME_IETF);
    321 
    322             if (numBytesRead == -1) {
    323                 ALOGE("PV AMR decoder AMRDecode() call failed");
    324 
    325                 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
    326                 mSignalledError = true;
    327 
    328                 return;
    329             }
    330 
    331             ++numBytesRead;  // Include the frame type header byte.
    332 
    333             if (static_cast<size_t>(numBytesRead) > inHeader->nFilledLen) {
    334                 // This is bad, should never have happened, but did. Abort now.
    335 
    336                 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
    337                 mSignalledError = true;
    338 
    339                 return;
    340             }
    341         } else {
    342             int16 mode = ((inputPtr[0] >> 3) & 0x0f);
    343 
    344             if (mode >= 10 && mode <= 13) {
    345                 ALOGE("encountered illegal frame type %d in AMR WB content.",
    346                       mode);
    347 
    348                 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
    349                 mSignalledError = true;
    350 
    351                 return;
    352             }
    353 
    354             size_t frameSize = getFrameSize(mode);
    355             CHECK_GE(inHeader->nFilledLen, frameSize);
    356 
    357             int16_t *outPtr = (int16_t *)outHeader->pBuffer;
    358 
    359             if (mode >= 9) {
    360                 // Produce silence instead of comfort noise and for
    361                 // speech lost/no data.
    362                 memset(outPtr, 0, kNumSamplesPerFrameWB * sizeof(int16_t));
    363             } else if (mode < 9) {
    364                 int16 frameType;
    365                 RX_State_wb rx_state;
    366                 mime_unsorting(
    367                         const_cast<uint8_t *>(&inputPtr[1]),
    368                         mInputSampleBuffer,
    369                         &frameType, &mode, 1, &rx_state);
    370 
    371                 int16_t numSamplesOutput;
    372                 pvDecoder_AmrWb(
    373                         mode, mInputSampleBuffer,
    374                         outPtr,
    375                         &numSamplesOutput,
    376                         mDecoderBuf, frameType, mDecoderCookie);
    377 
    378                 CHECK_EQ((int)numSamplesOutput, (int)kNumSamplesPerFrameWB);
    379 
    380                 for (int i = 0; i < kNumSamplesPerFrameWB; ++i) {
    381                     /* Delete the 2 LSBs (14-bit output) */
    382                     outPtr[i] &= 0xfffC;
    383                 }
    384             }
    385 
    386             numBytesRead = frameSize;
    387         }
    388 
    389         inHeader->nOffset += numBytesRead;
    390         inHeader->nFilledLen -= numBytesRead;
    391 
    392         outHeader->nFlags = 0;
    393         outHeader->nOffset = 0;
    394 
    395         if (mMode == MODE_NARROW) {
    396             outHeader->nFilledLen = kNumSamplesPerFrameNB * sizeof(int16_t);
    397 
    398             outHeader->nTimeStamp =
    399                 mAnchorTimeUs
    400                     + (mNumSamplesOutput * 1000000ll) / kSampleRateNB;
    401 
    402             mNumSamplesOutput += kNumSamplesPerFrameNB;
    403         } else {
    404             outHeader->nFilledLen = kNumSamplesPerFrameWB * sizeof(int16_t);
    405 
    406             outHeader->nTimeStamp =
    407                 mAnchorTimeUs
    408                     + (mNumSamplesOutput * 1000000ll) / kSampleRateWB;
    409 
    410             mNumSamplesOutput += kNumSamplesPerFrameWB;
    411         }
    412 
    413         if (inHeader->nFilledLen == 0) {
    414             inInfo->mOwnedByUs = false;
    415             inQueue.erase(inQueue.begin());
    416             inInfo = NULL;
    417             notifyEmptyBufferDone(inHeader);
    418             inHeader = NULL;
    419         }
    420 
    421         outInfo->mOwnedByUs = false;
    422         outQueue.erase(outQueue.begin());
    423         outInfo = NULL;
    424         notifyFillBufferDone(outHeader);
    425         outHeader = NULL;
    426 
    427         ++mInputBufferCount;
    428     }
    429 }
    430 
    431 void SoftAMR::onPortFlushCompleted(OMX_U32 portIndex) {
    432 }
    433 
    434 void SoftAMR::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
    435     if (portIndex != 1) {
    436         return;
    437     }
    438 
    439     switch (mOutputPortSettingsChange) {
    440         case NONE:
    441             break;
    442 
    443         case AWAITING_DISABLED:
    444         {
    445             CHECK(!enabled);
    446             mOutputPortSettingsChange = AWAITING_ENABLED;
    447             break;
    448         }
    449 
    450         default:
    451         {
    452             CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
    453             CHECK(enabled);
    454             mOutputPortSettingsChange = NONE;
    455             break;
    456         }
    457     }
    458 }
    459 
    460 }  // namespace android
    461 
    462 android::SoftOMXComponent *createSoftOMXComponent(
    463         const char *name, const OMX_CALLBACKTYPE *callbacks,
    464         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
    465     return new android::SoftAMR(name, callbacks, appData, component);
    466 }
    467 
    468