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