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