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