SoftAAC2.cpp revision 66fe2e9ee30bcb4161bc487ec63d2ae4a05f4051
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_TAG "SoftAAC2"
18//#define LOG_NDEBUG 0
19#include <utils/Log.h>
20
21#include "SoftAAC2.h"
22
23#include <cutils/properties.h>
24#include <media/stagefright/foundation/ADebug.h>
25#include <media/stagefright/foundation/hexdump.h>
26#include <media/stagefright/MediaErrors.h>
27
28#define FILEREAD_MAX_LAYERS 2
29
30#define DRC_DEFAULT_MOBILE_REF_LEVEL 64  /* 64*-0.25dB = -16 dB below full scale for mobile conf */
31#define DRC_DEFAULT_MOBILE_DRC_CUT   127 /* maximum compression of dynamic range for mobile conf */
32#define DRC_DEFAULT_MOBILE_DRC_BOOST 127 /* maximum compression of dynamic range for mobile conf */
33#define MAX_CHANNEL_COUNT            6  /* maximum number of audio channels that can be decoded */
34// names of properties that can be used to override the default DRC settings
35#define PROP_DRC_OVERRIDE_REF_LEVEL  "aac_drc_reference_level"
36#define PROP_DRC_OVERRIDE_CUT        "aac_drc_cut"
37#define PROP_DRC_OVERRIDE_BOOST      "aac_drc_boost"
38
39namespace android {
40
41template<class T>
42static void InitOMXParams(T *params) {
43    params->nSize = sizeof(T);
44    params->nVersion.s.nVersionMajor = 1;
45    params->nVersion.s.nVersionMinor = 0;
46    params->nVersion.s.nRevision = 0;
47    params->nVersion.s.nStep = 0;
48}
49
50SoftAAC2::SoftAAC2(
51        const char *name,
52        const OMX_CALLBACKTYPE *callbacks,
53        OMX_PTR appData,
54        OMX_COMPONENTTYPE **component)
55    : SimpleSoftOMXComponent(name, callbacks, appData, component),
56      mAACDecoder(NULL),
57      mStreamInfo(NULL),
58      mIsADTS(false),
59      mInputBufferCount(0),
60      mSignalledError(false),
61      mSawInputEos(false),
62      mSignalledOutputEos(false),
63      mAnchorTimeUs(0),
64      mNumSamplesOutput(0),
65      mOutputPortSettingsChange(NONE) {
66    initPorts();
67    CHECK_EQ(initDecoder(), (status_t)OK);
68}
69
70SoftAAC2::~SoftAAC2() {
71    aacDecoder_Close(mAACDecoder);
72}
73
74void SoftAAC2::initPorts() {
75    OMX_PARAM_PORTDEFINITIONTYPE def;
76    InitOMXParams(&def);
77
78    def.nPortIndex = 0;
79    def.eDir = OMX_DirInput;
80    def.nBufferCountMin = kNumInputBuffers;
81    def.nBufferCountActual = def.nBufferCountMin;
82    def.nBufferSize = 8192;
83    def.bEnabled = OMX_TRUE;
84    def.bPopulated = OMX_FALSE;
85    def.eDomain = OMX_PortDomainAudio;
86    def.bBuffersContiguous = OMX_FALSE;
87    def.nBufferAlignment = 1;
88
89    def.format.audio.cMIMEType = const_cast<char *>("audio/aac");
90    def.format.audio.pNativeRender = NULL;
91    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
92    def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
93
94    addPort(def);
95
96    def.nPortIndex = 1;
97    def.eDir = OMX_DirOutput;
98    def.nBufferCountMin = kNumOutputBuffers;
99    def.nBufferCountActual = def.nBufferCountMin;
100    def.nBufferSize = 4096 * MAX_CHANNEL_COUNT;
101    def.bEnabled = OMX_TRUE;
102    def.bPopulated = OMX_FALSE;
103    def.eDomain = OMX_PortDomainAudio;
104    def.bBuffersContiguous = OMX_FALSE;
105    def.nBufferAlignment = 2;
106
107    def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
108    def.format.audio.pNativeRender = NULL;
109    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
110    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
111
112    addPort(def);
113}
114
115status_t SoftAAC2::initDecoder() {
116    status_t status = UNKNOWN_ERROR;
117    mAACDecoder = aacDecoder_Open(TT_MP4_ADIF, /* num layers */ 1);
118    if (mAACDecoder != NULL) {
119        mStreamInfo = aacDecoder_GetStreamInfo(mAACDecoder);
120        if (mStreamInfo != NULL) {
121            status = OK;
122        }
123    }
124    mDecoderHasData = false;
125
126    // for streams that contain metadata, use the mobile profile DRC settings unless overridden
127    // by platform properties:
128    char value[PROPERTY_VALUE_MAX];
129    //  * AAC_DRC_REFERENCE_LEVEL
130    if (property_get(PROP_DRC_OVERRIDE_REF_LEVEL, value, NULL)) {
131        unsigned refLevel = atoi(value);
132        ALOGV("AAC decoder using AAC_DRC_REFERENCE_LEVEL of %d instead of %d",
133                refLevel, DRC_DEFAULT_MOBILE_REF_LEVEL);
134        aacDecoder_SetParam(mAACDecoder, AAC_DRC_REFERENCE_LEVEL, refLevel);
135    } else {
136        aacDecoder_SetParam(mAACDecoder, AAC_DRC_REFERENCE_LEVEL, DRC_DEFAULT_MOBILE_REF_LEVEL);
137    }
138    //  * AAC_DRC_ATTENUATION_FACTOR
139    if (property_get(PROP_DRC_OVERRIDE_CUT, value, NULL)) {
140        unsigned cut = atoi(value);
141        ALOGV("AAC decoder using AAC_DRC_ATTENUATION_FACTOR of %d instead of %d",
142                        cut, DRC_DEFAULT_MOBILE_DRC_CUT);
143        aacDecoder_SetParam(mAACDecoder, AAC_DRC_ATTENUATION_FACTOR, cut);
144    } else {
145        aacDecoder_SetParam(mAACDecoder, AAC_DRC_ATTENUATION_FACTOR, DRC_DEFAULT_MOBILE_DRC_CUT);
146    }
147    //  * AAC_DRC_BOOST_FACTOR (note: no default, using cut)
148    if (property_get(PROP_DRC_OVERRIDE_BOOST, value, NULL)) {
149        unsigned boost = atoi(value);
150        ALOGV("AAC decoder using AAC_DRC_BOOST_FACTOR of %d", boost);
151        aacDecoder_SetParam(mAACDecoder, AAC_DRC_BOOST_FACTOR, boost);
152    } else {
153        aacDecoder_SetParam(mAACDecoder, AAC_DRC_BOOST_FACTOR, DRC_DEFAULT_MOBILE_DRC_BOOST);
154    }
155
156    return status;
157}
158
159OMX_ERRORTYPE SoftAAC2::internalGetParameter(
160        OMX_INDEXTYPE index, OMX_PTR params) {
161    switch (index) {
162        case OMX_IndexParamAudioAac:
163        {
164            OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
165                (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
166
167            if (aacParams->nPortIndex != 0) {
168                return OMX_ErrorUndefined;
169            }
170
171            aacParams->nBitRate = 0;
172            aacParams->nAudioBandWidth = 0;
173            aacParams->nAACtools = 0;
174            aacParams->nAACERtools = 0;
175            aacParams->eAACProfile = OMX_AUDIO_AACObjectMain;
176
177            aacParams->eAACStreamFormat =
178                mIsADTS
179                    ? OMX_AUDIO_AACStreamFormatMP4ADTS
180                    : OMX_AUDIO_AACStreamFormatMP4FF;
181
182            aacParams->eChannelMode = OMX_AUDIO_ChannelModeStereo;
183
184            if (!isConfigured()) {
185                aacParams->nChannels = 1;
186                aacParams->nSampleRate = 44100;
187                aacParams->nFrameLength = 0;
188            } else {
189                aacParams->nChannels = mStreamInfo->numChannels;
190                aacParams->nSampleRate = mStreamInfo->sampleRate;
191                aacParams->nFrameLength = mStreamInfo->frameSize;
192            }
193
194            return OMX_ErrorNone;
195        }
196
197        case OMX_IndexParamAudioPcm:
198        {
199            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
200                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
201
202            if (pcmParams->nPortIndex != 1) {
203                return OMX_ErrorUndefined;
204            }
205
206            pcmParams->eNumData = OMX_NumericalDataSigned;
207            pcmParams->eEndian = OMX_EndianBig;
208            pcmParams->bInterleaved = OMX_TRUE;
209            pcmParams->nBitPerSample = 16;
210            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
211            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
212            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
213            pcmParams->eChannelMapping[2] = OMX_AUDIO_ChannelCF;
214            pcmParams->eChannelMapping[3] = OMX_AUDIO_ChannelLFE;
215            pcmParams->eChannelMapping[4] = OMX_AUDIO_ChannelLS;
216            pcmParams->eChannelMapping[5] = OMX_AUDIO_ChannelRS;
217
218            if (!isConfigured()) {
219                pcmParams->nChannels = 1;
220                pcmParams->nSamplingRate = 44100;
221            } else {
222                pcmParams->nChannels = mStreamInfo->numChannels;
223                pcmParams->nSamplingRate = mStreamInfo->sampleRate;
224            }
225
226            return OMX_ErrorNone;
227        }
228
229        default:
230            return SimpleSoftOMXComponent::internalGetParameter(index, params);
231    }
232}
233
234OMX_ERRORTYPE SoftAAC2::internalSetParameter(
235        OMX_INDEXTYPE index, const OMX_PTR params) {
236    switch (index) {
237        case OMX_IndexParamStandardComponentRole:
238        {
239            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
240                (const OMX_PARAM_COMPONENTROLETYPE *)params;
241
242            if (strncmp((const char *)roleParams->cRole,
243                        "audio_decoder.aac",
244                        OMX_MAX_STRINGNAME_SIZE - 1)) {
245                return OMX_ErrorUndefined;
246            }
247
248            return OMX_ErrorNone;
249        }
250
251        case OMX_IndexParamAudioAac:
252        {
253            const OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
254                (const OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
255
256            if (aacParams->nPortIndex != 0) {
257                return OMX_ErrorUndefined;
258            }
259
260            if (aacParams->eAACStreamFormat == OMX_AUDIO_AACStreamFormatMP4FF) {
261                mIsADTS = false;
262            } else if (aacParams->eAACStreamFormat
263                        == OMX_AUDIO_AACStreamFormatMP4ADTS) {
264                mIsADTS = true;
265            } else {
266                return OMX_ErrorUndefined;
267            }
268
269            return OMX_ErrorNone;
270        }
271
272        case OMX_IndexParamAudioPcm:
273        {
274            const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
275                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
276
277            if (pcmParams->nPortIndex != 1) {
278                return OMX_ErrorUndefined;
279            }
280
281            return OMX_ErrorNone;
282        }
283
284        default:
285            return SimpleSoftOMXComponent::internalSetParameter(index, params);
286    }
287}
288
289bool SoftAAC2::isConfigured() const {
290    return mInputBufferCount > 0;
291}
292
293void SoftAAC2::maybeConfigureDownmix() const {
294    if (mStreamInfo->numChannels > 2) {
295        char value[PROPERTY_VALUE_MAX];
296        if (!(property_get("media.aac_51_output_enabled", value, NULL) &&
297                (!strcmp(value, "1") || !strcasecmp(value, "true")))) {
298            ALOGI("Downmixing multichannel AAC to stereo");
299            aacDecoder_SetParam(mAACDecoder, AAC_PCM_OUTPUT_CHANNELS, 2);
300            mStreamInfo->numChannels = 2;
301        }
302    }
303}
304
305void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
306    if (mSignalledError || mOutputPortSettingsChange != NONE) {
307        return;
308    }
309
310    UCHAR* inBuffer[FILEREAD_MAX_LAYERS];
311    UINT inBufferLength[FILEREAD_MAX_LAYERS] = {0};
312    UINT bytesValid[FILEREAD_MAX_LAYERS] = {0};
313
314    List<BufferInfo *> &inQueue = getPortQueue(0);
315    List<BufferInfo *> &outQueue = getPortQueue(1);
316
317    if (portIndex == 0 && mInputBufferCount == 0) {
318        ++mInputBufferCount;
319        BufferInfo *info = *inQueue.begin();
320        OMX_BUFFERHEADERTYPE *header = info->mHeader;
321
322        inBuffer[0] = header->pBuffer + header->nOffset;
323        inBufferLength[0] = header->nFilledLen;
324
325        AAC_DECODER_ERROR decoderErr =
326            aacDecoder_ConfigRaw(mAACDecoder,
327                                 inBuffer,
328                                 inBufferLength);
329
330        if (decoderErr != AAC_DEC_OK) {
331            mSignalledError = true;
332            notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
333            return;
334        }
335
336        inQueue.erase(inQueue.begin());
337        info->mOwnedByUs = false;
338        notifyEmptyBufferDone(header);
339
340        // Only send out port settings changed event if both sample rate
341        // and numChannels are valid.
342        if (mStreamInfo->sampleRate && mStreamInfo->numChannels) {
343            maybeConfigureDownmix();
344            ALOGI("Initially configuring decoder: %d Hz, %d channels",
345                mStreamInfo->sampleRate,
346                mStreamInfo->numChannels);
347
348            notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
349            mOutputPortSettingsChange = AWAITING_DISABLED;
350        }
351
352        return;
353    }
354
355    while ((!inQueue.empty() || (mSawInputEos && !mSignalledOutputEos)) && !outQueue.empty()) {
356        BufferInfo *inInfo = NULL;
357        OMX_BUFFERHEADERTYPE *inHeader = NULL;
358        if (!inQueue.empty()) {
359            inInfo = *inQueue.begin();
360            inHeader = inInfo->mHeader;
361        }
362
363        BufferInfo *outInfo = *outQueue.begin();
364        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
365        outHeader->nFlags = 0;
366
367        if (inHeader) {
368            if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
369                mSawInputEos = true;
370            }
371
372            if (inHeader->nOffset == 0 && inHeader->nFilledLen) {
373                mAnchorTimeUs = inHeader->nTimeStamp;
374                mNumSamplesOutput = 0;
375            }
376
377            if (mIsADTS) {
378                size_t adtsHeaderSize = 0;
379                // skip 30 bits, aac_frame_length follows.
380                // ssssssss ssssiiip ppffffPc ccohCCll llllllll lll?????
381
382                const uint8_t *adtsHeader = inHeader->pBuffer + inHeader->nOffset;
383
384                bool signalError = false;
385                if (inHeader->nFilledLen < 7) {
386                    ALOGE("Audio data too short to contain even the ADTS header. "
387                          "Got %d bytes.", inHeader->nFilledLen);
388                    hexdump(adtsHeader, inHeader->nFilledLen);
389                    signalError = true;
390                } else {
391                    bool protectionAbsent = (adtsHeader[1] & 1);
392
393                    unsigned aac_frame_length =
394                        ((adtsHeader[3] & 3) << 11)
395                        | (adtsHeader[4] << 3)
396                        | (adtsHeader[5] >> 5);
397
398                    if (inHeader->nFilledLen < aac_frame_length) {
399                        ALOGE("Not enough audio data for the complete frame. "
400                              "Got %d bytes, frame size according to the ADTS "
401                              "header is %u bytes.",
402                              inHeader->nFilledLen, aac_frame_length);
403                        hexdump(adtsHeader, inHeader->nFilledLen);
404                        signalError = true;
405                    } else {
406                        adtsHeaderSize = (protectionAbsent ? 7 : 9);
407
408                        inBuffer[0] = (UCHAR *)adtsHeader + adtsHeaderSize;
409                        inBufferLength[0] = aac_frame_length - adtsHeaderSize;
410
411                        inHeader->nOffset += adtsHeaderSize;
412                        inHeader->nFilledLen -= adtsHeaderSize;
413                    }
414                }
415
416                if (signalError) {
417                    mSignalledError = true;
418
419                    notify(OMX_EventError,
420                           OMX_ErrorStreamCorrupt,
421                           ERROR_MALFORMED,
422                           NULL);
423
424                    return;
425                }
426            } else {
427                inBuffer[0] = inHeader->pBuffer + inHeader->nOffset;
428                inBufferLength[0] = inHeader->nFilledLen;
429            }
430        } else {
431            inBufferLength[0] = 0;
432        }
433
434        // Fill and decode
435        INT_PCM *outBuffer = reinterpret_cast<INT_PCM *>(
436                outHeader->pBuffer + outHeader->nOffset);
437
438        bytesValid[0] = inBufferLength[0];
439
440        int prevSampleRate = mStreamInfo->sampleRate;
441        int prevNumChannels = mStreamInfo->numChannels;
442
443        AAC_DECODER_ERROR decoderErr = AAC_DEC_NOT_ENOUGH_BITS;
444        while ((bytesValid[0] > 0 || mSawInputEos) && decoderErr == AAC_DEC_NOT_ENOUGH_BITS) {
445            mDecoderHasData |= (bytesValid[0] > 0);
446            aacDecoder_Fill(mAACDecoder,
447                            inBuffer,
448                            inBufferLength,
449                            bytesValid);
450
451            decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
452                                                outBuffer,
453                                                outHeader->nAllocLen,
454                                                0 /* flags */);
455            if (decoderErr == AAC_DEC_NOT_ENOUGH_BITS) {
456                if (mSawInputEos && bytesValid[0] <= 0) {
457                    if (mDecoderHasData) {
458                        // flush out the decoder's delayed data by calling DecodeFrame
459                        // one more time, with the AACDEC_FLUSH flag set
460                        decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
461                                                            outBuffer,
462                                                            outHeader->nAllocLen,
463                                                            AACDEC_FLUSH);
464                        mDecoderHasData = false;
465                    }
466                    outHeader->nFlags = OMX_BUFFERFLAG_EOS;
467                    mSignalledOutputEos = true;
468                    break;
469                } else {
470                    ALOGW("Not enough bits, bytesValid %d", bytesValid[0]);
471                }
472            }
473        }
474
475        size_t numOutBytes =
476            mStreamInfo->frameSize * sizeof(int16_t) * mStreamInfo->numChannels;
477
478        if (inHeader) {
479            if (decoderErr == AAC_DEC_OK) {
480                UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0];
481                inHeader->nFilledLen -= inBufferUsedLength;
482                inHeader->nOffset += inBufferUsedLength;
483            } else {
484                ALOGW("AAC decoder returned error %d, substituting silence",
485                      decoderErr);
486
487                memset(outHeader->pBuffer + outHeader->nOffset, 0, numOutBytes);
488
489                // Discard input buffer.
490                inHeader->nFilledLen = 0;
491
492                aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1);
493
494                // fall through
495            }
496
497            if (inHeader->nFilledLen == 0) {
498                inInfo->mOwnedByUs = false;
499                inQueue.erase(inQueue.begin());
500                inInfo = NULL;
501                notifyEmptyBufferDone(inHeader);
502                inHeader = NULL;
503            }
504        }
505
506        /*
507         * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
508         * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
509         * rate system and the sampling rate in the final output is actually
510         * doubled compared with the core AAC decoder sampling rate.
511         *
512         * Explicit signalling is done by explicitly defining SBR audio object
513         * type in the bitstream. Implicit signalling is done by embedding
514         * SBR content in AAC extension payload specific to SBR, and hence
515         * requires an AAC decoder to perform pre-checks on actual audio frames.
516         *
517         * Thus, we could not say for sure whether a stream is
518         * AAC+/eAAC+ until the first data frame is decoded.
519         */
520        if (mInputBufferCount <= 2) {
521            if (mStreamInfo->sampleRate != prevSampleRate ||
522                mStreamInfo->numChannels != prevNumChannels) {
523                maybeConfigureDownmix();
524                ALOGI("Reconfiguring decoder: %d->%d Hz, %d->%d channels",
525                      prevSampleRate, mStreamInfo->sampleRate,
526                      prevNumChannels, mStreamInfo->numChannels);
527
528                notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
529                mOutputPortSettingsChange = AWAITING_DISABLED;
530                return;
531            }
532        } else if (!mStreamInfo->sampleRate || !mStreamInfo->numChannels) {
533            ALOGW("Invalid AAC stream");
534            mSignalledError = true;
535            notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
536            return;
537        }
538
539        if (decoderErr == AAC_DEC_OK || mNumSamplesOutput > 0) {
540            // We'll only output data if we successfully decoded it or
541            // we've previously decoded valid data, in the latter case
542            // (decode failed) we'll output a silent frame.
543            outHeader->nFilledLen = numOutBytes;
544
545            outHeader->nTimeStamp =
546                mAnchorTimeUs
547                    + (mNumSamplesOutput * 1000000ll) / mStreamInfo->sampleRate;
548
549            mNumSamplesOutput += mStreamInfo->frameSize;
550
551            outInfo->mOwnedByUs = false;
552            outQueue.erase(outQueue.begin());
553            outInfo = NULL;
554            notifyFillBufferDone(outHeader);
555            outHeader = NULL;
556        }
557
558        if (decoderErr == AAC_DEC_OK) {
559            ++mInputBufferCount;
560        }
561    }
562}
563
564void SoftAAC2::onPortFlushCompleted(OMX_U32 portIndex) {
565    if (portIndex == 0) {
566        // Make sure that the next buffer output does not still
567        // depend on fragments from the last one decoded.
568        // drain all existing data
569        drainDecoder();
570        // force decoder loop to drop the first decoded buffer by resetting these state variables,
571        // but only if initialization has already happened.
572        if (mInputBufferCount != 0) {
573            mInputBufferCount = 1;
574            mStreamInfo->sampleRate = 0;
575        }
576    }
577}
578
579void SoftAAC2::drainDecoder() {
580    // a buffer big enough for 6 channels of decoded HE-AAC
581    short buf [2048*6];
582    aacDecoder_DecodeFrame(mAACDecoder,
583            buf, sizeof(buf), AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR);
584    aacDecoder_DecodeFrame(mAACDecoder,
585            buf, sizeof(buf), AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR);
586    aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1);
587    mDecoderHasData = false;
588}
589
590void SoftAAC2::onReset() {
591    drainDecoder();
592    // reset the "configured" state
593    mInputBufferCount = 0;
594    mNumSamplesOutput = 0;
595    // To make the codec behave the same before and after a reset, we need to invalidate the
596    // streaminfo struct. This does that:
597    mStreamInfo->sampleRate = 0;
598
599    mSignalledError = false;
600    mSawInputEos = false;
601    mSignalledOutputEos = false;
602    mOutputPortSettingsChange = NONE;
603}
604
605void SoftAAC2::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
606    if (portIndex != 1) {
607        return;
608    }
609
610    switch (mOutputPortSettingsChange) {
611        case NONE:
612            break;
613
614        case AWAITING_DISABLED:
615        {
616            CHECK(!enabled);
617            mOutputPortSettingsChange = AWAITING_ENABLED;
618            break;
619        }
620
621        default:
622        {
623            CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
624            CHECK(enabled);
625            mOutputPortSettingsChange = NONE;
626            break;
627        }
628    }
629}
630
631}  // namespace android
632
633android::SoftOMXComponent *createSoftOMXComponent(
634        const char *name, const OMX_CALLBACKTYPE *callbacks,
635        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
636    return new android::SoftAAC2(name, callbacks, appData, component);
637}
638