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_AACObjectHE_PS) {
    296         return AOT_PS;
    297     } else if (profile == OMX_AUDIO_AACObjectLD) {
    298         return AOT_ER_AAC_LD;
    299     } else if (profile == OMX_AUDIO_AACObjectELD) {
    300         return AOT_ER_AAC_ELD;
    301     } else {
    302         ALOGW("Unsupported AAC profile - defaulting to AAC-LC");
    303         return AOT_AAC_LC;
    304     }
    305 }
    306 
    307 status_t SoftAACEncoder2::setAudioParams() {
    308     // We call this whenever sample rate, number of channels or bitrate change
    309     // in reponse to setParameter calls.
    310 
    311     ALOGV("setAudioParams: %lu Hz, %lu channels, %lu bps",
    312          mSampleRate, mNumChannels, mBitRate);
    313 
    314     if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_AOT,
    315             getAOTFromProfile(mAACProfile))) {
    316         ALOGE("Failed to set AAC encoder parameters");
    317         return UNKNOWN_ERROR;
    318     }
    319 
    320     if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SAMPLERATE, mSampleRate)) {
    321         ALOGE("Failed to set AAC encoder parameters");
    322         return UNKNOWN_ERROR;
    323     }
    324     if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_BITRATE, mBitRate)) {
    325         ALOGE("Failed to set AAC encoder parameters");
    326         return UNKNOWN_ERROR;
    327     }
    328     if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_CHANNELMODE,
    329             getChannelMode(mNumChannels))) {
    330         ALOGE("Failed to set AAC encoder parameters");
    331         return UNKNOWN_ERROR;
    332     }
    333     if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_TRANSMUX, TT_MP4_RAW)) {
    334         ALOGE("Failed to set AAC encoder parameters");
    335         return UNKNOWN_ERROR;
    336     }
    337 
    338     return OK;
    339 }
    340 
    341 void SoftAACEncoder2::onQueueFilled(OMX_U32 portIndex) {
    342     if (mSignalledError) {
    343         return;
    344     }
    345 
    346     List<BufferInfo *> &inQueue = getPortQueue(0);
    347     List<BufferInfo *> &outQueue = getPortQueue(1);
    348 
    349     if (!mSentCodecSpecificData) {
    350         // The very first thing we want to output is the codec specific
    351         // data. It does not require any input data but we will need an
    352         // output buffer to store it in.
    353 
    354         if (outQueue.empty()) {
    355             return;
    356         }
    357 
    358         if (AACENC_OK != aacEncEncode(mAACEncoder, NULL, NULL, NULL, NULL)) {
    359             ALOGE("Unable to initialize encoder for profile / sample-rate / bit-rate / channels");
    360             notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
    361             mSignalledError = true;
    362             return;
    363         }
    364 
    365         OMX_U32 actualBitRate  = aacEncoder_GetParam(mAACEncoder, AACENC_BITRATE);
    366         if (mBitRate != actualBitRate) {
    367             ALOGW("Requested bitrate %lu unsupported, using %lu", mBitRate, actualBitRate);
    368         }
    369 
    370         AACENC_InfoStruct encInfo;
    371         if (AACENC_OK != aacEncInfo(mAACEncoder, &encInfo)) {
    372             ALOGE("Failed to get AAC encoder info");
    373             notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
    374             mSignalledError = true;
    375             return;
    376         }
    377 
    378         BufferInfo *outInfo = *outQueue.begin();
    379         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
    380         outHeader->nFilledLen = encInfo.confSize;
    381         outHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG;
    382 
    383         uint8_t *out = outHeader->pBuffer + outHeader->nOffset;
    384         memcpy(out, encInfo.confBuf, encInfo.confSize);
    385 
    386         outQueue.erase(outQueue.begin());
    387         outInfo->mOwnedByUs = false;
    388         notifyFillBufferDone(outHeader);
    389 
    390         mSentCodecSpecificData = true;
    391     }
    392 
    393     size_t numBytesPerInputFrame =
    394         mNumChannels * kNumSamplesPerFrame * sizeof(int16_t);
    395 
    396     // Limit input size so we only get one ELD frame
    397     if (mAACProfile == OMX_AUDIO_AACObjectELD && numBytesPerInputFrame > 512) {
    398         numBytesPerInputFrame = 512;
    399     }
    400 
    401     for (;;) {
    402         // We do the following until we run out of buffers.
    403 
    404         while (mInputSize < numBytesPerInputFrame) {
    405             // As long as there's still input data to be read we
    406             // will drain "kNumSamplesPerFrame * mNumChannels" samples
    407             // into the "mInputFrame" buffer and then encode those
    408             // as a unit into an output buffer.
    409 
    410             if (mSawInputEOS || inQueue.empty()) {
    411                 return;
    412             }
    413 
    414             BufferInfo *inInfo = *inQueue.begin();
    415             OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
    416 
    417             const void *inData = inHeader->pBuffer + inHeader->nOffset;
    418 
    419             size_t copy = numBytesPerInputFrame - mInputSize;
    420             if (copy > inHeader->nFilledLen) {
    421                 copy = inHeader->nFilledLen;
    422             }
    423 
    424             if (mInputFrame == NULL) {
    425                 mInputFrame = new int16_t[numBytesPerInputFrame / sizeof(int16_t)];
    426             }
    427 
    428             if (mInputSize == 0) {
    429                 mInputTimeUs = inHeader->nTimeStamp;
    430             }
    431 
    432             memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy);
    433             mInputSize += copy;
    434 
    435             inHeader->nOffset += copy;
    436             inHeader->nFilledLen -= copy;
    437 
    438             // "Time" on the input buffer has in effect advanced by the
    439             // number of audio frames we just advanced nOffset by.
    440             inHeader->nTimeStamp +=
    441                 (copy * 1000000ll / mSampleRate)
    442                     / (mNumChannels * sizeof(int16_t));
    443 
    444             if (inHeader->nFilledLen == 0) {
    445                 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
    446                     mSawInputEOS = true;
    447 
    448                     // Pad any remaining data with zeroes.
    449                     memset((uint8_t *)mInputFrame + mInputSize,
    450                            0,
    451                            numBytesPerInputFrame - mInputSize);
    452 
    453                     mInputSize = numBytesPerInputFrame;
    454                 }
    455 
    456                 inQueue.erase(inQueue.begin());
    457                 inInfo->mOwnedByUs = false;
    458                 notifyEmptyBufferDone(inHeader);
    459 
    460                 inData = NULL;
    461                 inHeader = NULL;
    462                 inInfo = NULL;
    463             }
    464         }
    465 
    466         // At this  point we have all the input data necessary to encode
    467         // a single frame, all we need is an output buffer to store the result
    468         // in.
    469 
    470         if (outQueue.empty()) {
    471             return;
    472         }
    473 
    474         BufferInfo *outInfo = *outQueue.begin();
    475         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
    476 
    477         uint8_t *outPtr = (uint8_t *)outHeader->pBuffer + outHeader->nOffset;
    478         size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset;
    479 
    480         AACENC_InArgs inargs;
    481         AACENC_OutArgs outargs;
    482         memset(&inargs, 0, sizeof(inargs));
    483         memset(&outargs, 0, sizeof(outargs));
    484         inargs.numInSamples = numBytesPerInputFrame / sizeof(int16_t);
    485 
    486         void* inBuffer[]        = { (unsigned char *)mInputFrame };
    487         INT   inBufferIds[]     = { IN_AUDIO_DATA };
    488         INT   inBufferSize[]    = { (INT)numBytesPerInputFrame };
    489         INT   inBufferElSize[]  = { sizeof(int16_t) };
    490 
    491         AACENC_BufDesc inBufDesc;
    492         inBufDesc.numBufs           = sizeof(inBuffer) / sizeof(void*);
    493         inBufDesc.bufs              = (void**)&inBuffer;
    494         inBufDesc.bufferIdentifiers = inBufferIds;
    495         inBufDesc.bufSizes          = inBufferSize;
    496         inBufDesc.bufElSizes        = inBufferElSize;
    497 
    498         void* outBuffer[]       = { outPtr };
    499         INT   outBufferIds[]    = { OUT_BITSTREAM_DATA };
    500         INT   outBufferSize[]   = { 0 };
    501         INT   outBufferElSize[] = { sizeof(UCHAR) };
    502 
    503         AACENC_BufDesc outBufDesc;
    504         outBufDesc.numBufs           = sizeof(outBuffer) / sizeof(void*);
    505         outBufDesc.bufs              = (void**)&outBuffer;
    506         outBufDesc.bufferIdentifiers = outBufferIds;
    507         outBufDesc.bufSizes          = outBufferSize;
    508         outBufDesc.bufElSizes        = outBufferElSize;
    509 
    510         // Encode the mInputFrame, which is treated as a modulo buffer
    511         AACENC_ERROR encoderErr = AACENC_OK;
    512         size_t nOutputBytes = 0;
    513 
    514         do {
    515             memset(&outargs, 0, sizeof(outargs));
    516 
    517             outBuffer[0] = outPtr;
    518             outBufferSize[0] = outAvailable - nOutputBytes;
    519 
    520             encoderErr = aacEncEncode(mAACEncoder,
    521                                       &inBufDesc,
    522                                       &outBufDesc,
    523                                       &inargs,
    524                                       &outargs);
    525 
    526             if (encoderErr == AACENC_OK) {
    527                 outPtr += outargs.numOutBytes;
    528                 nOutputBytes += outargs.numOutBytes;
    529 
    530                 if (outargs.numInSamples > 0) {
    531                     int numRemainingSamples = inargs.numInSamples - outargs.numInSamples;
    532                     if (numRemainingSamples > 0) {
    533                         memmove(mInputFrame,
    534                                 &mInputFrame[outargs.numInSamples],
    535                                 sizeof(int16_t) * numRemainingSamples);
    536                     }
    537                     inargs.numInSamples -= outargs.numInSamples;
    538                 }
    539             }
    540         } while (encoderErr == AACENC_OK && inargs.numInSamples > 0);
    541 
    542         outHeader->nFilledLen = nOutputBytes;
    543 
    544         outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
    545 
    546         if (mSawInputEOS) {
    547             // We also tag this output buffer with EOS if it corresponds
    548             // to the final input buffer.
    549             outHeader->nFlags = OMX_BUFFERFLAG_EOS;
    550         }
    551 
    552         outHeader->nTimeStamp = mInputTimeUs;
    553 
    554 #if 0
    555         ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)",
    556               nOutputBytes, mInputTimeUs, outHeader->nFlags);
    557 
    558         hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
    559 #endif
    560 
    561         outQueue.erase(outQueue.begin());
    562         outInfo->mOwnedByUs = false;
    563         notifyFillBufferDone(outHeader);
    564 
    565         outHeader = NULL;
    566         outInfo = NULL;
    567 
    568         mInputSize = 0;
    569     }
    570 }
    571 
    572 }  // namespace android
    573 
    574 android::SoftOMXComponent *createSoftOMXComponent(
    575         const char *name, const OMX_CALLBACKTYPE *callbacks,
    576         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
    577     return new android::SoftAACEncoder2(name, callbacks, appData, component);
    578 }
    579