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