1 /* ------------------------------------------------------------------ 2 * Copyright (C) 1998-2009 PacketVideo 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 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 #include "oscl_base.h" 19 #include "pv_omxdefs.h" 20 #include "omx_amr_component.h" 21 22 #if PROXY_INTERFACE 23 #include "omx_proxy_interface.h" 24 #endif 25 26 // Use default DLL entry point 27 #ifndef OSCL_DLL_H_INCLUDED 28 #include "oscl_dll.h" 29 #endif 30 31 #define OMX_HALFRANGE_THRESHOLD 0x7FFFFFFF 32 /**** The duration of one output AMR frame (in microsec) is fixed and equal to 20000 microsec - needed for timestamp updates ****/ 33 /**** Note that AMR sampling rate is always 8khz, so a frame of 20000 microsec always corresponds to 160 (16-bit) samples = 320 bytes */ 34 #define OMX_AMR_DEC_FRAME_INTERVAL 20000 35 36 OSCL_DLL_ENTRY_POINT_DEFAULT() 37 38 // This function is called by OMX_GetHandle and it creates an instance of the amr component AO 39 OSCL_EXPORT_REF OMX_ERRORTYPE AmrOmxComponentFactory(OMX_OUT OMX_HANDLETYPE* pHandle, OMX_IN OMX_PTR pAppData, OMX_PTR pProxy, OMX_STRING aOmxLibName, OMX_PTR &aOmxLib, OMX_PTR aOsclUuid, OMX_U32 &aRefCount) 40 { 41 OSCL_UNUSED_ARG(aOmxLibName); 42 OSCL_UNUSED_ARG(aOmxLib); 43 OSCL_UNUSED_ARG(aOsclUuid); 44 OSCL_UNUSED_ARG(aRefCount); 45 46 OpenmaxAmrAO* pOpenmaxAOType; 47 OMX_ERRORTYPE Status; 48 49 // move InitAmrOmxComponentFields content to actual constructor 50 51 pOpenmaxAOType = (OpenmaxAmrAO*) OSCL_NEW(OpenmaxAmrAO, ()); 52 53 if (NULL == pOpenmaxAOType) 54 { 55 return OMX_ErrorInsufficientResources; 56 } 57 58 //Call the construct component to initialize OMX types 59 Status = pOpenmaxAOType->ConstructComponent(pAppData, pProxy); 60 61 *pHandle = pOpenmaxAOType->GetOmxHandle(); 62 63 return Status; 64 /////////////////////////////////////////////////////////////////////////////////////// 65 } 66 67 // This function is called by OMX_FreeHandle when component AO needs to be destroyed 68 OSCL_EXPORT_REF OMX_ERRORTYPE AmrOmxComponentDestructor(OMX_IN OMX_HANDLETYPE pHandle, OMX_PTR &aOmxLib, OMX_PTR aOsclUuid, OMX_U32 &aRefCount) 69 { 70 OSCL_UNUSED_ARG(aOmxLib); 71 OSCL_UNUSED_ARG(aOsclUuid); 72 OSCL_UNUSED_ARG(aRefCount); 73 74 // get pointer to component AO 75 OpenmaxAmrAO* pOpenmaxAOType = (OpenmaxAmrAO*)((OMX_COMPONENTTYPE*)pHandle)->pComponentPrivate; 76 77 // clean up decoder, OMX component stuff 78 pOpenmaxAOType->DestroyComponent(); 79 80 // destroy the AO class 81 OSCL_DELETE(pOpenmaxAOType); 82 83 return OMX_ErrorNone; 84 } 85 86 #if DYNAMIC_LOAD_OMX_AMR_COMPONENT 87 class AmrOmxSharedLibraryInterface: public OsclSharedLibraryInterface, 88 public OmxSharedLibraryInterface 89 90 { 91 public: 92 OsclAny *QueryOmxComponentInterface(const OsclUuid& aOmxTypeId, const OsclUuid& aInterfaceId) 93 { 94 if (PV_OMX_AMRDEC_UUID == aOmxTypeId) 95 { 96 if (PV_OMX_CREATE_INTERFACE == aInterfaceId) 97 { 98 return ((OsclAny*)(&AmrOmxComponentFactory)); 99 } 100 else if (PV_OMX_DESTROY_INTERFACE == aInterfaceId) 101 { 102 return ((OsclAny*)(&AmrOmxComponentDestructor)); 103 } 104 } 105 return NULL; 106 }; 107 OsclAny *SharedLibraryLookup(const OsclUuid& aInterfaceId) 108 { 109 if (aInterfaceId == PV_OMX_SHARED_INTERFACE) 110 { 111 return OSCL_STATIC_CAST(OmxSharedLibraryInterface*, this); 112 } 113 return NULL; 114 }; 115 116 AmrOmxSharedLibraryInterface() {}; 117 }; 118 119 // function to obtain the interface object from the shared library 120 extern "C" 121 { 122 OSCL_EXPORT_REF OsclAny* PVGetInterface() 123 { 124 return (OsclAny*) OSCL_NEW(AmrOmxSharedLibraryInterface, ()); 125 } 126 OSCL_EXPORT_REF void PVReleaseInterface(OsclSharedLibraryInterface* aInstance) 127 { 128 AmrOmxSharedLibraryInterface* module = (AmrOmxSharedLibraryInterface*)aInstance; 129 OSCL_DELETE(module); 130 } 131 } 132 133 #endif 134 135 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 136 137 OMX_ERRORTYPE OpenmaxAmrAO::ConstructComponent(OMX_PTR pAppData, OMX_PTR pProxy) 138 { 139 ComponentPortType* pInPort, *pOutPort; 140 OMX_ERRORTYPE Status; 141 142 iNumPorts = 2; 143 iOmxComponent.nSize = sizeof(OMX_COMPONENTTYPE); 144 iOmxComponent.pComponentPrivate = (OMX_PTR) this; // pComponentPrivate points to THIS component AO class 145 ipComponentProxy = pProxy; 146 iOmxComponent.pApplicationPrivate = pAppData; // init the App data 147 148 149 #if PROXY_INTERFACE 150 iPVCapabilityFlags.iIsOMXComponentMultiThreaded = OMX_TRUE; 151 152 iOmxComponent.SendCommand = OpenmaxAmrAO::BaseComponentProxySendCommand; 153 iOmxComponent.GetParameter = OpenmaxAmrAO::BaseComponentProxyGetParameter; 154 iOmxComponent.SetParameter = OpenmaxAmrAO::BaseComponentProxySetParameter; 155 iOmxComponent.GetConfig = OpenmaxAmrAO::BaseComponentProxyGetConfig; 156 iOmxComponent.SetConfig = OpenmaxAmrAO::BaseComponentProxySetConfig; 157 iOmxComponent.GetExtensionIndex = OpenmaxAmrAO::BaseComponentProxyGetExtensionIndex; 158 iOmxComponent.GetState = OpenmaxAmrAO::BaseComponentProxyGetState; 159 iOmxComponent.UseBuffer = OpenmaxAmrAO::BaseComponentProxyUseBuffer; 160 iOmxComponent.AllocateBuffer = OpenmaxAmrAO::BaseComponentProxyAllocateBuffer; 161 iOmxComponent.FreeBuffer = OpenmaxAmrAO::BaseComponentProxyFreeBuffer; 162 iOmxComponent.EmptyThisBuffer = OpenmaxAmrAO::BaseComponentProxyEmptyThisBuffer; 163 iOmxComponent.FillThisBuffer = OpenmaxAmrAO::BaseComponentProxyFillThisBuffer; 164 165 #else 166 iPVCapabilityFlags.iIsOMXComponentMultiThreaded = OMX_FALSE; 167 168 iOmxComponent.SendCommand = OpenmaxAmrAO::BaseComponentSendCommand; 169 iOmxComponent.GetParameter = OpenmaxAmrAO::BaseComponentGetParameter; 170 iOmxComponent.SetParameter = OpenmaxAmrAO::BaseComponentSetParameter; 171 iOmxComponent.GetConfig = OpenmaxAmrAO::BaseComponentGetConfig; 172 iOmxComponent.SetConfig = OpenmaxAmrAO::BaseComponentSetConfig; 173 iOmxComponent.GetExtensionIndex = OpenmaxAmrAO::BaseComponentGetExtensionIndex; 174 iOmxComponent.GetState = OpenmaxAmrAO::BaseComponentGetState; 175 iOmxComponent.UseBuffer = OpenmaxAmrAO::BaseComponentUseBuffer; 176 iOmxComponent.AllocateBuffer = OpenmaxAmrAO::BaseComponentAllocateBuffer; 177 iOmxComponent.FreeBuffer = OpenmaxAmrAO::BaseComponentFreeBuffer; 178 iOmxComponent.EmptyThisBuffer = OpenmaxAmrAO::BaseComponentEmptyThisBuffer; 179 iOmxComponent.FillThisBuffer = OpenmaxAmrAO::BaseComponentFillThisBuffer; 180 #endif 181 182 iOmxComponent.SetCallbacks = OpenmaxAmrAO::BaseComponentSetCallbacks; 183 iOmxComponent.nVersion.s.nVersionMajor = SPECVERSIONMAJOR; 184 iOmxComponent.nVersion.s.nVersionMinor = SPECVERSIONMINOR; 185 iOmxComponent.nVersion.s.nRevision = SPECREVISION; 186 iOmxComponent.nVersion.s.nStep = SPECSTEP; 187 188 // PV capability 189 iPVCapabilityFlags.iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE; 190 iPVCapabilityFlags.iOMXComponentSupportsExternalOutputBufferAlloc = OMX_TRUE; 191 iPVCapabilityFlags.iOMXComponentSupportsMovableInputBuffers = OMX_TRUE; 192 iPVCapabilityFlags.iOMXComponentSupportsPartialFrames = OMX_TRUE; 193 iPVCapabilityFlags.iOMXComponentUsesNALStartCodes = OMX_FALSE; 194 iPVCapabilityFlags.iOMXComponentCanHandleIncompleteFrames = OMX_TRUE; 195 iPVCapabilityFlags.iOMXComponentUsesFullAVCFrames = OMX_FALSE; 196 197 if (ipAppPriv) 198 { 199 oscl_free(ipAppPriv); 200 ipAppPriv = NULL; 201 } 202 203 ipAppPriv = (ComponentPrivateType*) oscl_malloc(sizeof(ComponentPrivateType)); 204 if (NULL == ipAppPriv) 205 { 206 return OMX_ErrorInsufficientResources; 207 } 208 209 //Construct base class now 210 Status = ConstructBaseComponent(pAppData); 211 212 if (OMX_ErrorNone != Status) 213 { 214 return Status; 215 } 216 217 /** Domain specific section for the ports. */ 218 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_INPUTPORT_INDEX; 219 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainAudio; 220 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.cMIMEType = (OMX_STRING)"audio/mpeg"; 221 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.pNativeRender = 0; 222 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.bFlagErrorConcealment = OMX_FALSE; 223 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.eEncoding = OMX_AUDIO_CodingAMR; 224 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.eDir = OMX_DirInput; 225 //Set to a default value, will change later during setparameter call 226 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferCountActual = NUMBER_INPUT_BUFFER_AMR; 227 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferCountMin = 1; 228 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize = INPUT_BUFFER_SIZE_AMR; 229 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE; 230 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE; 231 232 233 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 234 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainAudio; 235 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.cMIMEType = (OMX_STRING)"raw"; 236 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.pNativeRender = 0; 237 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.bFlagErrorConcealment = OMX_FALSE; 238 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 239 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDir = OMX_DirOutput; 240 //Set to a default value, will change later during setparameter call 241 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountActual = NUMBER_OUTPUT_BUFFER_AMR; 242 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountMin = 1; 243 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferSize = OUTPUT_BUFFER_SIZE_AMR * 6; 244 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE; 245 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE; 246 247 //Default values for AMR audio param port 248 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAmrParam.nPortIndex = OMX_PORT_INPUTPORT_INDEX; 249 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAmrParam.nChannels = 1; 250 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAmrParam.nBitRate = 0; 251 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAmrParam.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0; 252 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAmrParam.eAMRDTXMode = OMX_AUDIO_AMRDTXModeOnVAD1; 253 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAmrParam.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatConformance; 254 255 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 256 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.nChannels = 1; 257 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.eNumData = OMX_NumericalDataSigned; 258 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.bInterleaved = OMX_TRUE; 259 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.nBitPerSample = 16; 260 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.nSamplingRate = 8000; 261 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.ePCMMode = OMX_AUDIO_PCMModeLinear; 262 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.eChannelMapping[0] = OMX_AUDIO_ChannelLF; 263 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.eChannelMapping[1] = OMX_AUDIO_ChannelRF; 264 265 iPortTypesParam.nPorts = 2; 266 iPortTypesParam.nStartPortNumber = 0; 267 268 pInPort = (ComponentPortType*) ipPorts[OMX_PORT_INPUTPORT_INDEX]; 269 pOutPort = (ComponentPortType*) ipPorts[OMX_PORT_OUTPUTPORT_INDEX]; 270 271 SetHeader(&pInPort->AudioParam, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); 272 pInPort->AudioParam.nPortIndex = 0; 273 pInPort->AudioParam.nIndex = 0; 274 pInPort->AudioParam.eEncoding = OMX_AUDIO_CodingAMR; 275 276 SetHeader(&pOutPort->AudioParam, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); 277 pOutPort->AudioParam.nPortIndex = 1; 278 pOutPort->AudioParam.nIndex = 0; 279 pOutPort->AudioParam.eEncoding = OMX_AUDIO_CodingPCM; 280 281 iInputBufferRemainingBytes = 0; 282 283 oscl_strncpy((OMX_STRING)iComponentRole, (OMX_STRING)"audio_decoder.amrnb", OMX_MAX_STRINGNAME_SIZE); 284 285 if (ipAmrDec) 286 { 287 OSCL_DELETE(ipAmrDec); 288 ipAmrDec = NULL; 289 } 290 291 ipAmrDec = OSCL_NEW(OmxAmrDecoder, ()); 292 if (NULL == ipAmrDec) 293 { 294 return OMX_ErrorInsufficientResources; 295 } 296 297 //Commented memset here as some default values are set in the constructor 298 //oscl_memset(ipAmrDec, 0, sizeof (OmxAmrDecoder)); 299 300 #if PROXY_INTERFACE 301 302 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSendCommand = BaseComponentSendCommand; 303 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetParameter = BaseComponentGetParameter; 304 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetParameter = BaseComponentSetParameter; 305 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetConfig = BaseComponentGetConfig; 306 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetConfig = BaseComponentSetConfig; 307 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetExtensionIndex = BaseComponentGetExtensionIndex; 308 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetState = BaseComponentGetState; 309 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentUseBuffer = BaseComponentUseBuffer; 310 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentAllocateBuffer = BaseComponentAllocateBuffer; 311 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentFreeBuffer = BaseComponentFreeBuffer; 312 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentEmptyThisBuffer = BaseComponentEmptyThisBuffer; 313 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentFillThisBuffer = BaseComponentFillThisBuffer; 314 315 #endif 316 return OMX_ErrorNone; 317 } 318 319 320 /** This function is called by the omx core when the component 321 * is disposed by the IL client with a call to FreeHandle(). 322 * \param Component, the component to be disposed 323 */ 324 325 OMX_ERRORTYPE OpenmaxAmrAO::DestroyComponent() 326 { 327 if (iIsInit != OMX_FALSE) 328 { 329 ComponentDeInit(); 330 } 331 332 //Destroy the base class now 333 DestroyBaseComponent(); 334 335 if (ipAmrDec) 336 { 337 OSCL_DELETE(ipAmrDec); 338 ipAmrDec = NULL; 339 } 340 341 if (ipAppPriv) 342 { 343 ipAppPriv->CompHandle = NULL; 344 345 oscl_free(ipAppPriv); 346 ipAppPriv = NULL; 347 } 348 349 return OMX_ErrorNone; 350 } 351 352 353 /* This routine will extract the input timestamp, verify whether silence insertion 354 * is required or not and also handle the various tasks associated with repositioning */ 355 void OpenmaxAmrAO::SyncWithInputTimestamp() 356 { 357 //Do not check for silence insertion if the clip is repositioned 358 if (OMX_FALSE == iRepositionFlag) 359 { 360 CheckForSilenceInsertion(); 361 } 362 363 364 /* Set the current timestamp equal to input buffer timestamp in case of 365 * a) All input frames 366 * b) First frame after repositioning */ 367 if (OMX_FALSE == iSilenceInsertionInProgress || OMX_TRUE == iRepositionFlag) 368 { 369 iCurrentTimestamp = iFrameTimestamp; 370 371 //Reset the flag back to false, once timestamp has been updated from input frame 372 if (OMX_TRUE == iRepositionFlag) 373 { 374 iRepositionFlag = OMX_FALSE; 375 } 376 } 377 } 378 379 380 /* Reset the decoder library in case of repositioning or flush command or 381 * state transition (Executing ->Idle) */ 382 void OpenmaxAmrAO::ResetComponent() 383 { 384 // reset decoder 385 if (ipAmrDec) 386 { 387 ipAmrDec->ResetDecoder(); 388 } 389 } 390 391 /* A component specific routine called from BufferMgmtWithoutMarker */ 392 void OpenmaxAmrAO::ProcessInBufferFlag() 393 { 394 /* Used in timestamp calculation 395 * Since we copy one buffer in advance, so let the first buffer finish up 396 * before applying 2nd buffers timestamp into the output timestamp */ 397 if (iInputBufferRemainingBytes <= 0) 398 { 399 if (0 == iFrameCount) 400 { 401 iPreviousFrameLength = ipInputBuffer->nFilledLen; 402 iCurrentTimestamp = iFrameTimestamp; 403 } 404 405 iInputBufferRemainingBytes += iPreviousFrameLength; 406 } 407 408 iPreviousFrameLength = ipInputBuffer->nFilledLen; 409 } 410 411 412 /* This function will be called in case of buffer management without marker bit present 413 * The purpose is to copy the current input buffer into a big temporary buffer, so that 414 * an incomplete/partial frame is never passed to the decoder library for decode 415 */ 416 void OpenmaxAmrAO::ComponentBufferMgmtWithoutMarker() 417 { 418 //This common routine has been written in the base class 419 TempInputBufferMgmtWithoutMarker(); 420 } 421 422 423 void OpenmaxAmrAO::ProcessData() 424 { 425 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : ProcessData IN")); 426 if (!iEndOfFrameFlag) 427 { 428 DecodeWithoutMarker(); 429 } 430 else 431 { 432 DecodeWithMarker(); 433 } 434 435 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : ProcessData OUT")); 436 } 437 438 439 void OpenmaxAmrAO::DecodeWithoutMarker() 440 { 441 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DecodeWithoutMarker IN")); 442 443 QueueType* pInputQueue = ipPorts[OMX_PORT_INPUTPORT_INDEX]->pBufferQueue; 444 QueueType* pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue; 445 ComponentPortType* pOutPort = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]; 446 OMX_COMPONENTTYPE *pHandle = &iOmxComponent; 447 448 OMX_U8* pOutBuffer; 449 OMX_U32 OutputLength; 450 OMX_U8* pTempInBuffer; 451 OMX_U32 TempInLength; 452 OMX_BOOL DecodeReturn = OMX_FALSE; 453 454 OMX_U32 TempInputBufferSize = (2 * sizeof(uint8) * (ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize)); 455 456 457 if ((!iIsInputBufferEnded) || iEndofStream) 458 { 459 //Check whether prev output bufer has been released or not 460 if (OMX_TRUE == iNewOutBufRequired) 461 { 462 //Check whether a new output buffer is available or not 463 if (0 == (GetQueueNumElem(pOutputQueue))) 464 { 465 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DecodeWithoutMarker OUT output buffer unavailable")); 466 //Store the mark data for output buffer, as it will be overwritten next time 467 if (NULL != ipTargetComponent) 468 { 469 ipTempTargetComponent = ipTargetComponent; 470 iTempTargetMarkData = iTargetMarkData; 471 iMarkPropagate = OMX_TRUE; 472 } 473 return; 474 } 475 476 ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue); 477 if (NULL == ipOutputBuffer) 478 { 479 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DecodeWithoutMarker Error, Output Buffer Dequeue returned NULL, OUT")); 480 return; 481 } 482 ipOutputBuffer->nFilledLen = 0; 483 iNewOutBufRequired = OMX_FALSE; 484 485 //Set the current timestamp to the output buffer timestamp 486 ipOutputBuffer->nTimeStamp = iCurrentTimestamp; 487 488 489 } 490 491 /* Code for the marking buffer. Takes care of the OMX_CommandMarkBuffer 492 * command and hMarkTargetComponent as given by the specifications 493 */ 494 if (ipMark != NULL) 495 { 496 ipOutputBuffer->hMarkTargetComponent = ipMark->hMarkTargetComponent; 497 ipOutputBuffer->pMarkData = ipMark->pMarkData; 498 ipMark = NULL; 499 } 500 501 if ((OMX_TRUE == iMarkPropagate) && (ipTempTargetComponent != ipTargetComponent)) 502 { 503 ipOutputBuffer->hMarkTargetComponent = ipTempTargetComponent; 504 ipOutputBuffer->pMarkData = iTempTargetMarkData; 505 ipTempTargetComponent = NULL; 506 iMarkPropagate = OMX_FALSE; 507 } 508 else if (ipTargetComponent != NULL) 509 { 510 ipOutputBuffer->hMarkTargetComponent = ipTargetComponent; 511 ipOutputBuffer->pMarkData = iTargetMarkData; 512 ipTargetComponent = NULL; 513 iMarkPropagate = OMX_FALSE; 514 515 } 516 //Mark buffer code ends here 517 518 if (iTempInputBufferLength > 0) 519 { 520 pOutBuffer = &ipOutputBuffer->pBuffer[ipOutputBuffer->nFilledLen]; 521 OutputLength = 0; 522 523 pTempInBuffer = ipTempInputBuffer + iTempConsumedLength; 524 TempInLength = iTempInputBufferLength; 525 526 //Output buffer is passed as a short pointer 527 DecodeReturn = ipAmrDec->AmrDecodeFrame((OMX_S16*) pOutBuffer, 528 (OMX_U32*) & OutputLength, 529 &(pTempInBuffer), 530 &TempInLength, 531 &iFrameCount); 532 533 534 //If decoder returned error, report it to the client via a callback 535 if (OMX_FALSE == DecodeReturn && OMX_FALSE == iEndofStream) 536 { 537 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DecodeWithoutMarker ErrorStreamCorrupt callback send")); 538 539 (*(ipCallbacks->EventHandler)) 540 (pHandle, 541 iCallbackData, 542 OMX_EventError, 543 OMX_ErrorStreamCorrupt, 544 0, 545 NULL); 546 } 547 548 549 ipOutputBuffer->nFilledLen += OutputLength; 550 551 //offset not required in our case, set it to zero 552 ipOutputBuffer->nOffset = 0; 553 554 if (OutputLength > 0) 555 { 556 iCurrentTimestamp += OMX_AMR_DEC_FRAME_INTERVAL; 557 } 558 559 iTempConsumedLength += (iTempInputBufferLength - TempInLength); 560 iInputBufferRemainingBytes -= (iTempInputBufferLength - TempInLength); 561 562 iTempInputBufferLength = TempInLength; 563 564 if (iInputBufferRemainingBytes <= 0) 565 { 566 iCurrentTimestamp = iFrameTimestamp; 567 } 568 569 //Do not decode if big buffer is less than half the size 570 if (TempInLength < (TempInputBufferSize >> 1)) 571 { 572 iIsInputBufferEnded = OMX_TRUE; 573 iNewInBufferRequired = OMX_TRUE; 574 } 575 } 576 577 578 /* If EOS flag has come from the client & there are no more 579 * input buffers to decode, send the callback to the client 580 */ 581 if (OMX_TRUE == iEndofStream) 582 { 583 if ((0 == iTempInputBufferLength) || (OMX_FALSE == DecodeReturn)) 584 { 585 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DecodeWithoutMarker EOS callback send")); 586 587 (*(ipCallbacks->EventHandler)) 588 (pHandle, 589 iCallbackData, 590 OMX_EventBufferFlag, 591 1, 592 OMX_BUFFERFLAG_EOS, 593 NULL); 594 595 iNewInBufferRequired = OMX_TRUE; 596 iEndofStream = OMX_FALSE; 597 598 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_EOS; 599 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 600 ipOutputBuffer = NULL; 601 602 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DecodeWithoutMarker OUT")); 603 604 return; 605 } 606 } 607 608 //Send the output buffer back after decode 609 if ((ipOutputBuffer->nAllocLen - ipOutputBuffer->nFilledLen) < (iOutputFrameLength)) 610 { 611 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 612 ipOutputBuffer = NULL; 613 } 614 615 /* If there is some more processing left with current buffers, re-schedule the AO 616 * Do not go for more than one round of processing at a time. 617 * This may block the AO longer than required. 618 */ 619 if ((iTempInputBufferLength != 0 || GetQueueNumElem(pInputQueue) > 0) 620 && (GetQueueNumElem(pOutputQueue) > 0)) 621 622 { 623 RunIfNotReady(); 624 } 625 } 626 627 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DecodeWithoutMarker OUT")); 628 return; 629 } 630 631 632 void OpenmaxAmrAO::DecodeWithMarker() 633 { 634 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DecodeWithMarker IN")); 635 636 QueueType* pInputQueue = ipPorts[OMX_PORT_INPUTPORT_INDEX]->pBufferQueue; 637 QueueType* pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue; 638 639 ComponentPortType* pInPort = ipPorts[OMX_PORT_INPUTPORT_INDEX]; 640 ComponentPortType* pOutPort = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]; 641 642 OMX_U8* pOutBuffer; 643 OMX_U32 OutputLength; 644 OMX_BOOL DecodeReturn = OMX_FALSE; 645 OMX_COMPONENTTYPE* pHandle = &iOmxComponent; 646 647 if ((!iIsInputBufferEnded) || (iEndofStream)) 648 { 649 if (OMX_TRUE == iSilenceInsertionInProgress) 650 { 651 DoSilenceInsertion(); 652 //If the flag is still true, come back to this routine again 653 if (OMX_TRUE == iSilenceInsertionInProgress) 654 { 655 return; 656 } 657 } 658 659 //Check whether prev output bufer has been released or not 660 if (OMX_TRUE == iNewOutBufRequired) 661 { 662 //Check whether a new output buffer is available or not 663 if (0 == (GetQueueNumElem(pOutputQueue))) 664 { 665 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DecodeWithMarker OUT output buffer unavailable")); 666 return; 667 } 668 669 ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue); 670 if (NULL == ipOutputBuffer) 671 { 672 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DecodeWithMarker Error, Output Buffer Dequeue returned NULL, OUT")); 673 return; 674 } 675 676 ipOutputBuffer->nFilledLen = 0; 677 iNewOutBufRequired = OMX_FALSE; 678 679 //Set the current timestamp to the output buffer timestamp 680 ipOutputBuffer->nTimeStamp = iCurrentTimestamp; 681 682 683 } 684 685 /* Code for the marking buffer. Takes care of the OMX_CommandMarkBuffer 686 * command and hMarkTargetComponent as given by the specifications 687 */ 688 if (ipMark != NULL) 689 { 690 ipOutputBuffer->hMarkTargetComponent = ipMark->hMarkTargetComponent; 691 ipOutputBuffer->pMarkData = ipMark->pMarkData; 692 ipMark = NULL; 693 } 694 695 if (ipTargetComponent != NULL) 696 { 697 ipOutputBuffer->hMarkTargetComponent = ipTargetComponent; 698 ipOutputBuffer->pMarkData = iTargetMarkData; 699 ipTargetComponent = NULL; 700 701 } 702 //Mark buffer code ends here 703 704 if (iInputCurrLength > 0) 705 { 706 pOutBuffer = &ipOutputBuffer->pBuffer[ipOutputBuffer->nFilledLen]; 707 OutputLength = 0; 708 709 //Output buffer is passed as a short pointer 710 DecodeReturn = ipAmrDec->AmrDecodeFrame((OMX_S16*)pOutBuffer, 711 (OMX_U32*) & OutputLength, 712 &(ipFrameDecodeBuffer), 713 &(iInputCurrLength), 714 &iFrameCount); 715 716 //If decoder returned error, report it to the client via a callback 717 if ((OMX_FALSE == DecodeReturn) && (OMX_FALSE == iEndofStream)) 718 { 719 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DecodeWithMarker ErrorStreamCorrupt callback send")); 720 721 (*(ipCallbacks->EventHandler)) 722 (pHandle, 723 iCallbackData, 724 OMX_EventError, 725 OMX_ErrorStreamCorrupt, 726 0, 727 NULL); 728 } 729 730 731 ipOutputBuffer->nFilledLen += OutputLength; 732 if (OutputLength > 0) 733 { 734 iCurrentTimestamp += OMX_AMR_DEC_FRAME_INTERVAL; 735 } 736 //offset not required in our case, set it to zero 737 ipOutputBuffer->nOffset = 0; 738 739 740 /* Return the input buffer it has been consumed fully or decoder returned error*/ 741 if ((iInputCurrLength == 0) || (OMX_FALSE == DecodeReturn)) 742 { 743 ipInputBuffer->nFilledLen = 0; 744 ReturnInputBuffer(ipInputBuffer, pInPort); 745 iNewInBufferRequired = OMX_TRUE; 746 iIsInputBufferEnded = OMX_TRUE; 747 iInputCurrLength = 0; 748 ipInputBuffer = NULL; 749 } 750 else 751 { 752 iNewInBufferRequired = OMX_FALSE; 753 iIsInputBufferEnded = OMX_FALSE; 754 } 755 } 756 757 758 /* If EOS flag has come from the client & there are no more 759 * input buffers to decode, send the callback to the client 760 */ 761 if (OMX_TRUE == iEndofStream) 762 { 763 if ((0 == iInputCurrLength) || (OMX_FALSE == DecodeReturn)) 764 { 765 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DecodeWithMarker EOS callback send")); 766 767 (*(ipCallbacks->EventHandler)) 768 (pHandle, 769 iCallbackData, 770 OMX_EventBufferFlag, 771 1, 772 OMX_BUFFERFLAG_EOS, 773 NULL); 774 775 iNewInBufferRequired = OMX_TRUE; 776 //Mark this flag false once the callback has been send back 777 iEndofStream = OMX_FALSE; 778 779 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_EOS; 780 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 781 ipOutputBuffer = NULL; 782 783 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DecodeWithMarker OUT")); 784 return; 785 } 786 787 } 788 789 //Send the output buffer back when it has become full 790 if ((ipOutputBuffer->nAllocLen - ipOutputBuffer->nFilledLen) < (iOutputFrameLength)) 791 { 792 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 793 ipOutputBuffer = NULL; 794 } 795 796 /* If there is some more processing left with current buffers, re-schedule the AO 797 * Do not go for more than one round of processing at a time. 798 * This may block the AO longer than required. 799 */ 800 if ((iInputCurrLength != 0 || GetQueueNumElem(pInputQueue) > 0) 801 && (GetQueueNumElem(pOutputQueue) > 0)) 802 { 803 RunIfNotReady(); 804 } 805 } 806 807 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DecodeWithMarker OUT")); 808 return; 809 } 810 811 812 813 //Not implemented & supported in case of base profile components 814 815 void OpenmaxAmrAO::ComponentGetRolesOfComponent(OMX_STRING* aRoleString) 816 { 817 *aRoleString = (OMX_STRING)"audio_decoder.amr"; 818 } 819 820 821 //Component constructor 822 OpenmaxAmrAO::OpenmaxAmrAO() 823 { 824 ipAmrDec = NULL; 825 826 if (!IsAdded()) 827 { 828 AddToScheduler(); 829 } 830 831 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : constructed")); 832 } 833 834 835 //Active object destructor 836 OpenmaxAmrAO::~OpenmaxAmrAO() 837 { 838 if (IsAdded()) 839 { 840 RemoveFromScheduler(); 841 } 842 843 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : destructed")); 844 } 845 846 847 /** The Initialization function 848 */ 849 OMX_ERRORTYPE OpenmaxAmrAO::ComponentInit() 850 { 851 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : ComponentInit IN")); 852 853 OMX_BOOL Status = OMX_TRUE; 854 855 if (OMX_TRUE == iIsInit) 856 { 857 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : ComponentInit error incorrect operation")); 858 return OMX_ErrorIncorrectStateOperation; 859 } 860 iIsInit = OMX_TRUE; 861 862 863 // Added an extra check based on whether client has set nb or wb as Role in 864 // SetParameter() for index OMX_IndexParamStandardComponentRole 865 OMX_AUDIO_AMRBANDMODETYPE AmrBandMode = ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAmrParam.eAMRBandMode; 866 867 if (0 == oscl_strcmp((OMX_STRING)iComponentRole, (OMX_STRING)"audio_decoder.amrnb")) 868 { 869 if (OMX_TRUE == iComponentRoleFlag) 870 { 871 if ((AmrBandMode < OMX_AUDIO_AMRBandModeNB0) || (AmrBandMode > OMX_AUDIO_AMRBandModeNB7)) 872 { 873 //Narrow band component does not support these band modes 874 return OMX_ErrorInvalidComponent; 875 } 876 } 877 // set the fixed frame size 878 iOutputFrameLength = AMR_NB_OUTPUT_FRAME_SIZE_IN_BYTES; 879 } 880 else if (0 == oscl_strcmp((OMX_STRING)iComponentRole, (OMX_STRING)"audio_decoder.amrwb")) 881 { 882 if (OMX_TRUE == iComponentRoleFlag) 883 { 884 if ((AmrBandMode < OMX_AUDIO_AMRBandModeWB0) || (AmrBandMode > OMX_AUDIO_AMRBandModeWB8)) 885 { 886 //Wide band component does not support these band modes 887 return OMX_ErrorInvalidComponent; 888 } 889 } 890 891 // set the fixed frame size 892 iOutputFrameLength = AMR_WB_OUTPUT_FRAME_SIZE_IN_BYTES; 893 } 894 895 //amr lib init 896 if (!iCodecReady) 897 { 898 Status = ipAmrDec->AmrDecInit(ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAmrParam.eAMRFrameFormat, ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAmrParam.eAMRBandMode); 899 iCodecReady = OMX_TRUE; 900 } 901 902 //ipAmrDec->iAmrInitFlag = 0; 903 iInputCurrLength = 0; 904 //Used in dynamic port reconfiguration 905 iFrameCount = 0; 906 907 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : ComponentInit OUT")); 908 909 if (OMX_TRUE == Status) 910 { 911 return OMX_ErrorNone; 912 } 913 else 914 { 915 return OMX_ErrorInvalidComponent; 916 } 917 } 918 919 920 921 /** This function is called upon a transition to the idle or invalid state. 922 * Also it is called by the ComponentDestructor() function 923 */ 924 OMX_ERRORTYPE OpenmaxAmrAO::ComponentDeInit() 925 { 926 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : ComponentDeInit IN")); 927 928 iIsInit = OMX_FALSE; 929 930 if (iCodecReady) 931 { 932 ipAmrDec->AmrDecDeinit(); 933 iCodecReady = OMX_FALSE; 934 } 935 936 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : ComponentDeInit OUT")); 937 938 return OMX_ErrorNone; 939 940 } 941 942 943 //Check whether silence insertion is required here or not 944 void OpenmaxAmrAO::CheckForSilenceInsertion() 945 { 946 OMX_TICKS TimestampGap; 947 //Set the flag to false by default 948 iSilenceInsertionInProgress = OMX_FALSE; 949 950 TimestampGap = iFrameTimestamp - iCurrentTimestamp; 951 952 if ((TimestampGap > OMX_HALFRANGE_THRESHOLD) || (TimestampGap < OMX_AMR_DEC_FRAME_INTERVAL && iFrameCount > 0)) 953 { 954 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : CheckForSilenceInsertion OUT - No need to insert silence")); 955 return; 956 } 957 958 //Silence insertion needed, mark the flag to true 959 if (iFrameCount > 0) 960 { 961 iSilenceInsertionInProgress = OMX_TRUE; 962 //Determine the number of silence frames to insert 963 iSilenceFramesNeeded = TimestampGap / OMX_AMR_DEC_FRAME_INTERVAL; 964 iZeroFramesNeeded = 0; 965 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : CheckForSilenceInsertion OUT - Silence Insertion required here")); 966 } 967 968 return; 969 } 970 971 //Perform the silence insertion 972 void OpenmaxAmrAO::DoSilenceInsertion() 973 { 974 QueueType* pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue; 975 ComponentPortType* pOutPort = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]; 976 977 OMX_U8* pOutBuffer = NULL; 978 OMX_U32 OutputLength; 979 OMX_BOOL DecodeReturn; 980 981 982 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DoSilenceInsertion IN")); 983 984 while (iSilenceFramesNeeded > 0) 985 { 986 //Check whether prev output bufer has been consumed or not 987 if (OMX_TRUE == iNewOutBufRequired) 988 { 989 //Check whether a new output buffer is available or not 990 if (0 == (GetQueueNumElem(pOutputQueue))) 991 { 992 //Resume Silence insertion next time when component will be called 993 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DoSilenceInsertion OUT output buffer unavailable")); 994 iSilenceInsertionInProgress = OMX_TRUE; 995 return; 996 } 997 998 ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue); 999 if (NULL == ipOutputBuffer) 1000 { 1001 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DoSilenceInsertion Error, Output Buffer Dequeue returned NULL, OUT")); 1002 iSilenceInsertionInProgress = OMX_TRUE; 1003 return; 1004 } 1005 ipOutputBuffer->nFilledLen = 0; 1006 iNewOutBufRequired = OMX_FALSE; 1007 1008 //Set the current timestamp to the output buffer timestamp 1009 ipOutputBuffer->nTimeStamp = iCurrentTimestamp; 1010 } 1011 1012 pOutBuffer = &ipOutputBuffer->pBuffer[ipOutputBuffer->nFilledLen]; 1013 OutputLength = 0; 1014 1015 //Decode the silence frame 1016 DecodeReturn = ipAmrDec->AmrDecodeSilenceFrame((OMX_S16*) pOutBuffer, 1017 (OMX_U32*) & OutputLength); 1018 1019 1020 if (OMX_FALSE == DecodeReturn) 1021 { 1022 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DoSilenceInsertion - Decode error of silence generation, Insert zero frames instead")); 1023 iZeroFramesNeeded = iSilenceFramesNeeded; 1024 iSilenceFramesNeeded = 0; 1025 break; 1026 } 1027 1028 //Output length for a buffer of OMX_U8* will be double as that of OMX_S16* 1029 ipOutputBuffer->nFilledLen += OutputLength; 1030 //offset not required in our case, set it to zero 1031 ipOutputBuffer->nOffset = 0; 1032 1033 if (OutputLength > 0) 1034 { 1035 iCurrentTimestamp += OMX_AMR_DEC_FRAME_INTERVAL; 1036 } 1037 1038 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DoSilenceInsertion - silence frame decoded")); 1039 1040 //Send the output buffer back when it has become full 1041 if ((ipOutputBuffer->nAllocLen - ipOutputBuffer->nFilledLen) < iOutputFrameLength) 1042 { 1043 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 1044 ipOutputBuffer = NULL; 1045 } 1046 1047 // Decrement the silence frame counter 1048 --iSilenceFramesNeeded; 1049 } 1050 1051 // THE ZERO FRAME INSERTION IS PERFORMED ONLY IF SILENCE INSERTION FAILS 1052 while (iZeroFramesNeeded > 0) 1053 { 1054 //Check whether prev output bufer has been consumed or not 1055 if (OMX_TRUE == iNewOutBufRequired) 1056 { 1057 //Check whether a new output buffer is available or not 1058 if (0 == (GetQueueNumElem(pOutputQueue))) 1059 { 1060 //Resume Silence insertion next time when component will be called 1061 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DoSilenceInsertion OUT output buffer unavailable")); 1062 iSilenceInsertionInProgress = OMX_TRUE; 1063 return; 1064 } 1065 1066 ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue); 1067 if (NULL == ipOutputBuffer) 1068 { 1069 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DoSilenceInsertion Error, Output Buffer Dequeue returned NULL, OUT")); 1070 iSilenceInsertionInProgress = OMX_TRUE; 1071 return; 1072 } 1073 ipOutputBuffer->nFilledLen = 0; 1074 iNewOutBufRequired = OMX_FALSE; 1075 1076 //Set the current timestamp to the output buffer timestamp 1077 ipOutputBuffer->nTimeStamp = iCurrentTimestamp; 1078 } 1079 1080 pOutBuffer = &ipOutputBuffer->pBuffer[ipOutputBuffer->nFilledLen]; 1081 oscl_memset(pOutBuffer, 0, iOutputFrameLength); 1082 1083 ipOutputBuffer->nFilledLen += iOutputFrameLength; 1084 ipOutputBuffer->nOffset = 0; 1085 iCurrentTimestamp += OMX_AMR_DEC_FRAME_INTERVAL; 1086 1087 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DoSilenceInsertion - One frame of zeros inserted")); 1088 1089 //Send the output buffer back when it has become full 1090 if ((ipOutputBuffer->nAllocLen - ipOutputBuffer->nFilledLen) < iOutputFrameLength) 1091 { 1092 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 1093 ipOutputBuffer = NULL; 1094 } 1095 1096 // Decrement the silence frame counter 1097 --iZeroFramesNeeded; 1098 } 1099 1100 /* Completed Silence insertion successfully, now consider the input buffer already dequeued 1101 * for decoding & update the timestamps */ 1102 1103 iSilenceInsertionInProgress = OMX_FALSE; 1104 iCurrentTimestamp = iFrameTimestamp; 1105 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAmrAO : DoSilenceInsertion OUT - Done successfully")); 1106 1107 return; 1108 } 1109 1110 OMX_ERRORTYPE OpenmaxAmrAO::GetConfig( 1111 OMX_IN OMX_HANDLETYPE hComponent, 1112 OMX_IN OMX_INDEXTYPE nIndex, 1113 OMX_INOUT OMX_PTR pComponentConfigStructure) 1114 { 1115 OSCL_UNUSED_ARG(hComponent); 1116 OSCL_UNUSED_ARG(nIndex); 1117 OSCL_UNUSED_ARG(pComponentConfigStructure); 1118 return OMX_ErrorNotImplemented; 1119 } 1120