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