Home | History | Annotate | Download | only in aacenc
      1 /*
      2  * Copyright (C) 2010 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 "AACEncoder"
     19 #include <utils/Log.h>
     20 
     21 #include "AACEncoder.h"
     22 #include "voAAC.h"
     23 #include "cmnMemory.h"
     24 
     25 #include <media/stagefright/foundation/ADebug.h>
     26 #include <media/stagefright/MediaBufferGroup.h>
     27 #include <media/stagefright/MediaDefs.h>
     28 #include <media/stagefright/MediaErrors.h>
     29 #include <media/stagefright/MetaData.h>
     30 
     31 namespace android {
     32 
     33 AACEncoder::AACEncoder(const sp<IMediaSource> &source, const sp<MetaData> &meta)
     34     : mSource(source),
     35       mMeta(meta),
     36       mStarted(false),
     37       mBufferGroup(NULL),
     38       mInputBuffer(NULL),
     39       mInputFrame(NULL),
     40       mEncoderHandle(NULL),
     41       mApiHandle(NULL),
     42       mMemOperator(NULL) {
     43 }
     44 
     45 status_t AACEncoder::initCheck() {
     46     CHECK(mApiHandle == NULL && mEncoderHandle == NULL);
     47     CHECK(mMeta->findInt32(kKeySampleRate, &mSampleRate));
     48     CHECK(mMeta->findInt32(kKeyChannelCount, &mChannels));
     49     CHECK(mChannels <= 2 && mChannels >= 1);
     50     CHECK(mMeta->findInt32(kKeyBitRate, &mBitRate));
     51 
     52     mApiHandle = new VO_AUDIO_CODECAPI;
     53     CHECK(mApiHandle);
     54 
     55     if (VO_ERR_NONE != voGetAACEncAPI(mApiHandle)) {
     56         ALOGE("Failed to get api handle");
     57         return UNKNOWN_ERROR;
     58     }
     59 
     60     mMemOperator = new VO_MEM_OPERATOR;
     61     CHECK(mMemOperator != NULL);
     62     mMemOperator->Alloc = cmnMemAlloc;
     63     mMemOperator->Copy = cmnMemCopy;
     64     mMemOperator->Free = cmnMemFree;
     65     mMemOperator->Set = cmnMemSet;
     66     mMemOperator->Check = cmnMemCheck;
     67 
     68     VO_CODEC_INIT_USERDATA userData;
     69     memset(&userData, 0, sizeof(userData));
     70     userData.memflag = VO_IMF_USERMEMOPERATOR;
     71     userData.memData = (VO_PTR) mMemOperator;
     72     if (VO_ERR_NONE != mApiHandle->Init(&mEncoderHandle, VO_AUDIO_CodingAAC, &userData)) {
     73         ALOGE("Failed to init AAC encoder");
     74         return UNKNOWN_ERROR;
     75     }
     76     if (OK != setAudioSpecificConfigData()) {
     77         ALOGE("Failed to configure AAC encoder");
     78         return UNKNOWN_ERROR;
     79     }
     80 
     81     // Configure AAC encoder$
     82     AACENC_PARAM params;
     83     memset(&params, 0, sizeof(params));
     84     params.sampleRate = mSampleRate;
     85     params.bitRate = mBitRate;
     86     params.nChannels = mChannels;
     87     params.adtsUsed = 0;  // We add adts header in the file writer if needed.
     88     if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AAC_ENCPARAM,  &params)) {
     89         ALOGE("Failed to set AAC encoder parameters");
     90         return UNKNOWN_ERROR;
     91     }
     92 
     93     return OK;
     94 }
     95 
     96 static status_t getSampleRateTableIndex(int32_t sampleRate, int32_t &index) {
     97     static const int32_t kSampleRateTable[] = {
     98         96000, 88200, 64000, 48000, 44100, 32000,
     99         24000, 22050, 16000, 12000, 11025, 8000
    100     };
    101     const int32_t tableSize = sizeof(kSampleRateTable) / sizeof(kSampleRateTable[0]);
    102     for (int32_t i = 0; i < tableSize; ++i) {
    103         if (sampleRate == kSampleRateTable[i]) {
    104             index = i;
    105             return OK;
    106         }
    107     }
    108 
    109     ALOGE("Sampling rate %d bps is not supported", sampleRate);
    110     return UNKNOWN_ERROR;
    111 }
    112 
    113 status_t AACEncoder::setAudioSpecificConfigData() {
    114     ALOGV("setAudioSpecificConfigData: %d hz, %d bps, and %d channels",
    115          mSampleRate, mBitRate, mChannels);
    116 
    117     int32_t index = 0;
    118     CHECK_EQ((status_t)OK, getSampleRateTableIndex(mSampleRate, index));
    119     if (mChannels > 2 || mChannels <= 0) {
    120         ALOGE("Unsupported number of channels(%d)", mChannels);
    121         return UNKNOWN_ERROR;
    122     }
    123 
    124     // OMX_AUDIO_AACObjectLC
    125     mAudioSpecificConfigData[0] = ((0x02 << 3) | (index >> 1));
    126     mAudioSpecificConfigData[1] = ((index & 0x01) << 7) | (mChannels << 3);
    127     return OK;
    128 }
    129 
    130 AACEncoder::~AACEncoder() {
    131     if (mStarted) {
    132         stop();
    133     }
    134 }
    135 
    136 status_t AACEncoder::start(MetaData *params) {
    137     if (mStarted) {
    138         ALOGW("Call start() when encoder already started");
    139         return OK;
    140     }
    141 
    142     mBufferGroup = new MediaBufferGroup;
    143     mBufferGroup->add_buffer(new MediaBuffer(2048));
    144 
    145     CHECK_EQ((status_t)OK, initCheck());
    146 
    147     mNumInputSamples = 0;
    148     mAnchorTimeUs = 0;
    149     mFrameCount = 0;
    150 
    151     mInputFrame = new int16_t[mChannels * kNumSamplesPerFrame];
    152     CHECK(mInputFrame != NULL);
    153 
    154     status_t err = mSource->start(params);
    155     if (err != OK) {
    156          ALOGE("AudioSource is not available");
    157         return err;
    158     }
    159 
    160     mStarted = true;
    161 
    162     return OK;
    163 }
    164 
    165 status_t AACEncoder::stop() {
    166     if (mInputBuffer) {
    167         mInputBuffer->release();
    168         mInputBuffer = NULL;
    169     }
    170 
    171     delete mBufferGroup;
    172     mBufferGroup = NULL;
    173 
    174     if (mInputFrame) {
    175         delete[] mInputFrame;
    176         mInputFrame = NULL;
    177     }
    178 
    179     if (!mStarted) {
    180         ALOGW("Call stop() when encoder has not started");
    181         return ERROR_END_OF_STREAM;
    182     }
    183 
    184     mSource->stop();
    185     if (mEncoderHandle) {
    186         CHECK_EQ((VO_U32)VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle));
    187         mEncoderHandle = NULL;
    188     }
    189     delete mApiHandle;
    190     mApiHandle = NULL;
    191 
    192     delete mMemOperator;
    193     mMemOperator = NULL;
    194 
    195     mStarted = false;
    196 
    197     return OK;
    198 }
    199 
    200 sp<MetaData> AACEncoder::getFormat() {
    201     sp<MetaData> srcFormat = mSource->getFormat();
    202 
    203     mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
    204 
    205     int64_t durationUs;
    206     if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
    207         mMeta->setInt64(kKeyDuration, durationUs);
    208     }
    209 
    210     mMeta->setCString(kKeyDecoderComponent, "AACEncoder");
    211 
    212     return mMeta;
    213 }
    214 
    215 status_t AACEncoder::read(
    216         MediaBuffer **out, const ReadOptions *options) {
    217     *out = NULL;
    218 
    219     int64_t seekTimeUs;
    220     ReadOptions::SeekMode mode;
    221     CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode));
    222 
    223     MediaBuffer *buffer;
    224     CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), (status_t)OK);
    225     uint8_t *outPtr = (uint8_t *)buffer->data();
    226     bool readFromSource = false;
    227     int64_t wallClockTimeUs = -1;
    228 
    229     if (mFrameCount == 0) {
    230         memcpy(outPtr, mAudioSpecificConfigData, 2);
    231         buffer->set_range(0, 2);
    232         buffer->meta_data()->setInt32(kKeyIsCodecConfig, true);
    233         *out = buffer;
    234         ++mFrameCount;
    235         return OK;
    236     } else if (mFrameCount == 1) {
    237         buffer->meta_data()->setInt32(kKeyIsCodecConfig, false);
    238     }
    239 
    240     const int32_t nSamples = mChannels * kNumSamplesPerFrame;
    241     while (mNumInputSamples < nSamples) {
    242         if (mInputBuffer == NULL) {
    243             if (mSource->read(&mInputBuffer, options) != OK) {
    244                 if (mNumInputSamples == 0) {
    245                     buffer->release();
    246                     return ERROR_END_OF_STREAM;
    247                 }
    248                 memset(&mInputFrame[mNumInputSamples],
    249                        0,
    250                        sizeof(int16_t) * (nSamples - mNumInputSamples));
    251                 mNumInputSamples = 0;
    252                 break;
    253             }
    254 
    255             size_t align = mInputBuffer->range_length() % sizeof(int16_t);
    256             CHECK_EQ(align, (size_t)0);
    257 
    258             int64_t timeUs;
    259             if (mInputBuffer->meta_data()->findInt64(kKeyDriftTime, &timeUs)) {
    260                 wallClockTimeUs = timeUs;
    261             }
    262             if (mInputBuffer->meta_data()->findInt64(kKeyAnchorTime, &timeUs)) {
    263                 mAnchorTimeUs = timeUs;
    264             }
    265             readFromSource = true;
    266         } else {
    267             readFromSource = false;
    268         }
    269         size_t copy = (nSamples - mNumInputSamples) * sizeof(int16_t);
    270 
    271         if (copy > mInputBuffer->range_length()) {
    272             copy = mInputBuffer->range_length();
    273         }
    274 
    275         memcpy(&mInputFrame[mNumInputSamples],
    276                (const uint8_t *) mInputBuffer->data()
    277                     + mInputBuffer->range_offset(),
    278                copy);
    279 
    280         mInputBuffer->set_range(
    281                mInputBuffer->range_offset() + copy,
    282                mInputBuffer->range_length() - copy);
    283 
    284         if (mInputBuffer->range_length() == 0) {
    285             mInputBuffer->release();
    286             mInputBuffer = NULL;
    287         }
    288         mNumInputSamples += copy / sizeof(int16_t);
    289         if (mNumInputSamples >= nSamples) {
    290             mNumInputSamples %= nSamples;
    291             break;
    292         }
    293     }
    294 
    295     VO_CODECBUFFER inputData;
    296     memset(&inputData, 0, sizeof(inputData));
    297     inputData.Buffer = (unsigned char*) mInputFrame;
    298     inputData.Length = nSamples * sizeof(int16_t);
    299     CHECK((VO_U32)VO_ERR_NONE == mApiHandle->SetInputData(mEncoderHandle,&inputData));
    300 
    301     VO_CODECBUFFER outputData;
    302     memset(&outputData, 0, sizeof(outputData));
    303     VO_AUDIO_OUTPUTINFO outputInfo;
    304     memset(&outputInfo, 0, sizeof(outputInfo));
    305 
    306     VO_U32 ret = VO_ERR_NONE;
    307     size_t nOutputBytes = 0;
    308     do {
    309         outputData.Buffer = outPtr;
    310         outputData.Length = buffer->size() - nOutputBytes;
    311         ret = mApiHandle->GetOutputData(mEncoderHandle, &outputData, &outputInfo);
    312         if (ret == VO_ERR_NONE) {
    313             outPtr += outputData.Length;
    314             nOutputBytes += outputData.Length;
    315         }
    316     } while (ret != VO_ERR_INPUT_BUFFER_SMALL);
    317     buffer->set_range(0, nOutputBytes);
    318 
    319     int64_t mediaTimeUs =
    320         ((mFrameCount - 1) * 1000000LL * kNumSamplesPerFrame) / mSampleRate;
    321 
    322     buffer->meta_data()->setInt64(kKeyTime, mAnchorTimeUs + mediaTimeUs);
    323     if (readFromSource && wallClockTimeUs != -1) {
    324         buffer->meta_data()->setInt64(kKeyDriftTime, mediaTimeUs - wallClockTimeUs);
    325     }
    326     ++mFrameCount;
    327 
    328     *out = buffer;
    329     return OK;
    330 }
    331 
    332 }  // namespace android
    333