1252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber/*
2252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber * Copyright (C) 2012 The Android Open Source Project
3252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber *
4252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber * you may not use this file except in compliance with the License.
6252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber * You may obtain a copy of the License at
7252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber *
8252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber *
10252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber * Unless required by applicable law or agreed to in writing, software
11252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber * See the License for the specific language governing permissions and
14252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber * limitations under the License.
15252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber */
16252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
17252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber//#define LOG_NDEBUG 0
18252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber#define LOG_TAG "SoftAMRNBEncoder"
19252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber#include <utils/Log.h>
20252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
21252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber#include "SoftAMRNBEncoder.h"
22252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
23252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber#include "gsmamr_enc.h"
24252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
25252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber#include <media/stagefright/foundation/ADebug.h>
26252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber#include <media/stagefright/foundation/hexdump.h>
27252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
28252353088a5ebf8508fbc01439ff417805ef1417Andreas Hubernamespace android {
29252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
30252353088a5ebf8508fbc01439ff417805ef1417Andreas Huberstatic const int32_t kSampleRate = 8000;
31252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
32252353088a5ebf8508fbc01439ff417805ef1417Andreas Hubertemplate<class T>
33252353088a5ebf8508fbc01439ff417805ef1417Andreas Huberstatic void InitOMXParams(T *params) {
34252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    params->nSize = sizeof(T);
35252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    params->nVersion.s.nVersionMajor = 1;
36252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    params->nVersion.s.nVersionMinor = 0;
37252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    params->nVersion.s.nRevision = 0;
38252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    params->nVersion.s.nStep = 0;
39252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber}
40252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
41252353088a5ebf8508fbc01439ff417805ef1417Andreas HuberSoftAMRNBEncoder::SoftAMRNBEncoder(
42252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        const char *name,
43252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        const OMX_CALLBACKTYPE *callbacks,
44252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        OMX_PTR appData,
45252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        OMX_COMPONENTTYPE **component)
46252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    : SimpleSoftOMXComponent(name, callbacks, appData, component),
47252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber      mEncState(NULL),
48252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber      mSidState(NULL),
49252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber      mBitRate(0),
50252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber      mMode(MR475),
51252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber      mInputSize(0),
52252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber      mInputTimeUs(-1ll),
53252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber      mSawInputEOS(false),
54252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber      mSignalledError(false) {
55252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    initPorts();
56252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    CHECK_EQ(initEncoder(), (status_t)OK);
57252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber}
58252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
59252353088a5ebf8508fbc01439ff417805ef1417Andreas HuberSoftAMRNBEncoder::~SoftAMRNBEncoder() {
60252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    if (mEncState != NULL) {
61252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        AMREncodeExit(&mEncState, &mSidState);
62252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        mEncState = mSidState = NULL;
63252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    }
64252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber}
65252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
66252353088a5ebf8508fbc01439ff417805ef1417Andreas Hubervoid SoftAMRNBEncoder::initPorts() {
67252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    OMX_PARAM_PORTDEFINITIONTYPE def;
68252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    InitOMXParams(&def);
69252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
70252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.nPortIndex = 0;
71252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.eDir = OMX_DirInput;
72252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.nBufferCountMin = kNumBuffers;
73252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.nBufferCountActual = def.nBufferCountMin;
74252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t);
75252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.bEnabled = OMX_TRUE;
76252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.bPopulated = OMX_FALSE;
77252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.eDomain = OMX_PortDomainAudio;
78252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.bBuffersContiguous = OMX_FALSE;
79252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.nBufferAlignment = 1;
80252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
81252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
82252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.format.audio.pNativeRender = NULL;
83252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
84252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
85252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
86252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    addPort(def);
87252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
88252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.nPortIndex = 1;
89252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.eDir = OMX_DirOutput;
90252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.nBufferCountMin = kNumBuffers;
91252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.nBufferCountActual = def.nBufferCountMin;
92252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.nBufferSize = 8192;
93252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.bEnabled = OMX_TRUE;
94252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.bPopulated = OMX_FALSE;
95252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.eDomain = OMX_PortDomainAudio;
96252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.bBuffersContiguous = OMX_FALSE;
97252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.nBufferAlignment = 2;
98252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
99252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.format.audio.cMIMEType = const_cast<char *>("audio/3gpp");
100252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.format.audio.pNativeRender = NULL;
101252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
102252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    def.format.audio.eEncoding = OMX_AUDIO_CodingAMR;
103252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
104252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    addPort(def);
105252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber}
106252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
107252353088a5ebf8508fbc01439ff417805ef1417Andreas Huberstatus_t SoftAMRNBEncoder::initEncoder() {
108252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    if (AMREncodeInit(&mEncState, &mSidState, false /* dtx_enable */) != 0) {
109252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        return UNKNOWN_ERROR;
110252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    }
111252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
112252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    return OK;
113252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber}
114252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
115252353088a5ebf8508fbc01439ff417805ef1417Andreas HuberOMX_ERRORTYPE SoftAMRNBEncoder::internalGetParameter(
116252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        OMX_INDEXTYPE index, OMX_PTR params) {
117252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    switch (index) {
118252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        case OMX_IndexParamAudioPortFormat:
119252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        {
120252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
121252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
122252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
123252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (formatParams->nPortIndex > 1) {
124252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorUndefined;
125252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
126252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
127252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (formatParams->nIndex > 0) {
128252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorNoMore;
129252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
130252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
131252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            formatParams->eEncoding =
132252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                (formatParams->nPortIndex == 0)
133252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                    ? OMX_AUDIO_CodingPCM : OMX_AUDIO_CodingAMR;
134252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
135252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            return OMX_ErrorNone;
136252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        }
137252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
138252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        case OMX_IndexParamAudioAmr:
139252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        {
140252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            OMX_AUDIO_PARAM_AMRTYPE *amrParams =
141252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                (OMX_AUDIO_PARAM_AMRTYPE *)params;
142252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
143252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (amrParams->nPortIndex != 1) {
144252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorUndefined;
145252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
146252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
147252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            amrParams->nChannels = 1;
148252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            amrParams->nBitRate = mBitRate;
149252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            amrParams->eAMRBandMode = (OMX_AUDIO_AMRBANDMODETYPE)(mMode + 1);
150252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            amrParams->eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff;
151252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            amrParams->eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
152252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
153252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            return OMX_ErrorNone;
154252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        }
155252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
156252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        case OMX_IndexParamAudioPcm:
157252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        {
158252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
159252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
160252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
161252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (pcmParams->nPortIndex != 0) {
162252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorUndefined;
163252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
164252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
165252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            pcmParams->eNumData = OMX_NumericalDataSigned;
166252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            pcmParams->eEndian = OMX_EndianBig;
167252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            pcmParams->bInterleaved = OMX_TRUE;
168252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            pcmParams->nBitPerSample = 16;
169252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
170252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelCF;
171252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
172252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            pcmParams->nChannels = 1;
173252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            pcmParams->nSamplingRate = kSampleRate;
174252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
175252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            return OMX_ErrorNone;
176252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        }
177252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
178252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        default:
179252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            return SimpleSoftOMXComponent::internalGetParameter(index, params);
180252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    }
181252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber}
182252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
183252353088a5ebf8508fbc01439ff417805ef1417Andreas HuberOMX_ERRORTYPE SoftAMRNBEncoder::internalSetParameter(
184252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        OMX_INDEXTYPE index, const OMX_PTR params) {
185252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    switch (index) {
186252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        case OMX_IndexParamStandardComponentRole:
187252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        {
188252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
189252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                (const OMX_PARAM_COMPONENTROLETYPE *)params;
190252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
191252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (strncmp((const char *)roleParams->cRole,
192252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                        "audio_encoder.amrnb",
193252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                        OMX_MAX_STRINGNAME_SIZE - 1)) {
194252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorUndefined;
195252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
196252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
197252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            return OMX_ErrorNone;
198252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        }
199252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
200252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        case OMX_IndexParamAudioPortFormat:
201252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        {
202252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
203252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
204252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
205252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (formatParams->nPortIndex > 1) {
206252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorUndefined;
207252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
208252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
209252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (formatParams->nIndex > 0) {
210252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorNoMore;
211252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
212252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
213252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if ((formatParams->nPortIndex == 0
214252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                        && formatParams->eEncoding != OMX_AUDIO_CodingPCM)
215252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                || (formatParams->nPortIndex == 1
216252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                        && formatParams->eEncoding != OMX_AUDIO_CodingAMR)) {
217252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorUndefined;
218252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
219252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
220252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            return OMX_ErrorNone;
221252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        }
222252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
223252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        case OMX_IndexParamAudioAmr:
224252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        {
225252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            OMX_AUDIO_PARAM_AMRTYPE *amrParams =
226252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                (OMX_AUDIO_PARAM_AMRTYPE *)params;
227252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
228252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (amrParams->nPortIndex != 1) {
229252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorUndefined;
230252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
231252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
232252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (amrParams->nChannels != 1
233252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                    || amrParams->eAMRDTXMode != OMX_AUDIO_AMRDTXModeOff
234252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                    || amrParams->eAMRFrameFormat
235252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                            != OMX_AUDIO_AMRFrameFormatFSF
236252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                    || amrParams->eAMRBandMode < OMX_AUDIO_AMRBandModeNB0
237252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                    || amrParams->eAMRBandMode > OMX_AUDIO_AMRBandModeNB7) {
238252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorUndefined;
239252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
240252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
241252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            mBitRate = amrParams->nBitRate;
242252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            mMode = amrParams->eAMRBandMode - 1;
243252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
244252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            amrParams->eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff;
245252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            amrParams->eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
246252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
247252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            return OMX_ErrorNone;
248252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        }
249252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
250252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        case OMX_IndexParamAudioPcm:
251252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        {
252252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
253252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
254252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
255252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (pcmParams->nPortIndex != 0) {
256252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorUndefined;
257252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
258252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
259252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (pcmParams->nChannels != 1
260a5761dcb5f9f017ca9b83ec868565d7ce54a92acAndreas Huber                    || pcmParams->nSamplingRate != (OMX_U32)kSampleRate) {
261252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorUndefined;
262252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
263252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
264252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            return OMX_ErrorNone;
265252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        }
266252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
267252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
268252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        default:
269252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            return SimpleSoftOMXComponent::internalSetParameter(index, params);
270252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    }
271252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber}
272252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
27384333e0475bc911adc16417f4ca327c975cf6c36Andreas Hubervoid SoftAMRNBEncoder::onQueueFilled(OMX_U32 /* portIndex */) {
274252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    if (mSignalledError) {
275252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        return;
276252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    }
277252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
278252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    List<BufferInfo *> &inQueue = getPortQueue(0);
279252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    List<BufferInfo *> &outQueue = getPortQueue(1);
280252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
281252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    size_t numBytesPerInputFrame = kNumSamplesPerFrame * sizeof(int16_t);
282252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
283252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    for (;;) {
284252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        // We do the following until we run out of buffers.
285252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
286252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        while (mInputSize < numBytesPerInputFrame) {
287252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            // As long as there's still input data to be read we
288252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            // will drain "kNumSamplesPerFrame" samples
289252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            // into the "mInputFrame" buffer and then encode those
290252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            // as a unit into an output buffer.
291252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
292252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (mSawInputEOS || inQueue.empty()) {
293252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return;
294252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
295252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
296252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            BufferInfo *inInfo = *inQueue.begin();
297252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
298252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
299252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            const void *inData = inHeader->pBuffer + inHeader->nOffset;
300252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
301252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            size_t copy = numBytesPerInputFrame - mInputSize;
302252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (copy > inHeader->nFilledLen) {
303252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                copy = inHeader->nFilledLen;
304252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
305252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
306252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (mInputSize == 0) {
307252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                mInputTimeUs = inHeader->nTimeStamp;
308252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
309252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
310252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy);
311252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            mInputSize += copy;
312252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
313252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            inHeader->nOffset += copy;
314252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            inHeader->nFilledLen -= copy;
315252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
316252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            // "Time" on the input buffer has in effect advanced by the
317252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            // number of audio frames we just advanced nOffset by.
318252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            inHeader->nTimeStamp +=
319252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                (copy * 1000000ll / kSampleRate) / sizeof(int16_t);
320252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
321252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (inHeader->nFilledLen == 0) {
322252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
323252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                    ALOGV("saw input EOS");
324252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                    mSawInputEOS = true;
325252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
326252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                    // Pad any remaining data with zeroes.
327252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                    memset((uint8_t *)mInputFrame + mInputSize,
328252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                           0,
329252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                           numBytesPerInputFrame - mInputSize);
330252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
331252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                    mInputSize = numBytesPerInputFrame;
332252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                }
333252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
334252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                inQueue.erase(inQueue.begin());
335252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                inInfo->mOwnedByUs = false;
336252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                notifyEmptyBufferDone(inHeader);
337252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
338252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                inData = NULL;
339252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                inHeader = NULL;
340252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                inInfo = NULL;
341252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
342252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        }
343252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
344252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        // At this  point we have all the input data necessary to encode
345252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        // a single frame, all we need is an output buffer to store the result
346252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        // in.
347252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
348252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        if (outQueue.empty()) {
349252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            return;
350252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        }
351252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
352252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        BufferInfo *outInfo = *outQueue.begin();
353252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
354252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
355252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        uint8_t *outPtr = outHeader->pBuffer + outHeader->nOffset;
356252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset;
357252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
358252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        Frame_Type_3GPP frameType;
359252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        int res = AMREncode(
360252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                mEncState, mSidState, (Mode)mMode,
361252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                mInputFrame, outPtr, &frameType, AMR_TX_WMF);
362252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
363252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        CHECK_GE(res, 0);
364252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        CHECK_LE((size_t)res, outAvailable);
365252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
366252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        // Convert header byte from WMF to IETF format.
367252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        outPtr[0] = ((outPtr[0] << 3) | 4) & 0x7c;
368252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
369252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        outHeader->nFilledLen = res;
370252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
371252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
372252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        if (mSawInputEOS) {
373252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            // We also tag this output buffer with EOS if it corresponds
374252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            // to the final input buffer.
375252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
376252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        }
377252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
378252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        outHeader->nTimeStamp = mInputTimeUs;
379252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
380252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber#if 0
381252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)",
382252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber              nOutputBytes, mInputTimeUs, outHeader->nFlags);
383252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
384252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
385252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber#endif
386252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
387252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        outQueue.erase(outQueue.begin());
388252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        outInfo->mOwnedByUs = false;
389252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        notifyFillBufferDone(outHeader);
390252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
391252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        outHeader = NULL;
392252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        outInfo = NULL;
393252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
394252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        mInputSize = 0;
395252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    }
396252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber}
397252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
398252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber}  // namespace android
399252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
400252353088a5ebf8508fbc01439ff417805ef1417Andreas Huberandroid::SoftOMXComponent *createSoftOMXComponent(
401252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        const char *name, const OMX_CALLBACKTYPE *callbacks,
402252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
403252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    return new android::SoftAMRNBEncoder(name, callbacks, appData, component);
404252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber}
405