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