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->nPortIndex == 0 230252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber && formatParams->eEncoding != OMX_AUDIO_CodingPCM) 231252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber || (formatParams->nPortIndex == 1 232252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber && formatParams->eEncoding != OMX_AUDIO_CodingAMR)) { 233252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber return OMX_ErrorUndefined; 234252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber } 235252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 236252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber return OMX_ErrorNone; 237252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber } 238252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 239252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber case OMX_IndexParamAudioAmr: 240252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber { 241252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber OMX_AUDIO_PARAM_AMRTYPE *amrParams = 242252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber (OMX_AUDIO_PARAM_AMRTYPE *)params; 243252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 2442720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen if (!isValidOMXParam(amrParams)) { 2452720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen return OMX_ErrorBadParameter; 2462720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen } 2472720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen 248252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber if (amrParams->nPortIndex != 1) { 249252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber return OMX_ErrorUndefined; 250252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber } 251252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 252252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber if (amrParams->nChannels != 1 253252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber || amrParams->eAMRDTXMode != OMX_AUDIO_AMRDTXModeOff 254252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber || amrParams->eAMRFrameFormat 255252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber != OMX_AUDIO_AMRFrameFormatFSF 256252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber || amrParams->eAMRBandMode < OMX_AUDIO_AMRBandModeNB0 257252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber || amrParams->eAMRBandMode > OMX_AUDIO_AMRBandModeNB7) { 258252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber return OMX_ErrorUndefined; 259252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber } 260252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 261252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber mBitRate = amrParams->nBitRate; 262252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber mMode = amrParams->eAMRBandMode - 1; 263252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 264252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber amrParams->eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff; 265252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber amrParams->eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; 266252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 267252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber return OMX_ErrorNone; 268252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber } 269252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 270252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber case OMX_IndexParamAudioPcm: 271252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber { 272252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 273252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 274252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 2752720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen if (!isValidOMXParam(pcmParams)) { 2762720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen return OMX_ErrorBadParameter; 2772720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen } 2782720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen 279252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber if (pcmParams->nPortIndex != 0) { 280252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber return OMX_ErrorUndefined; 281252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber } 282252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 283252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber if (pcmParams->nChannels != 1 284a5761dcb5f9f017ca9b83ec868565d7ce54a92acAndreas Huber || pcmParams->nSamplingRate != (OMX_U32)kSampleRate) { 285252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber return OMX_ErrorUndefined; 286252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber } 287252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 288252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber return OMX_ErrorNone; 289252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber } 290252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 291252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 292252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber default: 293252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber return SimpleSoftOMXComponent::internalSetParameter(index, params); 294252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber } 295252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber} 296252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 29784333e0475bc911adc16417f4ca327c975cf6c36Andreas Hubervoid SoftAMRNBEncoder::onQueueFilled(OMX_U32 /* portIndex */) { 298252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber if (mSignalledError) { 299252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber return; 300252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber } 301252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 302252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber List<BufferInfo *> &inQueue = getPortQueue(0); 303252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber List<BufferInfo *> &outQueue = getPortQueue(1); 304252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 305252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber size_t numBytesPerInputFrame = kNumSamplesPerFrame * sizeof(int16_t); 306252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 307252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber for (;;) { 308252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber // We do the following until we run out of buffers. 309252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 310252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber while (mInputSize < numBytesPerInputFrame) { 311252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber // As long as there's still input data to be read we 312252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber // will drain "kNumSamplesPerFrame" samples 313252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber // into the "mInputFrame" buffer and then encode those 314252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber // as a unit into an output buffer. 315252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 316252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber if (mSawInputEOS || inQueue.empty()) { 317252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber return; 318252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber } 319252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 320252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber BufferInfo *inInfo = *inQueue.begin(); 321252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 322252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 323252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber const void *inData = inHeader->pBuffer + inHeader->nOffset; 324252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 325252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber size_t copy = numBytesPerInputFrame - mInputSize; 326252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber if (copy > inHeader->nFilledLen) { 327252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber copy = inHeader->nFilledLen; 328252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber } 329252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 330252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber if (mInputSize == 0) { 331252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber mInputTimeUs = inHeader->nTimeStamp; 332252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber } 333252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 334252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy); 335252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber mInputSize += copy; 336252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 337252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber inHeader->nOffset += copy; 338252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber inHeader->nFilledLen -= copy; 339252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 340252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber // "Time" on the input buffer has in effect advanced by the 341252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber // number of audio frames we just advanced nOffset by. 342252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber inHeader->nTimeStamp += 343252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber (copy * 1000000ll / kSampleRate) / sizeof(int16_t); 344252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 345252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber if (inHeader->nFilledLen == 0) { 346252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 347252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber ALOGV("saw input EOS"); 348252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber mSawInputEOS = true; 349252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 350252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber // Pad any remaining data with zeroes. 351252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber memset((uint8_t *)mInputFrame + mInputSize, 352252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 0, 353252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber numBytesPerInputFrame - mInputSize); 354252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 355252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber mInputSize = numBytesPerInputFrame; 356252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber } 357252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 358252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber inQueue.erase(inQueue.begin()); 359252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber inInfo->mOwnedByUs = false; 360252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber notifyEmptyBufferDone(inHeader); 361252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 362252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber inData = NULL; 363252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber inHeader = NULL; 364252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber inInfo = NULL; 365252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber } 366252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber } 367252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 368252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber // At this point we have all the input data necessary to encode 369252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber // a single frame, all we need is an output buffer to store the result 370252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber // in. 371252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 372252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber if (outQueue.empty()) { 373252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber return; 374252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber } 375252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 376252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber BufferInfo *outInfo = *outQueue.begin(); 377252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 378252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 379252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber uint8_t *outPtr = outHeader->pBuffer + outHeader->nOffset; 380252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset; 381252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 382252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber Frame_Type_3GPP frameType; 383252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber int res = AMREncode( 384252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber mEncState, mSidState, (Mode)mMode, 385252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber mInputFrame, outPtr, &frameType, AMR_TX_WMF); 386252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 387252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber CHECK_GE(res, 0); 388252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber CHECK_LE((size_t)res, outAvailable); 389252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 390252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber // Convert header byte from WMF to IETF format. 391252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber outPtr[0] = ((outPtr[0] << 3) | 4) & 0x7c; 392252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 393252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber outHeader->nFilledLen = res; 394252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME; 395252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 396252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber if (mSawInputEOS) { 397252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber // We also tag this output buffer with EOS if it corresponds 398252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber // to the final input buffer. 399252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber outHeader->nFlags = OMX_BUFFERFLAG_EOS; 400252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber } 401252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 402252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber outHeader->nTimeStamp = mInputTimeUs; 403252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 404252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber#if 0 405252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)", 406252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber nOutputBytes, mInputTimeUs, outHeader->nFlags); 407252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 408252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen); 409252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber#endif 410252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 411252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber outQueue.erase(outQueue.begin()); 412252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber outInfo->mOwnedByUs = false; 413252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber notifyFillBufferDone(outHeader); 414252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 415252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber outHeader = NULL; 416252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber outInfo = NULL; 417252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 418252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber mInputSize = 0; 419252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber } 420252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber} 421252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 422252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber} // namespace android 423252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber 424252353088a5ebf8508fbc01439ff417805ef1417Andreas Huberandroid::SoftOMXComponent *createSoftOMXComponent( 425252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber const char *name, const OMX_CALLBACKTYPE *callbacks, 426252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber OMX_PTR appData, OMX_COMPONENTTYPE **component) { 427252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber return new android::SoftAMRNBEncoder(name, callbacks, appData, component); 428252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber} 429