SoftAACEncoder2.cpp revision f60c660f048d5f5e2458cff243c20400d73757a7
1aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke/*
2aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke * Copyright (C) 2012 The Android Open Source Project
3aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke *
4aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke * Licensed under the Apache License, Version 2.0 (the "License");
5aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke * you may not use this file except in compliance with the License.
6aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke * You may obtain a copy of the License at
7aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke *
8aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke *      http://www.apache.org/licenses/LICENSE-2.0
9aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke *
10aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke * Unless required by applicable law or agreed to in writing, software
11aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke * distributed under the License is distributed on an "AS IS" BASIS,
12aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke * See the License for the specific language governing permissions and
14aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke * limitations under the License.
15aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke */
16aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
17aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke//#define LOG_NDEBUG 0
18aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke#define LOG_TAG "SoftAACEncoder2"
19aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke#include <utils/Log.h>
20aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
21aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke#include "SoftAACEncoder2.h"
22aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
23aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke#include <media/stagefright/foundation/ADebug.h>
24aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke#include <media/stagefright/foundation/hexdump.h>
25aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
26aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burkenamespace android {
27aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
28aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burketemplate<class T>
29aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burkestatic void InitOMXParams(T *params) {
30aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    params->nSize = sizeof(T);
31aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    params->nVersion.s.nVersionMajor = 1;
32aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    params->nVersion.s.nVersionMinor = 0;
33aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    params->nVersion.s.nRevision = 0;
34aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    params->nVersion.s.nStep = 0;
35aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke}
36aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
37aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave BurkeSoftAACEncoder2::SoftAACEncoder2(
38aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        const char *name,
39aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        const OMX_CALLBACKTYPE *callbacks,
40aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        OMX_PTR appData,
41aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        OMX_COMPONENTTYPE **component)
42aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    : SimpleSoftOMXComponent(name, callbacks, appData, component),
43aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke      mAACEncoder(NULL),
44aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke      mNumChannels(1),
45aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke      mSampleRate(44100),
46aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke      mBitRate(0),
47aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke      mAACProfile(OMX_AUDIO_AACObjectLC),
48aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke      mSentCodecSpecificData(false),
49aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke      mInputSize(0),
50aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke      mInputFrame(NULL),
51aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke      mInputTimeUs(-1ll),
52aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke      mSawInputEOS(false),
53aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke      mSignalledError(false) {
54aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    initPorts();
55aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    CHECK_EQ(initEncoder(), (status_t)OK);
56aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    setAudioParams();
57aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke}
58aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
59aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave BurkeSoftAACEncoder2::~SoftAACEncoder2() {
60aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    aacEncClose(&mAACEncoder);
61aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
62aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    delete[] mInputFrame;
63aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    mInputFrame = NULL;
64aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke}
65aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
66aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burkevoid SoftAACEncoder2::initPorts() {
67aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    OMX_PARAM_PORTDEFINITIONTYPE def;
68aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    InitOMXParams(&def);
69aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
70aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.nPortIndex = 0;
71aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.eDir = OMX_DirInput;
72aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.nBufferCountMin = kNumBuffers;
73aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.nBufferCountActual = def.nBufferCountMin;
74aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t) * 2;
75aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.bEnabled = OMX_TRUE;
76aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.bPopulated = OMX_FALSE;
77aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.eDomain = OMX_PortDomainAudio;
78aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.bBuffersContiguous = OMX_FALSE;
79aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.nBufferAlignment = 1;
80aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
81aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
82aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.format.audio.pNativeRender = NULL;
83aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
84aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
85aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
86aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    addPort(def);
87aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
88aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.nPortIndex = 1;
89aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.eDir = OMX_DirOutput;
90aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.nBufferCountMin = kNumBuffers;
91aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.nBufferCountActual = def.nBufferCountMin;
92aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.nBufferSize = 8192;
93aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.bEnabled = OMX_TRUE;
94aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.bPopulated = OMX_FALSE;
95aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.eDomain = OMX_PortDomainAudio;
96aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.bBuffersContiguous = OMX_FALSE;
97aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.nBufferAlignment = 2;
98aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
99aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.format.audio.cMIMEType = const_cast<char *>("audio/aac");
100aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.format.audio.pNativeRender = NULL;
101aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
102aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
103aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
104aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    addPort(def);
105aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke}
106aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
107aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burkestatus_t SoftAACEncoder2::initEncoder() {
108aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    if (AACENC_OK != aacEncOpen(&mAACEncoder, 0, 0)) {
109aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        ALOGE("Failed to init AAC encoder");
110aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        return UNKNOWN_ERROR;
111aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    }
112aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    return OK;
113aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke}
114aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
115aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave BurkeOMX_ERRORTYPE SoftAACEncoder2::internalGetParameter(
116aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        OMX_INDEXTYPE index, OMX_PTR params) {
117aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    switch (index) {
118aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        case OMX_IndexParamAudioPortFormat:
119aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        {
120aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
121aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
122aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
123aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            if (formatParams->nPortIndex > 1) {
124aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                return OMX_ErrorUndefined;
125aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            }
126aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
127aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            if (formatParams->nIndex > 0) {
128aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                return OMX_ErrorNoMore;
129aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            }
130aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
131aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            formatParams->eEncoding =
132aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                (formatParams->nPortIndex == 0)
133aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                    ? OMX_AUDIO_CodingPCM : OMX_AUDIO_CodingAAC;
134aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
135aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            return OMX_ErrorNone;
136aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        }
137aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
138aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        case OMX_IndexParamAudioAac:
139aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        {
140aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
141aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
142aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
143aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            if (aacParams->nPortIndex != 1) {
144aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                return OMX_ErrorUndefined;
145aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            }
146aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
147aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            aacParams->nBitRate = mBitRate;
148aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            aacParams->nAudioBandWidth = 0;
149aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            aacParams->nAACtools = 0;
150aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            aacParams->nAACERtools = 0;
151aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            aacParams->eAACProfile = (OMX_AUDIO_AACPROFILETYPE) mAACProfile;
152aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            aacParams->eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
153aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            aacParams->eChannelMode = OMX_AUDIO_ChannelModeStereo;
154aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
155aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            aacParams->nChannels = mNumChannels;
156aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            aacParams->nSampleRate = mSampleRate;
157aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            aacParams->nFrameLength = 0;
158aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
159aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            return OMX_ErrorNone;
160aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        }
161aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
162aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        case OMX_IndexParamAudioPcm:
163aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        {
164aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
165aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
166aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
167aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            if (pcmParams->nPortIndex != 0) {
168aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                return OMX_ErrorUndefined;
169aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            }
170aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
171aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            pcmParams->eNumData = OMX_NumericalDataSigned;
172aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            pcmParams->eEndian = OMX_EndianBig;
173aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            pcmParams->bInterleaved = OMX_TRUE;
174aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            pcmParams->nBitPerSample = 16;
175aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
176aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
177aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
178aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
179aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            pcmParams->nChannels = mNumChannels;
180aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            pcmParams->nSamplingRate = mSampleRate;
181aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
182aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            return OMX_ErrorNone;
183aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        }
184aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
185aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        default:
186aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            return SimpleSoftOMXComponent::internalGetParameter(index, params);
187aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    }
188aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke}
189aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
190aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave BurkeOMX_ERRORTYPE SoftAACEncoder2::internalSetParameter(
191aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        OMX_INDEXTYPE index, const OMX_PTR params) {
192aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    switch (index) {
193aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        case OMX_IndexParamStandardComponentRole:
194aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        {
195aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
196aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                (const OMX_PARAM_COMPONENTROLETYPE *)params;
197aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
198aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            if (strncmp((const char *)roleParams->cRole,
199aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                        "audio_encoder.aac",
200aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                        OMX_MAX_STRINGNAME_SIZE - 1)) {
201aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                return OMX_ErrorUndefined;
202aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            }
203aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
204aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            return OMX_ErrorNone;
205aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        }
206aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
207aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        case OMX_IndexParamAudioPortFormat:
208aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        {
209aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
210aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
211aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
212aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            if (formatParams->nPortIndex > 1) {
213aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                return OMX_ErrorUndefined;
214aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            }
215aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
216aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            if (formatParams->nIndex > 0) {
217aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                return OMX_ErrorNoMore;
218aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            }
219aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
220aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            if ((formatParams->nPortIndex == 0
221aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                        && formatParams->eEncoding != OMX_AUDIO_CodingPCM)
222aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                || (formatParams->nPortIndex == 1
223aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                        && formatParams->eEncoding != OMX_AUDIO_CodingAAC)) {
224aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                return OMX_ErrorUndefined;
225aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            }
226aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
227aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            return OMX_ErrorNone;
228aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        }
229aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
230aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        case OMX_IndexParamAudioAac:
231aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        {
232aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
233aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
234aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
235aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            if (aacParams->nPortIndex != 1) {
236aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                return OMX_ErrorUndefined;
237aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            }
238aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
239aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            mBitRate = aacParams->nBitRate;
240aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            mNumChannels = aacParams->nChannels;
241aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            mSampleRate = aacParams->nSampleRate;
242aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            if (aacParams->eAACProfile != OMX_AUDIO_AACObjectNull) {
243aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                mAACProfile = aacParams->eAACProfile;
244aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            }
245aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
246aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            if (setAudioParams() != OK) {
247aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                return OMX_ErrorUndefined;
248aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            }
249aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
250aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            return OMX_ErrorNone;
251aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        }
252aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
253aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        case OMX_IndexParamAudioPcm:
254aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        {
255aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
256aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
257aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
258aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            if (pcmParams->nPortIndex != 0) {
259aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                return OMX_ErrorUndefined;
260aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            }
261aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
262aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            mNumChannels = pcmParams->nChannels;
263aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            mSampleRate = pcmParams->nSamplingRate;
264aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            if (setAudioParams() != OK) {
265aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                return OMX_ErrorUndefined;
266aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            }
267aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
268aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            return OMX_ErrorNone;
269aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        }
270aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
271aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        default:
272aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            return SimpleSoftOMXComponent::internalSetParameter(index, params);
273aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    }
274aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke}
275aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
276f60c660f048d5f5e2458cff243c20400d73757a7Dave Burkestatic CHANNEL_MODE getChannelMode(OMX_U32 nChannels) {
277aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    CHANNEL_MODE chMode = MODE_INVALID;
278aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    switch (nChannels) {
279aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        case 1: chMode = MODE_1; break;
280aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        case 2: chMode = MODE_2; break;
281aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        case 3: chMode = MODE_1_2; break;
282aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        case 4: chMode = MODE_1_2_1; break;
283aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        case 5: chMode = MODE_1_2_2; break;
284aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        case 6: chMode = MODE_1_2_2_1; break;
285aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        default: chMode = MODE_INVALID;
286aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    }
287aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    return chMode;
288aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke}
289aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
290f60c660f048d5f5e2458cff243c20400d73757a7Dave Burkestatic AUDIO_OBJECT_TYPE getAOTFromProfile(OMX_U32 profile) {
291f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke    if (profile == OMX_AUDIO_AACObjectLC) {
292f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke        return AOT_AAC_LC;
293f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke    } else if (profile == OMX_AUDIO_AACObjectHE) {
294f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke        return AOT_SBR;
295f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke    } else if (profile == OMX_AUDIO_AACObjectELD) {
296f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke        return AOT_ER_AAC_ELD;
297f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke    } else {
298f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke        ALOGW("Unsupported AAC profile - defaulting to AAC-LC");
299f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke        return AOT_AAC_LC;
300f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke    }
301f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke}
302f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke
303aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burkestatus_t SoftAACEncoder2::setAudioParams() {
304aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    // We call this whenever sample rate, number of channels or bitrate change
305aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    // in reponse to setParameter calls.
306aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
307aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    ALOGV("setAudioParams: %lu Hz, %lu channels, %lu bps",
308aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke         mSampleRate, mNumChannels, mBitRate);
309aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
310aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_AOT,
311f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke            getAOTFromProfile(mAACProfile))) {
312aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        ALOGE("Failed to set AAC encoder parameters");
313aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        return UNKNOWN_ERROR;
314aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    }
315aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
316aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SAMPLERATE, mSampleRate)) {
317aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        ALOGE("Failed to set AAC encoder parameters");
318aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        return UNKNOWN_ERROR;
319aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    }
320aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_BITRATE, mBitRate)) {
321aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        ALOGE("Failed to set AAC encoder parameters");
322aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        return UNKNOWN_ERROR;
323aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    }
324aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_CHANNELMODE,
325aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            getChannelMode(mNumChannels))) {
326aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        ALOGE("Failed to set AAC encoder parameters");
327aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        return UNKNOWN_ERROR;
328aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    }
329aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_TRANSMUX, TT_MP4_RAW)) {
330aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        ALOGE("Failed to set AAC encoder parameters");
331aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        return UNKNOWN_ERROR;
332aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    }
333aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
334aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    return OK;
335aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke}
336aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
337aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burkevoid SoftAACEncoder2::onQueueFilled(OMX_U32 portIndex) {
338aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    if (mSignalledError) {
339aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        return;
340aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    }
341aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
342aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    List<BufferInfo *> &inQueue = getPortQueue(0);
343aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    List<BufferInfo *> &outQueue = getPortQueue(1);
344aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
345aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    if (!mSentCodecSpecificData) {
346aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        // The very first thing we want to output is the codec specific
347aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        // data. It does not require any input data but we will need an
348aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        // output buffer to store it in.
349aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
350aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        if (outQueue.empty()) {
351aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            return;
352aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        }
353aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
354aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        if (AACENC_OK != aacEncEncode(mAACEncoder, NULL, NULL, NULL, NULL)) {
355f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke            ALOGE("Unable to initialize encoder for profile / sample-rate / bit-rate / channels");
356aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
357aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            mSignalledError = true;
358aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            return;
359aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        }
360aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
361f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke        OMX_U32 actualBitRate  = aacEncoder_GetParam(mAACEncoder, AACENC_BITRATE);
362f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke        if (mBitRate != actualBitRate) {
363f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke            ALOGW("Requested bitrate %lu unsupported, using %lu", mBitRate, actualBitRate);
364f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke        }
365f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke
366aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        AACENC_InfoStruct encInfo;
367aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        if (AACENC_OK != aacEncInfo(mAACEncoder, &encInfo)) {
368aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            ALOGE("Failed to get AAC encoder info");
369aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
370aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            mSignalledError = true;
371aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            return;
372aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        }
373aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
374aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        BufferInfo *outInfo = *outQueue.begin();
375aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
376aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        outHeader->nFilledLen = encInfo.confSize;
377aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        outHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG;
378aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
379aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        uint8_t *out = outHeader->pBuffer + outHeader->nOffset;
380aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        memcpy(out, encInfo.confBuf, encInfo.confSize);
381aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
382aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        outQueue.erase(outQueue.begin());
383aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        outInfo->mOwnedByUs = false;
384aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        notifyFillBufferDone(outHeader);
385aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
386aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        mSentCodecSpecificData = true;
387aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    }
388aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
389aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    size_t numBytesPerInputFrame =
390aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        mNumChannels * kNumSamplesPerFrame * sizeof(int16_t);
391aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
392f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke    // Limit input size so we only get one ELD frame
393aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    if (mAACProfile == OMX_AUDIO_AACObjectELD && numBytesPerInputFrame > 512) {
394aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        numBytesPerInputFrame = 512;
395aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    }
396aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
397aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    for (;;) {
398aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        // We do the following until we run out of buffers.
399aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
400aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        while (mInputSize < numBytesPerInputFrame) {
401aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            // As long as there's still input data to be read we
402aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            // will drain "kNumSamplesPerFrame * mNumChannels" samples
403aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            // into the "mInputFrame" buffer and then encode those
404aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            // as a unit into an output buffer.
405aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
406aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            if (mSawInputEOS || inQueue.empty()) {
407aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                return;
408aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            }
409aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
410aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            BufferInfo *inInfo = *inQueue.begin();
411aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
412aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
413aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            const void *inData = inHeader->pBuffer + inHeader->nOffset;
414aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
415aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            size_t copy = numBytesPerInputFrame - mInputSize;
416aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            if (copy > inHeader->nFilledLen) {
417aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                copy = inHeader->nFilledLen;
418aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            }
419aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
420aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            if (mInputFrame == NULL) {
421f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke                mInputFrame = new int16_t[numBytesPerInputFrame / sizeof(int16_t)];
422aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            }
423aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
424aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            if (mInputSize == 0) {
425aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                mInputTimeUs = inHeader->nTimeStamp;
426aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            }
427aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
428aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy);
429aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            mInputSize += copy;
430aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
431aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            inHeader->nOffset += copy;
432aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            inHeader->nFilledLen -= copy;
433aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
434aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            // "Time" on the input buffer has in effect advanced by the
435aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            // number of audio frames we just advanced nOffset by.
436aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            inHeader->nTimeStamp +=
437aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                (copy * 1000000ll / mSampleRate)
438aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                    / (mNumChannels * sizeof(int16_t));
439aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
440aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            if (inHeader->nFilledLen == 0) {
441aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
442aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                    mSawInputEOS = true;
443aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
444aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                    // Pad any remaining data with zeroes.
445aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                    memset((uint8_t *)mInputFrame + mInputSize,
446aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                           0,
447aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                           numBytesPerInputFrame - mInputSize);
448aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
449aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                    mInputSize = numBytesPerInputFrame;
450aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                }
451aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
452aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                inQueue.erase(inQueue.begin());
453aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                inInfo->mOwnedByUs = false;
454aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                notifyEmptyBufferDone(inHeader);
455aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
456aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                inData = NULL;
457aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                inHeader = NULL;
458aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                inInfo = NULL;
459aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            }
460aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        }
461aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
462aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        // At this  point we have all the input data necessary to encode
463aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        // a single frame, all we need is an output buffer to store the result
464aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        // in.
465aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
466aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        if (outQueue.empty()) {
467aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            return;
468aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        }
469aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
470aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        BufferInfo *outInfo = *outQueue.begin();
471aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
472aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
473aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        uint8_t *outPtr = (uint8_t *)outHeader->pBuffer + outHeader->nOffset;
474aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset;
475aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
476aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        AACENC_InArgs inargs;
477aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        AACENC_OutArgs outargs;
478aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        memset(&inargs, 0, sizeof(inargs));
479aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        memset(&outargs, 0, sizeof(outargs));
480aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        inargs.numInSamples = numBytesPerInputFrame / sizeof(int16_t);
481aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
482aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        void* inBuffer[]        = { (unsigned char *)mInputFrame };
483aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        INT   inBufferIds[]     = { IN_AUDIO_DATA };
484aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        INT   inBufferSize[]    = { numBytesPerInputFrame };
485aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        INT   inBufferElSize[]  = { sizeof(int16_t) };
486aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
487aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        AACENC_BufDesc inBufDesc;
488aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        inBufDesc.numBufs           = sizeof(inBuffer) / sizeof(void*);
489aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        inBufDesc.bufs              = (void**)&inBuffer;
490aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        inBufDesc.bufferIdentifiers = inBufferIds;
491aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        inBufDesc.bufSizes          = inBufferSize;
492aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        inBufDesc.bufElSizes        = inBufferElSize;
493aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
494aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        void* outBuffer[]       = { outPtr };
495aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        INT   outBufferIds[]    = { OUT_BITSTREAM_DATA };
496aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        INT   outBufferSize[]   = { 0 };
497aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        INT   outBufferElSize[] = { sizeof(UCHAR) };
498aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
499aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        AACENC_BufDesc outBufDesc;
500aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        outBufDesc.numBufs           = sizeof(outBuffer) / sizeof(void*);
501aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        outBufDesc.bufs              = (void**)&outBuffer;
502aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        outBufDesc.bufferIdentifiers = outBufferIds;
503aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        outBufDesc.bufSizes          = outBufferSize;
504aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        outBufDesc.bufElSizes        = outBufferElSize;
505aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
506aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        // Encode the mInputFrame, which is treated as a modulo buffer
507aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        AACENC_ERROR encoderErr = AACENC_OK;
508aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        size_t nOutputBytes = 0;
509f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke
510aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        do {
511aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            memset(&outargs, 0, sizeof(outargs));
512aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
513aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            outBuffer[0] = outPtr;
514aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            outBufferSize[0] = outAvailable - nOutputBytes;
515aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
516aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            encoderErr = aacEncEncode(mAACEncoder,
517aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                                      &inBufDesc,
518aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                                      &outBufDesc,
519aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                                      &inargs,
520aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                                      &outargs);
521aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
522aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            if (encoderErr == AACENC_OK) {
523aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                outPtr += outargs.numOutBytes;
524aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                nOutputBytes += outargs.numOutBytes;
525aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
526aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                if (outargs.numInSamples > 0) {
527aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                    int numRemainingSamples = inargs.numInSamples - outargs.numInSamples;
528aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                    if (numRemainingSamples > 0) {
529aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                        memmove(mInputFrame,
530aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                                &mInputFrame[outargs.numInSamples],
531aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                                sizeof(int16_t) * numRemainingSamples);
532aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                    }
533aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                    inargs.numInSamples -= outargs.numInSamples;
534aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke                }
535aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            }
536aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        } while (encoderErr == AACENC_OK && inargs.numInSamples > 0);
537aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
538aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        outHeader->nFilledLen = nOutputBytes;
539aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
540aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
541aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
542aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        if (mSawInputEOS) {
543aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            // We also tag this output buffer with EOS if it corresponds
544aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            // to the final input buffer.
545aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
546aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        }
547aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
548aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        outHeader->nTimeStamp = mInputTimeUs;
549aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
550aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke#if 0
551aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)",
552aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke              nOutputBytes, mInputTimeUs, outHeader->nFlags);
553aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
554aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
555aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke#endif
556aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
557aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        outQueue.erase(outQueue.begin());
558aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        outInfo->mOwnedByUs = false;
559aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        notifyFillBufferDone(outHeader);
560aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
561aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        outHeader = NULL;
562aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        outInfo = NULL;
563aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
564aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        mInputSize = 0;
565aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    }
566aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke}
567aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
568aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke}  // namespace android
569aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
570aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burkeandroid::SoftOMXComponent *createSoftOMXComponent(
571aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        const char *name, const OMX_CALLBACKTYPE *callbacks,
572aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
573aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    return new android::SoftAACEncoder2(name, callbacks, appData, component);
574aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke}
575