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 21 #include "omx_aac_component.h" 22 23 #if PROXY_INTERFACE 24 #include "omx_proxy_interface.h" 25 #endif 26 27 // Use default DLL entry point 28 #ifndef OSCL_DLL_H_INCLUDED 29 #include "oscl_dll.h" 30 #endif 31 32 #define OMX_HALFRANGE_THRESHOLD 0x7FFFFFFF 33 34 #define AAC_MONO_SILENCE_FRAME_SIZE 10 35 #define AAC_STEREO_SILENCE_FRAME_SIZE 11 36 37 static const OMX_U8 AAC_MONO_SILENCE_FRAME[] = {0x01, 0x40, 0x20, 0x06, 0x4F, 0xDE, 0x02, 0x70, 0x0C, 0x1C}; // 10 bytes 38 static const OMX_U8 AAC_STEREO_SILENCE_FRAME[] = {0x21, 0x10, 0x05, 0x00, 0xA0, 0x19, 0x33, 0x87, 0xC0, 0x00, 0x7E}; // 11 bytes) 39 40 OSCL_DLL_ENTRY_POINT_DEFAULT() 41 42 43 // This function is called by OMX_GetHandle and it creates an instance of the aac component AO 44 OSCL_EXPORT_REF OMX_ERRORTYPE AacOmxComponentFactory(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) 45 { 46 OSCL_UNUSED_ARG(aOmxLibName); 47 OSCL_UNUSED_ARG(aOmxLib); 48 OSCL_UNUSED_ARG(aOsclUuid); 49 OSCL_UNUSED_ARG(aRefCount); 50 51 OpenmaxAacAO* pOpenmaxAOType; 52 OMX_ERRORTYPE Status; 53 54 // move InitAacOmxComponentFields content to actual constructor 55 56 pOpenmaxAOType = (OpenmaxAacAO*) OSCL_NEW(OpenmaxAacAO, ()); 57 58 if (NULL == pOpenmaxAOType) 59 { 60 return OMX_ErrorInsufficientResources; 61 } 62 63 //Call the construct component to initialize OMX types 64 Status = pOpenmaxAOType->ConstructComponent(pAppData, pProxy); 65 66 *pHandle = pOpenmaxAOType->GetOmxHandle(); 67 68 return Status; 69 /////////////////////////////////////////////////////////////////////////////////////// 70 } 71 72 // This function is called by OMX_FreeHandle when component AO needs to be destroyed 73 OSCL_EXPORT_REF OMX_ERRORTYPE AacOmxComponentDestructor(OMX_IN OMX_HANDLETYPE pHandle, OMX_PTR &aOmxLib, OMX_PTR aOsclUuid, OMX_U32 &aRefCount) 74 { 75 OSCL_UNUSED_ARG(aOmxLib); 76 OSCL_UNUSED_ARG(aOsclUuid); 77 OSCL_UNUSED_ARG(aRefCount); 78 79 // get pointer to component AO 80 OpenmaxAacAO* pOpenmaxAOType = (OpenmaxAacAO*)((OMX_COMPONENTTYPE*)pHandle)->pComponentPrivate; 81 82 // clean up decoder, OMX component stuff 83 pOpenmaxAOType->DestroyComponent(); 84 85 // destroy the AO class 86 OSCL_DELETE(pOpenmaxAOType); 87 88 return OMX_ErrorNone; 89 } 90 91 #if DYNAMIC_LOAD_OMX_AAC_COMPONENT 92 class AacOmxSharedLibraryInterface: public OsclSharedLibraryInterface, 93 public OmxSharedLibraryInterface 94 95 { 96 public: 97 OsclAny *QueryOmxComponentInterface(const OsclUuid& aOmxTypeId, const OsclUuid& aInterfaceId) 98 { 99 if (PV_OMX_AACDEC_UUID == aOmxTypeId) 100 { 101 if (PV_OMX_CREATE_INTERFACE == aInterfaceId) 102 { 103 return ((OsclAny*)(&AacOmxComponentFactory)); 104 } 105 else if (PV_OMX_DESTROY_INTERFACE == aInterfaceId) 106 { 107 return ((OsclAny*)(&AacOmxComponentDestructor)); 108 } 109 } 110 return NULL; 111 }; 112 OsclAny *SharedLibraryLookup(const OsclUuid& aInterfaceId) 113 { 114 if (aInterfaceId == PV_OMX_SHARED_INTERFACE) 115 { 116 return OSCL_STATIC_CAST(OmxSharedLibraryInterface*, this); 117 } 118 return NULL; 119 }; 120 121 AacOmxSharedLibraryInterface() {}; 122 }; 123 124 // function to obtain the interface object from the shared library 125 extern "C" 126 { 127 OSCL_EXPORT_REF OsclAny* PVGetInterface() 128 { 129 return (OsclAny*) OSCL_NEW(AacOmxSharedLibraryInterface, ()); 130 } 131 OSCL_EXPORT_REF void PVReleaseInterface(OsclSharedLibraryInterface* aInstance) 132 { 133 AacOmxSharedLibraryInterface* module = (AacOmxSharedLibraryInterface*)aInstance; 134 OSCL_DELETE(module); 135 } 136 } 137 138 #endif 139 140 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 141 142 OMX_ERRORTYPE OpenmaxAacAO::ConstructComponent(OMX_PTR pAppData, OMX_PTR pProxy) 143 { 144 ComponentPortType* pInPort, *pOutPort; 145 OMX_ERRORTYPE Status; 146 147 iNumPorts = 2; 148 iOmxComponent.nSize = sizeof(OMX_COMPONENTTYPE); 149 iOmxComponent.pComponentPrivate = (OMX_PTR) this; // pComponentPrivate points to THIS component AO class 150 ipComponentProxy = pProxy; 151 iOmxComponent.pApplicationPrivate = pAppData; // init the App data 152 153 154 #if PROXY_INTERFACE 155 iPVCapabilityFlags.iIsOMXComponentMultiThreaded = OMX_TRUE; 156 157 iOmxComponent.SendCommand = OpenmaxAacAO::BaseComponentProxySendCommand; 158 iOmxComponent.GetParameter = OpenmaxAacAO::BaseComponentProxyGetParameter; 159 iOmxComponent.SetParameter = OpenmaxAacAO::BaseComponentProxySetParameter; 160 iOmxComponent.GetConfig = OpenmaxAacAO::BaseComponentProxyGetConfig; 161 iOmxComponent.SetConfig = OpenmaxAacAO::BaseComponentProxySetConfig; 162 iOmxComponent.GetExtensionIndex = OpenmaxAacAO::BaseComponentProxyGetExtensionIndex; 163 iOmxComponent.GetState = OpenmaxAacAO::BaseComponentProxyGetState; 164 iOmxComponent.UseBuffer = OpenmaxAacAO::BaseComponentProxyUseBuffer; 165 iOmxComponent.AllocateBuffer = OpenmaxAacAO::BaseComponentProxyAllocateBuffer; 166 iOmxComponent.FreeBuffer = OpenmaxAacAO::BaseComponentProxyFreeBuffer; 167 iOmxComponent.EmptyThisBuffer = OpenmaxAacAO::BaseComponentProxyEmptyThisBuffer; 168 iOmxComponent.FillThisBuffer = OpenmaxAacAO::BaseComponentProxyFillThisBuffer; 169 170 #else 171 iPVCapabilityFlags.iIsOMXComponentMultiThreaded = OMX_FALSE; 172 173 iOmxComponent.SendCommand = OpenmaxAacAO::BaseComponentSendCommand; 174 iOmxComponent.GetParameter = OpenmaxAacAO::BaseComponentGetParameter; 175 iOmxComponent.SetParameter = OpenmaxAacAO::BaseComponentSetParameter; 176 iOmxComponent.GetConfig = OpenmaxAacAO::BaseComponentGetConfig; 177 iOmxComponent.SetConfig = OpenmaxAacAO::BaseComponentSetConfig; 178 iOmxComponent.GetExtensionIndex = OpenmaxAacAO::BaseComponentGetExtensionIndex; 179 iOmxComponent.GetState = OpenmaxAacAO::BaseComponentGetState; 180 iOmxComponent.UseBuffer = OpenmaxAacAO::BaseComponentUseBuffer; 181 iOmxComponent.AllocateBuffer = OpenmaxAacAO::BaseComponentAllocateBuffer; 182 iOmxComponent.FreeBuffer = OpenmaxAacAO::BaseComponentFreeBuffer; 183 iOmxComponent.EmptyThisBuffer = OpenmaxAacAO::BaseComponentEmptyThisBuffer; 184 iOmxComponent.FillThisBuffer = OpenmaxAacAO::BaseComponentFillThisBuffer; 185 #endif 186 187 iOmxComponent.SetCallbacks = OpenmaxAacAO::BaseComponentSetCallbacks; 188 iOmxComponent.nVersion.s.nVersionMajor = SPECVERSIONMAJOR; 189 iOmxComponent.nVersion.s.nVersionMinor = SPECVERSIONMINOR; 190 iOmxComponent.nVersion.s.nRevision = SPECREVISION; 191 iOmxComponent.nVersion.s.nStep = SPECSTEP; 192 193 // PV capability 194 iPVCapabilityFlags.iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE; 195 iPVCapabilityFlags.iOMXComponentSupportsExternalOutputBufferAlloc = OMX_TRUE; 196 iPVCapabilityFlags.iOMXComponentSupportsMovableInputBuffers = OMX_TRUE; 197 iPVCapabilityFlags.iOMXComponentSupportsPartialFrames = OMX_TRUE; 198 iPVCapabilityFlags.iOMXComponentUsesNALStartCodes = OMX_FALSE; 199 iPVCapabilityFlags.iOMXComponentCanHandleIncompleteFrames = OMX_TRUE; 200 iPVCapabilityFlags.iOMXComponentUsesFullAVCFrames = OMX_FALSE; 201 202 if (ipAppPriv) 203 { 204 oscl_free(ipAppPriv); 205 ipAppPriv = NULL; 206 } 207 208 ipAppPriv = (ComponentPrivateType*) oscl_malloc(sizeof(ComponentPrivateType)); 209 if (NULL == ipAppPriv) 210 { 211 return OMX_ErrorInsufficientResources; 212 } 213 214 //Construct base class now 215 Status = ConstructBaseComponent(pAppData); 216 217 if (OMX_ErrorNone != Status) 218 { 219 return Status; 220 } 221 222 /** Domain specific section for the ports. */ 223 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_INPUTPORT_INDEX; 224 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainAudio; 225 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.cMIMEType = (OMX_STRING)"audio/mpeg"; 226 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.pNativeRender = 0; 227 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.bFlagErrorConcealment = OMX_FALSE; 228 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.eEncoding = OMX_AUDIO_CodingAAC; 229 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.eDir = OMX_DirInput; 230 //Set to a default value, will change later during setparameter call 231 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferCountActual = NUMBER_INPUT_BUFFER_AAC; 232 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferCountMin = 1; 233 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize = INPUT_BUFFER_SIZE_AAC; 234 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE; 235 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE; 236 237 238 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 239 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainAudio; 240 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.cMIMEType = (OMX_STRING)"raw"; 241 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.pNativeRender = 0; 242 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.bFlagErrorConcealment = OMX_FALSE; 243 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 244 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDir = OMX_DirOutput; 245 //Set to a default value, will change later during setparameter call 246 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountActual = NUMBER_OUTPUT_BUFFER_AAC; 247 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountMin = 1; 248 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferSize = OUTPUT_BUFFER_SIZE_AAC * 6; 249 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE; 250 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE; 251 252 //Default values for AAC audio param port 253 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAacParam.nPortIndex = OMX_PORT_INPUTPORT_INDEX; 254 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAacParam.nChannels = 2; 255 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAacParam.nBitRate = 0; 256 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAacParam.nSampleRate = 44100; 257 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAacParam.nAudioBandWidth = 0; 258 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAacParam.nFrameLength = 2048; // use HE_PS frame size as default 259 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAacParam.eChannelMode = OMX_AUDIO_ChannelModeStereo; 260 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAacParam.eAACProfile = OMX_AUDIO_AACObjectHE_PS; //OMX_AUDIO_AACObjectLC; 261 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAacParam.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP2ADTS; 262 263 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 264 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.nChannels = 2; 265 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.eNumData = OMX_NumericalDataSigned; 266 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.bInterleaved = OMX_TRUE; 267 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.nBitPerSample = 16; 268 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.nSamplingRate = 44100; 269 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.ePCMMode = OMX_AUDIO_PCMModeLinear; 270 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.eChannelMapping[0] = OMX_AUDIO_ChannelLF; 271 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.eChannelMapping[1] = OMX_AUDIO_ChannelRF; 272 273 iPortTypesParam.nPorts = 2; 274 iPortTypesParam.nStartPortNumber = 0; 275 276 pInPort = (ComponentPortType*) ipPorts[OMX_PORT_INPUTPORT_INDEX]; 277 pOutPort = (ComponentPortType*) ipPorts[OMX_PORT_OUTPUTPORT_INDEX]; 278 279 SetHeader(&pInPort->AudioParam, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); 280 pInPort->AudioParam.nPortIndex = 0; 281 pInPort->AudioParam.nIndex = 0; 282 pInPort->AudioParam.eEncoding = OMX_AUDIO_CodingAAC; 283 284 SetHeader(&pOutPort->AudioParam, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); 285 pOutPort->AudioParam.nPortIndex = 1; 286 pOutPort->AudioParam.nIndex = 0; 287 pOutPort->AudioParam.eEncoding = OMX_AUDIO_CodingPCM; 288 289 oscl_strncpy((OMX_STRING)iComponentRole, (OMX_STRING)"audio_decoder.aac", OMX_MAX_STRINGNAME_SIZE); 290 291 iOutputFrameLength = OUTPUT_BUFFER_SIZE_AAC; 292 293 if (ipAacDec) 294 { 295 OSCL_DELETE(ipAacDec); 296 ipAacDec = NULL; 297 } 298 299 ipAacDec = OSCL_NEW(OmxAacDecoder, ()); 300 if (NULL == ipAacDec) 301 { 302 return OMX_ErrorInsufficientResources; 303 } 304 305 oscl_memset(ipAacDec, 0, sizeof(OmxAacDecoder)); 306 307 iSamplesPerFrame = AACDEC_PCM_FRAME_SAMPLE_SIZE; 308 iOutputMicroSecPerFrame = iCurrentFrameTS.GetFrameDuration(); 309 310 #if PROXY_INTERFACE 311 312 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSendCommand = BaseComponentSendCommand; 313 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetParameter = BaseComponentGetParameter; 314 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetParameter = BaseComponentSetParameter; 315 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetConfig = BaseComponentGetConfig; 316 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetConfig = BaseComponentSetConfig; 317 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetExtensionIndex = BaseComponentGetExtensionIndex; 318 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetState = BaseComponentGetState; 319 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentUseBuffer = BaseComponentUseBuffer; 320 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentAllocateBuffer = BaseComponentAllocateBuffer; 321 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentFreeBuffer = BaseComponentFreeBuffer; 322 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentEmptyThisBuffer = BaseComponentEmptyThisBuffer; 323 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentFillThisBuffer = BaseComponentFillThisBuffer; 324 325 #endif 326 return OMX_ErrorNone; 327 } 328 329 330 /** This function is called by the omx core when the component 331 * is disposed by the IL client with a call to FreeHandle(). 332 */ 333 334 OMX_ERRORTYPE OpenmaxAacAO::DestroyComponent() 335 { 336 if (iIsInit != OMX_FALSE) 337 { 338 ComponentDeInit(); 339 } 340 341 //Destroy the base class now 342 DestroyBaseComponent(); 343 344 if (ipAacDec) 345 { 346 OSCL_DELETE(ipAacDec); 347 ipAacDec = NULL; 348 } 349 350 if (ipAppPriv) 351 { 352 ipAppPriv->CompHandle = NULL; 353 354 oscl_free(ipAppPriv); 355 ipAppPriv = NULL; 356 } 357 358 return OMX_ErrorNone; 359 360 } 361 362 363 /* This routine will extract the input timestamp, verify whether silence insertion 364 * is required or not and also handle the various tasks associated with repositioning */ 365 void OpenmaxAacAO::SyncWithInputTimestamp() 366 { 367 OMX_AUDIO_AACSTREAMFORMATTYPE InFormat = ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAacParam.eAACStreamFormat; 368 369 //Do not check for silence insertion if the clip is repositioned 370 if (OMX_FALSE == iRepositionFlag) 371 { 372 CheckForSilenceInsertion(); 373 } 374 375 376 /* Set the current timestamp equal to input buffer timestamp in case of 377 * a) first frame for ADIF format 378 * b) All input frames for other formats 379 * c) First frame after repositioning */ 380 if (OMX_FALSE == iSilenceInsertionInProgress) 381 { 382 if ((0 == iFrameCount) || (iFrameCount > 0 && OMX_AUDIO_AACStreamFormatADIF != InFormat) 383 || (OMX_TRUE == iRepositionFlag)) 384 { 385 iCurrentFrameTS.SetFromInputTimestamp(iFrameTimestamp); 386 387 //Reset the flag back to false, once timestamp has been updated from input frame 388 if (OMX_TRUE == iRepositionFlag) 389 { 390 iRepositionFlag = OMX_FALSE; 391 } 392 } 393 } 394 } 395 396 /* A component specific routine called from BufferMgmtWithoutMarker */ 397 void OpenmaxAacAO::ProcessInBufferFlag() 398 { 399 iIsInputBufferEnded = OMX_FALSE; 400 } 401 402 403 void OpenmaxAacAO::ProcessData() 404 { 405 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : ProcessData IN")); 406 407 QueueType* pInputQueue = ipPorts[OMX_PORT_INPUTPORT_INDEX]->pBufferQueue; 408 QueueType* pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue; 409 410 ComponentPortType* pInPort = (ComponentPortType*) ipPorts[OMX_PORT_INPUTPORT_INDEX]; 411 ComponentPortType* pOutPort = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]; 412 OMX_COMPONENTTYPE* pHandle = &iOmxComponent; 413 414 OMX_U8* pOutBuffer; 415 OMX_U32 OutputLength; 416 OMX_S32 DecodeReturn; 417 OMX_BOOL ResizeNeeded = OMX_FALSE; 418 419 OMX_U32 TempInputBufferSize = (2 * sizeof(uint8) * (ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize)); 420 421 422 if ((!iIsInputBufferEnded) || iEndofStream) 423 { 424 if (OMX_TRUE == iSilenceInsertionInProgress) 425 { 426 DoSilenceInsertion(); 427 //If the flag is still true, come back to this routine again 428 if (OMX_TRUE == iSilenceInsertionInProgress) 429 { 430 return; 431 } 432 } 433 434 //Check whether prev output bufer has been released or not 435 if (OMX_TRUE == iNewOutBufRequired) 436 { 437 //Check whether a new output buffer is available or not 438 if (0 == (GetQueueNumElem(pOutputQueue))) 439 { 440 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : ProcessData OUT output buffer unavailable")); 441 return; 442 } 443 444 ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue); 445 if (NULL == ipOutputBuffer) 446 { 447 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : ProcessData Error, output buffer dequeue returned NULL, OUT")); 448 return; 449 } 450 451 ipOutputBuffer->nFilledLen = 0; 452 iNewOutBufRequired = OMX_FALSE; 453 454 //Set the current timestamp to the output buffer timestamp 455 ipOutputBuffer->nTimeStamp = iCurrentFrameTS.GetConvertedTs(); 456 457 // Copy the output buffer that was stored locally before dynamic port reconfiguration 458 // in the new omx buffer received. 459 460 if (OMX_TRUE == iSendOutBufferAfterPortReconfigFlag) 461 { 462 if ((ipTempOutBufferForPortReconfig) 463 && (iSizeOutBufferForPortReconfig <= ipOutputBuffer->nAllocLen)) 464 { 465 oscl_memcpy(ipOutputBuffer->pBuffer, ipTempOutBufferForPortReconfig, iSizeOutBufferForPortReconfig); 466 ipOutputBuffer->nFilledLen = iSizeOutBufferForPortReconfig; 467 ipOutputBuffer->nTimeStamp = iTimestampOutBufferForPortReconfig; 468 } 469 470 iSendOutBufferAfterPortReconfigFlag = OMX_FALSE; 471 472 //Send the output buffer back only when it has become full 473 474 if ((ipOutputBuffer->nAllocLen - ipOutputBuffer->nFilledLen) < iOutputFrameLength) 475 { 476 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 477 } 478 479 480 //Free the temp output buffer 481 482 if (ipTempOutBufferForPortReconfig) 483 { 484 oscl_free(ipTempOutBufferForPortReconfig); 485 ipTempOutBufferForPortReconfig = NULL; 486 iSizeOutBufferForPortReconfig = 0; 487 } 488 489 //Dequeue new output buffer to continue decoding the next frame 490 491 if (OMX_TRUE == iNewOutBufRequired) 492 { 493 if (0 == (GetQueueNumElem(pOutputQueue))) 494 { 495 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : ProcessData OUT, output buffer unavailable")); 496 return; 497 } 498 499 ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue); 500 if (NULL == ipOutputBuffer) 501 { 502 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : ProcessData Error, output buffer dequeue returned NULL, OUT")); 503 return; 504 } 505 506 ipOutputBuffer->nFilledLen = 0; 507 iNewOutBufRequired = OMX_FALSE; 508 ipOutputBuffer->nTimeStamp = iCurrentFrameTS.GetConvertedTs(); 509 } 510 } 511 } 512 513 514 /* Code for the marking buffer. Takes care of the OMX_CommandMarkBuffer 515 * command and hMarkTargetComponent as given by the specifications 516 */ 517 if (ipMark != NULL) 518 { 519 ipOutputBuffer->hMarkTargetComponent = ipMark->hMarkTargetComponent; 520 ipOutputBuffer->pMarkData = ipMark->pMarkData; 521 ipMark = NULL; 522 } 523 524 if (ipTargetComponent != NULL) 525 { 526 ipOutputBuffer->hMarkTargetComponent = ipTargetComponent; 527 ipOutputBuffer->pMarkData = iTargetMarkData; 528 ipTargetComponent = NULL; 529 530 } 531 //Mark buffer code ends here 532 533 pOutBuffer = &ipOutputBuffer->pBuffer[ipOutputBuffer->nFilledLen]; 534 OutputLength = 0; 535 536 /* Copy the left-over data from last input buffer that is stored in temporary 537 * buffer to the next incoming buffer. 538 */ 539 if (iTempInputBufferLength > 0 && 540 ((iInputCurrLength + iTempInputBufferLength) < TempInputBufferSize)) 541 { 542 oscl_memcpy(&ipTempInputBuffer[iTempInputBufferLength], ipFrameDecodeBuffer, iInputCurrLength); 543 iInputCurrLength += iTempInputBufferLength; 544 iTempInputBufferLength = 0; 545 ipFrameDecodeBuffer = ipTempInputBuffer; 546 } 547 548 //Output buffer is passed as a short pointer 549 DecodeReturn = ipAacDec->AacDecodeFrames((OMX_S16*) pOutBuffer, 550 (OMX_U32*) & OutputLength, 551 &(ipFrameDecodeBuffer), 552 &iInputCurrLength, 553 &iFrameCount, 554 &(ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode), 555 &(ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAacParam), 556 &iSamplesPerFrame, 557 &ResizeNeeded); 558 559 if (ResizeNeeded == OMX_TRUE) 560 { 561 if (0 != OutputLength) 562 { 563 iOutputFrameLength = OutputLength * 2; 564 //In case of mono files keep the frame boundary more because decoder tries to write something beyond that level also 565 if (1 == ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.nChannels) 566 { 567 iOutputFrameLength *= 2; 568 } 569 570 iCurrentFrameTS.SetParameters(ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.nSamplingRate, iSamplesPerFrame); 571 iOutputMicroSecPerFrame = iCurrentFrameTS.GetFrameDuration(); 572 573 } 574 575 // set the flag to disable further processing until Client reacts to this 576 // by doing dynamic port reconfiguration 577 iResizePending = OMX_TRUE; 578 579 /* Do not return the output buffer generated yet, store it locally 580 * and wait for the dynamic port reconfig to complete */ 581 582 if ((NULL == ipTempOutBufferForPortReconfig)) 583 { 584 ipTempOutBufferForPortReconfig = (OMX_U8*) oscl_malloc(sizeof(uint8) * OutputLength * 2); 585 if (NULL == ipTempOutBufferForPortReconfig) 586 { 587 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : ProcessData error, insufficient resources")); 588 return; 589 } 590 } 591 592 //Copy the omx output buffer to the temporary internal buffer 593 oscl_memcpy(ipTempOutBufferForPortReconfig, pOutBuffer, OutputLength * 2); 594 iSizeOutBufferForPortReconfig = OutputLength * 2; 595 596 //Set the current timestamp to the output buffer timestamp for the first output frame, Later it will be done at the time of dequeue 597 //(reason here is that at the time of dequeue, output buffer timestamp was equal to timestamp of config input buffer, not the first input buffer) 598 iTimestampOutBufferForPortReconfig = iCurrentFrameTS.GetConvertedTs(); 599 600 iCurrentFrameTS.UpdateTimestamp(iSamplesPerFrame); 601 //Make this length 0 so that no output buffer is returned by the component 602 OutputLength = 0; 603 604 605 // send port settings changed event 606 OMX_COMPONENTTYPE* pHandle = (OMX_COMPONENTTYPE*) ipAppPriv->CompHandle; 607 608 (*(ipCallbacks->EventHandler)) 609 (pHandle, 610 iCallbackData, 611 OMX_EventPortSettingsChanged, //The command was completed 612 OMX_PORT_OUTPUTPORT_INDEX, 613 0, 614 NULL); 615 } 616 617 618 //Output length for a buffer of OMX_U8* will be double as that of OMX_S16* 619 ipOutputBuffer->nFilledLen += OutputLength * 2; 620 //offset not required in our case, set it to zero 621 ipOutputBuffer->nOffset = 0; 622 623 if (OutputLength > 0) 624 { 625 iCurrentFrameTS.UpdateTimestamp(iSamplesPerFrame); 626 } 627 628 /* If EOS flag has come from the client & there are no more 629 * input buffers to decode, send the callback to the client 630 */ 631 if (OMX_TRUE == iEndofStream) 632 { 633 if ((0 == iInputCurrLength) || (MP4AUDEC_SUCCESS != DecodeReturn)) 634 { 635 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : ProcessData EOS callback send")); 636 637 (*(ipCallbacks->EventHandler)) 638 (pHandle, 639 iCallbackData, 640 OMX_EventBufferFlag, 641 1, 642 OMX_BUFFERFLAG_EOS, 643 NULL); 644 645 iEndofStream = OMX_FALSE; 646 647 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_EOS; 648 649 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 650 ipOutputBuffer = NULL; 651 652 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : ProcessData OUT")); 653 654 return; 655 } 656 } 657 658 659 if (MP4AUDEC_SUCCESS == DecodeReturn) 660 { 661 ipInputBuffer->nFilledLen = iInputCurrLength; 662 } 663 else if (MP4AUDEC_INCOMPLETE_FRAME == DecodeReturn) 664 { 665 /* If decoder returns MP4AUDEC_INCOMPLETE_FRAME, 666 * this indicates the input buffer contains less than a frame data that 667 * can't be processed by the decoder. 668 * Copy it to a temp buffer to be used in next decode call 669 * buffers can be overlapping, use memmove() instead of memcpy() 670 */ 671 oscl_memmove(ipTempInputBuffer, ipFrameDecodeBuffer, iInputCurrLength); 672 iTempInputBufferLength = iInputCurrLength; 673 ipInputBuffer->nFilledLen = 0; 674 iInputCurrLength = 0; 675 } 676 else 677 { 678 OMX_U32 error = OMX_ErrorStreamCorrupt; 679 if (ipAacDec->iAacInitFlag == 0) 680 { 681 // If first frame, it means that the config has an issue. 682 error = OMX_ErrorBadParameter; 683 } 684 //bitstream error, discard the current data as it can't be decoded further 685 ipInputBuffer->nFilledLen = 0; 686 iInputCurrLength = 0; 687 688 //Report it to the client via a callback 689 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : ProcessData ErrorStreamCorrupt callback send")); 690 691 (*(ipCallbacks->EventHandler)) 692 (pHandle, 693 iCallbackData, 694 OMX_EventError, 695 error, 696 0, 697 NULL); 698 699 } 700 701 //Return the input buffer if it has been consumed fully by the decoder 702 if (0 == ipInputBuffer->nFilledLen) 703 { 704 ReturnInputBuffer(ipInputBuffer, pInPort); 705 iIsInputBufferEnded = OMX_TRUE; 706 iInputCurrLength = 0; 707 ipInputBuffer = NULL; 708 } 709 710 //Send the output buffer back when it has become full 711 if ((ipOutputBuffer->nAllocLen - ipOutputBuffer->nFilledLen) < (iOutputFrameLength)) 712 { 713 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 714 ipOutputBuffer = NULL; 715 } 716 717 /* If there is some more processing left with current buffers, re-schedule the AO 718 * Do not go for more than one round of processing at a time. 719 * This may block the AO longer than required. 720 */ 721 if (((iInputCurrLength != 0) || (GetQueueNumElem(pInputQueue) > 0)) 722 && ((GetQueueNumElem(pOutputQueue) > 0) || (OMX_FALSE == iNewOutBufRequired)) 723 && (ResizeNeeded == OMX_FALSE)) 724 { 725 RunIfNotReady(); 726 } 727 } 728 729 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : ProcessData OUT")); 730 return; 731 } 732 733 734 /* This routine will reset the decoder library and some of the associated flags*/ 735 void OpenmaxAacAO::ResetComponent() 736 { 737 // reset decoder 738 if (ipAacDec) 739 { 740 ipAacDec->ResetDecoder(); 741 ipAacDec->iInputUsedLength = 0; 742 } 743 744 } 745 746 747 748 /* Routine to call the respective function of the decoder library for updating the 749 * AAC+ flag, A separate routine is written here because the direct call can't be 750 * done from GetParameter of common audio base class */ 751 752 void OpenmaxAacAO::UpdateAACPlusFlag(OMX_BOOL aAacPlusFlag) 753 { 754 ipAacDec->UpdateAACPlusEnabled(aAacPlusFlag); 755 } 756 757 758 void OpenmaxAacAO::ComponentGetRolesOfComponent(OMX_STRING* aRoleString) 759 { 760 *aRoleString = (OMX_STRING)"audio_decoder.aac"; 761 } 762 763 764 //Active object constructor 765 OpenmaxAacAO::OpenmaxAacAO() 766 { 767 ipAacDec = NULL; 768 769 if (!IsAdded()) 770 { 771 AddToScheduler(); 772 } 773 774 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : constructed")); 775 } 776 777 778 //Active object destructor 779 OpenmaxAacAO::~OpenmaxAacAO() 780 { 781 if (IsAdded()) 782 { 783 RemoveFromScheduler(); 784 } 785 786 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : destructed")); 787 } 788 789 790 /** The Initialization function 791 */ 792 OMX_ERRORTYPE OpenmaxAacAO::ComponentInit() 793 { 794 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : ComponentInit IN")); 795 796 OMX_BOOL Status = OMX_TRUE; 797 798 if (OMX_TRUE == iIsInit) 799 { 800 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : ComponentInit error incorrect operation")); 801 return OMX_ErrorIncorrectStateOperation; 802 } 803 iIsInit = OMX_TRUE; 804 805 //aac lib init 806 if (!iCodecReady) 807 { 808 Status = ipAacDec->AacDecInit(ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.nChannels); 809 iCodecReady = OMX_TRUE; 810 } 811 812 //ipAacDec->iAacInitFlag = 0; 813 iInputCurrLength = 0; 814 //Used in dynamic port reconfiguration 815 iFrameCount = 0; 816 817 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : ComponentInit OUT")); 818 819 if (OMX_TRUE == Status) 820 { 821 return OMX_ErrorNone; 822 } 823 else 824 { 825 return OMX_ErrorInvalidComponent; 826 } 827 } 828 829 /** This function is called upon a transition to the idle or invalid state. 830 * Also it is called by the ComponentDestructor() function 831 */ 832 OMX_ERRORTYPE OpenmaxAacAO::ComponentDeInit() 833 { 834 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : ComponentDeInit IN")); 835 836 iIsInit = OMX_FALSE; 837 838 if (iCodecReady) 839 { 840 ipAacDec->AacDecDeinit(); 841 iCodecReady = OMX_FALSE; 842 } 843 844 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : ComponentDeInit OUT")); 845 846 return OMX_ErrorNone; 847 848 } 849 850 //Check whether silence insertion is required here or not 851 void OpenmaxAacAO::CheckForSilenceInsertion() 852 { 853 OMX_AUDIO_AACSTREAMFORMATTYPE InFormat = ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAacParam.eAACStreamFormat; 854 OMX_TICKS CurrTimestamp, TimestampGap; 855 //Set the flag to false by default 856 iSilenceInsertionInProgress = OMX_FALSE; 857 858 if (OMX_AUDIO_AACStreamFormatADIF == InFormat) 859 { 860 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : CheckForSilenceInsertion OUT - Don't do it for ADIF since there is no timestamp to sync")); 861 return; 862 } 863 864 CurrTimestamp = iCurrentFrameTS.GetCurrentTimestamp(); 865 TimestampGap = iFrameTimestamp - CurrTimestamp; 866 867 if ((TimestampGap > OMX_HALFRANGE_THRESHOLD) || (TimestampGap < iOutputMicroSecPerFrame && iFrameCount > 0)) 868 { 869 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : CheckForSilenceInsertion OUT - No need to insert silence")); 870 return; 871 } 872 873 //Silence insertion needed, mark the flag to true 874 if (iFrameCount > 0) 875 { 876 iSilenceInsertionInProgress = OMX_TRUE; 877 //Determine the number of silence frames to insert 878 if (0 != iOutputMicroSecPerFrame) 879 { 880 iSilenceFramesNeeded = TimestampGap / iOutputMicroSecPerFrame; 881 } 882 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : CheckForSilenceInsertion OUT - Silence Insertion required here")); 883 } 884 885 return; 886 } 887 888 //Perform the silence insertion 889 void OpenmaxAacAO::DoSilenceInsertion() 890 { 891 OMX_S32 NumOfChannels = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.nChannels; 892 QueueType* pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue; 893 ComponentPortType* pOutPort = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]; 894 895 OMX_U8* pOutBuffer = NULL; 896 OMX_U8* pSilenceInputBuffer = NULL; 897 OMX_U32 OutputLength, SilenceFrameLength; 898 OMX_S32 DecodeReturn; 899 OMX_BOOL ResizeNeeded = OMX_FALSE; 900 901 902 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : DoSilenceInsertion IN")); 903 904 while (iSilenceFramesNeeded > 0) 905 { 906 //Check whether prev output bufer has been consumed or not 907 if (OMX_TRUE == iNewOutBufRequired) 908 { 909 //Check whether a new output buffer is available or not 910 if (0 == (GetQueueNumElem(pOutputQueue))) 911 { 912 //Resume Silence insertion next time when component will be called 913 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : DoSilenceInsertion OUT output buffer unavailable")); 914 iSilenceInsertionInProgress = OMX_TRUE; 915 return; 916 } 917 918 ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue); 919 if (NULL == ipOutputBuffer) 920 { 921 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : DoSilenceInsertion Error, output buffer dequeue returned NULL, OUT")); 922 iSilenceInsertionInProgress = OMX_TRUE; 923 return; 924 } 925 ipOutputBuffer->nFilledLen = 0; 926 iNewOutBufRequired = OMX_FALSE; 927 928 //Set the current timestamp to the output buffer timestamp 929 ipOutputBuffer->nTimeStamp = iCurrentFrameTS.GetConvertedTs(); 930 } 931 932 // Setup the input side for silence frame 933 if (NumOfChannels > 1) 934 { 935 // Stereo silence frame 936 pSilenceInputBuffer = (OMX_U8*) AAC_STEREO_SILENCE_FRAME; 937 SilenceFrameLength = AAC_STEREO_SILENCE_FRAME_SIZE; 938 } 939 else 940 { 941 // Mono silence frame 942 pSilenceInputBuffer = (OMX_U8*) AAC_MONO_SILENCE_FRAME; 943 SilenceFrameLength = AAC_MONO_SILENCE_FRAME_SIZE; 944 } 945 946 947 pOutBuffer = &ipOutputBuffer->pBuffer[ipOutputBuffer->nFilledLen]; 948 OutputLength = 0; 949 950 //Decode the silence frame 951 DecodeReturn = ipAacDec->AacDecodeFrames((OMX_S16*) pOutBuffer, 952 (OMX_U32*) & OutputLength, 953 &(pSilenceInputBuffer), 954 &SilenceFrameLength, 955 &iFrameCount, 956 &(ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode), 957 &(ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioAacParam), 958 &iSamplesPerFrame, 959 &ResizeNeeded); 960 961 962 963 //Output length for a buffer of OMX_U8* will be double as that of OMX_S16* 964 ipOutputBuffer->nFilledLen += OutputLength * 2; 965 //offset not required in our case, set it to zero 966 ipOutputBuffer->nOffset = 0; 967 968 if (OutputLength > 0) 969 { 970 iCurrentFrameTS.UpdateTimestamp(iSamplesPerFrame); 971 } 972 973 if (MP4AUDEC_SUCCESS != DecodeReturn) 974 { 975 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : DoSilenceInsertion - Silence frame decoding error. Skip inserting silence frame and move the timestamp forward")); 976 iCurrentFrameTS.SetFromInputTimestamp(iFrameTimestamp); 977 iSilenceInsertionInProgress = OMX_FALSE; 978 return; 979 } 980 981 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : DoSilenceInsertion - silence frame decoded")); 982 983 //Send the output buffer back when it has become full 984 if ((ipOutputBuffer->nAllocLen - ipOutputBuffer->nFilledLen) < iOutputFrameLength) 985 { 986 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 987 ipOutputBuffer = NULL; 988 } 989 990 // Decrement the silence frame counter 991 --iSilenceFramesNeeded; 992 } 993 994 /* Completed Silence insertion successfully, now consider the input buffer already dequeued 995 * for decoding & update the timestamps */ 996 997 iSilenceInsertionInProgress = OMX_FALSE; 998 iCurrentFrameTS.SetFromInputTimestamp(iFrameTimestamp); 999 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAacAO : DoSilenceInsertion OUT - Done successfully")); 1000 1001 return; 1002 } 1003 1004 OMX_ERRORTYPE OpenmaxAacAO::GetConfig( 1005 OMX_IN OMX_HANDLETYPE hComponent, 1006 OMX_IN OMX_INDEXTYPE nIndex, 1007 OMX_INOUT OMX_PTR pComponentConfigStructure) 1008 { 1009 OSCL_UNUSED_ARG(hComponent); 1010 OSCL_UNUSED_ARG(nIndex); 1011 OSCL_UNUSED_ARG(pComponentConfigStructure); 1012 1013 return OMX_ErrorNotImplemented; 1014 } 1015