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