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