Home | History | Annotate | Download | only in aacenc
      1 /*
      2  * Copyright (C) 2012 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 "SoftAACEncoder2"
     19 #include <utils/Log.h>
     20 
     21 #include "SoftAACEncoder2.h"
     22 
     23 #include <media/stagefright/foundation/ADebug.h>
     24 #include <media/stagefright/foundation/hexdump.h>
     25 
     26 namespace android {
     27 
     28 template<class T>
     29 static void InitOMXParams(T *params) {
     30     params->nSize = sizeof(T);
     31     params->nVersion.s.nVersionMajor = 1;
     32     params->nVersion.s.nVersionMinor = 0;
     33     params->nVersion.s.nRevision = 0;
     34     params->nVersion.s.nStep = 0;
     35 }
     36 
     37 SoftAACEncoder2::SoftAACEncoder2(
     38         const char *name,
     39         const OMX_CALLBACKTYPE *callbacks,
     40         OMX_PTR appData,
     41         OMX_COMPONENTTYPE **component)
     42     : SimpleSoftOMXComponent(name, callbacks, appData, component),
     43       mAACEncoder(NULL),
     44       mNumChannels(1),
     45       mSampleRate(44100),
     46       mBitRate(0),
     47       mAACProfile(OMX_AUDIO_AACObjectLC),
     48       mSentCodecSpecificData(false),
     49       mInputSize(0),
     50       mInputFrame(NULL),
     51       mInputTimeUs(-1ll),
     52       mSawInputEOS(false),
     53       mSignalledError(false) {
     54     initPorts();
     55     CHECK_EQ(initEncoder(), (status_t)OK);
     56     setAudioParams();
     57 }
     58 
     59 SoftAACEncoder2::~SoftAACEncoder2() {
     60     aacEncClose(&mAACEncoder);
     61 
     62     delete[] mInputFrame;
     63     mInputFrame = NULL;
     64 }
     65 
     66 void SoftAACEncoder2::initPorts() {
     67     OMX_PARAM_PORTDEFINITIONTYPE def;
     68     InitOMXParams(&def);
     69 
     70     def.nPortIndex = 0;
     71     def.eDir = OMX_DirInput;
     72     def.nBufferCountMin = kNumBuffers;
     73     def.nBufferCountActual = def.nBufferCountMin;
     74     def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t) * 2;
     75     def.bEnabled = OMX_TRUE;
     76     def.bPopulated = OMX_FALSE;
     77     def.eDomain = OMX_PortDomainAudio;
     78     def.bBuffersContiguous = OMX_FALSE;
     79     def.nBufferAlignment = 1;
     80 
     81     def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
     82     def.format.audio.pNativeRender = NULL;
     83     def.format.audio.bFlagErrorConcealment = OMX_FALSE;
     84     def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
     85 
     86     addPort(def);
     87 
     88     def.nPortIndex = 1;
     89     def.eDir = OMX_DirOutput;
     90     def.nBufferCountMin = kNumBuffers;
     91     def.nBufferCountActual = def.nBufferCountMin;
     92     def.nBufferSize = 8192;
     93     def.bEnabled = OMX_TRUE;
     94     def.bPopulated = OMX_FALSE;
     95     def.eDomain = OMX_PortDomainAudio;
     96     def.bBuffersContiguous = OMX_FALSE;
     97     def.nBufferAlignment = 2;
     98 
     99     def.format.audio.cMIMEType = const_cast<char *>("audio/aac");
    100     def.format.audio.pNativeRender = NULL;
    101     def.format.audio.bFlagErrorConcealment = OMX_FALSE;
    102     def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
    103 
    104     addPort(def);
    105 }
    106 
    107 status_t SoftAACEncoder2::initEncoder() {
    108     if (AACENC_OK != aacEncOpen(&mAACEncoder, 0, 0)) {
    109         ALOGE("Failed to init AAC encoder");
    110         return UNKNOWN_ERROR;
    111     }
    112     return OK;
    113 }
    114 
    115 OMX_ERRORTYPE SoftAACEncoder2::internalGetParameter(
    116         OMX_INDEXTYPE index, OMX_PTR params) {
    117     switch (index) {
    118         case OMX_IndexParamAudioPortFormat:
    119         {
    120             OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
    121                 (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
    122 
    123             if (formatParams->nPortIndex > 1) {
    124                 return OMX_ErrorUndefined;
    125             }
    126 
    127             if (formatParams->nIndex > 0) {
    128                 return OMX_ErrorNoMore;
    129             }
    130 
    131             formatParams->eEncoding =
    132                 (formatParams->nPortIndex == 0)
    133                     ? OMX_AUDIO_CodingPCM : OMX_AUDIO_CodingAAC;
    134 
    135             return OMX_ErrorNone;
    136         }
    137 
    138         case OMX_IndexParamAudioAac:
    139         {
    140             OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
    141                 (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
    142 
    143             if (aacParams->nPortIndex != 1) {
    144                 return OMX_ErrorUndefined;
    145             }
    146 
    147             aacParams->nBitRate = mBitRate;
    148             aacParams->nAudioBandWidth = 0;
    149             aacParams->nAACtools = 0;
    150             aacParams->nAACERtools = 0;
    151             aacParams->eAACProfile = (OMX_AUDIO_AACPROFILETYPE) mAACProfile;
    152             aacParams->eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
    153             aacParams->eChannelMode = OMX_AUDIO_ChannelModeStereo;
    154 
    155             aacParams->nChannels = mNumChannels;
    156             aacParams->nSampleRate = mSampleRate;
    157             aacParams->nFrameLength = 0;
    158 
    159             return OMX_ErrorNone;
    160         }
    161 
    162         case OMX_IndexParamAudioPcm:
    163         {
    164             OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
    165                 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
    166 
    167             if (pcmParams->nPortIndex != 0) {
    168                 return OMX_ErrorUndefined;
    169             }
    170 
    171             pcmParams->eNumData = OMX_NumericalDataSigned;
    172             pcmParams->eEndian = OMX_EndianBig;
    173             pcmParams->bInterleaved = OMX_TRUE;
    174             pcmParams->nBitPerSample = 16;
    175             pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
    176             pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
    177             pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
    178 
    179             pcmParams->nChannels = mNumChannels;
    180             pcmParams->nSamplingRate = mSampleRate;
    181 
    182             return OMX_ErrorNone;
    183         }
    184 
    185         default:
    186             return SimpleSoftOMXComponent::internalGetParameter(index, params);
    187     }
    188 }
    189 
    190 OMX_ERRORTYPE SoftAACEncoder2::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 (strncmp((const char *)roleParams->cRole,
    199                         "audio_encoder.aac",
    200                         OMX_MAX_STRINGNAME_SIZE - 1)) {
    201                 return OMX_ErrorUndefined;
    202             }
    203 
    204             return OMX_ErrorNone;
    205         }
    206 
    207         case OMX_IndexParamAudioPortFormat:
    208         {
    209             const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
    210                 (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
    211 
    212             if (formatParams->nPortIndex > 1) {
    213                 return OMX_ErrorUndefined;
    214             }
    215 
    216             if (formatParams->nIndex > 0) {
    217                 return OMX_ErrorNoMore;
    218             }
    219 
    220             if ((formatParams->nPortIndex == 0
    221                         && formatParams->eEncoding != OMX_AUDIO_CodingPCM)
    222                 || (formatParams->nPortIndex == 1
    223                         && formatParams->eEncoding != OMX_AUDIO_CodingAAC)) {
    224                 return OMX_ErrorUndefined;
    225             }
    226 
    227             return OMX_ErrorNone;
    228         }
    229 
    230         case OMX_IndexParamAudioAac:
    231         {
    232             OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
    233                 (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
    234 
    235             if (aacParams->nPortIndex != 1) {
    236                 return OMX_ErrorUndefined;
    237             }
    238 
    239             mBitRate = aacParams->nBitRate;
    240             mNumChannels = aacParams->nChannels;
    241             mSampleRate = aacParams->nSampleRate;
    242             if (aacParams->eAACProfile != OMX_AUDIO_AACObjectNull) {
    243                 mAACProfile = aacParams->eAACProfile;
    244             }
    245 
    246             if (setAudioParams() != OK) {
    247                 return OMX_ErrorUndefined;
    248             }
    249 
    250             return OMX_ErrorNone;
    251         }
    252 
    253         case OMX_IndexParamAudioPcm:
    254         {
    255             OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
    256                 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
    257 
    258             if (pcmParams->nPortIndex != 0) {
    259                 return OMX_ErrorUndefined;
    260             }
    261 
    262             mNumChannels = pcmParams->nChannels;
    263             mSampleRate = pcmParams->nSamplingRate;
    264             if (setAudioParams() != OK) {
    265                 return OMX_ErrorUndefined;
    266             }
    267 
    268             return OMX_ErrorNone;
    269         }
    270 
    271         default:
    272             return SimpleSoftOMXComponent::internalSetParameter(index, params);
    273     }
    274 }
    275 
    276 static CHANNEL_MODE getChannelMode(OMX_U32 nChannels) {
    277     CHANNEL_MODE chMode = MODE_INVALID;
    278     switch (nChannels) {
    279         case 1: chMode = MODE_1; break;
    280         case 2: chMode = MODE_2; break;
    281         case 3: chMode = MODE_1_2; break;
    282         case 4: chMode = MODE_1_2_1; break;
    283         case 5: chMode = MODE_1_2_2; break;
    284         case 6: chMode = MODE_1_2_2_1; break;
    285         default: chMode = MODE_INVALID;
    286     }
    287     return chMode;
    288 }
    289 
    290 static AUDIO_OBJECT_TYPE getAOTFromProfile(OMX_U32 profile) {
    291     if (profile == OMX_AUDIO_AACObjectLC) {
    292         return AOT_AAC_LC;
    293     } else if (profile == OMX_AUDIO_AACObjectHE) {
    294         return AOT_SBR;
    295     } else if (profile == OMX_AUDIO_AACObjectELD) {
    296         return AOT_ER_AAC_ELD;
    297     } else {
    298         ALOGW("Unsupported AAC profile - defaulting to AAC-LC");
    299         return AOT_AAC_LC;
    300     }
    301 }
    302 
    303 status_t SoftAACEncoder2::setAudioParams() {
    304     // We call this whenever sample rate, number of channels or bitrate change
    305     // in reponse to setParameter calls.
    306 
    307     ALOGV("setAudioParams: %lu Hz, %lu channels, %lu bps",
    308          mSampleRate, mNumChannels, mBitRate);
    309 
    310     if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_AOT,
    311             getAOTFromProfile(mAACProfile))) {
    312         ALOGE("Failed to set AAC encoder parameters");
    313         return UNKNOWN_ERROR;
    314     }
    315 
    316     if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SAMPLERATE, mSampleRate)) {
    317         ALOGE("Failed to set AAC encoder parameters");
    318         return UNKNOWN_ERROR;
    319     }
    320     if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_BITRATE, mBitRate)) {
    321         ALOGE("Failed to set AAC encoder parameters");
    322         return UNKNOWN_ERROR;
    323     }
    324     if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_CHANNELMODE,
    325             getChannelMode(mNumChannels))) {
    326         ALOGE("Failed to set AAC encoder parameters");
    327         return UNKNOWN_ERROR;
    328     }
    329     if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_TRANSMUX, TT_MP4_RAW)) {
    330         ALOGE("Failed to set AAC encoder parameters");
    331         return UNKNOWN_ERROR;
    332     }
    333 
    334     return OK;
    335 }
    336 
    337 void SoftAACEncoder2::onQueueFilled(OMX_U32 portIndex) {
    338     if (mSignalledError) {
    339         return;
    340     }
    341 
    342     List<BufferInfo *> &inQueue = getPortQueue(0);
    343     List<BufferInfo *> &outQueue = getPortQueue(1);
    344 
    345     if (!mSentCodecSpecificData) {
    346         // The very first thing we want to output is the codec specific
    347         // data. It does not require any input data but we will need an
    348         // output buffer to store it in.
    349 
    350         if (outQueue.empty()) {
    351             return;
    352         }
    353 
    354         if (AACENC_OK != aacEncEncode(mAACEncoder, NULL, NULL, NULL, NULL)) {
    355             ALOGE("Unable to initialize encoder for profile / sample-rate / bit-rate / channels");
    356             notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
    357             mSignalledError = true;
    358             return;
    359         }
    360 
    361         OMX_U32 actualBitRate  = aacEncoder_GetParam(mAACEncoder, AACENC_BITRATE);
    362         if (mBitRate != actualBitRate) {
    363             ALOGW("Requested bitrate %lu unsupported, using %lu", mBitRate, actualBitRate);
    364         }
    365 
    366         AACENC_InfoStruct encInfo;
    367         if (AACENC_OK != aacEncInfo(mAACEncoder, &encInfo)) {
    368             ALOGE("Failed to get AAC encoder info");
    369             notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
    370             mSignalledError = true;
    371             return;
    372         }
    373 
    374         BufferInfo *outInfo = *outQueue.begin();
    375         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
    376         outHeader->nFilledLen = encInfo.confSize;
    377         outHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG;
    378 
    379         uint8_t *out = outHeader->pBuffer + outHeader->nOffset;
    380         memcpy(out, encInfo.confBuf, encInfo.confSize);
    381 
    382         outQueue.erase(outQueue.begin());
    383         outInfo->mOwnedByUs = false;
    384         notifyFillBufferDone(outHeader);
    385 
    386         mSentCodecSpecificData = true;
    387     }
    388 
    389     size_t numBytesPerInputFrame =
    390         mNumChannels * kNumSamplesPerFrame * sizeof(int16_t);
    391 
    392     // Limit input size so we only get one ELD frame
    393     if (mAACProfile == OMX_AUDIO_AACObjectELD && numBytesPerInputFrame > 512) {
    394         numBytesPerInputFrame = 512;
    395     }
    396 
    397     for (;;) {
    398         // We do the following until we run out of buffers.
    399 
    400         while (mInputSize < numBytesPerInputFrame) {
    401             // As long as there's still input data to be read we
    402             // will drain "kNumSamplesPerFrame * mNumChannels" samples
    403             // into the "mInputFrame" buffer and then encode those
    404             // as a unit into an output buffer.
    405 
    406             if (mSawInputEOS || inQueue.empty()) {
    407                 return;
    408             }
    409 
    410             BufferInfo *inInfo = *inQueue.begin();
    411             OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
    412 
    413             const void *inData = inHeader->pBuffer + inHeader->nOffset;
    414 
    415             size_t copy = numBytesPerInputFrame - mInputSize;
    416             if (copy > inHeader->nFilledLen) {
    417                 copy = inHeader->nFilledLen;
    418             }
    419 
    420             if (mInputFrame == NULL) {
    421                 mInputFrame = new int16_t[numBytesPerInputFrame / sizeof(int16_t)];
    422             }
    423 
    424             if (mInputSize == 0) {
    425                 mInputTimeUs = inHeader->nTimeStamp;
    426             }
    427 
    428             memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy);
    429             mInputSize += copy;
    430 
    431             inHeader->nOffset += copy;
    432             inHeader->nFilledLen -= copy;
    433 
    434             // "Time" on the input buffer has in effect advanced by the
    435             // number of audio frames we just advanced nOffset by.
    436             inHeader->nTimeStamp +=
    437                 (copy * 1000000ll / mSampleRate)
    438                     / (mNumChannels * sizeof(int16_t));
    439 
    440             if (inHeader->nFilledLen == 0) {
    441                 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
    442                     mSawInputEOS = true;
    443 
    444                     // Pad any remaining data with zeroes.
    445                     memset((uint8_t *)mInputFrame + mInputSize,
    446                            0,
    447                            numBytesPerInputFrame - mInputSize);
    448 
    449                     mInputSize = numBytesPerInputFrame;
    450                 }
    451 
    452                 inQueue.erase(inQueue.begin());
    453                 inInfo->mOwnedByUs = false;
    454                 notifyEmptyBufferDone(inHeader);
    455 
    456                 inData = NULL;
    457                 inHeader = NULL;
    458                 inInfo = NULL;
    459             }
    460         }
    461 
    462         // At this  point we have all the input data necessary to encode
    463         // a single frame, all we need is an output buffer to store the result
    464         // in.
    465 
    466         if (outQueue.empty()) {
    467             return;
    468         }
    469 
    470         BufferInfo *outInfo = *outQueue.begin();
    471         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
    472 
    473         uint8_t *outPtr = (uint8_t *)outHeader->pBuffer + outHeader->nOffset;
    474         size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset;
    475 
    476         AACENC_InArgs inargs;
    477         AACENC_OutArgs outargs;
    478         memset(&inargs, 0, sizeof(inargs));
    479         memset(&outargs, 0, sizeof(outargs));
    480         inargs.numInSamples = numBytesPerInputFrame / sizeof(int16_t);
    481 
    482         void* inBuffer[]        = { (unsigned char *)mInputFrame };
    483         INT   inBufferIds[]     = { IN_AUDIO_DATA };
    484         INT   inBufferSize[]    = { (INT)numBytesPerInputFrame };
    485         INT   inBufferElSize[]  = { sizeof(int16_t) };
    486 
    487         AACENC_BufDesc inBufDesc;
    488         inBufDesc.numBufs           = sizeof(inBuffer) / sizeof(void*);
    489         inBufDesc.bufs              = (void**)&inBuffer;
    490         inBufDesc.bufferIdentifiers = inBufferIds;
    491         inBufDesc.bufSizes          = inBufferSize;
    492         inBufDesc.bufElSizes        = inBufferElSize;
    493 
    494         void* outBuffer[]       = { outPtr };
    495         INT   outBufferIds[]    = { OUT_BITSTREAM_DATA };
    496         INT   outBufferSize[]   = { 0 };
    497         INT   outBufferElSize[] = { sizeof(UCHAR) };
    498 
    499         AACENC_BufDesc outBufDesc;
    500         outBufDesc.numBufs           = sizeof(outBuffer) / sizeof(void*);
    501         outBufDesc.bufs              = (void**)&outBuffer;
    502         outBufDesc.bufferIdentifiers = outBufferIds;
    503         outBufDesc.bufSizes          = outBufferSize;
    504         outBufDesc.bufElSizes        = outBufferElSize;
    505 
    506         // Encode the mInputFrame, which is treated as a modulo buffer
    507         AACENC_ERROR encoderErr = AACENC_OK;
    508         size_t nOutputBytes = 0;
    509 
    510         do {
    511             memset(&outargs, 0, sizeof(outargs));
    512 
    513             outBuffer[0] = outPtr;
    514             outBufferSize[0] = outAvailable - nOutputBytes;
    515 
    516             encoderErr = aacEncEncode(mAACEncoder,
    517                                       &inBufDesc,
    518                                       &outBufDesc,
    519                                       &inargs,
    520                                       &outargs);
    521 
    522             if (encoderErr == AACENC_OK) {
    523                 outPtr += outargs.numOutBytes;
    524                 nOutputBytes += outargs.numOutBytes;
    525 
    526                 if (outargs.numInSamples > 0) {
    527                     int numRemainingSamples = inargs.numInSamples - outargs.numInSamples;
    528                     if (numRemainingSamples > 0) {
    529                         memmove(mInputFrame,
    530                                 &mInputFrame[outargs.numInSamples],
    531                                 sizeof(int16_t) * numRemainingSamples);
    532                     }
    533                     inargs.numInSamples -= outargs.numInSamples;
    534                 }
    535             }
    536         } while (encoderErr == AACENC_OK && inargs.numInSamples > 0);
    537 
    538         outHeader->nFilledLen = nOutputBytes;
    539 
    540         outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
    541 
    542         if (mSawInputEOS) {
    543             // We also tag this output buffer with EOS if it corresponds
    544             // to the final input buffer.
    545             outHeader->nFlags = OMX_BUFFERFLAG_EOS;
    546         }
    547 
    548         outHeader->nTimeStamp = mInputTimeUs;
    549 
    550 #if 0
    551         ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)",
    552               nOutputBytes, mInputTimeUs, outHeader->nFlags);
    553 
    554         hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
    555 #endif
    556 
    557         outQueue.erase(outQueue.begin());
    558         outInfo->mOwnedByUs = false;
    559         notifyFillBufferDone(outHeader);
    560 
    561         outHeader = NULL;
    562         outInfo = NULL;
    563 
    564         mInputSize = 0;
    565     }
    566 }
    567 
    568 }  // namespace android
    569 
    570 android::SoftOMXComponent *createSoftOMXComponent(
    571         const char *name, const OMX_CALLBACKTYPE *callbacks,
    572         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
    573     return new android::SoftAACEncoder2(name, callbacks, appData, component);
    574 }
    575