Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2011 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 *************************************************************************
     18 * @file   VideoEditorAudioEncoder.cpp
     19 * @brief  StageFright shell Audio Encoder
     20 *************************************************************************
     21 */
     22 
     23 #define LOG_NDEBUG 1
     24 #define LOG_TAG "VIDEOEDITOR_AUDIOENCODER"
     25 
     26 #include "M4OSA_Debug.h"
     27 #include "VideoEditorAudioEncoder.h"
     28 #include "VideoEditorUtils.h"
     29 
     30 #include "utils/Log.h"
     31 #include <media/stagefright/foundation/ADebug.h>
     32 #include <media/stagefright/MediaSource.h>
     33 #include <media/stagefright/MediaDefs.h>
     34 #include <media/stagefright/MetaData.h>
     35 #include <media/stagefright/OMXClient.h>
     36 #include <media/stagefright/OMXCodec.h>
     37 
     38 /*** DEFINITIONS ***/
     39 // Force using software encoder as engine does not support prefetch
     40 #define VIDEOEDITOR_FORCECODEC kSoftwareCodecsOnly
     41 
     42 namespace android {
     43 struct VideoEditorAudioEncoderSource : public MediaSource {
     44     public:
     45         static sp<VideoEditorAudioEncoderSource> Create(
     46             const sp<MetaData> &format);
     47         virtual status_t start(MetaData *params = NULL);
     48         virtual status_t stop();
     49         virtual sp<MetaData> getFormat();
     50         virtual status_t read(MediaBuffer **buffer,
     51         const ReadOptions *options = NULL);
     52         virtual int32_t storeBuffer(MediaBuffer *buffer);
     53 
     54     protected:
     55         virtual ~VideoEditorAudioEncoderSource();
     56 
     57     private:
     58         struct MediaBufferChain {
     59             MediaBuffer* buffer;
     60             MediaBufferChain* nextLink;
     61         };
     62         enum State {
     63             CREATED,
     64             STARTED,
     65             ERROR
     66         };
     67 
     68         MediaBufferChain* mFirstBufferLink;
     69         MediaBufferChain* mLastBufferLink;
     70         int32_t mNbBuffer;
     71         State mState;
     72         sp<MetaData> mEncFormat;
     73 
     74         VideoEditorAudioEncoderSource(const sp<MetaData> &format);
     75 
     76         // Don't call me.
     77         VideoEditorAudioEncoderSource(const VideoEditorAudioEncoderSource&);
     78         VideoEditorAudioEncoderSource& operator=(
     79             const VideoEditorAudioEncoderSource&);
     80 };
     81 
     82 sp<VideoEditorAudioEncoderSource> VideoEditorAudioEncoderSource::Create(
     83     const sp<MetaData> &format) {
     84 
     85     ALOGV("VideoEditorAudioEncoderSource::Create");
     86     sp<VideoEditorAudioEncoderSource> aSource =
     87         new VideoEditorAudioEncoderSource(format);
     88 
     89     return aSource;
     90 }
     91 
     92 VideoEditorAudioEncoderSource::VideoEditorAudioEncoderSource(
     93     const sp<MetaData> &format):
     94         mFirstBufferLink(NULL),
     95         mLastBufferLink(NULL),
     96         mNbBuffer(0),
     97         mState(CREATED),
     98         mEncFormat(format) {
     99     ALOGV("VideoEditorAudioEncoderSource::VideoEditorAudioEncoderSource");
    100 }
    101 
    102 
    103 VideoEditorAudioEncoderSource::~VideoEditorAudioEncoderSource() {
    104     ALOGV("VideoEditorAudioEncoderSource::~VideoEditorAudioEncoderSource");
    105 
    106     if( STARTED == mState ) {
    107         stop();
    108     }
    109 }
    110 
    111 status_t VideoEditorAudioEncoderSource::start(MetaData *meta) {
    112     status_t err = OK;
    113 
    114     ALOGV("VideoEditorAudioEncoderSource::start");
    115 
    116     if( CREATED != mState ) {
    117         ALOGV("VideoEditorAudioEncoderSource::start ERROR : invalid state %d",
    118             mState);
    119         return UNKNOWN_ERROR;
    120     }
    121 
    122     mState = STARTED;
    123 
    124 cleanUp:
    125     ALOGV("VideoEditorAudioEncoderSource::start END (0x%x)", err);
    126     return err;
    127 }
    128 
    129 status_t VideoEditorAudioEncoderSource::stop() {
    130     status_t err = OK;
    131 
    132     ALOGV("VideoEditorAudioEncoderSource::stop");
    133 
    134     if( STARTED != mState ) {
    135         ALOGV("VideoEditorAudioEncoderSource::stop ERROR: invalid state %d",
    136             mState);
    137         return UNKNOWN_ERROR;
    138     }
    139 
    140     int32_t i = 0;
    141     MediaBufferChain* tmpLink = NULL;
    142     while( mFirstBufferLink ) {
    143         i++;
    144         tmpLink = mFirstBufferLink;
    145         mFirstBufferLink = mFirstBufferLink->nextLink;
    146         delete tmpLink;
    147     }
    148     ALOGV("VideoEditorAudioEncoderSource::stop : %d buffer remained", i);
    149     mFirstBufferLink = NULL;
    150     mLastBufferLink = NULL;
    151 
    152     mState = CREATED;
    153 
    154     ALOGV("VideoEditorAudioEncoderSource::stop END (0x%x)", err);
    155     return err;
    156 }
    157 
    158 sp<MetaData> VideoEditorAudioEncoderSource::getFormat() {
    159     ALOGV("VideoEditorAudioEncoderSource::getFormat");
    160     return mEncFormat;
    161 }
    162 
    163 status_t VideoEditorAudioEncoderSource::read(MediaBuffer **buffer,
    164         const ReadOptions *options) {
    165     MediaSource::ReadOptions readOptions;
    166     status_t err = OK;
    167     MediaBufferChain* tmpLink = NULL;
    168 
    169     ALOGV("VideoEditorAudioEncoderSource::read");
    170 
    171     if ( STARTED != mState ) {
    172         ALOGV("VideoEditorAudioEncoderSource::read ERROR : invalid state %d",
    173             mState);
    174         return UNKNOWN_ERROR;
    175     }
    176 
    177     if( NULL == mFirstBufferLink ) {
    178         *buffer = NULL;
    179         ALOGV("VideoEditorAudioEncoderSource::read : EOS");
    180         return ERROR_END_OF_STREAM;
    181     }
    182     *buffer = mFirstBufferLink->buffer;
    183 
    184     tmpLink = mFirstBufferLink;
    185     mFirstBufferLink = mFirstBufferLink->nextLink;
    186     if( NULL == mFirstBufferLink ) {
    187         mLastBufferLink = NULL;
    188     }
    189     delete tmpLink;
    190     mNbBuffer--;
    191 
    192     ALOGV("VideoEditorAudioEncoderSource::read END (0x%x)", err);
    193     return err;
    194 }
    195 
    196 int32_t VideoEditorAudioEncoderSource::storeBuffer(MediaBuffer *buffer) {
    197     status_t err = OK;
    198 
    199     ALOGV("VideoEditorAudioEncoderSource::storeBuffer");
    200 
    201     MediaBufferChain* newLink = new MediaBufferChain;
    202     newLink->buffer = buffer;
    203     newLink->nextLink = NULL;
    204     if( NULL != mLastBufferLink ) {
    205         mLastBufferLink->nextLink = newLink;
    206     } else {
    207         mFirstBufferLink = newLink;
    208     }
    209     mLastBufferLink = newLink;
    210     mNbBuffer++;
    211 
    212     ALOGV("VideoEditorAudioEncoderSource::storeBuffer END");
    213     return mNbBuffer;
    214 }
    215 
    216 /********************
    217  * ENGINE INTERFACE *
    218  ********************/
    219 /**
    220  ******************************************************************************
    221  * structure VideoEditorAudioEncoder_Context
    222  * @brief    This structure defines the context of the StageFright audio
    223  *           encoder shell
    224  ******************************************************************************
    225 */
    226 typedef struct {
    227     M4ENCODER_AudioFormat             mFormat;
    228     M4ENCODER_AudioParams*            mCodecParams;
    229     M4ENCODER_AudioDecSpecificInfo    mDSI;
    230     sp<VideoEditorAudioEncoderSource> mEncoderSource;
    231     OMXClient                         mClient;
    232     sp<MediaSource>                   mEncoder;
    233     uint32_t                          mNbInputFrames;
    234     uint32_t                          mNbOutputFrames;
    235     int64_t                           mFirstOutputCts;
    236     int64_t                           mLastOutputCts;
    237 } VideoEditorAudioEncoder_Context;
    238 
    239 M4OSA_ERR VideoEditorAudioEncoder_cleanup(M4OSA_Context pContext) {
    240 
    241     M4OSA_ERR err = M4NO_ERROR;
    242     VideoEditorAudioEncoder_Context* pEncoderContext = M4OSA_NULL;
    243 
    244     ALOGV("VideoEditorAudioEncoder_cleanup begin");
    245     VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
    246     pEncoderContext = (VideoEditorAudioEncoder_Context*)pContext;
    247 
    248     SAFE_FREE(pEncoderContext->mDSI.pInfo);
    249     SAFE_FREE(pEncoderContext);
    250     pContext = M4OSA_NULL;
    251 
    252 cleanUp:
    253     if( M4NO_ERROR == err ) {
    254         ALOGV("VideoEditorAudioEncoder_cleanup no error");
    255     } else {
    256         ALOGV("VideoEditorAudioEncoder_cleanup ERROR 0x%X", err);
    257     }
    258     ALOGV("VideoEditorAudioEncoder_cleanup end");
    259     return err;
    260 }
    261 
    262 M4OSA_ERR VideoEditorAudioEncoder_init(M4ENCODER_AudioFormat format,
    263         M4OSA_Context* pContext, M4OSA_Void* pUserData) {
    264 
    265     M4OSA_ERR err = M4NO_ERROR;
    266     VideoEditorAudioEncoder_Context* pEncoderContext = M4OSA_NULL;
    267 
    268     ALOGV(" VideoEditorAudioEncoder_init begin: format %d", format);
    269     VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
    270 
    271     SAFE_MALLOC(pEncoderContext, VideoEditorAudioEncoder_Context, 1,
    272         "VideoEditorAudioEncoder");
    273     pEncoderContext->mFormat = format;
    274 
    275     *pContext = pEncoderContext;
    276 
    277 cleanUp:
    278     if( M4NO_ERROR == err ) {
    279         ALOGV("VideoEditorAudioEncoder_init no error");
    280     } else {
    281         VideoEditorAudioEncoder_cleanup(pEncoderContext);
    282         *pContext = M4OSA_NULL;
    283         ALOGV("VideoEditorAudioEncoder_init ERROR 0x%X", err);
    284     }
    285     ALOGV("VideoEditorAudioEncoder_init end");
    286     return err;
    287 }
    288 
    289 M4OSA_ERR VideoEditorAudioEncoder_init_AAC(M4OSA_Context* pContext,
    290         M4OSA_Void* pUserData) {
    291     return VideoEditorAudioEncoder_init(M4ENCODER_kAAC, pContext, pUserData);
    292 }
    293 
    294 M4OSA_ERR VideoEditorAudioEncoder_init_AMRNB(M4OSA_Context* pContext,
    295         M4OSA_Void* pUserData) {
    296     return VideoEditorAudioEncoder_init(M4ENCODER_kAMRNB, pContext, pUserData);
    297 }
    298 
    299 M4OSA_ERR VideoEditorAudioEncoder_init_MP3(M4OSA_Context* pContext,
    300         M4OSA_Void* pUserData) {
    301     return VideoEditorAudioEncoder_init(M4ENCODER_kMP3, pContext, pUserData);
    302 }
    303 
    304 M4OSA_ERR VideoEditorAudioEncoder_close(M4OSA_Context pContext) {
    305 
    306     M4OSA_ERR err = M4NO_ERROR;
    307     VideoEditorAudioEncoder_Context* pEncoderContext = M4OSA_NULL;
    308 
    309     ALOGV("VideoEditorAudioEncoder_close begin");
    310 
    311     VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
    312     pEncoderContext = (VideoEditorAudioEncoder_Context*)pContext;
    313 
    314     SAFE_FREE(pEncoderContext->mCodecParams);
    315 
    316     pEncoderContext->mEncoder->stop();
    317     pEncoderContext->mEncoder.clear();
    318     pEncoderContext->mClient.disconnect();
    319     pEncoderContext->mEncoderSource.clear();
    320 
    321     ALOGV("AudioEncoder_close:IN %d frames,OUT %d frames from %lld to %lld",
    322         pEncoderContext->mNbInputFrames,
    323         pEncoderContext->mNbOutputFrames, pEncoderContext->mFirstOutputCts,
    324         pEncoderContext->mLastOutputCts);
    325 
    326     if( pEncoderContext->mNbInputFrames != pEncoderContext->mNbInputFrames ) {
    327         ALOGV("VideoEditorAudioEncoder_close:some frames were not encoded %d %d",
    328             pEncoderContext->mNbInputFrames, pEncoderContext->mNbInputFrames);
    329     }
    330 
    331 cleanUp:
    332     if( M4NO_ERROR == err ) {
    333         ALOGV("VideoEditorAudioEncoder_close no error");
    334     } else {
    335         ALOGV("VideoEditorAudioEncoder_close ERROR 0x%X", err);
    336     }
    337     ALOGV("VideoEditorAudioEncoder_close begin end");
    338     return err;
    339 }
    340 
    341 M4OSA_ERR VideoEditorAudioEncoder_open(M4OSA_Context pContext,
    342         M4ENCODER_AudioParams *pParams, M4ENCODER_AudioDecSpecificInfo *pDSI,
    343         M4OSA_Context pGrabberContext) {
    344 
    345     M4OSA_ERR err = M4NO_ERROR;
    346     VideoEditorAudioEncoder_Context* pEncoderContext = M4OSA_NULL;
    347     status_t result = OK;
    348     sp<MetaData> encoderMetadata = NULL;
    349     const char* mime = NULL;
    350     int32_t iNbChannel = 0;
    351     uint32_t codecFlags = 0;
    352 
    353     ALOGV("VideoEditorAudioEncoder_open begin");
    354 
    355     VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
    356     VIDEOEDITOR_CHECK(M4OSA_NULL != pParams,  M4ERR_PARAMETER);
    357     VIDEOEDITOR_CHECK(M4OSA_NULL != pDSI,     M4ERR_PARAMETER);
    358 
    359     pEncoderContext = (VideoEditorAudioEncoder_Context*)pContext;
    360     pDSI->pInfo = M4OSA_NULL;
    361     pDSI->infoSize = 0;
    362 
    363     pEncoderContext->mNbInputFrames  = 0;
    364     pEncoderContext->mNbOutputFrames = 0;
    365     pEncoderContext->mFirstOutputCts = -1;
    366     pEncoderContext->mLastOutputCts  = -1;
    367 
    368     // Allocate & initialize the encoding parameters
    369     ALOGV("VideoEditorAudioEncoder_open : params F=%d CN=%d BR=%d F=%d",
    370         pParams->Frequency, pParams->ChannelNum, pParams->Bitrate,
    371         pParams->Format);
    372     SAFE_MALLOC(pEncoderContext->mCodecParams, M4ENCODER_AudioParams, 1,
    373         "VIDEOEDITOR CodecParams");
    374     pEncoderContext->mCodecParams->Frequency  = pParams->Frequency;
    375     pEncoderContext->mCodecParams->ChannelNum = pParams->ChannelNum;
    376     pEncoderContext->mCodecParams->Bitrate    = pParams->Bitrate;
    377     pEncoderContext->mCodecParams->Format     = pParams->Format;
    378 
    379     // Check output format consistency
    380     VIDEOEDITOR_CHECK(pEncoderContext->mCodecParams->Format ==
    381         pEncoderContext->mFormat, M4ERR_PARAMETER);
    382 
    383     /**
    384      * StageFright graph building
    385      */
    386     // Create the meta data for the encoder
    387     encoderMetadata = new MetaData;
    388     switch( pEncoderContext->mCodecParams->Format ) {
    389         case M4ENCODER_kAAC:
    390         {
    391             mime = MEDIA_MIMETYPE_AUDIO_AAC;
    392             break;
    393         }
    394         case M4ENCODER_kAMRNB:
    395         {
    396             mime = MEDIA_MIMETYPE_AUDIO_AMR_NB;
    397             break;
    398         }
    399         default:
    400         {
    401             VIDEOEDITOR_CHECK(!"AudioEncoder_open : incorrect input format",
    402             M4ERR_PARAMETER);
    403             break;
    404         }
    405     }
    406     encoderMetadata->setCString(kKeyMIMEType, mime);
    407     encoderMetadata->setInt32(kKeySampleRate,
    408         (int32_t)pEncoderContext->mCodecParams->Frequency);
    409     encoderMetadata->setInt32(kKeyBitRate,
    410         (int32_t)pEncoderContext->mCodecParams->Bitrate);
    411 
    412     switch( pEncoderContext->mCodecParams->ChannelNum ) {
    413         case M4ENCODER_kMono:
    414         {
    415             iNbChannel = 1;
    416             break;
    417         }
    418         case M4ENCODER_kStereo:
    419         {
    420             iNbChannel = 2;
    421             break;
    422         }
    423         default:
    424         {
    425             VIDEOEDITOR_CHECK(!"AudioEncoder_open : incorrect channel number",
    426                 M4ERR_STATE);
    427             break;
    428         }
    429     }
    430     encoderMetadata->setInt32(kKeyChannelCount, iNbChannel);
    431 
    432     // Create the encoder source
    433     pEncoderContext->mEncoderSource = VideoEditorAudioEncoderSource::Create(
    434         encoderMetadata);
    435     VIDEOEDITOR_CHECK(NULL != pEncoderContext->mEncoderSource.get(),
    436         M4ERR_STATE);
    437 
    438     // Connect to the OMX client
    439     result = pEncoderContext->mClient.connect();
    440     VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
    441 
    442     // Create the OMX codec
    443 #ifdef VIDEOEDITOR_FORCECODEC
    444     codecFlags |= OMXCodec::VIDEOEDITOR_FORCECODEC;
    445 #endif /* VIDEOEDITOR_FORCECODEC */
    446     // FIXME:
    447     // We are moving away to use software AACEncoder and instead use OMX-based
    448     // software AAC audio encoder. We want to use AACEncoder for now. After we
    449     // fix the interface issue with the OMX-based AAC audio encoder, we should
    450     // then set the component name back to NULL to allow the system to pick up
    451     // the right AAC audio encoder.
    452     pEncoderContext->mEncoder = OMXCodec::Create(
    453             pEncoderContext->mClient.interface(), encoderMetadata, true,
    454             pEncoderContext->mEncoderSource, "AACEncoder" /* component name */,
    455             codecFlags);
    456     VIDEOEDITOR_CHECK(NULL != pEncoderContext->mEncoder.get(), M4ERR_STATE);
    457 
    458     // Start the graph
    459     result = pEncoderContext->mEncoder->start();
    460     VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
    461 
    462     // Get AAC DSI, this code can only work with software encoder
    463     if( M4ENCODER_kAAC == pEncoderContext->mCodecParams->Format ) {
    464         int32_t      isCodecConfig = 0;
    465         MediaBuffer* buffer        = NULL;
    466 
    467         // Read once to get the DSI
    468         result = pEncoderContext->mEncoder->read(&buffer, NULL);
    469         VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
    470         VIDEOEDITOR_CHECK(buffer->meta_data()->findInt32(kKeyIsCodecConfig,
    471             &isCodecConfig) && isCodecConfig, M4ERR_STATE);
    472 
    473         // Save the DSI
    474         pEncoderContext->mDSI.infoSize = (M4OSA_UInt32)buffer->range_length();
    475         SAFE_MALLOC(pEncoderContext->mDSI.pInfo, M4OSA_Int8,
    476             pEncoderContext->mDSI.infoSize, "Encoder header");
    477 
    478         memcpy((void *)pEncoderContext->mDSI.pInfo,
    479             (void *)((M4OSA_MemAddr8)(buffer->data())+buffer->range_offset()),
    480             pEncoderContext->mDSI.infoSize);
    481 
    482         buffer->release();
    483         *pDSI = pEncoderContext->mDSI;
    484     }
    485     ALOGV("VideoEditorAudioEncoder_open : DONE");
    486 
    487 cleanUp:
    488     if( M4NO_ERROR == err ) {
    489         ALOGV("VideoEditorAudioEncoder_open no error");
    490     } else {
    491         VideoEditorAudioEncoder_close(pEncoderContext);
    492         ALOGV("VideoEditorAudioEncoder_open ERROR 0x%X", err);
    493     }
    494     ALOGV("VideoEditorAudioEncoder_open end");
    495     return err;
    496 }
    497 
    498 M4OSA_ERR VideoEditorAudioEncoder_processInputBuffer(M4OSA_Context pContext,
    499         M4ENCODER_AudioBuffer* pInBuffer) {
    500 
    501     M4OSA_ERR err = M4NO_ERROR;
    502     VideoEditorAudioEncoder_Context* pEncoderContext = M4OSA_NULL;
    503     M4OSA_Int8* pData = M4OSA_NULL;
    504     MediaBuffer* buffer = NULL;
    505     int32_t nbBuffer = 0;
    506 
    507     ALOGV("VideoEditorAudioEncoder_processInputBuffer begin");
    508     VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
    509 
    510     pEncoderContext = (VideoEditorAudioEncoder_Context*)pContext;
    511 
    512     switch( pEncoderContext->mCodecParams->ChannelNum ) {
    513         case M4ENCODER_kMono:
    514         case M4ENCODER_kStereo:
    515             // Let the MediaBuffer own the data so we don't have to free it
    516             buffer = new MediaBuffer((size_t)pInBuffer->pTableBufferSize[0]);
    517             pData = (M4OSA_Int8*)buffer->data() + buffer->range_offset();
    518             memcpy((void *)pData, (void *)pInBuffer->pTableBuffer[0],
    519                 pInBuffer->pTableBufferSize[0]);
    520             break;
    521         default:
    522             ALOGV("VEAE_processInputBuffer unsupported channel configuration %d",
    523                 pEncoderContext->mCodecParams->ChannelNum);
    524             VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_PARAMETER);
    525             break;
    526     }
    527 
    528     ALOGV("VideoEditorAudioEncoder_processInputBuffer : store %d bytes",
    529         buffer->range_length());
    530     // Push the buffer to the source
    531     nbBuffer = pEncoderContext->mEncoderSource->storeBuffer(buffer);
    532 
    533 cleanUp:
    534     if( M4NO_ERROR == err ) {
    535         ALOGV("VideoEditorAudioEncoder_processInputBuffer no error");
    536     } else {
    537         if( NULL != buffer ) {
    538             buffer->release();
    539         }
    540         ALOGV("VideoEditorAudioEncoder_processInputBuffer ERROR 0x%X", err);
    541     }
    542     ALOGV("VideoEditorAudioEncoder_processInputBuffer end");
    543     return err;
    544 }
    545 
    546 M4OSA_ERR VideoEditorAudioEncoder_processOutputBuffer(M4OSA_Context pContext,
    547         MediaBuffer* buffer, M4ENCODER_AudioBuffer* pOutBuffer) {
    548 
    549     M4OSA_ERR err = M4NO_ERROR;
    550     VideoEditorAudioEncoder_Context* pEncoderContext = M4OSA_NULL;
    551     M4OSA_UInt32 Cts = 0;
    552     int32_t i32Tmp = 0;
    553     int64_t i64Tmp = 0;
    554     status_t result = OK;
    555 
    556     ALOGV("VideoEditorAudioEncoder_processOutputBuffer begin");
    557     VIDEOEDITOR_CHECK(M4OSA_NULL != pContext,   M4ERR_PARAMETER);
    558     VIDEOEDITOR_CHECK(M4OSA_NULL != buffer,     M4ERR_PARAMETER);
    559     VIDEOEDITOR_CHECK(M4OSA_NULL != pOutBuffer, M4ERR_PARAMETER);
    560 
    561     pEncoderContext = (VideoEditorAudioEncoder_Context*)pContext;
    562 
    563     // Process the returned AU
    564     if( 0 == buffer->range_length() ) {
    565         // Encoder has no data yet, nothing unusual
    566         ALOGV("VideoEditorAudioEncoder_processOutputBuffer : buffer is empty");
    567         pOutBuffer->pTableBufferSize[0] = 0;
    568         goto cleanUp;
    569     }
    570     if( buffer->meta_data()->findInt32(kKeyIsCodecConfig, &i32Tmp) && i32Tmp ) {
    571         /* This should not happen with software encoder,
    572          * DSI was retrieved beforehand */
    573         VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_STATE);
    574     } else {
    575         // Check the CTS
    576         VIDEOEDITOR_CHECK(buffer->meta_data()->findInt64(kKeyTime, &i64Tmp),
    577             M4ERR_STATE);
    578         Cts = (M4OSA_Int32)(i64Tmp/1000);
    579 
    580         pEncoderContext->mNbOutputFrames++;
    581         if( 0 > pEncoderContext->mFirstOutputCts ) {
    582             pEncoderContext->mFirstOutputCts = i64Tmp;
    583         }
    584         pEncoderContext->mLastOutputCts = i64Tmp;
    585 
    586         // Format the AU
    587         memcpy((void *)pOutBuffer->pTableBuffer[0],
    588             (void *)((M4OSA_MemAddr8)(buffer->data())+buffer->range_offset()),
    589             buffer->range_length());
    590         pOutBuffer->pTableBufferSize[0] = (M4OSA_UInt32)buffer->range_length();
    591     }
    592 
    593 cleanUp:
    594     // Release the buffer
    595     buffer->release();
    596     if( M4NO_ERROR == err ) {
    597         ALOGV("VideoEditorAudioEncoder_processOutputBuffer no error");
    598     } else {
    599         ALOGV("VideoEditorAudioEncoder_processOutputBuffer ERROR 0x%X", err);
    600     }
    601     ALOGV("VideoEditorAudioEncoder_processOutputBuffer end");
    602     return err;
    603 }
    604 
    605 M4OSA_ERR VideoEditorAudioEncoder_step(M4OSA_Context pContext,
    606         M4ENCODER_AudioBuffer* pInBuffer, M4ENCODER_AudioBuffer* pOutBuffer) {
    607     M4OSA_ERR err = M4NO_ERROR;
    608     VideoEditorAudioEncoder_Context* pEncoderContext = M4OSA_NULL;
    609     status_t result = OK;
    610     MediaBuffer* buffer = NULL;
    611 
    612     ALOGV("VideoEditorAudioEncoder_step begin");
    613 
    614     VIDEOEDITOR_CHECK(M4OSA_NULL != pContext,   M4ERR_PARAMETER);
    615     VIDEOEDITOR_CHECK(M4OSA_NULL != pInBuffer,  M4ERR_PARAMETER);
    616     VIDEOEDITOR_CHECK(M4OSA_NULL != pOutBuffer, M4ERR_PARAMETER);
    617 
    618     pEncoderContext = (VideoEditorAudioEncoder_Context*)pContext;
    619     pEncoderContext->mNbInputFrames++;
    620 
    621     // Push the input buffer to the encoder source
    622     err = VideoEditorAudioEncoder_processInputBuffer(pEncoderContext,pInBuffer);
    623     VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
    624 
    625     // Read
    626     result = pEncoderContext->mEncoder->read(&buffer, NULL);
    627     VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
    628 
    629     // Provide the encoded AU to the writer
    630     err = VideoEditorAudioEncoder_processOutputBuffer(pEncoderContext, buffer,
    631         pOutBuffer);
    632     VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
    633 
    634 cleanUp:
    635     if( M4NO_ERROR == err ) {
    636         ALOGV("VideoEditorAudioEncoder_step no error");
    637     } else {
    638         ALOGV("VideoEditorAudioEncoder_step ERROR 0x%X", err);
    639     }
    640     ALOGV("VideoEditorAudioEncoder_step end");
    641     return err;
    642 }
    643 
    644 M4OSA_ERR VideoEditorAudioEncoder_getOption(M4OSA_Context pContext,
    645         M4OSA_OptionID optionID, M4OSA_DataOption* optionValue) {
    646     M4OSA_ERR err = M4NO_ERROR;
    647     VideoEditorAudioEncoder_Context* pEncoderContext = M4OSA_NULL;
    648 
    649     ALOGV("VideoEditorAudioEncoder_getOption begin optionID 0x%X", optionID);
    650     VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
    651 
    652     pEncoderContext = (VideoEditorAudioEncoder_Context*)pContext;
    653 
    654     switch( optionID ) {
    655         default:
    656             ALOGV("VideoEditorAudioEncoder_getOption: unsupported optionId 0x%X",
    657                 optionID);
    658             VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_BAD_OPTION_ID);
    659             break;
    660     }
    661 
    662 cleanUp:
    663     if( M4NO_ERROR == err ) {
    664         ALOGV("VideoEditorAudioEncoder_getOption no error");
    665     } else {
    666         ALOGV("VideoEditorAudioEncoder_getOption ERROR 0x%X", err);
    667     }
    668     ALOGV("VideoEditorAudioEncoder_getOption end");
    669     return err;
    670 }
    671 
    672 M4OSA_ERR VideoEditorAudioEncoder_getInterface(
    673         M4ENCODER_AudioFormat format, M4ENCODER_AudioFormat* pFormat,
    674         M4ENCODER_AudioGlobalInterface** pEncoderInterface) {
    675     M4OSA_ERR err = M4NO_ERROR;
    676 
    677     // Input parameters check
    678     VIDEOEDITOR_CHECK(M4OSA_NULL != pFormat,           M4ERR_PARAMETER);
    679     VIDEOEDITOR_CHECK(M4OSA_NULL != pEncoderInterface, M4ERR_PARAMETER);
    680 
    681     ALOGV("VideoEditorAudioEncoder_getInterface 0x%x 0x%x",pFormat,
    682         pEncoderInterface);
    683     SAFE_MALLOC(*pEncoderInterface, M4ENCODER_AudioGlobalInterface, 1,
    684         "AudioEncoder");
    685 
    686     *pFormat = format;
    687 
    688     switch( format ) {
    689         case M4ENCODER_kAAC:
    690         {
    691             (*pEncoderInterface)->pFctInit = VideoEditorAudioEncoder_init_AAC;
    692             break;
    693         }
    694         case M4ENCODER_kAMRNB:
    695         {
    696             (*pEncoderInterface)->pFctInit = VideoEditorAudioEncoder_init_AMRNB;
    697             break;
    698         }
    699         case M4ENCODER_kMP3:
    700         {
    701             (*pEncoderInterface)->pFctInit = VideoEditorAudioEncoder_init_MP3;
    702             break;
    703         }
    704         default:
    705         {
    706             ALOGV("VideoEditorAudioEncoder_getInterface: unsupported format %d",
    707                 format);
    708             VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_PARAMETER);
    709         break;
    710         }
    711     }
    712     (*pEncoderInterface)->pFctCleanUp      = VideoEditorAudioEncoder_cleanup;
    713     (*pEncoderInterface)->pFctOpen         = VideoEditorAudioEncoder_open;
    714     (*pEncoderInterface)->pFctClose        = VideoEditorAudioEncoder_close;
    715     (*pEncoderInterface)->pFctStep         = VideoEditorAudioEncoder_step;
    716     (*pEncoderInterface)->pFctGetOption    = VideoEditorAudioEncoder_getOption;
    717 
    718 cleanUp:
    719     if( M4NO_ERROR == err ) {
    720         ALOGV("VideoEditorAudioEncoder_getInterface no error");
    721     } else {
    722         *pEncoderInterface = M4OSA_NULL;
    723         ALOGV("VideoEditorAudioEncoder_getInterface ERROR 0x%X", err);
    724     }
    725     return err;
    726 }
    727 extern "C" {
    728 
    729 M4OSA_ERR VideoEditorAudioEncoder_getInterface_AAC(
    730         M4ENCODER_AudioFormat* pFormat,
    731         M4ENCODER_AudioGlobalInterface** pEncoderInterface) {
    732     return VideoEditorAudioEncoder_getInterface(
    733         M4ENCODER_kAAC, pFormat, pEncoderInterface);
    734 }
    735 
    736 M4OSA_ERR VideoEditorAudioEncoder_getInterface_AMRNB(
    737         M4ENCODER_AudioFormat* pFormat,
    738         M4ENCODER_AudioGlobalInterface** pEncoderInterface) {
    739 
    740     return VideoEditorAudioEncoder_getInterface(
    741         M4ENCODER_kAMRNB, pFormat, pEncoderInterface);
    742 }
    743 
    744 M4OSA_ERR VideoEditorAudioEncoder_getInterface_MP3(
    745         M4ENCODER_AudioFormat* pFormat,
    746         M4ENCODER_AudioGlobalInterface** pEncoderInterface) {
    747     ALOGV("VideoEditorAudioEncoder_getInterface_MP3 no error");
    748 
    749     return VideoEditorAudioEncoder_getInterface(
    750         M4ENCODER_kMP3, pFormat, pEncoderInterface);
    751 }
    752 
    753 }  // extern "C"
    754 
    755 }  // namespace android
    756