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
1232720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            if (!isValidOMXParam(formatParams)) {
1242720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen                return OMX_ErrorBadParameter;
1252720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            }
1262720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen
127252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (formatParams->nPortIndex > 1) {
128252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorUndefined;
129252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
130252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
131252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (formatParams->nIndex > 0) {
132252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorNoMore;
133252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
134252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
135252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            formatParams->eEncoding =
136252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                (formatParams->nPortIndex == 0)
137252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                    ? OMX_AUDIO_CodingPCM : OMX_AUDIO_CodingAMR;
138252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
139252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            return OMX_ErrorNone;
140252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        }
141252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
142252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        case OMX_IndexParamAudioAmr:
143252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        {
144252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            OMX_AUDIO_PARAM_AMRTYPE *amrParams =
145252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                (OMX_AUDIO_PARAM_AMRTYPE *)params;
146252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
1472720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            if (!isValidOMXParam(amrParams)) {
1482720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen                return OMX_ErrorBadParameter;
1492720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            }
1502720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen
151252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (amrParams->nPortIndex != 1) {
152252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorUndefined;
153252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
154252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
155252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            amrParams->nChannels = 1;
156252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            amrParams->nBitRate = mBitRate;
157252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            amrParams->eAMRBandMode = (OMX_AUDIO_AMRBANDMODETYPE)(mMode + 1);
158252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            amrParams->eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff;
159252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            amrParams->eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
160252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
161252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            return OMX_ErrorNone;
162252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        }
163252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
164252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        case OMX_IndexParamAudioPcm:
165252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        {
166252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
167252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
168252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
1692720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            if (!isValidOMXParam(pcmParams)) {
1702720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen                return OMX_ErrorBadParameter;
1712720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            }
1722720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen
173252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (pcmParams->nPortIndex != 0) {
174252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorUndefined;
175252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
176252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
177252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            pcmParams->eNumData = OMX_NumericalDataSigned;
178252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            pcmParams->eEndian = OMX_EndianBig;
179252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            pcmParams->bInterleaved = OMX_TRUE;
180252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            pcmParams->nBitPerSample = 16;
181252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
182252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelCF;
183252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
184252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            pcmParams->nChannels = 1;
185252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            pcmParams->nSamplingRate = kSampleRate;
186252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
187252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            return OMX_ErrorNone;
188252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        }
189252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
190252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        default:
191252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            return SimpleSoftOMXComponent::internalGetParameter(index, params);
192252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    }
193252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber}
194252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
195252353088a5ebf8508fbc01439ff417805ef1417Andreas HuberOMX_ERRORTYPE SoftAMRNBEncoder::internalSetParameter(
196252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        OMX_INDEXTYPE index, const OMX_PTR params) {
197252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    switch (index) {
198252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        case OMX_IndexParamStandardComponentRole:
199252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        {
200252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
201252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                (const OMX_PARAM_COMPONENTROLETYPE *)params;
202252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
2032720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            if (!isValidOMXParam(roleParams)) {
2042720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen                return OMX_ErrorBadParameter;
2052720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            }
2062720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen
207252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (strncmp((const char *)roleParams->cRole,
208252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                        "audio_encoder.amrnb",
209252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                        OMX_MAX_STRINGNAME_SIZE - 1)) {
210252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorUndefined;
211252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
212252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
213252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            return OMX_ErrorNone;
214252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        }
215252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
216252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        case OMX_IndexParamAudioPortFormat:
217252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        {
218252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
219252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
220252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
2212720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            if (!isValidOMXParam(formatParams)) {
2222720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen                return OMX_ErrorBadParameter;
2232720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            }
2242720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen
225252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (formatParams->nPortIndex > 1) {
226252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorUndefined;
227252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
228252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
229252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (formatParams->nIndex > 0) {
230252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorNoMore;
231252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
232252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
233252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if ((formatParams->nPortIndex == 0
234252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                        && formatParams->eEncoding != OMX_AUDIO_CodingPCM)
235252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                || (formatParams->nPortIndex == 1
236252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                        && formatParams->eEncoding != OMX_AUDIO_CodingAMR)) {
237252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorUndefined;
238252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
239252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
240252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            return OMX_ErrorNone;
241252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        }
242252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
243252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        case OMX_IndexParamAudioAmr:
244252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        {
245252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            OMX_AUDIO_PARAM_AMRTYPE *amrParams =
246252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                (OMX_AUDIO_PARAM_AMRTYPE *)params;
247252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
2482720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            if (!isValidOMXParam(amrParams)) {
2492720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen                return OMX_ErrorBadParameter;
2502720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            }
2512720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen
252252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (amrParams->nPortIndex != 1) {
253252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorUndefined;
254252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
255252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
256252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (amrParams->nChannels != 1
257252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                    || amrParams->eAMRDTXMode != OMX_AUDIO_AMRDTXModeOff
258252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                    || amrParams->eAMRFrameFormat
259252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                            != OMX_AUDIO_AMRFrameFormatFSF
260252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                    || amrParams->eAMRBandMode < OMX_AUDIO_AMRBandModeNB0
261252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                    || amrParams->eAMRBandMode > OMX_AUDIO_AMRBandModeNB7) {
262252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorUndefined;
263252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
264252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
265252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            mBitRate = amrParams->nBitRate;
266252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            mMode = amrParams->eAMRBandMode - 1;
267252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
268252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            amrParams->eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff;
269252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            amrParams->eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
270252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
271252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            return OMX_ErrorNone;
272252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        }
273252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
274252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        case OMX_IndexParamAudioPcm:
275252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        {
276252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
277252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
278252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
2792720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            if (!isValidOMXParam(pcmParams)) {
2802720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen                return OMX_ErrorBadParameter;
2812720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            }
2822720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen
283252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (pcmParams->nPortIndex != 0) {
284252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorUndefined;
285252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
286252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
287252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (pcmParams->nChannels != 1
288a5761dcb5f9f017ca9b83ec868565d7ce54a92acAndreas Huber                    || pcmParams->nSamplingRate != (OMX_U32)kSampleRate) {
289252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return OMX_ErrorUndefined;
290252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
291252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
292252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            return OMX_ErrorNone;
293252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        }
294252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
295252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
296252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        default:
297252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            return SimpleSoftOMXComponent::internalSetParameter(index, params);
298252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    }
299252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber}
300252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
30184333e0475bc911adc16417f4ca327c975cf6c36Andreas Hubervoid SoftAMRNBEncoder::onQueueFilled(OMX_U32 /* portIndex */) {
302252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    if (mSignalledError) {
303252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        return;
304252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    }
305252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
306252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    List<BufferInfo *> &inQueue = getPortQueue(0);
307252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    List<BufferInfo *> &outQueue = getPortQueue(1);
308252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
309252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    size_t numBytesPerInputFrame = kNumSamplesPerFrame * sizeof(int16_t);
310252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
311252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    for (;;) {
312252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        // We do the following until we run out of buffers.
313252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
314252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        while (mInputSize < numBytesPerInputFrame) {
315252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            // As long as there's still input data to be read we
316252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            // will drain "kNumSamplesPerFrame" samples
317252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            // into the "mInputFrame" buffer and then encode those
318252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            // as a unit into an output buffer.
319252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
320252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (mSawInputEOS || inQueue.empty()) {
321252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                return;
322252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
323252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
324252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            BufferInfo *inInfo = *inQueue.begin();
325252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
326252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
327252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            const void *inData = inHeader->pBuffer + inHeader->nOffset;
328252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
329252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            size_t copy = numBytesPerInputFrame - mInputSize;
330252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (copy > inHeader->nFilledLen) {
331252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                copy = inHeader->nFilledLen;
332252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
333252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
334252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (mInputSize == 0) {
335252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                mInputTimeUs = inHeader->nTimeStamp;
336252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
337252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
338252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy);
339252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            mInputSize += copy;
340252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
341252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            inHeader->nOffset += copy;
342252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            inHeader->nFilledLen -= copy;
343252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
344252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            // "Time" on the input buffer has in effect advanced by the
345252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            // number of audio frames we just advanced nOffset by.
346252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            inHeader->nTimeStamp +=
347252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                (copy * 1000000ll / kSampleRate) / sizeof(int16_t);
348252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
349252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            if (inHeader->nFilledLen == 0) {
350252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
351252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                    ALOGV("saw input EOS");
352252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                    mSawInputEOS = true;
353252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
354252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                    // Pad any remaining data with zeroes.
355252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                    memset((uint8_t *)mInputFrame + mInputSize,
356252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                           0,
357252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                           numBytesPerInputFrame - mInputSize);
358252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
359252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                    mInputSize = numBytesPerInputFrame;
360252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                }
361252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
362252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                inQueue.erase(inQueue.begin());
363252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                inInfo->mOwnedByUs = false;
364252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                notifyEmptyBufferDone(inHeader);
365252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
366252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                inData = NULL;
367252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                inHeader = NULL;
368252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                inInfo = NULL;
369252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            }
370252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        }
371252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
372252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        // At this  point we have all the input data necessary to encode
373252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        // a single frame, all we need is an output buffer to store the result
374252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        // in.
375252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
376252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        if (outQueue.empty()) {
377252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            return;
378252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        }
379252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
380252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        BufferInfo *outInfo = *outQueue.begin();
381252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
382252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
383252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        uint8_t *outPtr = outHeader->pBuffer + outHeader->nOffset;
384252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset;
385252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
386252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        Frame_Type_3GPP frameType;
387252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        int res = AMREncode(
388252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                mEncState, mSidState, (Mode)mMode,
389252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber                mInputFrame, outPtr, &frameType, AMR_TX_WMF);
390252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
391252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        CHECK_GE(res, 0);
392252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        CHECK_LE((size_t)res, outAvailable);
393252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
394252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        // Convert header byte from WMF to IETF format.
395252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        outPtr[0] = ((outPtr[0] << 3) | 4) & 0x7c;
396252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
397252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        outHeader->nFilledLen = res;
398252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
399252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
400252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        if (mSawInputEOS) {
401252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            // We also tag this output buffer with EOS if it corresponds
402252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            // to the final input buffer.
403252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
404252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        }
405252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
406252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        outHeader->nTimeStamp = mInputTimeUs;
407252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
408252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber#if 0
409252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)",
410252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber              nOutputBytes, mInputTimeUs, outHeader->nFlags);
411252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
412252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
413252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber#endif
414252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
415252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        outQueue.erase(outQueue.begin());
416252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        outInfo->mOwnedByUs = false;
417252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        notifyFillBufferDone(outHeader);
418252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
419252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        outHeader = NULL;
420252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        outInfo = NULL;
421252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
422252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        mInputSize = 0;
423252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    }
424252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber}
425252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
426252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber}  // namespace android
427252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber
428252353088a5ebf8508fbc01439ff417805ef1417Andreas Huberandroid::SoftOMXComponent *createSoftOMXComponent(
429252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        const char *name, const OMX_CALLBACKTYPE *callbacks,
430252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
431252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber    return new android::SoftAMRNBEncoder(name, callbacks, appData, component);
432252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber}
433