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