SoftAMR.cpp revision 55e5218fd53f4da5c1fbad539ed960c04a883b0b
1/* 2 * Copyright (C) 2011 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 "SoftAMR" 19#include <utils/Log.h> 20 21#include "SoftAMR.h" 22 23#include "gsmamr_dec.h" 24#include "pvamrwbdecoder.h" 25 26#include <media/stagefright/foundation/ADebug.h> 27 28namespace android { 29 30template<class T> 31static void InitOMXParams(T *params) { 32 params->nSize = sizeof(T); 33 params->nVersion.s.nVersionMajor = 1; 34 params->nVersion.s.nVersionMinor = 0; 35 params->nVersion.s.nRevision = 0; 36 params->nVersion.s.nStep = 0; 37} 38 39SoftAMR::SoftAMR( 40 const char *name, 41 const OMX_CALLBACKTYPE *callbacks, 42 OMX_PTR appData, 43 OMX_COMPONENTTYPE **component) 44 : SimpleSoftOMXComponent(name, callbacks, appData, component), 45 mMode(MODE_NARROW), 46 mState(NULL), 47 mDecoderBuf(NULL), 48 mDecoderCookie(NULL), 49 mInputBufferCount(0), 50 mAnchorTimeUs(0), 51 mNumSamplesOutput(0), 52 mSignalledError(false), 53 mOutputPortSettingsChange(NONE) { 54 if (!strcmp(name, "OMX.google.amrwb.decoder")) { 55 mMode = MODE_WIDE; 56 } else { 57 CHECK(!strcmp(name, "OMX.google.amrnb.decoder")); 58 } 59 60 initPorts(); 61 CHECK_EQ(initDecoder(), (status_t)OK); 62} 63 64SoftAMR::~SoftAMR() { 65 if (mMode == MODE_NARROW) { 66 GSMDecodeFrameExit(&mState); 67 mState = NULL; 68 } else { 69 free(mDecoderBuf); 70 mDecoderBuf = NULL; 71 72 mState = NULL; 73 mDecoderCookie = NULL; 74 } 75} 76 77void SoftAMR::initPorts() { 78 OMX_PARAM_PORTDEFINITIONTYPE def; 79 InitOMXParams(&def); 80 81 def.nPortIndex = 0; 82 def.eDir = OMX_DirInput; 83 def.nBufferCountMin = kNumBuffers; 84 def.nBufferCountActual = def.nBufferCountMin; 85 def.nBufferSize = 8192; 86 def.bEnabled = OMX_TRUE; 87 def.bPopulated = OMX_FALSE; 88 def.eDomain = OMX_PortDomainAudio; 89 def.bBuffersContiguous = OMX_FALSE; 90 def.nBufferAlignment = 1; 91 92 def.format.audio.cMIMEType = 93 mMode == MODE_NARROW 94 ? const_cast<char *>("audio/amr") 95 : const_cast<char *>("audio/amrwb"); 96 97 def.format.audio.pNativeRender = NULL; 98 def.format.audio.bFlagErrorConcealment = OMX_FALSE; 99 def.format.audio.eEncoding = OMX_AUDIO_CodingAMR; 100 101 addPort(def); 102 103 def.nPortIndex = 1; 104 def.eDir = OMX_DirOutput; 105 def.nBufferCountMin = kNumBuffers; 106 def.nBufferCountActual = def.nBufferCountMin; 107 108 def.nBufferSize = 109 (mMode == MODE_NARROW ? kNumSamplesPerFrameNB : kNumSamplesPerFrameWB) 110 * sizeof(int16_t); 111 112 def.bEnabled = OMX_TRUE; 113 def.bPopulated = OMX_FALSE; 114 def.eDomain = OMX_PortDomainAudio; 115 def.bBuffersContiguous = OMX_FALSE; 116 def.nBufferAlignment = 2; 117 118 def.format.audio.cMIMEType = const_cast<char *>("audio/raw"); 119 def.format.audio.pNativeRender = NULL; 120 def.format.audio.bFlagErrorConcealment = OMX_FALSE; 121 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 122 123 addPort(def); 124} 125 126status_t SoftAMR::initDecoder() { 127 if (mMode == MODE_NARROW) { 128 Word16 err = GSMInitDecode(&mState, (Word8 *)"AMRNBDecoder"); 129 130 if (err != 0) { 131 return UNKNOWN_ERROR; 132 } 133 } else { 134 int32_t memReq = pvDecoder_AmrWbMemRequirements(); 135 mDecoderBuf = malloc(memReq); 136 137 pvDecoder_AmrWb_Init(&mState, mDecoderBuf, &mDecoderCookie); 138 } 139 140 return OK; 141} 142 143OMX_ERRORTYPE SoftAMR::internalGetParameter( 144 OMX_INDEXTYPE index, OMX_PTR params) { 145 switch (index) { 146 case OMX_IndexParamAudioAmr: 147 { 148 OMX_AUDIO_PARAM_AMRTYPE *amrParams = 149 (OMX_AUDIO_PARAM_AMRTYPE *)params; 150 151 if (!isValidOMXParam(amrParams)) { 152 return OMX_ErrorBadParameter; 153 } 154 155 if (amrParams->nPortIndex != 0) { 156 return OMX_ErrorUndefined; 157 } 158 159 amrParams->nChannels = 1; 160 amrParams->eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff; 161 amrParams->eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; 162 163 if (!isConfigured()) { 164 amrParams->nBitRate = 0; 165 amrParams->eAMRBandMode = OMX_AUDIO_AMRBandModeUnused; 166 } else { 167 amrParams->nBitRate = 0; 168 amrParams->eAMRBandMode = 169 mMode == MODE_NARROW 170 ? OMX_AUDIO_AMRBandModeNB0 : OMX_AUDIO_AMRBandModeWB0; 171 } 172 173 return OMX_ErrorNone; 174 } 175 176 case OMX_IndexParamAudioPcm: 177 { 178 OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 179 (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 180 181 if (!isValidOMXParam(pcmParams)) { 182 return OMX_ErrorBadParameter; 183 } 184 185 if (pcmParams->nPortIndex != 1) { 186 return OMX_ErrorUndefined; 187 } 188 189 pcmParams->nChannels = 1; 190 pcmParams->eNumData = OMX_NumericalDataSigned; 191 pcmParams->eEndian = OMX_EndianBig; 192 pcmParams->bInterleaved = OMX_TRUE; 193 pcmParams->nBitPerSample = 16; 194 195 pcmParams->nSamplingRate = 196 (mMode == MODE_NARROW) ? kSampleRateNB : kSampleRateWB; 197 198 pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear; 199 pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF; 200 pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF; 201 202 return OMX_ErrorNone; 203 } 204 205 default: 206 return SimpleSoftOMXComponent::internalGetParameter(index, params); 207 } 208} 209 210OMX_ERRORTYPE SoftAMR::internalSetParameter( 211 OMX_INDEXTYPE index, const OMX_PTR params) { 212 switch (index) { 213 case OMX_IndexParamStandardComponentRole: 214 { 215 const OMX_PARAM_COMPONENTROLETYPE *roleParams = 216 (const OMX_PARAM_COMPONENTROLETYPE *)params; 217 218 if (!isValidOMXParam(roleParams)) { 219 return OMX_ErrorBadParameter; 220 } 221 222 if (mMode == MODE_NARROW) { 223 if (strncmp((const char *)roleParams->cRole, 224 "audio_decoder.amrnb", 225 OMX_MAX_STRINGNAME_SIZE - 1)) { 226 return OMX_ErrorUndefined; 227 } 228 } else { 229 if (strncmp((const char *)roleParams->cRole, 230 "audio_decoder.amrwb", 231 OMX_MAX_STRINGNAME_SIZE - 1)) { 232 return OMX_ErrorUndefined; 233 } 234 } 235 236 return OMX_ErrorNone; 237 } 238 239 case OMX_IndexParamAudioAmr: 240 { 241 const OMX_AUDIO_PARAM_AMRTYPE *aacParams = 242 (const OMX_AUDIO_PARAM_AMRTYPE *)params; 243 244 if (!isValidOMXParam(aacParams)) { 245 return OMX_ErrorBadParameter; 246 } 247 248 if (aacParams->nPortIndex != 0) { 249 return OMX_ErrorUndefined; 250 } 251 252 return OMX_ErrorNone; 253 } 254 255 case OMX_IndexParamAudioPcm: 256 { 257 const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 258 (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 259 260 if (!isValidOMXParam(pcmParams)) { 261 return OMX_ErrorBadParameter; 262 } 263 264 if (pcmParams->nPortIndex != 1) { 265 return OMX_ErrorUndefined; 266 } 267 268 return OMX_ErrorNone; 269 } 270 271 default: 272 return SimpleSoftOMXComponent::internalSetParameter(index, params); 273 } 274} 275 276bool SoftAMR::isConfigured() const { 277 return mInputBufferCount > 0; 278} 279 280static size_t getFrameSize(unsigned FT) { 281 static const size_t kFrameSizeWB[10] = { 282 132, 177, 253, 285, 317, 365, 397, 461, 477, 40 283 }; 284 285 if (FT >= 10) { 286 return 1; 287 } 288 289 size_t frameSize = kFrameSizeWB[FT]; 290 291 // Round up bits to bytes and add 1 for the header byte. 292 frameSize = (frameSize + 7) / 8 + 1; 293 294 return frameSize; 295} 296 297void SoftAMR::onQueueFilled(OMX_U32 portIndex) { 298 List<BufferInfo *> &inQueue = getPortQueue(0); 299 List<BufferInfo *> &outQueue = getPortQueue(1); 300 301 if (mSignalledError || mOutputPortSettingsChange != NONE) { 302 return; 303 } 304 305 while (!inQueue.empty() && !outQueue.empty()) { 306 BufferInfo *inInfo = *inQueue.begin(); 307 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 308 309 if (inHeader->nFilledLen == 0) { 310 inInfo->mOwnedByUs = false; 311 inQueue.erase(inQueue.begin()); 312 notifyEmptyBufferDone(inHeader); 313 continue; 314 } 315 316 BufferInfo *outInfo = *outQueue.begin(); 317 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 318 319 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 320 inQueue.erase(inQueue.begin()); 321 inInfo->mOwnedByUs = false; 322 notifyEmptyBufferDone(inHeader); 323 324 outHeader->nFilledLen = 0; 325 outHeader->nFlags = OMX_BUFFERFLAG_EOS; 326 327 outQueue.erase(outQueue.begin()); 328 outInfo->mOwnedByUs = false; 329 notifyFillBufferDone(outHeader); 330 return; 331 } 332 333 if (inHeader->nOffset == 0) { 334 mAnchorTimeUs = inHeader->nTimeStamp; 335 mNumSamplesOutput = 0; 336 } 337 338 const uint8_t *inputPtr = inHeader->pBuffer + inHeader->nOffset; 339 int32_t numBytesRead; 340 341 if (mMode == MODE_NARROW) { 342 if (outHeader->nAllocLen < kNumSamplesPerFrameNB * sizeof(int16_t)) { 343 ALOGE("b/27662364: NB expected output buffer %zu bytes vs %u", 344 kNumSamplesPerFrameNB * sizeof(int16_t), outHeader->nAllocLen); 345 android_errorWriteLog(0x534e4554, "27662364"); 346 notify(OMX_EventError, OMX_ErrorOverflow, 0, NULL); 347 mSignalledError = true; 348 return; 349 } 350 351 int16 mode = ((inputPtr[0] >> 3) & 0x0f); 352 // for WMF since MIME_IETF is used when calling AMRDecode. 353 size_t frameSize = WmfDecBytesPerFrame[mode] + 1; 354 355 if (inHeader->nFilledLen < frameSize) { 356 ALOGE("b/27662364: expected %zu bytes vs %u", frameSize, inHeader->nFilledLen); 357 notify(OMX_EventError, OMX_ErrorStreamCorrupt, 0, NULL); 358 mSignalledError = true; 359 return; 360 } 361 362 numBytesRead = 363 AMRDecode(mState, 364 (Frame_Type_3GPP)((inputPtr[0] >> 3) & 0x0f), 365 (UWord8 *)&inputPtr[1], 366 reinterpret_cast<int16_t *>(outHeader->pBuffer), 367 MIME_IETF); 368 369 if (numBytesRead == -1) { 370 ALOGE("PV AMR decoder AMRDecode() call failed"); 371 372 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 373 mSignalledError = true; 374 375 return; 376 } 377 378 ++numBytesRead; // Include the frame type header byte. 379 380 if (static_cast<size_t>(numBytesRead) > inHeader->nFilledLen) { 381 // This is bad, should never have happened, but did. Abort now. 382 383 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 384 mSignalledError = true; 385 386 return; 387 } 388 } else { 389 if (outHeader->nAllocLen < kNumSamplesPerFrameWB * sizeof(int16_t)) { 390 ALOGE("b/27662364: WB expected output buffer %zu bytes vs %u", 391 kNumSamplesPerFrameWB * sizeof(int16_t), outHeader->nAllocLen); 392 android_errorWriteLog(0x534e4554, "27662364"); 393 notify(OMX_EventError, OMX_ErrorOverflow, 0, NULL); 394 mSignalledError = true; 395 return; 396 } 397 398 int16 mode = ((inputPtr[0] >> 3) & 0x0f); 399 400 if (mode >= 10 && mode <= 13) { 401 ALOGE("encountered illegal frame type %d in AMR WB content.", 402 mode); 403 404 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 405 mSignalledError = true; 406 407 return; 408 } 409 410 size_t frameSize = getFrameSize(mode); 411 if (inHeader->nFilledLen < frameSize) { 412 ALOGE("b/27662364: expected %zu bytes vs %u", frameSize, inHeader->nFilledLen); 413 notify(OMX_EventError, OMX_ErrorStreamCorrupt, 0, NULL); 414 mSignalledError = true; 415 return; 416 } 417 418 int16_t *outPtr = (int16_t *)outHeader->pBuffer; 419 420 if (mode >= 9) { 421 // Produce silence instead of comfort noise and for 422 // speech lost/no data. 423 memset(outPtr, 0, kNumSamplesPerFrameWB * sizeof(int16_t)); 424 } else if (mode < 9) { 425 int16 frameType; 426 RX_State_wb rx_state; 427 mime_unsorting( 428 const_cast<uint8_t *>(&inputPtr[1]), 429 mInputSampleBuffer, 430 &frameType, &mode, 1, &rx_state); 431 432 int16_t numSamplesOutput; 433 pvDecoder_AmrWb( 434 mode, mInputSampleBuffer, 435 outPtr, 436 &numSamplesOutput, 437 mDecoderBuf, frameType, mDecoderCookie); 438 439 CHECK_EQ((int)numSamplesOutput, (int)kNumSamplesPerFrameWB); 440 441 for (int i = 0; i < kNumSamplesPerFrameWB; ++i) { 442 /* Delete the 2 LSBs (14-bit output) */ 443 outPtr[i] &= 0xfffC; 444 } 445 } 446 447 numBytesRead = frameSize; 448 } 449 450 inHeader->nOffset += numBytesRead; 451 inHeader->nFilledLen -= numBytesRead; 452 453 outHeader->nFlags = 0; 454 outHeader->nOffset = 0; 455 456 if (mMode == MODE_NARROW) { 457 outHeader->nFilledLen = kNumSamplesPerFrameNB * sizeof(int16_t); 458 459 outHeader->nTimeStamp = 460 mAnchorTimeUs 461 + (mNumSamplesOutput * 1000000ll) / kSampleRateNB; 462 463 mNumSamplesOutput += kNumSamplesPerFrameNB; 464 } else { 465 outHeader->nFilledLen = kNumSamplesPerFrameWB * sizeof(int16_t); 466 467 outHeader->nTimeStamp = 468 mAnchorTimeUs 469 + (mNumSamplesOutput * 1000000ll) / kSampleRateWB; 470 471 mNumSamplesOutput += kNumSamplesPerFrameWB; 472 } 473 474 if (inHeader->nFilledLen == 0) { 475 inInfo->mOwnedByUs = false; 476 inQueue.erase(inQueue.begin()); 477 inInfo = NULL; 478 notifyEmptyBufferDone(inHeader); 479 inHeader = NULL; 480 } 481 482 outInfo->mOwnedByUs = false; 483 outQueue.erase(outQueue.begin()); 484 outInfo = NULL; 485 notifyFillBufferDone(outHeader); 486 outHeader = NULL; 487 488 ++mInputBufferCount; 489 } 490} 491 492void SoftAMR::onPortFlushCompleted(OMX_U32 portIndex) { 493} 494 495void SoftAMR::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) { 496 if (portIndex != 1) { 497 return; 498 } 499 500 switch (mOutputPortSettingsChange) { 501 case NONE: 502 break; 503 504 case AWAITING_DISABLED: 505 { 506 CHECK(!enabled); 507 mOutputPortSettingsChange = AWAITING_ENABLED; 508 break; 509 } 510 511 default: 512 { 513 CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED); 514 CHECK(enabled); 515 mOutputPortSettingsChange = NONE; 516 break; 517 } 518 } 519} 520 521void SoftAMR::onReset() { 522 mSignalledError = false; 523 mOutputPortSettingsChange = NONE; 524} 525 526} // namespace android 527 528android::SoftOMXComponent *createSoftOMXComponent( 529 const char *name, const OMX_CALLBACKTYPE *callbacks, 530 OMX_PTR appData, OMX_COMPONENTTYPE **component) { 531 return new android::SoftAMR(name, callbacks, appData, component); 532} 533 534