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 "SoftAACEncoder"
     19 #include <utils/Log.h>
     20 
     21 #include "SoftAACEncoder.h"
     22 
     23 #include "voAAC.h"
     24 #include "cmnMemory.h"
     25 
     26 #include <media/stagefright/foundation/ADebug.h>
     27 #include <media/stagefright/foundation/hexdump.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 SoftAACEncoder::SoftAACEncoder(
     41         const char *name,
     42         const OMX_CALLBACKTYPE *callbacks,
     43         OMX_PTR appData,
     44         OMX_COMPONENTTYPE **component)
     45     : SimpleSoftOMXComponent(name, callbacks, appData, component),
     46       mEncoderHandle(NULL),
     47       mApiHandle(NULL),
     48       mMemOperator(NULL),
     49       mNumChannels(1),
     50       mSampleRate(44100),
     51       mBitRate(0),
     52       mSentCodecSpecificData(false),
     53       mInputSize(0),
     54       mInputFrame(NULL),
     55       mInputTimeUs(-1ll),
     56       mSawInputEOS(false),
     57       mSignalledError(false) {
     58     initPorts();
     59     CHECK_EQ(initEncoder(), (status_t)OK);
     60 
     61     setAudioParams();
     62 }
     63 
     64 SoftAACEncoder::~SoftAACEncoder() {
     65     onReset();
     66 
     67     if (mEncoderHandle) {
     68         CHECK_EQ((VO_U32)VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle));
     69         mEncoderHandle = NULL;
     70     }
     71 
     72     delete mApiHandle;
     73     mApiHandle = NULL;
     74 
     75     delete mMemOperator;
     76     mMemOperator = NULL;
     77 }
     78 
     79 void SoftAACEncoder::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 SoftAACEncoder::initEncoder() {
    121     mApiHandle = new VO_AUDIO_CODECAPI;
    122 
    123     if (VO_ERR_NONE != voGetAACEncAPI(mApiHandle)) {
    124         ALOGE("Failed to get api handle");
    125         return UNKNOWN_ERROR;
    126     }
    127 
    128     mMemOperator = new VO_MEM_OPERATOR;
    129     mMemOperator->Alloc = cmnMemAlloc;
    130     mMemOperator->Copy = cmnMemCopy;
    131     mMemOperator->Free = cmnMemFree;
    132     mMemOperator->Set = cmnMemSet;
    133     mMemOperator->Check = cmnMemCheck;
    134 
    135     VO_CODEC_INIT_USERDATA userData;
    136     memset(&userData, 0, sizeof(userData));
    137     userData.memflag = VO_IMF_USERMEMOPERATOR;
    138     userData.memData = (VO_PTR) mMemOperator;
    139     if (VO_ERR_NONE !=
    140             mApiHandle->Init(&mEncoderHandle, VO_AUDIO_CodingAAC, &userData)) {
    141         ALOGE("Failed to init AAC encoder");
    142         return UNKNOWN_ERROR;
    143     }
    144 
    145     return OK;
    146 }
    147 
    148 OMX_ERRORTYPE SoftAACEncoder::internalGetParameter(
    149         OMX_INDEXTYPE index, OMX_PTR params) {
    150     switch (index) {
    151         case OMX_IndexParamAudioPortFormat:
    152         {
    153             OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
    154                 (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
    155 
    156             if (!isValidOMXParam(formatParams)) {
    157                 return OMX_ErrorBadParameter;
    158             }
    159 
    160             if (formatParams->nPortIndex > 1) {
    161                 return OMX_ErrorUndefined;
    162             }
    163 
    164             if (formatParams->nIndex > 0) {
    165                 return OMX_ErrorNoMore;
    166             }
    167 
    168             formatParams->eEncoding =
    169                 (formatParams->nPortIndex == 0)
    170                     ? OMX_AUDIO_CodingPCM : OMX_AUDIO_CodingAAC;
    171 
    172             return OMX_ErrorNone;
    173         }
    174 
    175         case OMX_IndexParamAudioAac:
    176         {
    177             OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
    178                 (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
    179 
    180             if (!isValidOMXParam(aacParams)) {
    181                 return OMX_ErrorBadParameter;
    182             }
    183 
    184             if (aacParams->nPortIndex != 1) {
    185                 return OMX_ErrorUndefined;
    186             }
    187 
    188             aacParams->nBitRate = mBitRate;
    189             aacParams->nAudioBandWidth = 0;
    190             aacParams->nAACtools = 0;
    191             aacParams->nAACERtools = 0;
    192             aacParams->eAACProfile = OMX_AUDIO_AACObjectMain;
    193             aacParams->eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
    194             aacParams->eChannelMode = OMX_AUDIO_ChannelModeStereo;
    195 
    196             aacParams->nChannels = mNumChannels;
    197             aacParams->nSampleRate = mSampleRate;
    198             aacParams->nFrameLength = 0;
    199 
    200             return OMX_ErrorNone;
    201         }
    202 
    203         case OMX_IndexParamAudioPcm:
    204         {
    205             OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
    206                 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
    207 
    208             if (!isValidOMXParam(pcmParams)) {
    209                 return OMX_ErrorBadParameter;
    210             }
    211 
    212             if (pcmParams->nPortIndex != 0) {
    213                 return OMX_ErrorUndefined;
    214             }
    215 
    216             pcmParams->eNumData = OMX_NumericalDataSigned;
    217             pcmParams->eEndian = OMX_EndianBig;
    218             pcmParams->bInterleaved = OMX_TRUE;
    219             pcmParams->nBitPerSample = 16;
    220             pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
    221             pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
    222             pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
    223 
    224             pcmParams->nChannels = mNumChannels;
    225             pcmParams->nSamplingRate = mSampleRate;
    226 
    227             return OMX_ErrorNone;
    228         }
    229 
    230         default:
    231             return SimpleSoftOMXComponent::internalGetParameter(index, params);
    232     }
    233 }
    234 
    235 OMX_ERRORTYPE SoftAACEncoder::internalSetParameter(
    236         OMX_INDEXTYPE index, const OMX_PTR params) {
    237     switch (index) {
    238         case OMX_IndexParamStandardComponentRole:
    239         {
    240             const OMX_PARAM_COMPONENTROLETYPE *roleParams =
    241                 (const OMX_PARAM_COMPONENTROLETYPE *)params;
    242 
    243             if (!isValidOMXParam(roleParams)) {
    244                 return OMX_ErrorBadParameter;
    245             }
    246 
    247             if (strncmp((const char *)roleParams->cRole,
    248                         "audio_encoder.aac",
    249                         OMX_MAX_STRINGNAME_SIZE - 1)) {
    250                 return OMX_ErrorUndefined;
    251             }
    252 
    253             return OMX_ErrorNone;
    254         }
    255 
    256         case OMX_IndexParamAudioPortFormat:
    257         {
    258             const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
    259                 (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
    260 
    261             if (!isValidOMXParam(formatParams)) {
    262                 return OMX_ErrorBadParameter;
    263             }
    264 
    265             if (formatParams->nPortIndex > 1) {
    266                 return OMX_ErrorUndefined;
    267             }
    268 
    269             if ((formatParams->nPortIndex == 0
    270                         && formatParams->eEncoding != OMX_AUDIO_CodingPCM)
    271                 || (formatParams->nPortIndex == 1
    272                         && formatParams->eEncoding != OMX_AUDIO_CodingAAC)) {
    273                 return OMX_ErrorUndefined;
    274             }
    275 
    276             return OMX_ErrorNone;
    277         }
    278 
    279         case OMX_IndexParamAudioAac:
    280         {
    281             OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
    282                 (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
    283 
    284             if (!isValidOMXParam(aacParams)) {
    285                 return OMX_ErrorBadParameter;
    286             }
    287 
    288             if (aacParams->nPortIndex != 1) {
    289                 return OMX_ErrorUndefined;
    290             }
    291 
    292             mBitRate = aacParams->nBitRate;
    293             mNumChannels = aacParams->nChannels;
    294             mSampleRate = aacParams->nSampleRate;
    295 
    296             if (setAudioParams() != OK) {
    297                 return OMX_ErrorUndefined;
    298             }
    299 
    300             return OMX_ErrorNone;
    301         }
    302 
    303         case OMX_IndexParamAudioPcm:
    304         {
    305             OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
    306                 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
    307 
    308             if (!isValidOMXParam(pcmParams)) {
    309                 return OMX_ErrorBadParameter;
    310             }
    311 
    312             if (pcmParams->nPortIndex != 0) {
    313                 return OMX_ErrorUndefined;
    314             }
    315 
    316             mNumChannels = pcmParams->nChannels;
    317             mSampleRate = pcmParams->nSamplingRate;
    318 
    319             if (setAudioParams() != OK) {
    320                 return OMX_ErrorUndefined;
    321             }
    322 
    323             return OMX_ErrorNone;
    324         }
    325 
    326 
    327         default:
    328             return SimpleSoftOMXComponent::internalSetParameter(index, params);
    329     }
    330 }
    331 
    332 status_t SoftAACEncoder::setAudioParams() {
    333     // We call this whenever sample rate, number of channels or bitrate change
    334     // in reponse to setParameter calls.
    335 
    336     ALOGV("setAudioParams: %u Hz, %u channels, %u bps",
    337          mSampleRate, mNumChannels, mBitRate);
    338 
    339     status_t err = setAudioSpecificConfigData();
    340 
    341     if (err != OK) {
    342         return err;
    343     }
    344 
    345     AACENC_PARAM params;
    346     memset(&params, 0, sizeof(params));
    347     params.sampleRate = mSampleRate;
    348     params.bitRate = mBitRate;
    349     params.nChannels = mNumChannels;
    350     params.adtsUsed = 0;  // We add adts header in the file writer if needed.
    351     if (VO_ERR_NONE != mApiHandle->SetParam(
    352                 mEncoderHandle, VO_PID_AAC_ENCPARAM,  &params)) {
    353         ALOGE("Failed to set AAC encoder parameters");
    354         return UNKNOWN_ERROR;
    355     }
    356 
    357     return OK;
    358 }
    359 
    360 static status_t getSampleRateTableIndex(int32_t sampleRate, int32_t &index) {
    361     static const int32_t kSampleRateTable[] = {
    362         96000, 88200, 64000, 48000, 44100, 32000,
    363         24000, 22050, 16000, 12000, 11025, 8000
    364     };
    365     const int32_t tableSize =
    366         sizeof(kSampleRateTable) / sizeof(kSampleRateTable[0]);
    367 
    368     for (int32_t i = 0; i < tableSize; ++i) {
    369         if (sampleRate == kSampleRateTable[i]) {
    370             index = i;
    371             return OK;
    372         }
    373     }
    374 
    375     return UNKNOWN_ERROR;
    376 }
    377 
    378 status_t SoftAACEncoder::setAudioSpecificConfigData() {
    379     // The AAC encoder's audio specific config really only encodes
    380     // number of channels and the sample rate (mapped to an index into
    381     // a fixed sample rate table).
    382 
    383     int32_t index;
    384     status_t err = getSampleRateTableIndex(mSampleRate, index);
    385     if (err != OK) {
    386         ALOGE("Unsupported sample rate (%u Hz)", mSampleRate);
    387         return err;
    388     }
    389 
    390     if (mNumChannels > 2 || mNumChannels <= 0) {
    391         ALOGE("Unsupported number of channels(%u)", mNumChannels);
    392         return UNKNOWN_ERROR;
    393     }
    394 
    395     // OMX_AUDIO_AACObjectLC
    396     mAudioSpecificConfigData[0] = ((0x02 << 3) | (index >> 1));
    397     mAudioSpecificConfigData[1] = ((index & 0x01) << 7) | (mNumChannels << 3);
    398 
    399     return OK;
    400 }
    401 
    402 void SoftAACEncoder::onQueueFilled(OMX_U32 /*portIndex*/) {
    403     if (mSignalledError) {
    404         return;
    405     }
    406 
    407     List<BufferInfo *> &inQueue = getPortQueue(0);
    408     List<BufferInfo *> &outQueue = getPortQueue(1);
    409 
    410     if (!mSentCodecSpecificData) {
    411         // The very first thing we want to output is the codec specific
    412         // data. It does not require any input data but we will need an
    413         // output buffer to store it in.
    414 
    415         if (outQueue.empty()) {
    416             return;
    417         }
    418 
    419         BufferInfo *outInfo = *outQueue.begin();
    420         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
    421         outHeader->nFilledLen = sizeof(mAudioSpecificConfigData);
    422         outHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG;
    423 
    424         uint8_t *out = outHeader->pBuffer + outHeader->nOffset;
    425         memcpy(out, mAudioSpecificConfigData, sizeof(mAudioSpecificConfigData));
    426 
    427 #if 0
    428         ALOGI("sending codec specific data.");
    429         hexdump(out, sizeof(mAudioSpecificConfigData));
    430 #endif
    431 
    432         outQueue.erase(outQueue.begin());
    433         outInfo->mOwnedByUs = false;
    434         notifyFillBufferDone(outHeader);
    435 
    436         mSentCodecSpecificData = true;
    437     }
    438 
    439     size_t numBytesPerInputFrame =
    440         mNumChannels * kNumSamplesPerFrame * sizeof(int16_t);
    441 
    442     for (;;) {
    443         // We do the following until we run out of buffers.
    444 
    445         while (mInputSize < numBytesPerInputFrame) {
    446             // As long as there's still input data to be read we
    447             // will drain "kNumSamplesPerFrame * mNumChannels" samples
    448             // into the "mInputFrame" buffer and then encode those
    449             // as a unit into an output buffer.
    450 
    451             if (mSawInputEOS || inQueue.empty()) {
    452                 return;
    453             }
    454 
    455             BufferInfo *inInfo = *inQueue.begin();
    456             OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
    457 
    458             const void *inData = inHeader->pBuffer + inHeader->nOffset;
    459 
    460             size_t copy = numBytesPerInputFrame - mInputSize;
    461             if (copy > inHeader->nFilledLen) {
    462                 copy = inHeader->nFilledLen;
    463             }
    464 
    465             if (mInputFrame == NULL) {
    466                 mInputFrame = new int16_t[kNumSamplesPerFrame * mNumChannels];
    467             }
    468 
    469             if (mInputSize == 0) {
    470                 mInputTimeUs = inHeader->nTimeStamp;
    471             }
    472 
    473             memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy);
    474             mInputSize += copy;
    475 
    476             inHeader->nOffset += copy;
    477             inHeader->nFilledLen -= copy;
    478 
    479             // "Time" on the input buffer has in effect advanced by the
    480             // number of audio frames we just advanced nOffset by.
    481             inHeader->nTimeStamp +=
    482                 (copy * 1000000ll / mSampleRate)
    483                     / (mNumChannels * sizeof(int16_t));
    484 
    485             if (inHeader->nFilledLen == 0) {
    486                 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
    487                     ALOGV("saw input EOS");
    488                     mSawInputEOS = true;
    489 
    490                     // Pad any remaining data with zeroes.
    491                     memset((uint8_t *)mInputFrame + mInputSize,
    492                            0,
    493                            numBytesPerInputFrame - mInputSize);
    494 
    495                     mInputSize = numBytesPerInputFrame;
    496                 }
    497 
    498                 inQueue.erase(inQueue.begin());
    499                 inInfo->mOwnedByUs = false;
    500                 notifyEmptyBufferDone(inHeader);
    501 
    502                 inData = NULL;
    503                 inHeader = NULL;
    504                 inInfo = NULL;
    505             }
    506         }
    507 
    508         // At this  point we have all the input data necessary to encode
    509         // a single frame, all we need is an output buffer to store the result
    510         // in.
    511 
    512         if (outQueue.empty()) {
    513             return;
    514         }
    515 
    516         BufferInfo *outInfo = *outQueue.begin();
    517         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
    518 
    519         VO_CODECBUFFER inputData;
    520         memset(&inputData, 0, sizeof(inputData));
    521         inputData.Buffer = (unsigned char *)mInputFrame;
    522         inputData.Length = numBytesPerInputFrame;
    523         CHECK((VO_U32)VO_ERR_NONE ==
    524                 mApiHandle->SetInputData(mEncoderHandle, &inputData));
    525 
    526         VO_CODECBUFFER outputData;
    527         memset(&outputData, 0, sizeof(outputData));
    528         VO_AUDIO_OUTPUTINFO outputInfo;
    529         memset(&outputInfo, 0, sizeof(outputInfo));
    530 
    531         uint8_t *outPtr = (uint8_t *)outHeader->pBuffer + outHeader->nOffset;
    532         size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset;
    533 
    534         VO_U32 ret = VO_ERR_NONE;
    535         size_t nOutputBytes = 0;
    536         do {
    537             outputData.Buffer = outPtr;
    538             outputData.Length = outAvailable - nOutputBytes;
    539             ret = mApiHandle->GetOutputData(
    540                     mEncoderHandle, &outputData, &outputInfo);
    541             if (ret == VO_ERR_NONE) {
    542                 outPtr += outputData.Length;
    543                 nOutputBytes += outputData.Length;
    544             }
    545         } while (ret != VO_ERR_INPUT_BUFFER_SMALL);
    546 
    547         outHeader->nFilledLen = nOutputBytes;
    548 
    549         outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
    550 
    551         if (mSawInputEOS) {
    552             // We also tag this output buffer with EOS if it corresponds
    553             // to the final input buffer.
    554             outHeader->nFlags = OMX_BUFFERFLAG_EOS;
    555         }
    556 
    557         outHeader->nTimeStamp = mInputTimeUs;
    558 
    559 #if 0
    560         ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)",
    561               nOutputBytes, mInputTimeUs, outHeader->nFlags);
    562 
    563         hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
    564 #endif
    565 
    566         outQueue.erase(outQueue.begin());
    567         outInfo->mOwnedByUs = false;
    568         notifyFillBufferDone(outHeader);
    569 
    570         outHeader = NULL;
    571         outInfo = NULL;
    572 
    573         mInputSize = 0;
    574     }
    575 }
    576 
    577 void SoftAACEncoder::onReset() {
    578     delete[] mInputFrame;
    579     mInputFrame = NULL;
    580     mInputSize = 0;
    581 
    582     mSentCodecSpecificData = false;
    583     mInputTimeUs = -1ll;
    584     mSawInputEOS = false;
    585     mSignalledError = false;
    586 }
    587 
    588 }  // namespace android
    589 
    590 android::SoftOMXComponent *createSoftOMXComponent(
    591         const char *name, const OMX_CALLBACKTYPE *callbacks,
    592         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
    593     return new android::SoftAACEncoder(name, callbacks, appData, component);
    594 }
    595