1ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen/* 2ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * Copyright (C) 2012 The Android Open Source Project 3ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * 4ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * Licensed under the Apache License, Version 2.0 (the "License"); 5ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * you may not use this file except in compliance with the License. 6ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * You may obtain a copy of the License at 7ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * 8ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * http://www.apache.org/licenses/LICENSE-2.0 9ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * 10ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * Unless required by applicable law or agreed to in writing, software 11ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * distributed under the License is distributed on an "AS IS" BASIS, 12ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * See the License for the specific language governing permissions and 14ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * limitations under the License. 15ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen */ 16ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 17ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen//#define LOG_NDEBUG 0 18ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen#define LOG_TAG "SoftGSM" 19ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen#include <utils/Log.h> 20ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 21ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen#include "SoftGSM.h" 22ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 23ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen#include <media/stagefright/foundation/ADebug.h> 24ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen#include <media/stagefright/MediaDefs.h> 25ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 26ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissennamespace android { 27ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 28ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissentemplate<class T> 29ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissenstatic void InitOMXParams(T *params) { 30ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen params->nSize = sizeof(T); 31ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen params->nVersion.s.nVersionMajor = 1; 32ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen params->nVersion.s.nVersionMinor = 0; 33ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen params->nVersion.s.nRevision = 0; 34ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen params->nVersion.s.nStep = 0; 35ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen} 36ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 37ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco NelissenSoftGSM::SoftGSM( 38ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen const char *name, 39ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen const OMX_CALLBACKTYPE *callbacks, 40ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen OMX_PTR appData, 41ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen OMX_COMPONENTTYPE **component) 42ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen : SimpleSoftOMXComponent(name, callbacks, appData, component), 43ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen mSignalledError(false) { 44ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 45ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen CHECK(!strcmp(name, "OMX.google.gsm.decoder")); 46ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 47ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen mGsm = gsm_create(); 48ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen CHECK(mGsm); 49ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen int msopt = 1; 50ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen gsm_option(mGsm, GSM_OPT_WAV49, &msopt); 51ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 52ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen initPorts(); 53ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen} 54ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 55ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco NelissenSoftGSM::~SoftGSM() { 56ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen gsm_destroy(mGsm); 57ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen} 58ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 59ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissenvoid SoftGSM::initPorts() { 60ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen OMX_PARAM_PORTDEFINITIONTYPE def; 61ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen InitOMXParams(&def); 62ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 63ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.nPortIndex = 0; 64ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.eDir = OMX_DirInput; 65ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.nBufferCountMin = kNumBuffers; 66ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.nBufferCountActual = def.nBufferCountMin; 67ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.nBufferSize = sizeof(gsm_frame); 68ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.bEnabled = OMX_TRUE; 69ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.bPopulated = OMX_FALSE; 70ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.eDomain = OMX_PortDomainAudio; 71ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.bBuffersContiguous = OMX_FALSE; 72ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.nBufferAlignment = 1; 73ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 74ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.format.audio.cMIMEType = 75ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen const_cast<char *>(MEDIA_MIMETYPE_AUDIO_MSGSM); 76ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 77ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.format.audio.pNativeRender = NULL; 78ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.format.audio.bFlagErrorConcealment = OMX_FALSE; 79ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.format.audio.eEncoding = OMX_AUDIO_CodingGSMFR; 80ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 81ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen addPort(def); 82ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 83ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.nPortIndex = 1; 84ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.eDir = OMX_DirOutput; 85ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.nBufferCountMin = kNumBuffers; 86ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.nBufferCountActual = def.nBufferCountMin; 87ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.nBufferSize = kMaxNumSamplesPerFrame * sizeof(int16_t); 88ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.bEnabled = OMX_TRUE; 89ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.bPopulated = OMX_FALSE; 90ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.eDomain = OMX_PortDomainAudio; 91ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.bBuffersContiguous = OMX_FALSE; 92ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.nBufferAlignment = 2; 93ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 94ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.format.audio.cMIMEType = const_cast<char *>("audio/raw"); 95ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.format.audio.pNativeRender = NULL; 96ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.format.audio.bFlagErrorConcealment = OMX_FALSE; 97ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 98ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 99ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen addPort(def); 100ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen} 101ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 102ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco NelissenOMX_ERRORTYPE SoftGSM::internalGetParameter( 103ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen OMX_INDEXTYPE index, OMX_PTR params) { 104ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen switch (index) { 105ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen case OMX_IndexParamAudioPcm: 106ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen { 107ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 108ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 109ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 110ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen if (pcmParams->nPortIndex > 1) { 111ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen return OMX_ErrorUndefined; 112ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen } 113ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 114ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen pcmParams->eNumData = OMX_NumericalDataSigned; 115ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen pcmParams->eEndian = OMX_EndianBig; 116ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen pcmParams->bInterleaved = OMX_TRUE; 117ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen pcmParams->nBitPerSample = 16; 118ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear; 119ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF; 120ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF; 121ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 122ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen pcmParams->nChannels = 1; 123ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen pcmParams->nSamplingRate = 8000; 124ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 125ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen return OMX_ErrorNone; 126ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen } 127ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 128ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen default: 129ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen return SimpleSoftOMXComponent::internalGetParameter(index, params); 130ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen } 131ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen} 132ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 133ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco NelissenOMX_ERRORTYPE SoftGSM::internalSetParameter( 134ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen OMX_INDEXTYPE index, const OMX_PTR params) { 135ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen switch (index) { 136ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen case OMX_IndexParamAudioPcm: 137ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen { 138ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 139ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 140ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 141ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen if (pcmParams->nPortIndex != 0 && pcmParams->nPortIndex != 1) { 142ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen return OMX_ErrorUndefined; 143ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen } 144ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 145ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen if (pcmParams->nChannels != 1) { 146ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen return OMX_ErrorUndefined; 147ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen } 148ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 149ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen if (pcmParams->nSamplingRate != 8000) { 150ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen return OMX_ErrorUndefined; 151ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen } 152ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 153ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen return OMX_ErrorNone; 154ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen } 155ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 156ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen case OMX_IndexParamStandardComponentRole: 157ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen { 158ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen const OMX_PARAM_COMPONENTROLETYPE *roleParams = 159ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen (const OMX_PARAM_COMPONENTROLETYPE *)params; 160ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 161ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen if (strncmp((const char *)roleParams->cRole, 162ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen "audio_decoder.gsm", 163ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen OMX_MAX_STRINGNAME_SIZE - 1)) { 164ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen return OMX_ErrorUndefined; 165ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen } 166ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 167ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen return OMX_ErrorNone; 168ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen } 169ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 170ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen default: 171ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen return SimpleSoftOMXComponent::internalSetParameter(index, params); 172ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen } 173ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen} 174ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 17584333e0475bc911adc16417f4ca327c975cf6c36Andreas Hubervoid SoftGSM::onQueueFilled(OMX_U32 /* portIndex */) { 176ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen if (mSignalledError) { 177ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen return; 178ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen } 179ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 180ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen List<BufferInfo *> &inQueue = getPortQueue(0); 181ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen List<BufferInfo *> &outQueue = getPortQueue(1); 182ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 183ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen while (!inQueue.empty() && !outQueue.empty()) { 184ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen BufferInfo *inInfo = *inQueue.begin(); 185ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 186ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 187ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen BufferInfo *outInfo = *outQueue.begin(); 188ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 189ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 190ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 191ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen inQueue.erase(inQueue.begin()); 192ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen inInfo->mOwnedByUs = false; 193ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen notifyEmptyBufferDone(inHeader); 194ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 195ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen outHeader->nFilledLen = 0; 196ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen outHeader->nFlags = OMX_BUFFERFLAG_EOS; 197ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 198ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen outQueue.erase(outQueue.begin()); 199ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen outInfo->mOwnedByUs = false; 200ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen notifyFillBufferDone(outHeader); 201ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen return; 202ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen } 203ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 204ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen if (inHeader->nFilledLen > kMaxNumSamplesPerFrame) { 20566fe2e9ee30bcb4161bc487ec63d2ae4a05f4051Glenn Kasten ALOGE("input buffer too large (%d).", inHeader->nFilledLen); 206ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 207ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen mSignalledError = true; 208ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen } 209ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 210ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen if(((inHeader->nFilledLen / 65) * 65) != inHeader->nFilledLen) { 21166fe2e9ee30bcb4161bc487ec63d2ae4a05f4051Glenn Kasten ALOGE("input buffer not multiple of 65 (%d).", inHeader->nFilledLen); 212ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 213ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen mSignalledError = true; 214ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen } 215ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 216ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen uint8_t *inputptr = inHeader->pBuffer + inHeader->nOffset; 217ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 218ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen int n = mSignalledError ? 0 : DecodeGSM(mGsm, 219ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen reinterpret_cast<int16_t *>(outHeader->pBuffer), inputptr, inHeader->nFilledLen); 220ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 221ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen outHeader->nTimeStamp = inHeader->nTimeStamp; 222ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen outHeader->nOffset = 0; 223ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen outHeader->nFilledLen = n * sizeof(int16_t); 224ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen outHeader->nFlags = 0; 225ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 226ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen inInfo->mOwnedByUs = false; 227ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen inQueue.erase(inQueue.begin()); 228ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen inInfo = NULL; 229ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen notifyEmptyBufferDone(inHeader); 230ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen inHeader = NULL; 231ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 232ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen outInfo->mOwnedByUs = false; 233ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen outQueue.erase(outQueue.begin()); 234ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen outInfo = NULL; 235ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen notifyFillBufferDone(outHeader); 236ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen outHeader = NULL; 237ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen } 238ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen} 239ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 240ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 241ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen// static 242ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissenint SoftGSM::DecodeGSM(gsm handle, 243ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen int16_t *out, uint8_t *in, size_t inSize) { 244ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 245ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen int ret = 0; 246ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen while (inSize > 0) { 247ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen gsm_decode(handle, in, out); 248ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen in += 33; 249ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen inSize -= 33; 250ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen out += 160; 251ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen ret += 160; 252ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen gsm_decode(handle, in, out); 253ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen in += 32; 254ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen inSize -= 32; 255ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen out += 160; 256ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen ret += 160; 257ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen } 258ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen return ret; 259ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen} 260ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 261ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 262ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen} // namespace android 263ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 264ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissenandroid::SoftOMXComponent *createSoftOMXComponent( 265ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen const char *name, const OMX_CALLBACKTYPE *callbacks, 266ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen OMX_PTR appData, OMX_COMPONENTTYPE **component) { 267ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen return new android::SoftGSM(name, callbacks, appData, component); 268ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen} 269ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen 270