12ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen/* 22ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * Copyright (C) 2012 The Android Open Source Project 32ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * 42ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * Licensed under the Apache License, Version 2.0 (the "License"); 52ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * you may not use this file except in compliance with the License. 62ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * You may obtain a copy of the License at 72ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * 82ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * http://www.apache.org/licenses/LICENSE-2.0 92ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * 102ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * Unless required by applicable law or agreed to in writing, software 112ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * distributed under the License is distributed on an "AS IS" BASIS, 122ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * See the License for the specific language governing permissions and 142ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * limitations under the License. 152ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen */ 162ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 172ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen//#define LOG_NDEBUG 0 182ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen#define LOG_TAG "SoftGSM" 192ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen#include <utils/Log.h> 202ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 212ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen#include "SoftGSM.h" 222ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 232ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen#include <media/stagefright/foundation/ADebug.h> 242ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen#include <media/stagefright/MediaDefs.h> 252ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 262ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissennamespace android { 272ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 282ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissentemplate<class T> 292ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissenstatic void InitOMXParams(T *params) { 302ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen params->nSize = sizeof(T); 312ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen params->nVersion.s.nVersionMajor = 1; 322ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen params->nVersion.s.nVersionMinor = 0; 332ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen params->nVersion.s.nRevision = 0; 342ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen params->nVersion.s.nStep = 0; 352ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen} 362ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 37cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen// Microsoft WAV GSM encoding packs two GSM frames into 65 bytes. 38cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissenstatic const int kMSGSMFrameSize = 65; 39cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen 402ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco NelissenSoftGSM::SoftGSM( 412ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen const char *name, 422ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen const OMX_CALLBACKTYPE *callbacks, 432ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen OMX_PTR appData, 442ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen OMX_COMPONENTTYPE **component) 452ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen : SimpleSoftOMXComponent(name, callbacks, appData, component), 462ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen mSignalledError(false) { 472ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 482ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen CHECK(!strcmp(name, "OMX.google.gsm.decoder")); 492ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 502ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen mGsm = gsm_create(); 512ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen CHECK(mGsm); 522ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen int msopt = 1; 532ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen gsm_option(mGsm, GSM_OPT_WAV49, &msopt); 542ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 552ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen initPorts(); 562ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen} 572ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 582ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco NelissenSoftGSM::~SoftGSM() { 592ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen gsm_destroy(mGsm); 602ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen} 612ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 622ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissenvoid SoftGSM::initPorts() { 632ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen OMX_PARAM_PORTDEFINITIONTYPE def; 642ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen InitOMXParams(&def); 652ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 662ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.nPortIndex = 0; 672ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.eDir = OMX_DirInput; 682ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.nBufferCountMin = kNumBuffers; 692ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.nBufferCountActual = def.nBufferCountMin; 70cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen def.nBufferSize = 1024 / kMSGSMFrameSize * kMSGSMFrameSize; 712ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.bEnabled = OMX_TRUE; 722ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.bPopulated = OMX_FALSE; 732ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.eDomain = OMX_PortDomainAudio; 742ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.bBuffersContiguous = OMX_FALSE; 752ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.nBufferAlignment = 1; 762ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 772ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.format.audio.cMIMEType = 782ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen const_cast<char *>(MEDIA_MIMETYPE_AUDIO_MSGSM); 792ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 802ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.format.audio.pNativeRender = NULL; 812ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.format.audio.bFlagErrorConcealment = OMX_FALSE; 822ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.format.audio.eEncoding = OMX_AUDIO_CodingGSMFR; 832ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 842ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen addPort(def); 852ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 862ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.nPortIndex = 1; 872ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.eDir = OMX_DirOutput; 882ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.nBufferCountMin = kNumBuffers; 892ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.nBufferCountActual = def.nBufferCountMin; 902ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.nBufferSize = kMaxNumSamplesPerFrame * sizeof(int16_t); 912ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.bEnabled = OMX_TRUE; 922ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.bPopulated = OMX_FALSE; 932ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.eDomain = OMX_PortDomainAudio; 942ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.bBuffersContiguous = OMX_FALSE; 952ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.nBufferAlignment = 2; 962ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 972ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.format.audio.cMIMEType = const_cast<char *>("audio/raw"); 982ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.format.audio.pNativeRender = NULL; 992ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.format.audio.bFlagErrorConcealment = OMX_FALSE; 1002ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 1012ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 1022ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen addPort(def); 1032ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen} 1042ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 1052ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco NelissenOMX_ERRORTYPE SoftGSM::internalGetParameter( 1062ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen OMX_INDEXTYPE index, OMX_PTR params) { 1072ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen switch (index) { 1081e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan case OMX_IndexParamAudioPortFormat: 1091e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan { 1101e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams = 1111e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params; 1121e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 1131e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan if (!isValidOMXParam(formatParams)) { 1141e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan return OMX_ErrorBadParameter; 1151e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan } 1161e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 1171e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan if (formatParams->nPortIndex > 1) { 1181e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan return OMX_ErrorUndefined; 1191e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan } 1201e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 1211e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan if (formatParams->nIndex > 0) { 1221e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan return OMX_ErrorNoMore; 1231e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan } 1241e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 1251e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan formatParams->eEncoding = 1261e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan (formatParams->nPortIndex == 0) 1271e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan ? OMX_AUDIO_CodingGSMFR : OMX_AUDIO_CodingPCM; 1281e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 1291e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan return OMX_ErrorNone; 1301e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan } 1311e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 1322ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen case OMX_IndexParamAudioPcm: 1332ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen { 1342ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 1352ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 1362ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 137f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen if (!isValidOMXParam(pcmParams)) { 138f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen return OMX_ErrorBadParameter; 139f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen } 140f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen 1412ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen if (pcmParams->nPortIndex > 1) { 1422ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen return OMX_ErrorUndefined; 1432ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen } 1442ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 1452ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen pcmParams->eNumData = OMX_NumericalDataSigned; 1462ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen pcmParams->eEndian = OMX_EndianBig; 1472ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen pcmParams->bInterleaved = OMX_TRUE; 1482ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen pcmParams->nBitPerSample = 16; 1492ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear; 1502ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF; 1512ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF; 1522ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 1532ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen pcmParams->nChannels = 1; 1542ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen pcmParams->nSamplingRate = 8000; 1552ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 1562ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen return OMX_ErrorNone; 1572ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen } 1582ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 1592ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen default: 1602ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen return SimpleSoftOMXComponent::internalGetParameter(index, params); 1612ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen } 1622ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen} 1632ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 1642ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco NelissenOMX_ERRORTYPE SoftGSM::internalSetParameter( 1652ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen OMX_INDEXTYPE index, const OMX_PTR params) { 1662ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen switch (index) { 1672ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen case OMX_IndexParamAudioPcm: 1682ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen { 1692ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 1702ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 1712ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 172f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen if (!isValidOMXParam(pcmParams)) { 173f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen return OMX_ErrorBadParameter; 174f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen } 175f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen 1762ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen if (pcmParams->nPortIndex != 0 && pcmParams->nPortIndex != 1) { 1772ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen return OMX_ErrorUndefined; 1782ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen } 1792ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 1802ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen if (pcmParams->nChannels != 1) { 1812ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen return OMX_ErrorUndefined; 1822ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen } 1832ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 1842ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen if (pcmParams->nSamplingRate != 8000) { 1852ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen return OMX_ErrorUndefined; 1862ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen } 1872ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 1882ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen return OMX_ErrorNone; 1892ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen } 1902ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 1911e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan case OMX_IndexParamAudioPortFormat: 1921e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan { 1931e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams = 1941e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params; 1951e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 1961e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan if (!isValidOMXParam(formatParams)) { 1971e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan return OMX_ErrorBadParameter; 1981e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan } 1991e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 2001e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan if (formatParams->nPortIndex > 1) { 2011e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan return OMX_ErrorUndefined; 2021e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan } 2031e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 2041e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan if ((formatParams->nPortIndex == 0 2051e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan && formatParams->eEncoding != OMX_AUDIO_CodingGSMFR) 2061e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan || (formatParams->nPortIndex == 1 2071e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan && formatParams->eEncoding != OMX_AUDIO_CodingPCM)) { 2081e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan return OMX_ErrorUndefined; 2091e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan } 2101e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 2111e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan return OMX_ErrorNone; 2121e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan } 2131e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 2142ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen case OMX_IndexParamStandardComponentRole: 2152ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen { 2162ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen const OMX_PARAM_COMPONENTROLETYPE *roleParams = 2172ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen (const OMX_PARAM_COMPONENTROLETYPE *)params; 2182ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 219f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen if (!isValidOMXParam(roleParams)) { 220f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen return OMX_ErrorBadParameter; 221f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen } 222f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen 2232ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen if (strncmp((const char *)roleParams->cRole, 2242ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen "audio_decoder.gsm", 2252ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen OMX_MAX_STRINGNAME_SIZE - 1)) { 2262ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen return OMX_ErrorUndefined; 2272ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen } 2282ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 2292ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen return OMX_ErrorNone; 2302ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen } 2312ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 2322ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen default: 2332ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen return SimpleSoftOMXComponent::internalSetParameter(index, params); 2342ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen } 2352ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen} 2362ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 237d411b4ca2945cd8974a3a78199fce94646950128Andreas Hubervoid SoftGSM::onQueueFilled(OMX_U32 /* portIndex */) { 2382ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen if (mSignalledError) { 2392ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen return; 2402ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen } 2412ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 2422ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen List<BufferInfo *> &inQueue = getPortQueue(0); 2432ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen List<BufferInfo *> &outQueue = getPortQueue(1); 2442ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 2452ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen while (!inQueue.empty() && !outQueue.empty()) { 2462ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen BufferInfo *inInfo = *inQueue.begin(); 2472ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 2482ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 2492ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen BufferInfo *outInfo = *outQueue.begin(); 2502ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 2512ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 252199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia if ((inHeader->nFlags & OMX_BUFFERFLAG_EOS) && inHeader->nFilledLen == 0) { 2532ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen inQueue.erase(inQueue.begin()); 2542ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen inInfo->mOwnedByUs = false; 2552ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen notifyEmptyBufferDone(inHeader); 2562ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 2572ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen outHeader->nFilledLen = 0; 2582ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen outHeader->nFlags = OMX_BUFFERFLAG_EOS; 2592ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 2602ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen outQueue.erase(outQueue.begin()); 2612ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen outInfo->mOwnedByUs = false; 2622ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen notifyFillBufferDone(outHeader); 2632ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen return; 2642ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen } 2652ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 2662ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen if (inHeader->nFilledLen > kMaxNumSamplesPerFrame) { 26766fe2e9ee30bcb4161bc487ec63d2ae4a05f4051Glenn Kasten ALOGE("input buffer too large (%d).", inHeader->nFilledLen); 2682ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 2692ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen mSignalledError = true; 2702ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen } 2712ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 272cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen if(((inHeader->nFilledLen / kMSGSMFrameSize) * kMSGSMFrameSize) != inHeader->nFilledLen) { 273cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen ALOGE("input buffer not multiple of %d (%d).", kMSGSMFrameSize, inHeader->nFilledLen); 2742ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 2752ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen mSignalledError = true; 2762ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen } 2772ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 278d211045926b78d2bc82611c97a7cfd18a9790c4bWonsik Kim if (outHeader->nAllocLen < (inHeader->nFilledLen / kMSGSMFrameSize) * 320) { 279d211045926b78d2bc82611c97a7cfd18a9790c4bWonsik Kim ALOGE("output buffer is not large enough (%d).", outHeader->nAllocLen); 280d211045926b78d2bc82611c97a7cfd18a9790c4bWonsik Kim android_errorWriteLog(0x534e4554, "27793367"); 281d211045926b78d2bc82611c97a7cfd18a9790c4bWonsik Kim notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 282d211045926b78d2bc82611c97a7cfd18a9790c4bWonsik Kim mSignalledError = true; 283d211045926b78d2bc82611c97a7cfd18a9790c4bWonsik Kim return; 284d211045926b78d2bc82611c97a7cfd18a9790c4bWonsik Kim } 285d211045926b78d2bc82611c97a7cfd18a9790c4bWonsik Kim 2862ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen uint8_t *inputptr = inHeader->pBuffer + inHeader->nOffset; 2872ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 2882ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen int n = mSignalledError ? 0 : DecodeGSM(mGsm, 2892ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen reinterpret_cast<int16_t *>(outHeader->pBuffer), inputptr, inHeader->nFilledLen); 2902ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 2912ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen outHeader->nTimeStamp = inHeader->nTimeStamp; 2922ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen outHeader->nOffset = 0; 2932ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen outHeader->nFilledLen = n * sizeof(int16_t); 2942ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen outHeader->nFlags = 0; 2952ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 296199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 297199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia inHeader->nFilledLen = 0; 298199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia } else { 299199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia inInfo->mOwnedByUs = false; 300199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia inQueue.erase(inQueue.begin()); 301199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia inInfo = NULL; 302199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia notifyEmptyBufferDone(inHeader); 303199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia inHeader = NULL; 304199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia } 3052ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 3062ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen outInfo->mOwnedByUs = false; 3072ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen outQueue.erase(outQueue.begin()); 3082ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen outInfo = NULL; 3092ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen notifyFillBufferDone(outHeader); 3102ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen outHeader = NULL; 3112ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen } 3122ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen} 3132ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 3142ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 3152ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen// static 3162ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissenint SoftGSM::DecodeGSM(gsm handle, 3172ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen int16_t *out, uint8_t *in, size_t inSize) { 3182ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 3192ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen int ret = 0; 3202ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen while (inSize > 0) { 3212ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen gsm_decode(handle, in, out); 3222ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen in += 33; 3232ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen inSize -= 33; 3242ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen out += 160; 3252ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen ret += 160; 3262ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen gsm_decode(handle, in, out); 3272ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen in += 32; 3282ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen inSize -= 32; 3292ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen out += 160; 3302ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen ret += 160; 3312ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen } 3322ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen return ret; 3332ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen} 3342ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 335cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissenvoid SoftGSM::onPortFlushCompleted(OMX_U32 portIndex) { 336cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen if (portIndex == 0) { 337cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen gsm_destroy(mGsm); 338cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen mGsm = gsm_create(); 339cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen int msopt = 1; 340cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen gsm_option(mGsm, GSM_OPT_WAV49, &msopt); 341cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen } 342cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen} 343cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen 344cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissenvoid SoftGSM::onReset() { 345cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen gsm_destroy(mGsm); 346cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen mGsm = gsm_create(); 347cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen int msopt = 1; 348cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen gsm_option(mGsm, GSM_OPT_WAV49, &msopt); 349cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen mSignalledError = false; 350cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen} 351cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen 352cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen 353cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen 3542ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 3552ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen} // namespace android 3562ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 3572ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissenandroid::SoftOMXComponent *createSoftOMXComponent( 3582ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen const char *name, const OMX_CALLBACKTYPE *callbacks, 3592ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen OMX_PTR appData, OMX_COMPONENTTYPE **component) { 3602ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen return new android::SoftGSM(name, callbacks, appData, component); 3612ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen} 3622ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen 363