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