1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define LOG_NDEBUG 0 18#define LOG_TAG "SoftGSM" 19#include <utils/Log.h> 20 21#include "SoftGSM.h" 22 23#include <media/stagefright/foundation/ADebug.h> 24#include <media/stagefright/MediaDefs.h> 25 26namespace android { 27 28template<class T> 29static void InitOMXParams(T *params) { 30 params->nSize = sizeof(T); 31 params->nVersion.s.nVersionMajor = 1; 32 params->nVersion.s.nVersionMinor = 0; 33 params->nVersion.s.nRevision = 0; 34 params->nVersion.s.nStep = 0; 35} 36 37// Microsoft WAV GSM encoding packs two GSM frames into 65 bytes. 38static const int kMSGSMFrameSize = 65; 39 40SoftGSM::SoftGSM( 41 const char *name, 42 const OMX_CALLBACKTYPE *callbacks, 43 OMX_PTR appData, 44 OMX_COMPONENTTYPE **component) 45 : SimpleSoftOMXComponent(name, callbacks, appData, component), 46 mSignalledError(false) { 47 48 CHECK(!strcmp(name, "OMX.google.gsm.decoder")); 49 50 mGsm = gsm_create(); 51 CHECK(mGsm); 52 int msopt = 1; 53 gsm_option(mGsm, GSM_OPT_WAV49, &msopt); 54 55 initPorts(); 56} 57 58SoftGSM::~SoftGSM() { 59 gsm_destroy(mGsm); 60} 61 62void SoftGSM::initPorts() { 63 OMX_PARAM_PORTDEFINITIONTYPE def; 64 InitOMXParams(&def); 65 66 def.nPortIndex = 0; 67 def.eDir = OMX_DirInput; 68 def.nBufferCountMin = kNumBuffers; 69 def.nBufferCountActual = def.nBufferCountMin; 70 def.nBufferSize = 1024 / kMSGSMFrameSize * kMSGSMFrameSize; 71 def.bEnabled = OMX_TRUE; 72 def.bPopulated = OMX_FALSE; 73 def.eDomain = OMX_PortDomainAudio; 74 def.bBuffersContiguous = OMX_FALSE; 75 def.nBufferAlignment = 1; 76 77 def.format.audio.cMIMEType = 78 const_cast<char *>(MEDIA_MIMETYPE_AUDIO_MSGSM); 79 80 def.format.audio.pNativeRender = NULL; 81 def.format.audio.bFlagErrorConcealment = OMX_FALSE; 82 def.format.audio.eEncoding = OMX_AUDIO_CodingGSMFR; 83 84 addPort(def); 85 86 def.nPortIndex = 1; 87 def.eDir = OMX_DirOutput; 88 def.nBufferCountMin = kNumBuffers; 89 def.nBufferCountActual = def.nBufferCountMin; 90 def.nBufferSize = kMaxNumSamplesPerFrame * sizeof(int16_t); 91 def.bEnabled = OMX_TRUE; 92 def.bPopulated = OMX_FALSE; 93 def.eDomain = OMX_PortDomainAudio; 94 def.bBuffersContiguous = OMX_FALSE; 95 def.nBufferAlignment = 2; 96 97 def.format.audio.cMIMEType = const_cast<char *>("audio/raw"); 98 def.format.audio.pNativeRender = NULL; 99 def.format.audio.bFlagErrorConcealment = OMX_FALSE; 100 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 101 102 addPort(def); 103} 104 105OMX_ERRORTYPE SoftGSM::internalGetParameter( 106 OMX_INDEXTYPE index, OMX_PTR params) { 107 switch (index) { 108 case OMX_IndexParamAudioPortFormat: 109 { 110 OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams = 111 (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params; 112 113 if (!isValidOMXParam(formatParams)) { 114 return OMX_ErrorBadParameter; 115 } 116 117 if (formatParams->nPortIndex > 1) { 118 return OMX_ErrorUndefined; 119 } 120 121 if (formatParams->nIndex > 0) { 122 return OMX_ErrorNoMore; 123 } 124 125 formatParams->eEncoding = 126 (formatParams->nPortIndex == 0) 127 ? OMX_AUDIO_CodingGSMFR : OMX_AUDIO_CodingPCM; 128 129 return OMX_ErrorNone; 130 } 131 132 case OMX_IndexParamAudioPcm: 133 { 134 OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 135 (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 136 137 if (!isValidOMXParam(pcmParams)) { 138 return OMX_ErrorBadParameter; 139 } 140 141 if (pcmParams->nPortIndex > 1) { 142 return OMX_ErrorUndefined; 143 } 144 145 pcmParams->eNumData = OMX_NumericalDataSigned; 146 pcmParams->eEndian = OMX_EndianBig; 147 pcmParams->bInterleaved = OMX_TRUE; 148 pcmParams->nBitPerSample = 16; 149 pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear; 150 pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF; 151 pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF; 152 153 pcmParams->nChannels = 1; 154 pcmParams->nSamplingRate = 8000; 155 156 return OMX_ErrorNone; 157 } 158 159 default: 160 return SimpleSoftOMXComponent::internalGetParameter(index, params); 161 } 162} 163 164OMX_ERRORTYPE SoftGSM::internalSetParameter( 165 OMX_INDEXTYPE index, const OMX_PTR params) { 166 switch (index) { 167 case OMX_IndexParamAudioPcm: 168 { 169 OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 170 (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 171 172 if (!isValidOMXParam(pcmParams)) { 173 return OMX_ErrorBadParameter; 174 } 175 176 if (pcmParams->nPortIndex != 0 && pcmParams->nPortIndex != 1) { 177 return OMX_ErrorUndefined; 178 } 179 180 if (pcmParams->nChannels != 1) { 181 return OMX_ErrorUndefined; 182 } 183 184 if (pcmParams->nSamplingRate != 8000) { 185 return OMX_ErrorUndefined; 186 } 187 188 return OMX_ErrorNone; 189 } 190 191 case OMX_IndexParamAudioPortFormat: 192 { 193 const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams = 194 (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params; 195 196 if (!isValidOMXParam(formatParams)) { 197 return OMX_ErrorBadParameter; 198 } 199 200 if (formatParams->nPortIndex > 1) { 201 return OMX_ErrorUndefined; 202 } 203 204 if ((formatParams->nPortIndex == 0 205 && formatParams->eEncoding != OMX_AUDIO_CodingGSMFR) 206 || (formatParams->nPortIndex == 1 207 && formatParams->eEncoding != OMX_AUDIO_CodingPCM)) { 208 return OMX_ErrorUndefined; 209 } 210 211 return OMX_ErrorNone; 212 } 213 214 case OMX_IndexParamStandardComponentRole: 215 { 216 const OMX_PARAM_COMPONENTROLETYPE *roleParams = 217 (const OMX_PARAM_COMPONENTROLETYPE *)params; 218 219 if (!isValidOMXParam(roleParams)) { 220 return OMX_ErrorBadParameter; 221 } 222 223 if (strncmp((const char *)roleParams->cRole, 224 "audio_decoder.gsm", 225 OMX_MAX_STRINGNAME_SIZE - 1)) { 226 return OMX_ErrorUndefined; 227 } 228 229 return OMX_ErrorNone; 230 } 231 232 default: 233 return SimpleSoftOMXComponent::internalSetParameter(index, params); 234 } 235} 236 237void SoftGSM::onQueueFilled(OMX_U32 /* portIndex */) { 238 if (mSignalledError) { 239 return; 240 } 241 242 List<BufferInfo *> &inQueue = getPortQueue(0); 243 List<BufferInfo *> &outQueue = getPortQueue(1); 244 245 while (!inQueue.empty() && !outQueue.empty()) { 246 BufferInfo *inInfo = *inQueue.begin(); 247 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 248 249 BufferInfo *outInfo = *outQueue.begin(); 250 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 251 252 if ((inHeader->nFlags & OMX_BUFFERFLAG_EOS) && inHeader->nFilledLen == 0) { 253 inQueue.erase(inQueue.begin()); 254 inInfo->mOwnedByUs = false; 255 notifyEmptyBufferDone(inHeader); 256 257 outHeader->nFilledLen = 0; 258 outHeader->nFlags = OMX_BUFFERFLAG_EOS; 259 260 outQueue.erase(outQueue.begin()); 261 outInfo->mOwnedByUs = false; 262 notifyFillBufferDone(outHeader); 263 return; 264 } 265 266 if (inHeader->nFilledLen > kMaxNumSamplesPerFrame) { 267 ALOGE("input buffer too large (%d).", inHeader->nFilledLen); 268 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 269 mSignalledError = true; 270 } 271 272 if(((inHeader->nFilledLen / kMSGSMFrameSize) * kMSGSMFrameSize) != inHeader->nFilledLen) { 273 ALOGE("input buffer not multiple of %d (%d).", kMSGSMFrameSize, inHeader->nFilledLen); 274 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 275 mSignalledError = true; 276 } 277 278 if (outHeader->nAllocLen < (inHeader->nFilledLen / kMSGSMFrameSize) * 320) { 279 ALOGE("output buffer is not large enough (%d).", outHeader->nAllocLen); 280 android_errorWriteLog(0x534e4554, "27793367"); 281 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 282 mSignalledError = true; 283 return; 284 } 285 286 uint8_t *inputptr = inHeader->pBuffer + inHeader->nOffset; 287 288 int n = mSignalledError ? 0 : DecodeGSM(mGsm, 289 reinterpret_cast<int16_t *>(outHeader->pBuffer), inputptr, inHeader->nFilledLen); 290 291 outHeader->nTimeStamp = inHeader->nTimeStamp; 292 outHeader->nOffset = 0; 293 outHeader->nFilledLen = n * sizeof(int16_t); 294 outHeader->nFlags = 0; 295 296 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 297 inHeader->nFilledLen = 0; 298 } else { 299 inInfo->mOwnedByUs = false; 300 inQueue.erase(inQueue.begin()); 301 inInfo = NULL; 302 notifyEmptyBufferDone(inHeader); 303 inHeader = NULL; 304 } 305 306 outInfo->mOwnedByUs = false; 307 outQueue.erase(outQueue.begin()); 308 outInfo = NULL; 309 notifyFillBufferDone(outHeader); 310 outHeader = NULL; 311 } 312} 313 314 315// static 316int SoftGSM::DecodeGSM(gsm handle, 317 int16_t *out, uint8_t *in, size_t inSize) { 318 319 int ret = 0; 320 while (inSize > 0) { 321 gsm_decode(handle, in, out); 322 in += 33; 323 inSize -= 33; 324 out += 160; 325 ret += 160; 326 gsm_decode(handle, in, out); 327 in += 32; 328 inSize -= 32; 329 out += 160; 330 ret += 160; 331 } 332 return ret; 333} 334 335void SoftGSM::onPortFlushCompleted(OMX_U32 portIndex) { 336 if (portIndex == 0) { 337 gsm_destroy(mGsm); 338 mGsm = gsm_create(); 339 int msopt = 1; 340 gsm_option(mGsm, GSM_OPT_WAV49, &msopt); 341 } 342} 343 344void SoftGSM::onReset() { 345 gsm_destroy(mGsm); 346 mGsm = gsm_create(); 347 int msopt = 1; 348 gsm_option(mGsm, GSM_OPT_WAV49, &msopt); 349 mSignalledError = false; 350} 351 352 353 354 355} // namespace android 356 357android::SoftOMXComponent *createSoftOMXComponent( 358 const char *name, const OMX_CALLBACKTYPE *callbacks, 359 OMX_PTR appData, OMX_COMPONENTTYPE **component) { 360 return new android::SoftGSM(name, callbacks, appData, component); 361} 362 363