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
42namespace android {
43struct 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
82sp<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
92VideoEditorAudioEncoderSource::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
103VideoEditorAudioEncoderSource::~VideoEditorAudioEncoderSource() {
104    ALOGV("VideoEditorAudioEncoderSource::~VideoEditorAudioEncoderSource");
105
106    if( STARTED == mState ) {
107        stop();
108    }
109}
110
111status_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
124cleanUp:
125    ALOGV("VideoEditorAudioEncoderSource::start END (0x%x)", err);
126    return err;
127}
128
129status_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
158sp<MetaData> VideoEditorAudioEncoderSource::getFormat() {
159    ALOGV("VideoEditorAudioEncoderSource::getFormat");
160    return mEncFormat;
161}
162
163status_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
196int32_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*/
226typedef 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
239M4OSA_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
252cleanUp:
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
262M4OSA_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
277cleanUp:
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
289M4OSA_ERR VideoEditorAudioEncoder_init_AAC(M4OSA_Context* pContext,
290        M4OSA_Void* pUserData) {
291    return VideoEditorAudioEncoder_init(M4ENCODER_kAAC, pContext, pUserData);
292}
293
294M4OSA_ERR VideoEditorAudioEncoder_init_AMRNB(M4OSA_Context* pContext,
295        M4OSA_Void* pUserData) {
296    return VideoEditorAudioEncoder_init(M4ENCODER_kAMRNB, pContext, pUserData);
297}
298
299M4OSA_ERR VideoEditorAudioEncoder_init_MP3(M4OSA_Context* pContext,
300        M4OSA_Void* pUserData) {
301    return VideoEditorAudioEncoder_init(M4ENCODER_kMP3, pContext, pUserData);
302}
303
304M4OSA_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
331cleanUp:
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
341M4OSA_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
487cleanUp:
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
498M4OSA_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
533cleanUp:
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
546M4OSA_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
593cleanUp:
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
605M4OSA_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
634cleanUp:
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
644M4OSA_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
662cleanUp:
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
672M4OSA_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
718cleanUp:
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}
727extern "C" {
728
729M4OSA_ERR VideoEditorAudioEncoder_getInterface_AAC(
730        M4ENCODER_AudioFormat* pFormat,
731        M4ENCODER_AudioGlobalInterface** pEncoderInterface) {
732    return VideoEditorAudioEncoder_getInterface(
733        M4ENCODER_kAAC, pFormat, pEncoderInterface);
734}
735
736M4OSA_ERR VideoEditorAudioEncoder_getInterface_AMRNB(
737        M4ENCODER_AudioFormat* pFormat,
738        M4ENCODER_AudioGlobalInterface** pEncoderInterface) {
739
740    return VideoEditorAudioEncoder_getInterface(
741        M4ENCODER_kAMRNB, pFormat, pEncoderInterface);
742}
743
744M4OSA_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