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