SoftAAC2.cpp revision 347f35436be724a64272c41e6325f03fe6b9d43a
1b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke/*
2b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke * Copyright (C) 2012 The Android Open Source Project
3b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke *
4b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke * Licensed under the Apache License, Version 2.0 (the "License");
5b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke * you may not use this file except in compliance with the License.
6b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke * You may obtain a copy of the License at
7b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke *
8b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke *      http://www.apache.org/licenses/LICENSE-2.0
9b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke *
10b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke * Unless required by applicable law or agreed to in writing, software
11b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke * distributed under the License is distributed on an "AS IS" BASIS,
12b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke * See the License for the specific language governing permissions and
14b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke * limitations under the License.
15b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke */
16b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
17b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke#define LOG_TAG "SoftAAC2"
184213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi//#define LOG_NDEBUG 0
19b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke#include <utils/Log.h>
20b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
21b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke#include "SoftAAC2.h"
22b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
231adacd921319ec52fac1a4596ab6eaf8689e6a7dDave Burke#include <cutils/properties.h>
24b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke#include <media/stagefright/foundation/ADebug.h>
25b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke#include <media/stagefright/foundation/hexdump.h>
268370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber#include <media/stagefright/MediaErrors.h>
27b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
28b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke#define FILEREAD_MAX_LAYERS 2
29b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
30347f35436be724a64272c41e6325f03fe6b9d43aJean-Michel Trivi#define DRC_DEFAULT_MOBILE_REF_LEVEL 64  /* 64*-0.25dB = -16 dB below full scale for mobile conf */
314213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi#define DRC_DEFAULT_MOBILE_DRC_CUT   127 /* maximum compression of dynamic range for mobile conf */
324213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi#define MAX_CHANNEL_COUNT            6  /* maximum number of audio channels that can be decoded */
334213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi// names of properties that can be used to override the default DRC settings
344213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi#define PROP_DRC_OVERRIDE_REF_LEVEL  "aac_drc_reference_level"
354213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi#define PROP_DRC_OVERRIDE_CUT        "aac_drc_cut"
364213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi#define PROP_DRC_OVERRIDE_BOOST      "aac_drc_boost"
375696a4efef79ee474ac6bcf2639c741e159bed1bJean-Michel Trivi
38b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burkenamespace android {
39b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
40b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burketemplate<class T>
41b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burkestatic void InitOMXParams(T *params) {
42b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    params->nSize = sizeof(T);
43b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    params->nVersion.s.nVersionMajor = 1;
44b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    params->nVersion.s.nVersionMinor = 0;
45b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    params->nVersion.s.nRevision = 0;
46b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    params->nVersion.s.nStep = 0;
47b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke}
48b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
49b7ddcc9460f488f0b032aeb27b52a423318a97eaDave BurkeSoftAAC2::SoftAAC2(
50b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        const char *name,
51b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        const OMX_CALLBACKTYPE *callbacks,
52b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        OMX_PTR appData,
53b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        OMX_COMPONENTTYPE **component)
54b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    : SimpleSoftOMXComponent(name, callbacks, appData, component),
55b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke      mAACDecoder(NULL),
56b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke      mStreamInfo(NULL),
57b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke      mIsADTS(false),
58b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke      mInputBufferCount(0),
59b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke      mSignalledError(false),
60b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke      mAnchorTimeUs(0),
61b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke      mNumSamplesOutput(0),
62b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke      mOutputPortSettingsChange(NONE) {
63b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    initPorts();
64b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    CHECK_EQ(initDecoder(), (status_t)OK);
65b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke}
66b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
67b7ddcc9460f488f0b032aeb27b52a423318a97eaDave BurkeSoftAAC2::~SoftAAC2() {
68b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    aacDecoder_Close(mAACDecoder);
69b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke}
70b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
71b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burkevoid SoftAAC2::initPorts() {
72b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    OMX_PARAM_PORTDEFINITIONTYPE def;
73b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    InitOMXParams(&def);
74b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
75b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.nPortIndex = 0;
76b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.eDir = OMX_DirInput;
77eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber    def.nBufferCountMin = kNumInputBuffers;
78b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.nBufferCountActual = def.nBufferCountMin;
79b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.nBufferSize = 8192;
80b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.bEnabled = OMX_TRUE;
81b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.bPopulated = OMX_FALSE;
82b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.eDomain = OMX_PortDomainAudio;
83b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.bBuffersContiguous = OMX_FALSE;
84b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.nBufferAlignment = 1;
85b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
86b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.format.audio.cMIMEType = const_cast<char *>("audio/aac");
87b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.format.audio.pNativeRender = NULL;
88b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
89b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
90b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
91b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    addPort(def);
92b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
93b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.nPortIndex = 1;
94b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.eDir = OMX_DirOutput;
95eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber    def.nBufferCountMin = kNumOutputBuffers;
96b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.nBufferCountActual = def.nBufferCountMin;
97888f63bcde37347061de1aabb1b7febb2eca0875Jean-Michel Trivi    def.nBufferSize = 4096 * MAX_CHANNEL_COUNT;
98b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.bEnabled = OMX_TRUE;
99b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.bPopulated = OMX_FALSE;
100b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.eDomain = OMX_PortDomainAudio;
101b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.bBuffersContiguous = OMX_FALSE;
102b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.nBufferAlignment = 2;
103b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
104b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
105b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.format.audio.pNativeRender = NULL;
106b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
107b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
108b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
109b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    addPort(def);
110b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke}
111b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
112b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burkestatus_t SoftAAC2::initDecoder() {
113b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    status_t status = UNKNOWN_ERROR;
114e672a0eea2cdc2ed43e002f0583902f20705de57Andreas Huber    mAACDecoder = aacDecoder_Open(TT_MP4_ADIF, /* num layers */ 1);
115b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    if (mAACDecoder != NULL) {
116b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        mStreamInfo = aacDecoder_GetStreamInfo(mAACDecoder);
117b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        if (mStreamInfo != NULL) {
118b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            status = OK;
119b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        }
120b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    }
12141914becfd019c619783d875c61ef71db0e67400Marco Nelissen    mIsFirst = true;
1224213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi
1234213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi    // for streams that contain metadata, use the mobile profile DRC settings unless overridden
1244213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi    // by platform properties:
1254213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi    char value[PROPERTY_VALUE_MAX];
1264213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi    //  * AAC_DRC_REFERENCE_LEVEL
1274213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi    if (property_get(PROP_DRC_OVERRIDE_REF_LEVEL, value, NULL)) {
1284213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi        unsigned refLevel = atoi(value);
1294213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi        ALOGV("AAC decoder using AAC_DRC_REFERENCE_LEVEL of %d instead of %d",
1304213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi                refLevel, DRC_DEFAULT_MOBILE_REF_LEVEL);
1314213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi        aacDecoder_SetParam(mAACDecoder, AAC_DRC_REFERENCE_LEVEL, refLevel);
1324213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi    } else {
1334213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi        aacDecoder_SetParam(mAACDecoder, AAC_DRC_REFERENCE_LEVEL, DRC_DEFAULT_MOBILE_REF_LEVEL);
1344213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi    }
1354213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi    //  * AAC_DRC_ATTENUATION_FACTOR
1364213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi    if (property_get(PROP_DRC_OVERRIDE_CUT, value, NULL)) {
1374213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi        unsigned cut = atoi(value);
1384213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi        ALOGV("AAC decoder using AAC_DRC_ATTENUATION_FACTOR of %d instead of %d",
1394213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi                        cut, DRC_DEFAULT_MOBILE_DRC_CUT);
1404213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi        aacDecoder_SetParam(mAACDecoder, AAC_DRC_ATTENUATION_FACTOR, cut);
1414213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi    } else {
1424213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi        aacDecoder_SetParam(mAACDecoder, AAC_DRC_ATTENUATION_FACTOR, DRC_DEFAULT_MOBILE_DRC_CUT);
1434213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi    }
1444213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi    //  * AAC_DRC_BOOST_FACTOR (note: no default, using cut)
1454213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi    if (property_get(PROP_DRC_OVERRIDE_BOOST, value, NULL)) {
1464213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi        unsigned boost = atoi(value);
1474213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi        ALOGV("AAC decoder using AAC_DRC_BOOST_FACTOR of %d", boost);
1484213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi        aacDecoder_SetParam(mAACDecoder, AAC_DRC_BOOST_FACTOR, boost);
1494213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi    }
1504213e9db1cc57ab593bb63432b4e0cf477c3f835Jean-Michel Trivi
151b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    return status;
152b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke}
153b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
154b7ddcc9460f488f0b032aeb27b52a423318a97eaDave BurkeOMX_ERRORTYPE SoftAAC2::internalGetParameter(
155b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        OMX_INDEXTYPE index, OMX_PTR params) {
156b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    switch (index) {
157b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        case OMX_IndexParamAudioAac:
158b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        {
159b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
160b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
161b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
162b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            if (aacParams->nPortIndex != 0) {
163b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                return OMX_ErrorUndefined;
164b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            }
165b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
166b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            aacParams->nBitRate = 0;
167b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            aacParams->nAudioBandWidth = 0;
168b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            aacParams->nAACtools = 0;
169b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            aacParams->nAACERtools = 0;
170b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            aacParams->eAACProfile = OMX_AUDIO_AACObjectMain;
171b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
172b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            aacParams->eAACStreamFormat =
173b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                mIsADTS
174b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                    ? OMX_AUDIO_AACStreamFormatMP4ADTS
175b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                    : OMX_AUDIO_AACStreamFormatMP4FF;
176b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
177b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            aacParams->eChannelMode = OMX_AUDIO_ChannelModeStereo;
178b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
179bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke            if (!isConfigured()) {
180b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                aacParams->nChannels = 1;
181b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                aacParams->nSampleRate = 44100;
182b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                aacParams->nFrameLength = 0;
183b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            } else {
184f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke                aacParams->nChannels = mStreamInfo->numChannels;
185f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke                aacParams->nSampleRate = mStreamInfo->sampleRate;
186f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke                aacParams->nFrameLength = mStreamInfo->frameSize;
187b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            }
188b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
189b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            return OMX_ErrorNone;
190b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        }
191b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
192b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        case OMX_IndexParamAudioPcm:
193b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        {
194b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
195b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
196b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
197b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            if (pcmParams->nPortIndex != 1) {
198b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                return OMX_ErrorUndefined;
199b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            }
200b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
201b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            pcmParams->eNumData = OMX_NumericalDataSigned;
202b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            pcmParams->eEndian = OMX_EndianBig;
203b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            pcmParams->bInterleaved = OMX_TRUE;
204b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            pcmParams->nBitPerSample = 16;
205b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
206b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
207b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
208095c2da8d6c2058b02142c940f6e6346d6581780Dave Burke            pcmParams->eChannelMapping[2] = OMX_AUDIO_ChannelCF;
209095c2da8d6c2058b02142c940f6e6346d6581780Dave Burke            pcmParams->eChannelMapping[3] = OMX_AUDIO_ChannelLFE;
210095c2da8d6c2058b02142c940f6e6346d6581780Dave Burke            pcmParams->eChannelMapping[4] = OMX_AUDIO_ChannelLS;
211095c2da8d6c2058b02142c940f6e6346d6581780Dave Burke            pcmParams->eChannelMapping[5] = OMX_AUDIO_ChannelRS;
212b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
213bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke            if (!isConfigured()) {
214b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                pcmParams->nChannels = 1;
215b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                pcmParams->nSamplingRate = 44100;
216b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            } else {
217f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke                pcmParams->nChannels = mStreamInfo->numChannels;
218b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                pcmParams->nSamplingRate = mStreamInfo->sampleRate;
219b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            }
220b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
221b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            return OMX_ErrorNone;
222b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        }
223b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
224b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        default:
225b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            return SimpleSoftOMXComponent::internalGetParameter(index, params);
226b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    }
227b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke}
228b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
229b7ddcc9460f488f0b032aeb27b52a423318a97eaDave BurkeOMX_ERRORTYPE SoftAAC2::internalSetParameter(
230b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        OMX_INDEXTYPE index, const OMX_PTR params) {
231b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    switch (index) {
232b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        case OMX_IndexParamStandardComponentRole:
233b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        {
234b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
235b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                (const OMX_PARAM_COMPONENTROLETYPE *)params;
236b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
237b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            if (strncmp((const char *)roleParams->cRole,
238b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                        "audio_decoder.aac",
239b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                        OMX_MAX_STRINGNAME_SIZE - 1)) {
240b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                return OMX_ErrorUndefined;
241b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            }
242b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
243b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            return OMX_ErrorNone;
244b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        }
245b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
246b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        case OMX_IndexParamAudioAac:
247b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        {
248b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            const OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
249b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                (const OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
250b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
251b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            if (aacParams->nPortIndex != 0) {
252b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                return OMX_ErrorUndefined;
253b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            }
254b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
255b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            if (aacParams->eAACStreamFormat == OMX_AUDIO_AACStreamFormatMP4FF) {
256b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                mIsADTS = false;
257b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            } else if (aacParams->eAACStreamFormat
258b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                        == OMX_AUDIO_AACStreamFormatMP4ADTS) {
259b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                mIsADTS = true;
260b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            } else {
261b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                return OMX_ErrorUndefined;
262b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            }
263b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
264b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            return OMX_ErrorNone;
265b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        }
266b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
267b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        case OMX_IndexParamAudioPcm:
268b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        {
269b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
270b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
271b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
272b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            if (pcmParams->nPortIndex != 1) {
273b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                return OMX_ErrorUndefined;
274b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            }
275b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
276b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            return OMX_ErrorNone;
277b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        }
278b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
279b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        default:
280b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            return SimpleSoftOMXComponent::internalSetParameter(index, params);
281b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    }
282b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke}
283b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
284b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burkebool SoftAAC2::isConfigured() const {
285b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    return mInputBufferCount > 0;
286b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke}
287b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
2881adacd921319ec52fac1a4596ab6eaf8689e6a7dDave Burkevoid SoftAAC2::maybeConfigureDownmix() const {
2891adacd921319ec52fac1a4596ab6eaf8689e6a7dDave Burke    if (mStreamInfo->numChannels > 2) {
2901adacd921319ec52fac1a4596ab6eaf8689e6a7dDave Burke        char value[PROPERTY_VALUE_MAX];
2911adacd921319ec52fac1a4596ab6eaf8689e6a7dDave Burke        if (!(property_get("media.aac_51_output_enabled", value, NULL) &&
2921adacd921319ec52fac1a4596ab6eaf8689e6a7dDave Burke                (!strcmp(value, "1") || !strcasecmp(value, "true")))) {
2931adacd921319ec52fac1a4596ab6eaf8689e6a7dDave Burke            ALOGI("Downmixing multichannel AAC to stereo");
2941adacd921319ec52fac1a4596ab6eaf8689e6a7dDave Burke            aacDecoder_SetParam(mAACDecoder, AAC_PCM_OUTPUT_CHANNELS, 2);
2951adacd921319ec52fac1a4596ab6eaf8689e6a7dDave Burke            mStreamInfo->numChannels = 2;
2961adacd921319ec52fac1a4596ab6eaf8689e6a7dDave Burke        }
2971adacd921319ec52fac1a4596ab6eaf8689e6a7dDave Burke    }
2981adacd921319ec52fac1a4596ab6eaf8689e6a7dDave Burke}
2991adacd921319ec52fac1a4596ab6eaf8689e6a7dDave Burke
300b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burkevoid SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
301b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    if (mSignalledError || mOutputPortSettingsChange != NONE) {
302b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        return;
303b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    }
304b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
305b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    UCHAR* inBuffer[FILEREAD_MAX_LAYERS];
306b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    UINT inBufferLength[FILEREAD_MAX_LAYERS] = {0};
307b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    UINT bytesValid[FILEREAD_MAX_LAYERS] = {0};
308b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
309b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    List<BufferInfo *> &inQueue = getPortQueue(0);
310b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    List<BufferInfo *> &outQueue = getPortQueue(1);
311b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
312b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    if (portIndex == 0 && mInputBufferCount == 0) {
313b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        ++mInputBufferCount;
314b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        BufferInfo *info = *inQueue.begin();
315b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        OMX_BUFFERHEADERTYPE *header = info->mHeader;
316b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
317b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        inBuffer[0] = header->pBuffer + header->nOffset;
318b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        inBufferLength[0] = header->nFilledLen;
319b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
320b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        AAC_DECODER_ERROR decoderErr =
321b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            aacDecoder_ConfigRaw(mAACDecoder,
322b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                                 inBuffer,
323b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                                 inBufferLength);
324b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
325b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        if (decoderErr != AAC_DEC_OK) {
326b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            mSignalledError = true;
327b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
328b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            return;
329b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        }
330b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        inQueue.erase(inQueue.begin());
331b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        info->mOwnedByUs = false;
332b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        notifyEmptyBufferDone(header);
333b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
334cc9833b5db0e96f12daddb90a747fd146627377dJames Dong        // Only send out port settings changed event if both sample rate
335cc9833b5db0e96f12daddb90a747fd146627377dJames Dong        // and numChannels are valid.
336cc9833b5db0e96f12daddb90a747fd146627377dJames Dong        if (mStreamInfo->sampleRate && mStreamInfo->numChannels) {
337cc9833b5db0e96f12daddb90a747fd146627377dJames Dong            maybeConfigureDownmix();
338cc9833b5db0e96f12daddb90a747fd146627377dJames Dong            ALOGI("Initially configuring decoder: %d Hz, %d channels",
339cc9833b5db0e96f12daddb90a747fd146627377dJames Dong                mStreamInfo->sampleRate,
340cc9833b5db0e96f12daddb90a747fd146627377dJames Dong                mStreamInfo->numChannels);
341cc9833b5db0e96f12daddb90a747fd146627377dJames Dong
342cc9833b5db0e96f12daddb90a747fd146627377dJames Dong            notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
343cc9833b5db0e96f12daddb90a747fd146627377dJames Dong            mOutputPortSettingsChange = AWAITING_DISABLED;
344cc9833b5db0e96f12daddb90a747fd146627377dJames Dong        }
345cc9833b5db0e96f12daddb90a747fd146627377dJames Dong
346b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        return;
347b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    }
348b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
349b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    while (!inQueue.empty() && !outQueue.empty()) {
350b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        BufferInfo *inInfo = *inQueue.begin();
351b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
352b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
353b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        BufferInfo *outInfo = *outQueue.begin();
354b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
355b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
356b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
357b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            inQueue.erase(inQueue.begin());
358b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            inInfo->mOwnedByUs = false;
359b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            notifyEmptyBufferDone(inHeader);
360b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
36151d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber            if (!mIsFirst) {
36251d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                // flush out the decoder's delayed data by calling DecodeFrame
36351d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                // one more time, with the AACDEC_FLUSH flag set
36451d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                INT_PCM *outBuffer =
36551d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                        reinterpret_cast<INT_PCM *>(
36651d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                                outHeader->pBuffer + outHeader->nOffset);
36751d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber
36851d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                AAC_DECODER_ERROR decoderErr =
36951d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                    aacDecoder_DecodeFrame(mAACDecoder,
37051d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                                           outBuffer,
37151d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                                           outHeader->nAllocLen,
37251d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                                           AACDEC_FLUSH);
37351d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber
37451d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                if (decoderErr != AAC_DEC_OK) {
37551d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                    mSignalledError = true;
37651d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber
37751d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                    notify(OMX_EventError, OMX_ErrorUndefined, decoderErr,
37851d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                           NULL);
37951d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber
38051d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                    return;
38151d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                }
38251d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber
38351d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                outHeader->nFilledLen =
38451d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                        mStreamInfo->frameSize
38551d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                            * sizeof(int16_t)
38651d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                            * mStreamInfo->numChannels;
38751d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber            } else {
38851d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                // Since we never discarded frames from the start, we won't have
38951d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                // to add any padding at the end either.
39051d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber
39151d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                outHeader->nFilledLen = 0;
392f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke            }
393f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke
394b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
395b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
396b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            outQueue.erase(outQueue.begin());
397b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            outInfo->mOwnedByUs = false;
398b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            notifyFillBufferDone(outHeader);
399b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            return;
400b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        }
401b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
402b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        if (inHeader->nOffset == 0) {
403b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            mAnchorTimeUs = inHeader->nTimeStamp;
404b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            mNumSamplesOutput = 0;
405b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        }
406b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
4076b7b8227cc8753fde4094ca8af2d381c2740826fAndreas Huber        size_t adtsHeaderSize = 0;
408b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        if (mIsADTS) {
409b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            // skip 30 bits, aac_frame_length follows.
410b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            // ssssssss ssssiiip ppffffPc ccohCCll llllllll lll?????
411b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
412b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            const uint8_t *adtsHeader = inHeader->pBuffer + inHeader->nOffset;
413b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
4148370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber            bool signalError = false;
4158370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber            if (inHeader->nFilledLen < 7) {
4168370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                ALOGE("Audio data too short to contain even the ADTS header. "
4178370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                      "Got %ld bytes.", inHeader->nFilledLen);
4188370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                hexdump(adtsHeader, inHeader->nFilledLen);
4198370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                signalError = true;
4208370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber            } else {
4218370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                bool protectionAbsent = (adtsHeader[1] & 1);
4228370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber
4238370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                unsigned aac_frame_length =
4248370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                    ((adtsHeader[3] & 3) << 11)
4258370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                    | (adtsHeader[4] << 3)
4268370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                    | (adtsHeader[5] >> 5);
4278370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber
4288370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                if (inHeader->nFilledLen < aac_frame_length) {
4298370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                    ALOGE("Not enough audio data for the complete frame. "
4308370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                          "Got %ld bytes, frame size according to the ADTS "
4318370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                          "header is %u bytes.",
4328370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                          inHeader->nFilledLen, aac_frame_length);
4338370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                    hexdump(adtsHeader, inHeader->nFilledLen);
4348370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                    signalError = true;
4358370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                } else {
4368370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                    adtsHeaderSize = (protectionAbsent ? 7 : 9);
4378370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber
4388370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                    inBuffer[0] = (UCHAR *)adtsHeader + adtsHeaderSize;
4398370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                    inBufferLength[0] = aac_frame_length - adtsHeaderSize;
4408370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber
4418370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                    inHeader->nOffset += adtsHeaderSize;
4428370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                    inHeader->nFilledLen -= adtsHeaderSize;
4438370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber                }
444e35ac2860e99d809a2ccca59bd4eb2f8c02d15adAndreas Huber            }
4458370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber
446e35ac2860e99d809a2ccca59bd4eb2f8c02d15adAndreas Huber            if (signalError) {
447e35ac2860e99d809a2ccca59bd4eb2f8c02d15adAndreas Huber                mSignalledError = true;
4488370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber
449e35ac2860e99d809a2ccca59bd4eb2f8c02d15adAndreas Huber                notify(OMX_EventError,
450e35ac2860e99d809a2ccca59bd4eb2f8c02d15adAndreas Huber                       OMX_ErrorStreamCorrupt,
451e35ac2860e99d809a2ccca59bd4eb2f8c02d15adAndreas Huber                       ERROR_MALFORMED,
452e35ac2860e99d809a2ccca59bd4eb2f8c02d15adAndreas Huber                       NULL);
4538370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber
454e35ac2860e99d809a2ccca59bd4eb2f8c02d15adAndreas Huber                return;
4558370c7ad4136ad7e0787d5a91ccfa3d63cfbe5ccAndreas Huber            }
456b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        } else {
457b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            inBuffer[0] = inHeader->pBuffer + inHeader->nOffset;
458b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            inBufferLength[0] = inHeader->nFilledLen;
459b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        }
460b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
461b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        // Fill and decode
46251d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber        INT_PCM *outBuffer = reinterpret_cast<INT_PCM *>(
46351d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                outHeader->pBuffer + outHeader->nOffset);
46451d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber
465b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        bytesValid[0] = inBufferLength[0];
466b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
467b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        int prevSampleRate = mStreamInfo->sampleRate;
468f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke        int prevNumChannels = mStreamInfo->numChannels;
4696b7b8227cc8753fde4094ca8af2d381c2740826fAndreas Huber
470f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke        AAC_DECODER_ERROR decoderErr = AAC_DEC_NOT_ENOUGH_BITS;
471f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke        while (bytesValid[0] > 0 && decoderErr == AAC_DEC_NOT_ENOUGH_BITS) {
472f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke            aacDecoder_Fill(mAACDecoder,
473f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke                            inBuffer,
474f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke                            inBufferLength,
475f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke                            bytesValid);
4766b7b8227cc8753fde4094ca8af2d381c2740826fAndreas Huber
477f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke            decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
478f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke                                                outBuffer,
479f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke                                                outHeader->nAllocLen,
4803748b71a7fe73b0365a93f1fd28ced14219f85e5Dave Burke                                                0 /* flags */);
481f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke
482503775e4e2c3ead1cbd3c10561e3bdd90f2e70d5Dave Burke            if (decoderErr == AAC_DEC_NOT_ENOUGH_BITS) {
483503775e4e2c3ead1cbd3c10561e3bdd90f2e70d5Dave Burke                ALOGW("Not enough bits, bytesValid %d", bytesValid[0]);
484503775e4e2c3ead1cbd3c10561e3bdd90f2e70d5Dave Burke            }
485f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke        }
4863748b71a7fe73b0365a93f1fd28ced14219f85e5Dave Burke
487bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke        /*
488bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke         * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
489bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke         * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
490bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke         * rate system and the sampling rate in the final output is actually
491bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke         * doubled compared with the core AAC decoder sampling rate.
492bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke         *
493bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke         * Explicit signalling is done by explicitly defining SBR audio object
494bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke         * type in the bitstream. Implicit signalling is done by embedding
495bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke         * SBR content in AAC extension payload specific to SBR, and hence
496bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke         * requires an AAC decoder to perform pre-checks on actual audio frames.
497bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke         *
498bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke         * Thus, we could not say for sure whether a stream is
499bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke         * AAC+/eAAC+ until the first data frame is decoded.
500bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke         */
501bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke        if (mInputBufferCount <= 2) {
502bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke            if (mStreamInfo->sampleRate != prevSampleRate ||
503bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke                mStreamInfo->numChannels != prevNumChannels) {
5041adacd921319ec52fac1a4596ab6eaf8689e6a7dDave Burke                maybeConfigureDownmix();
505bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke                ALOGI("Reconfiguring decoder: %d Hz, %d channels",
506bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke                      mStreamInfo->sampleRate,
507bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke                      mStreamInfo->numChannels);
508bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke
509bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke                // We're going to want to revisit this input buffer, but
510bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke                // may have already advanced the offset. Undo that if
511bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke                // necessary.
512bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke                inHeader->nOffset -= adtsHeaderSize;
513bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke                inHeader->nFilledLen += adtsHeaderSize;
514bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke
515bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke                notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
516bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke                mOutputPortSettingsChange = AWAITING_DISABLED;
517bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke                return;
518bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke            }
519bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke        } else if (!mStreamInfo->sampleRate || !mStreamInfo->numChannels) {
520bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke            ALOGW("Invalid AAC stream");
521bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke            mSignalledError = true;
522bf2461ecc71c0aacf8c03fcdaf0dc46bc8285c7fDave Burke            notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
5233748b71a7fe73b0365a93f1fd28ced14219f85e5Dave Burke            return;
524b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        }
525b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
526b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        size_t numOutBytes =
527b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            mStreamInfo->frameSize * sizeof(int16_t) * mStreamInfo->numChannels;
528b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
529b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        if (decoderErr == AAC_DEC_OK) {
530b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0];
531b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            inHeader->nFilledLen -= inBufferUsedLength;
532b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            inHeader->nOffset += inBufferUsedLength;
533b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        } else {
534b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            ALOGW("AAC decoder returned error %d, substituting silence",
535b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                  decoderErr);
536b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
537b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            memset(outHeader->pBuffer + outHeader->nOffset, 0, numOutBytes);
538b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
539b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            // Discard input buffer.
540b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            inHeader->nFilledLen = 0;
541b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
542e672a0eea2cdc2ed43e002f0583902f20705de57Andreas Huber            aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1);
543e672a0eea2cdc2ed43e002f0583902f20705de57Andreas Huber
544b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            // fall through
545b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        }
546b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
547b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        if (decoderErr == AAC_DEC_OK || mNumSamplesOutput > 0) {
548b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            // We'll only output data if we successfully decoded it or
549b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            // we've previously decoded valid data, in the latter case
550b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            // (decode failed) we'll output a silent frame.
55141914becfd019c619783d875c61ef71db0e67400Marco Nelissen            if (mIsFirst) {
55241914becfd019c619783d875c61ef71db0e67400Marco Nelissen                mIsFirst = false;
55351d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                // the first decoded frame should be discarded to account
55451d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                // for decoder delay
55541914becfd019c619783d875c61ef71db0e67400Marco Nelissen                numOutBytes = 0;
55641914becfd019c619783d875c61ef71db0e67400Marco Nelissen            }
55741914becfd019c619783d875c61ef71db0e67400Marco Nelissen
558b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            outHeader->nFilledLen = numOutBytes;
559b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            outHeader->nFlags = 0;
560b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
561b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            outHeader->nTimeStamp =
562b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                mAnchorTimeUs
563b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke                    + (mNumSamplesOutput * 1000000ll) / mStreamInfo->sampleRate;
564b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
565b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            mNumSamplesOutput += mStreamInfo->frameSize;
566b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
567b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            outInfo->mOwnedByUs = false;
568b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            outQueue.erase(outQueue.begin());
569b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            outInfo = NULL;
570b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            notifyFillBufferDone(outHeader);
571b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            outHeader = NULL;
572b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        }
573b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
574b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        if (inHeader->nFilledLen == 0) {
575b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            inInfo->mOwnedByUs = false;
576b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            inQueue.erase(inQueue.begin());
577b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            inInfo = NULL;
578b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            notifyEmptyBufferDone(inHeader);
579b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            inHeader = NULL;
580b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        }
581b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
582b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        if (decoderErr == AAC_DEC_OK) {
583b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            ++mInputBufferCount;
584b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        }
585b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    }
586b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke}
587b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
588b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burkevoid SoftAAC2::onPortFlushCompleted(OMX_U32 portIndex) {
589b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    if (portIndex == 0) {
590b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        // Make sure that the next buffer output does not still
591b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        // depend on fragments from the last one decoded.
5923748b71a7fe73b0365a93f1fd28ced14219f85e5Dave Burke        aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1);
59341914becfd019c619783d875c61ef71db0e67400Marco Nelissen        mIsFirst = true;
594b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    }
595b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke}
596b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
597b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burkevoid SoftAAC2::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
598b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    if (portIndex != 1) {
599b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        return;
600b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    }
601b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
602b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    switch (mOutputPortSettingsChange) {
603b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        case NONE:
604b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            break;
605b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
606b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        case AWAITING_DISABLED:
607b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        {
608b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            CHECK(!enabled);
609b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            mOutputPortSettingsChange = AWAITING_ENABLED;
610b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            break;
611b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        }
612b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
613b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        default:
614b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        {
615b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
616b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            CHECK(enabled);
617b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            mOutputPortSettingsChange = NONE;
618b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke            break;
619b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        }
620b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    }
621b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke}
622b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
623b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke}  // namespace android
624b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke
625b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burkeandroid::SoftOMXComponent *createSoftOMXComponent(
626b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        const char *name, const OMX_CALLBACKTYPE *callbacks,
627b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
628b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke    return new android::SoftAAC2(name, callbacks, appData, component);
629b7ddcc9460f488f0b032aeb27b52a423318a97eaDave Burke}
630