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