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