SoftAACEncoder2.cpp revision ed2a94af7d53374d40c346cd4771ca168924e1e2
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 "SoftAACEncoder2"
19#include <utils/Log.h>
20
21#include "SoftAACEncoder2.h"
22#include <OMX_AudioExt.h>
23#include <OMX_IndexExt.h>
24
25#include <media/stagefright/foundation/ADebug.h>
26#include <media/stagefright/foundation/hexdump.h>
27#include <utils/misc.h>
28
29namespace android {
30
31template<class T>
32static 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
40static const OMX_U32 kSupportedProfiles[] = {
41    OMX_AUDIO_AACObjectLC,
42    OMX_AUDIO_AACObjectHE,
43    OMX_AUDIO_AACObjectHE_PS,
44    OMX_AUDIO_AACObjectLD,
45    OMX_AUDIO_AACObjectELD,
46};
47
48SoftAACEncoder2::SoftAACEncoder2(
49        const char *name,
50        const OMX_CALLBACKTYPE *callbacks,
51        OMX_PTR appData,
52        OMX_COMPONENTTYPE **component)
53    : SimpleSoftOMXComponent(name, callbacks, appData, component),
54      mAACEncoder(NULL),
55      mNumChannels(1),
56      mSampleRate(44100),
57      mBitRate(0),
58      mSBRMode(-1),
59      mSBRRatio(0),
60      mAACProfile(OMX_AUDIO_AACObjectLC),
61      mSentCodecSpecificData(false),
62      mInputSize(0),
63      mInputFrame(NULL),
64      mInputTimeUs(-1ll),
65      mSawInputEOS(false),
66      mSignalledError(false) {
67    initPorts();
68    CHECK_EQ(initEncoder(), (status_t)OK);
69    setAudioParams();
70}
71
72SoftAACEncoder2::~SoftAACEncoder2() {
73    aacEncClose(&mAACEncoder);
74
75    delete[] mInputFrame;
76    mInputFrame = NULL;
77}
78
79void SoftAACEncoder2::initPorts() {
80    OMX_PARAM_PORTDEFINITIONTYPE def;
81    InitOMXParams(&def);
82
83    def.nPortIndex = 0;
84    def.eDir = OMX_DirInput;
85    def.nBufferCountMin = kNumBuffers;
86    def.nBufferCountActual = def.nBufferCountMin;
87    def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t) * 2;
88    def.bEnabled = OMX_TRUE;
89    def.bPopulated = OMX_FALSE;
90    def.eDomain = OMX_PortDomainAudio;
91    def.bBuffersContiguous = OMX_FALSE;
92    def.nBufferAlignment = 1;
93
94    def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
95    def.format.audio.pNativeRender = NULL;
96    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
97    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
98
99    addPort(def);
100
101    def.nPortIndex = 1;
102    def.eDir = OMX_DirOutput;
103    def.nBufferCountMin = kNumBuffers;
104    def.nBufferCountActual = def.nBufferCountMin;
105    def.nBufferSize = 8192;
106    def.bEnabled = OMX_TRUE;
107    def.bPopulated = OMX_FALSE;
108    def.eDomain = OMX_PortDomainAudio;
109    def.bBuffersContiguous = OMX_FALSE;
110    def.nBufferAlignment = 2;
111
112    def.format.audio.cMIMEType = const_cast<char *>("audio/aac");
113    def.format.audio.pNativeRender = NULL;
114    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
115    def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
116
117    addPort(def);
118}
119
120status_t SoftAACEncoder2::initEncoder() {
121    if (AACENC_OK != aacEncOpen(&mAACEncoder, 0, 0)) {
122        ALOGE("Failed to init AAC encoder");
123        return UNKNOWN_ERROR;
124    }
125    return OK;
126}
127
128OMX_ERRORTYPE SoftAACEncoder2::internalGetParameter(
129        OMX_INDEXTYPE index, OMX_PTR params) {
130    switch ((OMX_U32) index) {
131        case OMX_IndexParamAudioPortFormat:
132        {
133            OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
134                (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
135
136            if (formatParams->nPortIndex > 1) {
137                return OMX_ErrorUndefined;
138            }
139
140            if (formatParams->nIndex > 0) {
141                return OMX_ErrorNoMore;
142            }
143
144            formatParams->eEncoding =
145                (formatParams->nPortIndex == 0)
146                    ? OMX_AUDIO_CodingPCM : OMX_AUDIO_CodingAAC;
147
148            return OMX_ErrorNone;
149        }
150
151        case OMX_IndexParamAudioAac:
152        {
153            OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
154                (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
155
156            if (aacParams->nPortIndex != 1) {
157                return OMX_ErrorUndefined;
158            }
159
160            aacParams->nBitRate = mBitRate;
161            aacParams->nAudioBandWidth = 0;
162            aacParams->nAACtools = 0;
163            aacParams->nAACERtools = 0;
164            aacParams->eAACProfile = (OMX_AUDIO_AACPROFILETYPE) mAACProfile;
165            aacParams->eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
166            aacParams->eChannelMode = OMX_AUDIO_ChannelModeStereo;
167
168            aacParams->nChannels = mNumChannels;
169            aacParams->nSampleRate = mSampleRate;
170            aacParams->nFrameLength = 0;
171
172            switch (mSBRMode) {
173            case 1: // sbr on
174                switch (mSBRRatio) {
175                case 0:
176                    // set both OMX AAC tool flags
177                    aacParams->nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
178                    aacParams->nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
179                    break;
180                case 1:
181                    // set single-rate SBR active
182                    aacParams->nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
183                    aacParams->nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
184                    break;
185                case 2:
186                    // set dual-rate SBR active
187                    aacParams->nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
188                    aacParams->nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
189                    break;
190                default:
191                    ALOGE("invalid SBR ratio %d", mSBRRatio);
192                    TRESPASS();
193                }
194                break;
195            case 0:  // sbr off
196            case -1: // sbr undefined
197                aacParams->nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
198                aacParams->nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
199                break;
200            default:
201                ALOGE("invalid SBR mode %d", mSBRMode);
202                TRESPASS();
203            }
204
205
206
207            return OMX_ErrorNone;
208        }
209
210        case OMX_IndexParamAudioPcm:
211        {
212            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
213                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
214
215            if (pcmParams->nPortIndex != 0) {
216                return OMX_ErrorUndefined;
217            }
218
219            pcmParams->eNumData = OMX_NumericalDataSigned;
220            pcmParams->eEndian = OMX_EndianBig;
221            pcmParams->bInterleaved = OMX_TRUE;
222            pcmParams->nBitPerSample = 16;
223            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
224            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
225            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
226
227            pcmParams->nChannels = mNumChannels;
228            pcmParams->nSamplingRate = mSampleRate;
229
230            return OMX_ErrorNone;
231        }
232
233        case OMX_IndexParamAudioProfileQuerySupported:
234        {
235            OMX_AUDIO_PARAM_ANDROID_PROFILETYPE *profileParams =
236                (OMX_AUDIO_PARAM_ANDROID_PROFILETYPE *)params;
237
238            if (profileParams->nPortIndex != 1) {
239                return OMX_ErrorUndefined;
240            }
241
242            if (profileParams->nProfileIndex >= NELEM(kSupportedProfiles)) {
243                return OMX_ErrorNoMore;
244            }
245
246            profileParams->eProfile =
247                kSupportedProfiles[profileParams->nProfileIndex];
248
249            return OMX_ErrorNone;
250        }
251
252        default:
253            return SimpleSoftOMXComponent::internalGetParameter(index, params);
254    }
255}
256
257OMX_ERRORTYPE SoftAACEncoder2::internalSetParameter(
258        OMX_INDEXTYPE index, const OMX_PTR params) {
259    switch (index) {
260        case OMX_IndexParamStandardComponentRole:
261        {
262            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
263                (const OMX_PARAM_COMPONENTROLETYPE *)params;
264
265            if (strncmp((const char *)roleParams->cRole,
266                        "audio_encoder.aac",
267                        OMX_MAX_STRINGNAME_SIZE - 1)) {
268                return OMX_ErrorUndefined;
269            }
270
271            return OMX_ErrorNone;
272        }
273
274        case OMX_IndexParamAudioPortFormat:
275        {
276            const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
277                (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
278
279            if (formatParams->nPortIndex > 1) {
280                return OMX_ErrorUndefined;
281            }
282
283            if (formatParams->nIndex > 0) {
284                return OMX_ErrorNoMore;
285            }
286
287            if ((formatParams->nPortIndex == 0
288                        && formatParams->eEncoding != OMX_AUDIO_CodingPCM)
289                || (formatParams->nPortIndex == 1
290                        && formatParams->eEncoding != OMX_AUDIO_CodingAAC)) {
291                return OMX_ErrorUndefined;
292            }
293
294            return OMX_ErrorNone;
295        }
296
297        case OMX_IndexParamAudioAac:
298        {
299            OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
300                (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
301
302            if (aacParams->nPortIndex != 1) {
303                return OMX_ErrorUndefined;
304            }
305
306            mBitRate = aacParams->nBitRate;
307            mNumChannels = aacParams->nChannels;
308            mSampleRate = aacParams->nSampleRate;
309            if (aacParams->eAACProfile != OMX_AUDIO_AACObjectNull) {
310                mAACProfile = aacParams->eAACProfile;
311            }
312
313            if (!(aacParams->nAACtools & OMX_AUDIO_AACToolAndroidSSBR)
314                    && !(aacParams->nAACtools & OMX_AUDIO_AACToolAndroidDSBR)) {
315                mSBRMode = 0;
316                mSBRRatio = 0;
317            } else if ((aacParams->nAACtools & OMX_AUDIO_AACToolAndroidSSBR)
318                    && !(aacParams->nAACtools & OMX_AUDIO_AACToolAndroidDSBR)) {
319                mSBRMode = 1;
320                mSBRRatio = 1;
321            } else if (!(aacParams->nAACtools & OMX_AUDIO_AACToolAndroidSSBR)
322                    && (aacParams->nAACtools & OMX_AUDIO_AACToolAndroidDSBR)) {
323                mSBRMode = 1;
324                mSBRRatio = 2;
325            } else {
326                mSBRMode = -1; // codec default sbr mode
327                mSBRRatio = 0;
328            }
329
330            if (setAudioParams() != OK) {
331                return OMX_ErrorUndefined;
332            }
333
334            return OMX_ErrorNone;
335        }
336
337        case OMX_IndexParamAudioPcm:
338        {
339            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
340                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
341
342            if (pcmParams->nPortIndex != 0) {
343                return OMX_ErrorUndefined;
344            }
345
346            mNumChannels = pcmParams->nChannels;
347            mSampleRate = pcmParams->nSamplingRate;
348            if (setAudioParams() != OK) {
349                return OMX_ErrorUndefined;
350            }
351
352            return OMX_ErrorNone;
353        }
354
355        default:
356            return SimpleSoftOMXComponent::internalSetParameter(index, params);
357    }
358}
359
360static CHANNEL_MODE getChannelMode(OMX_U32 nChannels) {
361    CHANNEL_MODE chMode = MODE_INVALID;
362    switch (nChannels) {
363        case 1: chMode = MODE_1; break;
364        case 2: chMode = MODE_2; break;
365        case 3: chMode = MODE_1_2; break;
366        case 4: chMode = MODE_1_2_1; break;
367        case 5: chMode = MODE_1_2_2; break;
368        case 6: chMode = MODE_1_2_2_1; break;
369        default: chMode = MODE_INVALID;
370    }
371    return chMode;
372}
373
374static AUDIO_OBJECT_TYPE getAOTFromProfile(OMX_U32 profile) {
375    if (profile == OMX_AUDIO_AACObjectLC) {
376        return AOT_AAC_LC;
377    } else if (profile == OMX_AUDIO_AACObjectHE) {
378        return AOT_SBR;
379    } else if (profile == OMX_AUDIO_AACObjectHE_PS) {
380        return AOT_PS;
381    } else if (profile == OMX_AUDIO_AACObjectLD) {
382        return AOT_ER_AAC_LD;
383    } else if (profile == OMX_AUDIO_AACObjectELD) {
384        return AOT_ER_AAC_ELD;
385    } else {
386        ALOGW("Unsupported AAC profile - defaulting to AAC-LC");
387        return AOT_AAC_LC;
388    }
389}
390
391status_t SoftAACEncoder2::setAudioParams() {
392    // We call this whenever sample rate, number of channels, bitrate or SBR mode change
393    // in reponse to setParameter calls.
394
395    ALOGV("setAudioParams: %u Hz, %u channels, %u bps, %i sbr mode, %i sbr ratio",
396         mSampleRate, mNumChannels, mBitRate, mSBRMode, mSBRRatio);
397
398    if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_AOT,
399            getAOTFromProfile(mAACProfile))) {
400        ALOGE("Failed to set AAC encoder parameters");
401        return UNKNOWN_ERROR;
402    }
403
404    if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SAMPLERATE, mSampleRate)) {
405        ALOGE("Failed to set AAC encoder parameters");
406        return UNKNOWN_ERROR;
407    }
408    if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_BITRATE, mBitRate)) {
409        ALOGE("Failed to set AAC encoder parameters");
410        return UNKNOWN_ERROR;
411    }
412    if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_CHANNELMODE,
413            getChannelMode(mNumChannels))) {
414        ALOGE("Failed to set AAC encoder parameters");
415        return UNKNOWN_ERROR;
416    }
417    if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_TRANSMUX, TT_MP4_RAW)) {
418        ALOGE("Failed to set AAC encoder parameters");
419        return UNKNOWN_ERROR;
420    }
421
422    if (mSBRMode != -1 && mAACProfile == OMX_AUDIO_AACObjectELD) {
423        if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_MODE, mSBRMode)) {
424            ALOGE("Failed to set AAC encoder parameters");
425            return UNKNOWN_ERROR;
426        }
427    }
428
429    /* SBR ratio parameter configurations:
430       0: Default configuration wherein SBR ratio is configured depending on audio object type by
431          the FDK.
432       1: Downsampled SBR (default for ELD)
433       2: Dualrate SBR (default for HE-AAC)
434     */
435    if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_RATIO, mSBRRatio)) {
436        ALOGE("Failed to set AAC encoder parameters");
437        return UNKNOWN_ERROR;
438    }
439
440    return OK;
441}
442
443void SoftAACEncoder2::onQueueFilled(OMX_U32 /* portIndex */) {
444    if (mSignalledError) {
445        return;
446    }
447
448    List<BufferInfo *> &inQueue = getPortQueue(0);
449    List<BufferInfo *> &outQueue = getPortQueue(1);
450
451    if (!mSentCodecSpecificData) {
452        // The very first thing we want to output is the codec specific
453        // data. It does not require any input data but we will need an
454        // output buffer to store it in.
455
456        if (outQueue.empty()) {
457            return;
458        }
459
460        if (AACENC_OK != aacEncEncode(mAACEncoder, NULL, NULL, NULL, NULL)) {
461            ALOGE("Unable to initialize encoder for profile / sample-rate / bit-rate / channels");
462            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
463            mSignalledError = true;
464            return;
465        }
466
467        OMX_U32 actualBitRate  = aacEncoder_GetParam(mAACEncoder, AACENC_BITRATE);
468        if (mBitRate != actualBitRate) {
469            ALOGW("Requested bitrate %u unsupported, using %u", mBitRate, actualBitRate);
470        }
471
472        AACENC_InfoStruct encInfo;
473        if (AACENC_OK != aacEncInfo(mAACEncoder, &encInfo)) {
474            ALOGE("Failed to get AAC encoder info");
475            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
476            mSignalledError = true;
477            return;
478        }
479
480        BufferInfo *outInfo = *outQueue.begin();
481        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
482        outHeader->nFilledLen = encInfo.confSize;
483        outHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG;
484
485        uint8_t *out = outHeader->pBuffer + outHeader->nOffset;
486        memcpy(out, encInfo.confBuf, encInfo.confSize);
487
488        outQueue.erase(outQueue.begin());
489        outInfo->mOwnedByUs = false;
490        notifyFillBufferDone(outHeader);
491
492        mSentCodecSpecificData = true;
493    }
494
495    size_t numBytesPerInputFrame =
496        mNumChannels * kNumSamplesPerFrame * sizeof(int16_t);
497
498    // Limit input size so we only get one ELD frame
499    if (mAACProfile == OMX_AUDIO_AACObjectELD && numBytesPerInputFrame > 512) {
500        numBytesPerInputFrame = 512;
501    }
502
503    for (;;) {
504        // We do the following until we run out of buffers.
505
506        while (mInputSize < numBytesPerInputFrame) {
507            // As long as there's still input data to be read we
508            // will drain "kNumSamplesPerFrame * mNumChannels" samples
509            // into the "mInputFrame" buffer and then encode those
510            // as a unit into an output buffer.
511
512            if (mSawInputEOS || inQueue.empty()) {
513                return;
514            }
515
516            BufferInfo *inInfo = *inQueue.begin();
517            OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
518
519            const void *inData = inHeader->pBuffer + inHeader->nOffset;
520
521            size_t copy = numBytesPerInputFrame - mInputSize;
522            if (copy > inHeader->nFilledLen) {
523                copy = inHeader->nFilledLen;
524            }
525
526            if (mInputFrame == NULL) {
527                mInputFrame = new int16_t[numBytesPerInputFrame / sizeof(int16_t)];
528            }
529
530            if (mInputSize == 0) {
531                mInputTimeUs = inHeader->nTimeStamp;
532            }
533
534            memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy);
535            mInputSize += copy;
536
537            inHeader->nOffset += copy;
538            inHeader->nFilledLen -= copy;
539
540            // "Time" on the input buffer has in effect advanced by the
541            // number of audio frames we just advanced nOffset by.
542            inHeader->nTimeStamp +=
543                (copy * 1000000ll / mSampleRate)
544                    / (mNumChannels * sizeof(int16_t));
545
546            if (inHeader->nFilledLen == 0) {
547                if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
548                    mSawInputEOS = true;
549
550                    // Pad any remaining data with zeroes.
551                    memset((uint8_t *)mInputFrame + mInputSize,
552                           0,
553                           numBytesPerInputFrame - mInputSize);
554
555                    mInputSize = numBytesPerInputFrame;
556                }
557
558                inQueue.erase(inQueue.begin());
559                inInfo->mOwnedByUs = false;
560                notifyEmptyBufferDone(inHeader);
561
562                inData = NULL;
563                inHeader = NULL;
564                inInfo = NULL;
565            }
566        }
567
568        // At this  point we have all the input data necessary to encode
569        // a single frame, all we need is an output buffer to store the result
570        // in.
571
572        if (outQueue.empty()) {
573            return;
574        }
575
576        BufferInfo *outInfo = *outQueue.begin();
577        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
578
579        uint8_t *outPtr = (uint8_t *)outHeader->pBuffer + outHeader->nOffset;
580        size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset;
581
582        AACENC_InArgs inargs;
583        AACENC_OutArgs outargs;
584        memset(&inargs, 0, sizeof(inargs));
585        memset(&outargs, 0, sizeof(outargs));
586        inargs.numInSamples = numBytesPerInputFrame / sizeof(int16_t);
587
588        void* inBuffer[]        = { (unsigned char *)mInputFrame };
589        INT   inBufferIds[]     = { IN_AUDIO_DATA };
590        INT   inBufferSize[]    = { (INT)numBytesPerInputFrame };
591        INT   inBufferElSize[]  = { sizeof(int16_t) };
592
593        AACENC_BufDesc inBufDesc;
594        inBufDesc.numBufs           = sizeof(inBuffer) / sizeof(void*);
595        inBufDesc.bufs              = (void**)&inBuffer;
596        inBufDesc.bufferIdentifiers = inBufferIds;
597        inBufDesc.bufSizes          = inBufferSize;
598        inBufDesc.bufElSizes        = inBufferElSize;
599
600        void* outBuffer[]       = { outPtr };
601        INT   outBufferIds[]    = { OUT_BITSTREAM_DATA };
602        INT   outBufferSize[]   = { 0 };
603        INT   outBufferElSize[] = { sizeof(UCHAR) };
604
605        AACENC_BufDesc outBufDesc;
606        outBufDesc.numBufs           = sizeof(outBuffer) / sizeof(void*);
607        outBufDesc.bufs              = (void**)&outBuffer;
608        outBufDesc.bufferIdentifiers = outBufferIds;
609        outBufDesc.bufSizes          = outBufferSize;
610        outBufDesc.bufElSizes        = outBufferElSize;
611
612        // Encode the mInputFrame, which is treated as a modulo buffer
613        AACENC_ERROR encoderErr = AACENC_OK;
614        size_t nOutputBytes = 0;
615
616        do {
617            memset(&outargs, 0, sizeof(outargs));
618
619            outBuffer[0] = outPtr;
620            outBufferSize[0] = outAvailable - nOutputBytes;
621
622            encoderErr = aacEncEncode(mAACEncoder,
623                                      &inBufDesc,
624                                      &outBufDesc,
625                                      &inargs,
626                                      &outargs);
627
628            if (encoderErr == AACENC_OK) {
629                outPtr += outargs.numOutBytes;
630                nOutputBytes += outargs.numOutBytes;
631
632                if (outargs.numInSamples > 0) {
633                    int numRemainingSamples = inargs.numInSamples - outargs.numInSamples;
634                    if (numRemainingSamples > 0) {
635                        memmove(mInputFrame,
636                                &mInputFrame[outargs.numInSamples],
637                                sizeof(int16_t) * numRemainingSamples);
638                    }
639                    inargs.numInSamples -= outargs.numInSamples;
640                }
641            }
642        } while (encoderErr == AACENC_OK && inargs.numInSamples > 0);
643
644        outHeader->nFilledLen = nOutputBytes;
645
646        outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
647
648        if (mSawInputEOS) {
649            // We also tag this output buffer with EOS if it corresponds
650            // to the final input buffer.
651            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
652        }
653
654        outHeader->nTimeStamp = mInputTimeUs;
655
656#if 0
657        ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)",
658              nOutputBytes, mInputTimeUs, outHeader->nFlags);
659
660        hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
661#endif
662
663        outQueue.erase(outQueue.begin());
664        outInfo->mOwnedByUs = false;
665        notifyFillBufferDone(outHeader);
666
667        outHeader = NULL;
668        outInfo = NULL;
669
670        mInputSize = 0;
671    }
672}
673
674}  // namespace android
675
676android::SoftOMXComponent *createSoftOMXComponent(
677        const char *name, const OMX_CALLBACKTYPE *callbacks,
678        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
679    return new android::SoftAACEncoder2(name, callbacks, appData, component);
680}
681