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 "SoftAAC2"
19#include <utils/Log.h>
20
21#include "SoftAAC2.h"
22#include <OMX_AudioExt.h>
23#include <OMX_IndexExt.h>
24
25#include <cutils/properties.h>
26#include <media/stagefright/foundation/ADebug.h>
27#include <media/stagefright/foundation/hexdump.h>
28#include <media/stagefright/MediaErrors.h>
29#include <utils/misc.h>
30
31#include <math.h>
32
33#define FILEREAD_MAX_LAYERS 2
34
35#define DRC_DEFAULT_MOBILE_REF_LEVEL 64  /* 64*-0.25dB = -16 dB below full scale for mobile conf */
36#define DRC_DEFAULT_MOBILE_DRC_CUT   127 /* maximum compression of dynamic range for mobile conf */
37#define DRC_DEFAULT_MOBILE_DRC_BOOST 127 /* maximum compression of dynamic range for mobile conf */
38#define DRC_DEFAULT_MOBILE_DRC_HEAVY 1   /* switch for heavy compression for mobile conf */
39#define DRC_DEFAULT_MOBILE_ENC_LEVEL (-1) /* encoder target level; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
40#define MAX_CHANNEL_COUNT            8  /* maximum number of audio channels that can be decoded */
41// names of properties that can be used to override the default DRC settings
42#define PROP_DRC_OVERRIDE_REF_LEVEL  "aac_drc_reference_level"
43#define PROP_DRC_OVERRIDE_CUT        "aac_drc_cut"
44#define PROP_DRC_OVERRIDE_BOOST      "aac_drc_boost"
45#define PROP_DRC_OVERRIDE_HEAVY      "aac_drc_heavy"
46#define PROP_DRC_OVERRIDE_ENC_LEVEL "aac_drc_enc_target_level"
47
48namespace android {
49
50template<class T>
51static void InitOMXParams(T *params) {
52    params->nSize = sizeof(T);
53    params->nVersion.s.nVersionMajor = 1;
54    params->nVersion.s.nVersionMinor = 0;
55    params->nVersion.s.nRevision = 0;
56    params->nVersion.s.nStep = 0;
57}
58
59static const OMX_U32 kSupportedProfiles[] = {
60    OMX_AUDIO_AACObjectLC,
61    OMX_AUDIO_AACObjectHE,
62    OMX_AUDIO_AACObjectHE_PS,
63    OMX_AUDIO_AACObjectLD,
64    OMX_AUDIO_AACObjectELD,
65    OMX_AUDIO_AACObjectER_Scalable,
66};
67
68SoftAAC2::SoftAAC2(
69        const char *name,
70        const OMX_CALLBACKTYPE *callbacks,
71        OMX_PTR appData,
72        OMX_COMPONENTTYPE **component)
73    : SimpleSoftOMXComponent(name, callbacks, appData, component),
74      mAACDecoder(NULL),
75      mStreamInfo(NULL),
76      mIsADTS(false),
77      mInputBufferCount(0),
78      mOutputBufferCount(0),
79      mSignalledError(false),
80      mLastInHeader(NULL),
81      mOutputPortSettingsChange(NONE) {
82    initPorts();
83    CHECK_EQ(initDecoder(), (status_t)OK);
84}
85
86SoftAAC2::~SoftAAC2() {
87    aacDecoder_Close(mAACDecoder);
88    delete[] mOutputDelayRingBuffer;
89}
90
91void SoftAAC2::initPorts() {
92    OMX_PARAM_PORTDEFINITIONTYPE def;
93    InitOMXParams(&def);
94
95    def.nPortIndex = 0;
96    def.eDir = OMX_DirInput;
97    def.nBufferCountMin = kNumInputBuffers;
98    def.nBufferCountActual = def.nBufferCountMin;
99    def.nBufferSize = 8192;
100    def.bEnabled = OMX_TRUE;
101    def.bPopulated = OMX_FALSE;
102    def.eDomain = OMX_PortDomainAudio;
103    def.bBuffersContiguous = OMX_FALSE;
104    def.nBufferAlignment = 1;
105
106    def.format.audio.cMIMEType = const_cast<char *>("audio/aac");
107    def.format.audio.pNativeRender = NULL;
108    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
109    def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
110
111    addPort(def);
112
113    def.nPortIndex = 1;
114    def.eDir = OMX_DirOutput;
115    def.nBufferCountMin = kNumOutputBuffers;
116    def.nBufferCountActual = def.nBufferCountMin;
117    def.nBufferSize = 4096 * MAX_CHANNEL_COUNT;
118    def.bEnabled = OMX_TRUE;
119    def.bPopulated = OMX_FALSE;
120    def.eDomain = OMX_PortDomainAudio;
121    def.bBuffersContiguous = OMX_FALSE;
122    def.nBufferAlignment = 2;
123
124    def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
125    def.format.audio.pNativeRender = NULL;
126    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
127    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
128
129    addPort(def);
130}
131
132status_t SoftAAC2::initDecoder() {
133    ALOGV("initDecoder()");
134    status_t status = UNKNOWN_ERROR;
135    mAACDecoder = aacDecoder_Open(TT_MP4_ADIF, /* num layers */ 1);
136    if (mAACDecoder != NULL) {
137        mStreamInfo = aacDecoder_GetStreamInfo(mAACDecoder);
138        if (mStreamInfo != NULL) {
139            status = OK;
140        }
141    }
142
143    mEndOfInput = false;
144    mEndOfOutput = false;
145    mOutputDelayCompensated = 0;
146    mOutputDelayRingBufferSize = 2048 * MAX_CHANNEL_COUNT * kNumDelayBlocksMax;
147    mOutputDelayRingBuffer = new short[mOutputDelayRingBufferSize];
148    mOutputDelayRingBufferWritePos = 0;
149    mOutputDelayRingBufferReadPos = 0;
150    mOutputDelayRingBufferFilled = 0;
151
152    if (mAACDecoder == NULL) {
153        ALOGE("AAC decoder is null. TODO: Can not call aacDecoder_SetParam in the following code");
154    }
155
156    //aacDecoder_SetParam(mAACDecoder, AAC_PCM_LIMITER_ENABLE, 0);
157
158    //init DRC wrapper
159    mDrcWrap.setDecoderHandle(mAACDecoder);
160    mDrcWrap.submitStreamData(mStreamInfo);
161
162    // for streams that contain metadata, use the mobile profile DRC settings unless overridden by platform properties
163    // TODO: change the DRC settings depending on audio output device type (HDMI, loadspeaker, headphone)
164    char value[PROPERTY_VALUE_MAX];
165    //  DRC_PRES_MODE_WRAP_DESIRED_TARGET
166    if (property_get(PROP_DRC_OVERRIDE_REF_LEVEL, value, NULL)) {
167        unsigned refLevel = atoi(value);
168        ALOGV("AAC decoder using desired DRC target reference level of %d instead of %d", refLevel,
169                DRC_DEFAULT_MOBILE_REF_LEVEL);
170        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET, refLevel);
171    } else {
172        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET, DRC_DEFAULT_MOBILE_REF_LEVEL);
173    }
174    //  DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR
175    if (property_get(PROP_DRC_OVERRIDE_CUT, value, NULL)) {
176        unsigned cut = atoi(value);
177        ALOGV("AAC decoder using desired DRC attenuation factor of %d instead of %d", cut,
178                DRC_DEFAULT_MOBILE_DRC_CUT);
179        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, cut);
180    } else {
181        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, DRC_DEFAULT_MOBILE_DRC_CUT);
182    }
183    //  DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR
184    if (property_get(PROP_DRC_OVERRIDE_BOOST, value, NULL)) {
185        unsigned boost = atoi(value);
186        ALOGV("AAC decoder using desired DRC boost factor of %d instead of %d", boost,
187                DRC_DEFAULT_MOBILE_DRC_BOOST);
188        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR, boost);
189    } else {
190        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR, DRC_DEFAULT_MOBILE_DRC_BOOST);
191    }
192    //  DRC_PRES_MODE_WRAP_DESIRED_HEAVY
193    if (property_get(PROP_DRC_OVERRIDE_HEAVY, value, NULL)) {
194        unsigned heavy = atoi(value);
195        ALOGV("AAC decoder using desried DRC heavy compression switch of %d instead of %d", heavy,
196                DRC_DEFAULT_MOBILE_DRC_HEAVY);
197        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY, heavy);
198    } else {
199        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY, DRC_DEFAULT_MOBILE_DRC_HEAVY);
200    }
201    // DRC_PRES_MODE_WRAP_ENCODER_TARGET
202    if (property_get(PROP_DRC_OVERRIDE_ENC_LEVEL, value, NULL)) {
203        unsigned encoderRefLevel = atoi(value);
204        ALOGV("AAC decoder using encoder-side DRC reference level of %d instead of %d",
205                encoderRefLevel, DRC_DEFAULT_MOBILE_ENC_LEVEL);
206        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET, encoderRefLevel);
207    } else {
208        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET, DRC_DEFAULT_MOBILE_ENC_LEVEL);
209    }
210
211    // By default, the decoder creates a 5.1 channel downmix signal.
212    // For seven and eight channel input streams, enable 6.1 and 7.1 channel output
213    aacDecoder_SetParam(mAACDecoder, AAC_PCM_MAX_OUTPUT_CHANNELS, -1);
214
215    return status;
216}
217
218OMX_ERRORTYPE SoftAAC2::internalGetParameter(
219        OMX_INDEXTYPE index, OMX_PTR params) {
220    switch ((OMX_U32) index) {
221        case OMX_IndexParamAudioAac:
222        {
223            OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
224                (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
225
226            if (!isValidOMXParam(aacParams)) {
227                return OMX_ErrorBadParameter;
228            }
229
230            if (aacParams->nPortIndex != 0) {
231                return OMX_ErrorUndefined;
232            }
233
234            aacParams->nBitRate = 0;
235            aacParams->nAudioBandWidth = 0;
236            aacParams->nAACtools = 0;
237            aacParams->nAACERtools = 0;
238            aacParams->eAACProfile = OMX_AUDIO_AACObjectMain;
239
240            aacParams->eAACStreamFormat =
241                mIsADTS
242                    ? OMX_AUDIO_AACStreamFormatMP4ADTS
243                    : OMX_AUDIO_AACStreamFormatMP4FF;
244
245            aacParams->eChannelMode = OMX_AUDIO_ChannelModeStereo;
246
247            if (!isConfigured()) {
248                aacParams->nChannels = 1;
249                aacParams->nSampleRate = 44100;
250                aacParams->nFrameLength = 0;
251            } else {
252                aacParams->nChannels = mStreamInfo->numChannels;
253                aacParams->nSampleRate = mStreamInfo->sampleRate;
254                aacParams->nFrameLength = mStreamInfo->frameSize;
255            }
256
257            return OMX_ErrorNone;
258        }
259
260        case OMX_IndexParamAudioPcm:
261        {
262            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
263                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
264
265            if (!isValidOMXParam(pcmParams)) {
266                return OMX_ErrorBadParameter;
267            }
268
269            if (pcmParams->nPortIndex != 1) {
270                return OMX_ErrorUndefined;
271            }
272
273            pcmParams->eNumData = OMX_NumericalDataSigned;
274            pcmParams->eEndian = OMX_EndianBig;
275            pcmParams->bInterleaved = OMX_TRUE;
276            pcmParams->nBitPerSample = 16;
277            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
278            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
279            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
280            pcmParams->eChannelMapping[2] = OMX_AUDIO_ChannelCF;
281            pcmParams->eChannelMapping[3] = OMX_AUDIO_ChannelLFE;
282            pcmParams->eChannelMapping[4] = OMX_AUDIO_ChannelLS;
283            pcmParams->eChannelMapping[5] = OMX_AUDIO_ChannelRS;
284
285            if (!isConfigured()) {
286                pcmParams->nChannels = 1;
287                pcmParams->nSamplingRate = 44100;
288            } else {
289                pcmParams->nChannels = mStreamInfo->numChannels;
290                pcmParams->nSamplingRate = mStreamInfo->sampleRate;
291            }
292
293            return OMX_ErrorNone;
294        }
295
296        case OMX_IndexParamAudioProfileQuerySupported:
297        {
298            OMX_AUDIO_PARAM_ANDROID_PROFILETYPE *profileParams =
299                (OMX_AUDIO_PARAM_ANDROID_PROFILETYPE *)params;
300
301            if (!isValidOMXParam(profileParams)) {
302                return OMX_ErrorBadParameter;
303            }
304
305            if (profileParams->nPortIndex != 0) {
306                return OMX_ErrorUndefined;
307            }
308
309            if (profileParams->nProfileIndex >= NELEM(kSupportedProfiles)) {
310                return OMX_ErrorNoMore;
311            }
312
313            profileParams->eProfile =
314                kSupportedProfiles[profileParams->nProfileIndex];
315
316            return OMX_ErrorNone;
317        }
318
319        default:
320            return SimpleSoftOMXComponent::internalGetParameter(index, params);
321    }
322}
323
324OMX_ERRORTYPE SoftAAC2::internalSetParameter(
325        OMX_INDEXTYPE index, const OMX_PTR params) {
326    switch ((int)index) {
327        case OMX_IndexParamStandardComponentRole:
328        {
329            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
330                (const OMX_PARAM_COMPONENTROLETYPE *)params;
331
332            if (!isValidOMXParam(roleParams)) {
333                return OMX_ErrorBadParameter;
334            }
335
336            if (strncmp((const char *)roleParams->cRole,
337                        "audio_decoder.aac",
338                        OMX_MAX_STRINGNAME_SIZE - 1)) {
339                return OMX_ErrorUndefined;
340            }
341
342            return OMX_ErrorNone;
343        }
344
345        case OMX_IndexParamAudioAac:
346        {
347            const OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
348                (const OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
349
350            if (!isValidOMXParam(aacParams)) {
351                return OMX_ErrorBadParameter;
352            }
353
354            if (aacParams->nPortIndex != 0) {
355                return OMX_ErrorUndefined;
356            }
357
358            if (aacParams->eAACStreamFormat == OMX_AUDIO_AACStreamFormatMP4FF) {
359                mIsADTS = false;
360            } else if (aacParams->eAACStreamFormat
361                        == OMX_AUDIO_AACStreamFormatMP4ADTS) {
362                mIsADTS = true;
363            } else {
364                return OMX_ErrorUndefined;
365            }
366
367            return OMX_ErrorNone;
368        }
369
370        case OMX_IndexParamAudioAndroidAacPresentation:
371        {
372            const OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE *aacPresParams =
373                    (const OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE *)params;
374
375            if (!isValidOMXParam(aacPresParams)) {
376                return OMX_ErrorBadParameter;
377            }
378
379            // for the following parameters of the OMX_AUDIO_PARAM_AACPROFILETYPE structure,
380            // a value of -1 implies the parameter is not set by the application:
381            //   nMaxOutputChannels     -1 by default
382            //   nDrcCut                uses default platform properties, see initDecoder()
383            //   nDrcBoost                idem
384            //   nHeavyCompression        idem
385            //   nTargetReferenceLevel    idem
386            //   nEncodedTargetLevel      idem
387            if (aacPresParams->nMaxOutputChannels >= 0) {
388                int max;
389                if (aacPresParams->nMaxOutputChannels >= 8) { max = 8; }
390                else if (aacPresParams->nMaxOutputChannels >= 6) { max = 6; }
391                else if (aacPresParams->nMaxOutputChannels >= 2) { max = 2; }
392                else {
393                    // -1 or 0: disable downmix,  1: mono
394                    max = aacPresParams->nMaxOutputChannels;
395                }
396                ALOGV("set nMaxOutputChannels=%d", max);
397                aacDecoder_SetParam(mAACDecoder, AAC_PCM_MAX_OUTPUT_CHANNELS, max);
398            }
399            bool updateDrcWrapper = false;
400            if (aacPresParams->nDrcBoost >= 0) {
401                ALOGV("set nDrcBoost=%d", aacPresParams->nDrcBoost);
402                mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR,
403                        aacPresParams->nDrcBoost);
404                updateDrcWrapper = true;
405            }
406            if (aacPresParams->nDrcCut >= 0) {
407                ALOGV("set nDrcCut=%d", aacPresParams->nDrcCut);
408                mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, aacPresParams->nDrcCut);
409                updateDrcWrapper = true;
410            }
411            if (aacPresParams->nHeavyCompression >= 0) {
412                ALOGV("set nHeavyCompression=%d", aacPresParams->nHeavyCompression);
413                mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY,
414                        aacPresParams->nHeavyCompression);
415                updateDrcWrapper = true;
416            }
417            if (aacPresParams->nTargetReferenceLevel >= 0) {
418                ALOGV("set nTargetReferenceLevel=%d", aacPresParams->nTargetReferenceLevel);
419                mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET,
420                        aacPresParams->nTargetReferenceLevel);
421                updateDrcWrapper = true;
422            }
423            if (aacPresParams->nEncodedTargetLevel >= 0) {
424                ALOGV("set nEncodedTargetLevel=%d", aacPresParams->nEncodedTargetLevel);
425                mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET,
426                        aacPresParams->nEncodedTargetLevel);
427                updateDrcWrapper = true;
428            }
429            if (aacPresParams->nPCMLimiterEnable >= 0) {
430                aacDecoder_SetParam(mAACDecoder, AAC_PCM_LIMITER_ENABLE,
431                        (aacPresParams->nPCMLimiterEnable != 0));
432            }
433            if (updateDrcWrapper) {
434                mDrcWrap.update();
435            }
436
437            return OMX_ErrorNone;
438        }
439
440        case OMX_IndexParamAudioPcm:
441        {
442            const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
443                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
444
445            if (!isValidOMXParam(pcmParams)) {
446                return OMX_ErrorBadParameter;
447            }
448
449            if (pcmParams->nPortIndex != 1) {
450                return OMX_ErrorUndefined;
451            }
452
453            return OMX_ErrorNone;
454        }
455
456        default:
457            return SimpleSoftOMXComponent::internalSetParameter(index, params);
458    }
459}
460
461bool SoftAAC2::isConfigured() const {
462    return mInputBufferCount > 0;
463}
464
465bool SoftAAC2::outputDelayRingBufferPutSamples(INT_PCM *samples, int32_t numSamples) {
466    if (numSamples == 0) {
467        return true;
468    }
469    if (outputDelayRingBufferSpaceLeft() < numSamples) {
470        ALOGE("RING BUFFER WOULD OVERFLOW");
471        return false;
472    }
473    if (mOutputDelayRingBufferWritePos + numSamples <= mOutputDelayRingBufferSize
474            && (mOutputDelayRingBufferReadPos <= mOutputDelayRingBufferWritePos
475                    || mOutputDelayRingBufferReadPos > mOutputDelayRingBufferWritePos + numSamples)) {
476        // faster memcopy loop without checks, if the preconditions allow this
477        for (int32_t i = 0; i < numSamples; i++) {
478            mOutputDelayRingBuffer[mOutputDelayRingBufferWritePos++] = samples[i];
479        }
480
481        if (mOutputDelayRingBufferWritePos >= mOutputDelayRingBufferSize) {
482            mOutputDelayRingBufferWritePos -= mOutputDelayRingBufferSize;
483        }
484    } else {
485        ALOGV("slow SoftAAC2::outputDelayRingBufferPutSamples()");
486
487        for (int32_t i = 0; i < numSamples; i++) {
488            mOutputDelayRingBuffer[mOutputDelayRingBufferWritePos] = samples[i];
489            mOutputDelayRingBufferWritePos++;
490            if (mOutputDelayRingBufferWritePos >= mOutputDelayRingBufferSize) {
491                mOutputDelayRingBufferWritePos -= mOutputDelayRingBufferSize;
492            }
493        }
494    }
495    mOutputDelayRingBufferFilled += numSamples;
496    return true;
497}
498
499int32_t SoftAAC2::outputDelayRingBufferGetSamples(INT_PCM *samples, int32_t numSamples) {
500
501    if (numSamples > mOutputDelayRingBufferFilled) {
502        ALOGE("RING BUFFER WOULD UNDERRUN");
503        return -1;
504    }
505
506    if (mOutputDelayRingBufferReadPos + numSamples <= mOutputDelayRingBufferSize
507            && (mOutputDelayRingBufferWritePos < mOutputDelayRingBufferReadPos
508                    || mOutputDelayRingBufferWritePos >= mOutputDelayRingBufferReadPos + numSamples)) {
509        // faster memcopy loop without checks, if the preconditions allow this
510        if (samples != 0) {
511            for (int32_t i = 0; i < numSamples; i++) {
512                samples[i] = mOutputDelayRingBuffer[mOutputDelayRingBufferReadPos++];
513            }
514        } else {
515            mOutputDelayRingBufferReadPos += numSamples;
516        }
517        if (mOutputDelayRingBufferReadPos >= mOutputDelayRingBufferSize) {
518            mOutputDelayRingBufferReadPos -= mOutputDelayRingBufferSize;
519        }
520    } else {
521        ALOGV("slow SoftAAC2::outputDelayRingBufferGetSamples()");
522
523        for (int32_t i = 0; i < numSamples; i++) {
524            if (samples != 0) {
525                samples[i] = mOutputDelayRingBuffer[mOutputDelayRingBufferReadPos];
526            }
527            mOutputDelayRingBufferReadPos++;
528            if (mOutputDelayRingBufferReadPos >= mOutputDelayRingBufferSize) {
529                mOutputDelayRingBufferReadPos -= mOutputDelayRingBufferSize;
530            }
531        }
532    }
533    mOutputDelayRingBufferFilled -= numSamples;
534    return numSamples;
535}
536
537int32_t SoftAAC2::outputDelayRingBufferSamplesAvailable() {
538    return mOutputDelayRingBufferFilled;
539}
540
541int32_t SoftAAC2::outputDelayRingBufferSpaceLeft() {
542    return mOutputDelayRingBufferSize - outputDelayRingBufferSamplesAvailable();
543}
544
545
546void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) {
547    if (mSignalledError || mOutputPortSettingsChange != NONE) {
548        return;
549    }
550
551    UCHAR* inBuffer[FILEREAD_MAX_LAYERS];
552    UINT inBufferLength[FILEREAD_MAX_LAYERS] = {0};
553    UINT bytesValid[FILEREAD_MAX_LAYERS] = {0};
554
555    List<BufferInfo *> &inQueue = getPortQueue(0);
556    List<BufferInfo *> &outQueue = getPortQueue(1);
557
558    while ((!inQueue.empty() || mEndOfInput) && !outQueue.empty()) {
559        if (!inQueue.empty()) {
560            INT_PCM tmpOutBuffer[2048 * MAX_CHANNEL_COUNT];
561            BufferInfo *inInfo = *inQueue.begin();
562            OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
563
564            mEndOfInput = (inHeader->nFlags & OMX_BUFFERFLAG_EOS) != 0;
565
566            if (mInputBufferCount == 0 && !(inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
567                ALOGE("first buffer should have OMX_BUFFERFLAG_CODECCONFIG set");
568                inHeader->nFlags |= OMX_BUFFERFLAG_CODECCONFIG;
569            }
570            if ((inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) != 0) {
571                BufferInfo *inInfo = *inQueue.begin();
572                OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
573
574                inBuffer[0] = inHeader->pBuffer + inHeader->nOffset;
575                inBufferLength[0] = inHeader->nFilledLen;
576
577                AAC_DECODER_ERROR decoderErr =
578                    aacDecoder_ConfigRaw(mAACDecoder,
579                                         inBuffer,
580                                         inBufferLength);
581
582                if (decoderErr != AAC_DEC_OK) {
583                    ALOGW("aacDecoder_ConfigRaw decoderErr = 0x%4.4x", decoderErr);
584                    mSignalledError = true;
585                    notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
586                    return;
587                }
588
589                mInputBufferCount++;
590                mOutputBufferCount++; // fake increase of outputBufferCount to keep the counters aligned
591
592                inInfo->mOwnedByUs = false;
593                inQueue.erase(inQueue.begin());
594                mLastInHeader = NULL;
595                inInfo = NULL;
596                notifyEmptyBufferDone(inHeader);
597                inHeader = NULL;
598
599                // Only send out port settings changed event if both sample rate
600                // and numChannels are valid.
601                if (mStreamInfo->sampleRate && mStreamInfo->numChannels) {
602                    ALOGI("Initially configuring decoder: %d Hz, %d channels",
603                        mStreamInfo->sampleRate,
604                        mStreamInfo->numChannels);
605
606                    notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
607                    mOutputPortSettingsChange = AWAITING_DISABLED;
608                }
609                return;
610            }
611
612            if (inHeader->nFilledLen == 0) {
613                inInfo->mOwnedByUs = false;
614                inQueue.erase(inQueue.begin());
615                mLastInHeader = NULL;
616                inInfo = NULL;
617                notifyEmptyBufferDone(inHeader);
618                inHeader = NULL;
619                continue;
620            }
621
622            if (mIsADTS) {
623                size_t adtsHeaderSize = 0;
624                // skip 30 bits, aac_frame_length follows.
625                // ssssssss ssssiiip ppffffPc ccohCCll llllllll lll?????
626
627                const uint8_t *adtsHeader = inHeader->pBuffer + inHeader->nOffset;
628
629                bool signalError = false;
630                if (inHeader->nFilledLen < 7) {
631                    ALOGE("Audio data too short to contain even the ADTS header. "
632                            "Got %d bytes.", inHeader->nFilledLen);
633                    hexdump(adtsHeader, inHeader->nFilledLen);
634                    signalError = true;
635                } else {
636                    bool protectionAbsent = (adtsHeader[1] & 1);
637
638                    unsigned aac_frame_length =
639                        ((adtsHeader[3] & 3) << 11)
640                        | (adtsHeader[4] << 3)
641                        | (adtsHeader[5] >> 5);
642
643                    if (inHeader->nFilledLen < aac_frame_length) {
644                        ALOGE("Not enough audio data for the complete frame. "
645                                "Got %d bytes, frame size according to the ADTS "
646                                "header is %u bytes.",
647                                inHeader->nFilledLen, aac_frame_length);
648                        hexdump(adtsHeader, inHeader->nFilledLen);
649                        signalError = true;
650                    } else {
651                        adtsHeaderSize = (protectionAbsent ? 7 : 9);
652                        if (aac_frame_length < adtsHeaderSize) {
653                            signalError = true;
654                        } else {
655                            inBuffer[0] = (UCHAR *)adtsHeader + adtsHeaderSize;
656                            inBufferLength[0] = aac_frame_length - adtsHeaderSize;
657
658                            inHeader->nOffset += adtsHeaderSize;
659                            inHeader->nFilledLen -= adtsHeaderSize;
660                        }
661                    }
662                }
663
664                if (signalError) {
665                    mSignalledError = true;
666                    notify(OMX_EventError, OMX_ErrorStreamCorrupt, ERROR_MALFORMED, NULL);
667                    return;
668                }
669
670                // insert buffer size and time stamp
671                mBufferSizes.add(inBufferLength[0]);
672                if (mLastInHeader != inHeader) {
673                    mBufferTimestamps.add(inHeader->nTimeStamp);
674                    mLastInHeader = inHeader;
675                } else {
676                    int64_t currentTime = mBufferTimestamps.top();
677                    currentTime += mStreamInfo->aacSamplesPerFrame *
678                            1000000ll / mStreamInfo->aacSampleRate;
679                    mBufferTimestamps.add(currentTime);
680                }
681            } else {
682                inBuffer[0] = inHeader->pBuffer + inHeader->nOffset;
683                inBufferLength[0] = inHeader->nFilledLen;
684                mLastInHeader = inHeader;
685                mBufferTimestamps.add(inHeader->nTimeStamp);
686                mBufferSizes.add(inHeader->nFilledLen);
687            }
688
689            // Fill and decode
690            bytesValid[0] = inBufferLength[0];
691
692            INT prevSampleRate = mStreamInfo->sampleRate;
693            INT prevNumChannels = mStreamInfo->numChannels;
694
695            aacDecoder_Fill(mAACDecoder,
696                            inBuffer,
697                            inBufferLength,
698                            bytesValid);
699
700            // run DRC check
701            mDrcWrap.submitStreamData(mStreamInfo);
702            mDrcWrap.update();
703
704            UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0];
705            inHeader->nFilledLen -= inBufferUsedLength;
706            inHeader->nOffset += inBufferUsedLength;
707
708            AAC_DECODER_ERROR decoderErr;
709            int numLoops = 0;
710            do {
711                if (outputDelayRingBufferSpaceLeft() <
712                        (mStreamInfo->frameSize * mStreamInfo->numChannels)) {
713                    ALOGV("skipping decode: not enough space left in ringbuffer");
714                    break;
715                }
716
717                int numConsumed = mStreamInfo->numTotalBytes;
718                decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
719                                           tmpOutBuffer,
720                                           2048 * MAX_CHANNEL_COUNT,
721                                           0 /* flags */);
722
723                numConsumed = mStreamInfo->numTotalBytes - numConsumed;
724                numLoops++;
725
726                if (decoderErr == AAC_DEC_NOT_ENOUGH_BITS) {
727                    break;
728                }
729                mDecodedSizes.add(numConsumed);
730
731                if (decoderErr != AAC_DEC_OK) {
732                    ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr);
733                }
734
735                if (bytesValid[0] != 0) {
736                    ALOGE("bytesValid[0] != 0 should never happen");
737                    mSignalledError = true;
738                    notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
739                    return;
740                }
741
742                size_t numOutBytes =
743                    mStreamInfo->frameSize * sizeof(int16_t) * mStreamInfo->numChannels;
744
745                if (decoderErr == AAC_DEC_OK) {
746                    if (!outputDelayRingBufferPutSamples(tmpOutBuffer,
747                            mStreamInfo->frameSize * mStreamInfo->numChannels)) {
748                        mSignalledError = true;
749                        notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
750                        return;
751                    }
752                } else {
753                    ALOGW("AAC decoder returned error 0x%4.4x, substituting silence", decoderErr);
754
755                    memset(tmpOutBuffer, 0, numOutBytes); // TODO: check for overflow
756
757                    if (!outputDelayRingBufferPutSamples(tmpOutBuffer,
758                            mStreamInfo->frameSize * mStreamInfo->numChannels)) {
759                        mSignalledError = true;
760                        notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
761                        return;
762                    }
763
764                    // Discard input buffer.
765                    if (inHeader) {
766                        inHeader->nFilledLen = 0;
767                    }
768
769                    aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1);
770
771                    // After an error, replace the last entry in mBufferSizes with the sum of the
772                    // last <numLoops> entries from mDecodedSizes to resynchronize the in/out lists.
773                    mBufferSizes.pop();
774                    int n = 0;
775                    for (int i = 0; i < numLoops; i++) {
776                        n += mDecodedSizes.itemAt(mDecodedSizes.size() - numLoops + i);
777                    }
778                    mBufferSizes.add(n);
779
780                    // fall through
781                }
782
783                /*
784                 * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
785                 * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
786                 * rate system and the sampling rate in the final output is actually
787                 * doubled compared with the core AAC decoder sampling rate.
788                 *
789                 * Explicit signalling is done by explicitly defining SBR audio object
790                 * type in the bitstream. Implicit signalling is done by embedding
791                 * SBR content in AAC extension payload specific to SBR, and hence
792                 * requires an AAC decoder to perform pre-checks on actual audio frames.
793                 *
794                 * Thus, we could not say for sure whether a stream is
795                 * AAC+/eAAC+ until the first data frame is decoded.
796                 */
797                if (!mStreamInfo->sampleRate || !mStreamInfo->numChannels) {
798                    if ((mInputBufferCount > 2) && (mOutputBufferCount <= 1)) {
799                        ALOGW("Invalid AAC stream");
800                        mSignalledError = true;
801                        notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
802                        return;
803                    }
804                } else if ((mStreamInfo->sampleRate != prevSampleRate) ||
805                           (mStreamInfo->numChannels != prevNumChannels)) {
806                    ALOGI("Reconfiguring decoder: %d->%d Hz, %d->%d channels",
807                          prevSampleRate, mStreamInfo->sampleRate,
808                          prevNumChannels, mStreamInfo->numChannels);
809
810                    notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
811                    mOutputPortSettingsChange = AWAITING_DISABLED;
812
813                    if (inHeader && inHeader->nFilledLen == 0) {
814                        inInfo->mOwnedByUs = false;
815                        mInputBufferCount++;
816                        inQueue.erase(inQueue.begin());
817                        mLastInHeader = NULL;
818                        inInfo = NULL;
819                        notifyEmptyBufferDone(inHeader);
820                        inHeader = NULL;
821                    }
822                    return;
823                }
824                if (inHeader && inHeader->nFilledLen == 0) {
825                    inInfo->mOwnedByUs = false;
826                    mInputBufferCount++;
827                    inQueue.erase(inQueue.begin());
828                    mLastInHeader = NULL;
829                    inInfo = NULL;
830                    notifyEmptyBufferDone(inHeader);
831                    inHeader = NULL;
832                } else {
833                    ALOGV("inHeader->nFilledLen = %d", inHeader ? inHeader->nFilledLen : 0);
834                }
835            } while (decoderErr == AAC_DEC_OK);
836        }
837
838        int32_t outputDelay = mStreamInfo->outputDelay * mStreamInfo->numChannels;
839
840        if (!mEndOfInput && mOutputDelayCompensated < outputDelay) {
841            // discard outputDelay at the beginning
842            int32_t toCompensate = outputDelay - mOutputDelayCompensated;
843            int32_t discard = outputDelayRingBufferSamplesAvailable();
844            if (discard > toCompensate) {
845                discard = toCompensate;
846            }
847            int32_t discarded = outputDelayRingBufferGetSamples(0, discard);
848            mOutputDelayCompensated += discarded;
849            continue;
850        }
851
852        if (mEndOfInput) {
853            while (mOutputDelayCompensated > 0) {
854                // a buffer big enough for MAX_CHANNEL_COUNT channels of decoded HE-AAC
855                INT_PCM tmpOutBuffer[2048 * MAX_CHANNEL_COUNT];
856
857                // run DRC check
858                mDrcWrap.submitStreamData(mStreamInfo);
859                mDrcWrap.update();
860
861                AAC_DECODER_ERROR decoderErr =
862                    aacDecoder_DecodeFrame(mAACDecoder,
863                                           tmpOutBuffer,
864                                           2048 * MAX_CHANNEL_COUNT,
865                                           AACDEC_FLUSH);
866                if (decoderErr != AAC_DEC_OK) {
867                    ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr);
868                }
869
870                int32_t tmpOutBufferSamples = mStreamInfo->frameSize * mStreamInfo->numChannels;
871                if (tmpOutBufferSamples > mOutputDelayCompensated) {
872                    tmpOutBufferSamples = mOutputDelayCompensated;
873                }
874                outputDelayRingBufferPutSamples(tmpOutBuffer, tmpOutBufferSamples);
875                mOutputDelayCompensated -= tmpOutBufferSamples;
876            }
877        }
878
879        while (!outQueue.empty()
880                && outputDelayRingBufferSamplesAvailable()
881                        >= mStreamInfo->frameSize * mStreamInfo->numChannels) {
882            BufferInfo *outInfo = *outQueue.begin();
883            OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
884
885            if (outHeader->nOffset != 0) {
886                ALOGE("outHeader->nOffset != 0 is not handled");
887                mSignalledError = true;
888                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
889                return;
890            }
891
892            INT_PCM *outBuffer =
893                    reinterpret_cast<INT_PCM *>(outHeader->pBuffer + outHeader->nOffset);
894            int samplesize = mStreamInfo->numChannels * sizeof(int16_t);
895            if (outHeader->nOffset
896                    + mStreamInfo->frameSize * samplesize
897                    > outHeader->nAllocLen) {
898                ALOGE("buffer overflow");
899                mSignalledError = true;
900                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
901                return;
902
903            }
904
905            int available = outputDelayRingBufferSamplesAvailable();
906            int numSamples = outHeader->nAllocLen / sizeof(int16_t);
907            if (numSamples > available) {
908                numSamples = available;
909            }
910            int64_t currentTime = 0;
911            if (available) {
912
913                int numFrames = numSamples / (mStreamInfo->frameSize * mStreamInfo->numChannels);
914                numSamples = numFrames * (mStreamInfo->frameSize * mStreamInfo->numChannels);
915
916                ALOGV("%d samples available (%d), or %d frames",
917                        numSamples, available, numFrames);
918                int64_t *nextTimeStamp = &mBufferTimestamps.editItemAt(0);
919                currentTime = *nextTimeStamp;
920                int32_t *currentBufLeft = &mBufferSizes.editItemAt(0);
921                for (int i = 0; i < numFrames; i++) {
922                    int32_t decodedSize = mDecodedSizes.itemAt(0);
923                    mDecodedSizes.removeAt(0);
924                    ALOGV("decoded %d of %d", decodedSize, *currentBufLeft);
925                    if (*currentBufLeft > decodedSize) {
926                        // adjust/interpolate next time stamp
927                        *currentBufLeft -= decodedSize;
928                        *nextTimeStamp += mStreamInfo->aacSamplesPerFrame *
929                                1000000ll / mStreamInfo->aacSampleRate;
930                        ALOGV("adjusted nextTimeStamp/size to %lld/%d",
931                                (long long) *nextTimeStamp, *currentBufLeft);
932                    } else {
933                        // move to next timestamp in list
934                        if (mBufferTimestamps.size() > 0) {
935                            mBufferTimestamps.removeAt(0);
936                            nextTimeStamp = &mBufferTimestamps.editItemAt(0);
937                            mBufferSizes.removeAt(0);
938                            currentBufLeft = &mBufferSizes.editItemAt(0);
939                            ALOGV("moved to next time/size: %lld/%d",
940                                    (long long) *nextTimeStamp, *currentBufLeft);
941                        }
942                        // try to limit output buffer size to match input buffers
943                        // (e.g when an input buffer contained 4 "sub" frames, output
944                        // at most 4 decoded units in the corresponding output buffer)
945                        // This is optional. Remove the next three lines to fill the output
946                        // buffer with as many units as available.
947                        numFrames = i + 1;
948                        numSamples = numFrames * mStreamInfo->frameSize * mStreamInfo->numChannels;
949                        break;
950                    }
951                }
952
953                ALOGV("getting %d from ringbuffer", numSamples);
954                int32_t ns = outputDelayRingBufferGetSamples(outBuffer, numSamples);
955                if (ns != numSamples) {
956                    ALOGE("not a complete frame of samples available");
957                    mSignalledError = true;
958                    notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
959                    return;
960                }
961            }
962
963            outHeader->nFilledLen = numSamples * sizeof(int16_t);
964
965            if (mEndOfInput && !outQueue.empty() && outputDelayRingBufferSamplesAvailable() == 0) {
966                outHeader->nFlags = OMX_BUFFERFLAG_EOS;
967                mEndOfOutput = true;
968            } else {
969                outHeader->nFlags = 0;
970            }
971
972            outHeader->nTimeStamp = currentTime;
973
974            mOutputBufferCount++;
975            outInfo->mOwnedByUs = false;
976            outQueue.erase(outQueue.begin());
977            outInfo = NULL;
978            ALOGV("out timestamp %lld / %d", outHeader->nTimeStamp, outHeader->nFilledLen);
979            notifyFillBufferDone(outHeader);
980            outHeader = NULL;
981        }
982
983        if (mEndOfInput) {
984            int ringBufAvail = outputDelayRingBufferSamplesAvailable();
985            if (!outQueue.empty()
986                    && ringBufAvail < mStreamInfo->frameSize * mStreamInfo->numChannels) {
987                if (!mEndOfOutput) {
988                    // send partial or empty block signaling EOS
989                    mEndOfOutput = true;
990                    BufferInfo *outInfo = *outQueue.begin();
991                    OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
992
993                    INT_PCM *outBuffer = reinterpret_cast<INT_PCM *>(outHeader->pBuffer
994                            + outHeader->nOffset);
995                    int32_t ns = outputDelayRingBufferGetSamples(outBuffer, ringBufAvail);
996                    if (ns < 0) {
997                        ns = 0;
998                    }
999                    outHeader->nFilledLen = ns;
1000                    outHeader->nFlags = OMX_BUFFERFLAG_EOS;
1001
1002                    outHeader->nTimeStamp = mBufferTimestamps.itemAt(0);
1003                    mBufferTimestamps.clear();
1004                    mBufferSizes.clear();
1005                    mDecodedSizes.clear();
1006
1007                    mOutputBufferCount++;
1008                    outInfo->mOwnedByUs = false;
1009                    outQueue.erase(outQueue.begin());
1010                    outInfo = NULL;
1011                    notifyFillBufferDone(outHeader);
1012                    outHeader = NULL;
1013                }
1014                break; // if outQueue not empty but no more output
1015            }
1016        }
1017    }
1018}
1019
1020void SoftAAC2::onPortFlushCompleted(OMX_U32 portIndex) {
1021    if (portIndex == 0) {
1022        // Make sure that the next buffer output does not still
1023        // depend on fragments from the last one decoded.
1024        // drain all existing data
1025        drainDecoder();
1026        mBufferTimestamps.clear();
1027        mBufferSizes.clear();
1028        mDecodedSizes.clear();
1029        mLastInHeader = NULL;
1030        mEndOfInput = false;
1031    } else {
1032        int avail;
1033        while ((avail = outputDelayRingBufferSamplesAvailable()) > 0) {
1034            if (avail > mStreamInfo->frameSize * mStreamInfo->numChannels) {
1035                avail = mStreamInfo->frameSize * mStreamInfo->numChannels;
1036            }
1037            int32_t ns = outputDelayRingBufferGetSamples(0, avail);
1038            if (ns != avail) {
1039                ALOGW("not a complete frame of samples available");
1040                break;
1041            }
1042            mOutputBufferCount++;
1043        }
1044        mOutputDelayRingBufferReadPos = mOutputDelayRingBufferWritePos;
1045        mEndOfOutput = false;
1046    }
1047}
1048
1049void SoftAAC2::drainDecoder() {
1050    // flush decoder until outputDelay is compensated
1051    while (mOutputDelayCompensated > 0) {
1052        // a buffer big enough for MAX_CHANNEL_COUNT channels of decoded HE-AAC
1053        INT_PCM tmpOutBuffer[2048 * MAX_CHANNEL_COUNT];
1054
1055        // run DRC check
1056        mDrcWrap.submitStreamData(mStreamInfo);
1057        mDrcWrap.update();
1058
1059        AAC_DECODER_ERROR decoderErr =
1060            aacDecoder_DecodeFrame(mAACDecoder,
1061                                   tmpOutBuffer,
1062                                   2048 * MAX_CHANNEL_COUNT,
1063                                   AACDEC_FLUSH);
1064        if (decoderErr != AAC_DEC_OK) {
1065            ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr);
1066        }
1067
1068        int32_t tmpOutBufferSamples = mStreamInfo->frameSize * mStreamInfo->numChannels;
1069        if (tmpOutBufferSamples > mOutputDelayCompensated) {
1070            tmpOutBufferSamples = mOutputDelayCompensated;
1071        }
1072        outputDelayRingBufferPutSamples(tmpOutBuffer, tmpOutBufferSamples);
1073
1074        mOutputDelayCompensated -= tmpOutBufferSamples;
1075    }
1076}
1077
1078void SoftAAC2::onReset() {
1079    drainDecoder();
1080    // reset the "configured" state
1081    mInputBufferCount = 0;
1082    mOutputBufferCount = 0;
1083    mOutputDelayCompensated = 0;
1084    mOutputDelayRingBufferWritePos = 0;
1085    mOutputDelayRingBufferReadPos = 0;
1086    mOutputDelayRingBufferFilled = 0;
1087    mEndOfInput = false;
1088    mEndOfOutput = false;
1089    mBufferTimestamps.clear();
1090    mBufferSizes.clear();
1091    mDecodedSizes.clear();
1092    mLastInHeader = NULL;
1093
1094    // To make the codec behave the same before and after a reset, we need to invalidate the
1095    // streaminfo struct. This does that:
1096    mStreamInfo->sampleRate = 0; // TODO: mStreamInfo is read only
1097
1098    mSignalledError = false;
1099    mOutputPortSettingsChange = NONE;
1100}
1101
1102void SoftAAC2::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
1103    if (portIndex != 1) {
1104        return;
1105    }
1106
1107    switch (mOutputPortSettingsChange) {
1108        case NONE:
1109            break;
1110
1111        case AWAITING_DISABLED:
1112        {
1113            CHECK(!enabled);
1114            mOutputPortSettingsChange = AWAITING_ENABLED;
1115            break;
1116        }
1117
1118        default:
1119        {
1120            CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
1121            CHECK(enabled);
1122            mOutputPortSettingsChange = NONE;
1123            break;
1124        }
1125    }
1126}
1127
1128}  // namespace android
1129
1130android::SoftOMXComponent *createSoftOMXComponent(
1131        const char *name, const OMX_CALLBACKTYPE *callbacks,
1132        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
1133    return new android::SoftAAC2(name, callbacks, appData, component);
1134}
1135