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 "OMX_Types.h" 20 #include "pv_omxdefs.h" 21 #include "omx_avc_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 OSCL_DLL_ENTRY_POINT_DEFAULT() 33 34 // This function is called by OMX_GetHandle and it creates an instance of the avc component AO 35 OSCL_EXPORT_REF OMX_ERRORTYPE AvcOmxComponentFactory(OMX_OUT OMX_HANDLETYPE* pHandle, OMX_IN OMX_PTR pAppData, OMX_IN OMX_PTR pProxy , OMX_STRING aOmxLibName, OMX_PTR &aOmxLib, OMX_PTR aOsclUuid, OMX_U32 &aRefCount) 36 { 37 OSCL_UNUSED_ARG(aOmxLibName); 38 OSCL_UNUSED_ARG(aOmxLib); 39 OSCL_UNUSED_ARG(aOsclUuid); 40 OSCL_UNUSED_ARG(aRefCount); 41 42 OpenmaxAvcAO* pOpenmaxAOType; 43 OMX_ERRORTYPE Status; 44 45 // move InitAvcOmxComponentFields content to actual constructor 46 47 pOpenmaxAOType = (OpenmaxAvcAO*) OSCL_NEW(OpenmaxAvcAO, ()); 48 49 if (NULL == pOpenmaxAOType) 50 { 51 return OMX_ErrorInsufficientResources; 52 } 53 54 //Call the construct component to initialize OMX types 55 Status = pOpenmaxAOType->ConstructComponent(pAppData, pProxy); 56 57 *pHandle = pOpenmaxAOType->GetOmxHandle(); 58 59 return Status; 60 /////////////////////////////////////////////////////////////////////////////////////// 61 } 62 63 // This function is called by OMX_FreeHandle when component AO needs to be destroyed 64 OSCL_EXPORT_REF OMX_ERRORTYPE AvcOmxComponentDestructor(OMX_IN OMX_HANDLETYPE pHandle, OMX_PTR &aOmxLib, OMX_PTR aOsclUuid, OMX_U32 &aRefCount) 65 { 66 OSCL_UNUSED_ARG(aOmxLib); 67 OSCL_UNUSED_ARG(aOsclUuid); 68 OSCL_UNUSED_ARG(aRefCount); 69 70 // get pointer to component AO 71 OpenmaxAvcAO* pOpenmaxAOType = (OpenmaxAvcAO*)((OMX_COMPONENTTYPE*)pHandle)->pComponentPrivate; 72 73 // clean up decoder, OMX component stuff 74 pOpenmaxAOType->DestroyComponent(); 75 76 // destroy the AO class 77 OSCL_DELETE(pOpenmaxAOType); 78 79 return OMX_ErrorNone; 80 } 81 82 #if DYNAMIC_LOAD_OMX_AVC_COMPONENT 83 class OsclSharedLibraryInterface; 84 class AvcOmxSharedLibraryInterface: public OsclSharedLibraryInterface, 85 public OmxSharedLibraryInterface 86 87 { 88 public: 89 OsclAny *QueryOmxComponentInterface(const OsclUuid& aOmxTypeId, const OsclUuid& aInterfaceId) 90 { 91 if (PV_OMX_AVCDEC_UUID == aOmxTypeId) 92 { 93 if (PV_OMX_CREATE_INTERFACE == aInterfaceId) 94 { 95 return ((OsclAny*)(&AvcOmxComponentFactory)); 96 } 97 else if (PV_OMX_DESTROY_INTERFACE == aInterfaceId) 98 { 99 return ((OsclAny*)(&AvcOmxComponentDestructor)); 100 } 101 } 102 return NULL; 103 }; 104 OsclAny *SharedLibraryLookup(const OsclUuid& aInterfaceId) 105 { 106 if (aInterfaceId == PV_OMX_SHARED_INTERFACE) 107 { 108 return OSCL_STATIC_CAST(OmxSharedLibraryInterface*, this); 109 } 110 return NULL; 111 }; 112 113 AvcOmxSharedLibraryInterface() {}; 114 }; 115 116 // function to obtain the interface object from the shared library 117 extern "C" 118 { 119 OSCL_EXPORT_REF OsclAny* PVGetInterface() 120 { 121 return (OsclAny*) OSCL_NEW(AvcOmxSharedLibraryInterface, ()); 122 } 123 124 OSCL_EXPORT_REF void PVReleaseInterface(OsclSharedLibraryInterface* aInstance) 125 { 126 AvcOmxSharedLibraryInterface* module = (AvcOmxSharedLibraryInterface*)aInstance; 127 OSCL_DELETE(module); 128 } 129 } 130 131 #endif 132 133 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 134 OMX_ERRORTYPE OpenmaxAvcAO::ConstructComponent(OMX_PTR pAppData, OMX_PTR pProxy) 135 { 136 ComponentPortType* pInPort, *pOutPort; 137 OMX_ERRORTYPE Status; 138 139 iNumPorts = 2; 140 iOmxComponent.nSize = sizeof(OMX_COMPONENTTYPE); 141 iOmxComponent.pComponentPrivate = (OMX_PTR) this; // pComponentPrivate points to THIS component AO class 142 ipComponentProxy = pProxy; 143 iOmxComponent.pApplicationPrivate = pAppData; // init the App data 144 145 iNumNALs = 0; 146 iCurrNAL = 0; 147 iNALOffset = 0; 148 oscl_memset(iNALSizeArray, 0, MAX_NAL_PER_FRAME * sizeof(uint32)); 149 150 151 #if PROXY_INTERFACE 152 iPVCapabilityFlags.iIsOMXComponentMultiThreaded = OMX_TRUE; 153 154 iOmxComponent.SendCommand = OpenmaxAvcAO::BaseComponentProxySendCommand; 155 iOmxComponent.GetParameter = OpenmaxAvcAO::BaseComponentProxyGetParameter; 156 iOmxComponent.SetParameter = OpenmaxAvcAO::BaseComponentProxySetParameter; 157 iOmxComponent.GetConfig = OpenmaxAvcAO::BaseComponentProxyGetConfig; 158 iOmxComponent.SetConfig = OpenmaxAvcAO::BaseComponentProxySetConfig; 159 iOmxComponent.GetExtensionIndex = OpenmaxAvcAO::BaseComponentProxyGetExtensionIndex; 160 iOmxComponent.GetState = OpenmaxAvcAO::BaseComponentProxyGetState; 161 iOmxComponent.UseBuffer = OpenmaxAvcAO::BaseComponentProxyUseBuffer; 162 iOmxComponent.AllocateBuffer = OpenmaxAvcAO::BaseComponentProxyAllocateBuffer; 163 iOmxComponent.FreeBuffer = OpenmaxAvcAO::BaseComponentProxyFreeBuffer; 164 iOmxComponent.EmptyThisBuffer = OpenmaxAvcAO::BaseComponentProxyEmptyThisBuffer; 165 iOmxComponent.FillThisBuffer = OpenmaxAvcAO::BaseComponentProxyFillThisBuffer; 166 167 #else 168 iPVCapabilityFlags.iIsOMXComponentMultiThreaded = OMX_FALSE; 169 170 iOmxComponent.SendCommand = OpenmaxAvcAO::BaseComponentSendCommand; 171 iOmxComponent.GetParameter = OpenmaxAvcAO::BaseComponentGetParameter; 172 iOmxComponent.SetParameter = OpenmaxAvcAO::BaseComponentSetParameter; 173 iOmxComponent.GetConfig = OpenmaxAvcAO::BaseComponentGetConfig; 174 iOmxComponent.SetConfig = OpenmaxAvcAO::BaseComponentSetConfig; 175 iOmxComponent.GetExtensionIndex = OpenmaxAvcAO::BaseComponentGetExtensionIndex; 176 iOmxComponent.GetState = OpenmaxAvcAO::BaseComponentGetState; 177 iOmxComponent.UseBuffer = OpenmaxAvcAO::BaseComponentUseBuffer; 178 iOmxComponent.AllocateBuffer = OpenmaxAvcAO::BaseComponentAllocateBuffer; 179 iOmxComponent.FreeBuffer = OpenmaxAvcAO::BaseComponentFreeBuffer; 180 iOmxComponent.EmptyThisBuffer = OpenmaxAvcAO::BaseComponentEmptyThisBuffer; 181 iOmxComponent.FillThisBuffer = OpenmaxAvcAO::BaseComponentFillThisBuffer; 182 #endif 183 184 iOmxComponent.SetCallbacks = OpenmaxAvcAO::BaseComponentSetCallbacks; 185 iOmxComponent.nVersion.s.nVersionMajor = SPECVERSIONMAJOR; 186 iOmxComponent.nVersion.s.nVersionMinor = SPECVERSIONMINOR; 187 iOmxComponent.nVersion.s.nRevision = SPECREVISION; 188 iOmxComponent.nVersion.s.nStep = SPECSTEP; 189 190 // PV capability 191 #ifdef TEST_FULL_AVC_FRAME_MODE 192 iPVCapabilityFlags.iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE; 193 iPVCapabilityFlags.iOMXComponentSupportsExternalOutputBufferAlloc = OMX_TRUE; 194 iPVCapabilityFlags.iOMXComponentSupportsMovableInputBuffers = OMX_FALSE; // since we need copying for frame assembly in streaming case 195 iPVCapabilityFlags.iOMXComponentSupportsPartialFrames = OMX_FALSE; 196 iPVCapabilityFlags.iOMXComponentUsesNALStartCodes = OMX_FALSE; 197 iPVCapabilityFlags.iOMXComponentCanHandleIncompleteFrames = OMX_TRUE; 198 iPVCapabilityFlags.iOMXComponentUsesFullAVCFrames = OMX_TRUE; 199 #elif TEST_FULL_AVC_FRAME_MODE_SC 200 iPVCapabilityFlags.iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE; 201 iPVCapabilityFlags.iOMXComponentSupportsExternalOutputBufferAlloc = OMX_TRUE; 202 iPVCapabilityFlags.iOMXComponentSupportsMovableInputBuffers = OMX_FALSE; // since we need copying for frame assembly in streaming case 203 iPVCapabilityFlags.iOMXComponentSupportsPartialFrames = OMX_FALSE; 204 iPVCapabilityFlags.iOMXComponentUsesNALStartCodes = OMX_TRUE; 205 iPVCapabilityFlags.iOMXComponentCanHandleIncompleteFrames = OMX_TRUE; 206 iPVCapabilityFlags.iOMXComponentUsesFullAVCFrames = OMX_TRUE; 207 #else 208 iPVCapabilityFlags.iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE; 209 iPVCapabilityFlags.iOMXComponentSupportsExternalOutputBufferAlloc = OMX_TRUE; 210 iPVCapabilityFlags.iOMXComponentSupportsMovableInputBuffers = OMX_TRUE; 211 iPVCapabilityFlags.iOMXComponentSupportsPartialFrames = OMX_TRUE; 212 iPVCapabilityFlags.iOMXComponentUsesNALStartCodes = OMX_FALSE; 213 iPVCapabilityFlags.iOMXComponentCanHandleIncompleteFrames = OMX_TRUE; 214 iPVCapabilityFlags.iOMXComponentUsesFullAVCFrames = OMX_FALSE; 215 #endif 216 217 if (ipAppPriv) 218 { 219 oscl_free(ipAppPriv); 220 ipAppPriv = NULL; 221 } 222 223 ipAppPriv = (ComponentPrivateType*) oscl_malloc(sizeof(ComponentPrivateType)); 224 if (NULL == ipAppPriv) 225 { 226 return OMX_ErrorInsufficientResources; 227 } 228 229 //Construct base class now 230 Status = ConstructBaseComponent(pAppData); 231 232 if (OMX_ErrorNone != Status) 233 { 234 return Status; 235 } 236 237 /** Domain specific section for the ports. */ 238 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_INPUTPORT_INDEX; 239 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainVideo; 240 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.cMIMEType = (OMX_STRING)"video/Avc"; 241 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.pNativeRender = 0; 242 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.bFlagErrorConcealment = OMX_FALSE; 243 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; 244 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.eColorFormat = OMX_COLOR_FormatUnused; 245 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.nFrameWidth = 176; 246 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.nFrameHeight = 144; 247 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.nBitrate = 64000; 248 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.xFramerate = (15 << 16); 249 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.eDir = OMX_DirInput; 250 //Set to a default value, will change later during setparameter call 251 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferCountActual = NUMBER_INPUT_BUFFER_AVC; 252 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferCountMin = 1; 253 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize = INPUT_BUFFER_SIZE_AVC; 254 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE; 255 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE; 256 257 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 258 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainVideo; 259 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.cMIMEType = (OMX_STRING)"raw"; 260 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.pNativeRender = 0; 261 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.bFlagErrorConcealment = OMX_FALSE; 262 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; 263 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar; 264 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameWidth = 176; 265 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nStride = 176; 266 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameHeight = 144; 267 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nSliceHeight = 144; 268 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nBitrate = 64000; 269 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.xFramerate = (15 << 16); 270 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDir = OMX_DirOutput; 271 //Set to a default value, will change later during setparameter call 272 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountActual = NUMBER_OUTPUT_BUFFER_AVC 273 ; 274 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountMin = 1; 275 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferSize = OUTPUT_BUFFER_SIZE_AVC; //just use QCIF (as default) 276 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE; 277 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE; 278 279 //Default values for Avc video param port 280 ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoAvc.nPortIndex = OMX_PORT_INPUTPORT_INDEX; 281 ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoAvc.eProfile = OMX_VIDEO_AVCProfileBaseline; 282 ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoAvc.eLevel = OMX_VIDEO_AVCLevel1; 283 284 ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.nPortIndex = OMX_PORT_INPUTPORT_INDEX; 285 ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.nProfileIndex = 0; 286 ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.eProfile = OMX_VIDEO_AVCProfileBaseline; 287 ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.eLevel = OMX_VIDEO_AVCLevel1; 288 289 iPortTypesParam.nPorts = 2; 290 iPortTypesParam.nStartPortNumber = 0; 291 292 pInPort = (ComponentPortType*) ipPorts[OMX_PORT_INPUTPORT_INDEX]; 293 pOutPort = (ComponentPortType*) ipPorts[OMX_PORT_OUTPUTPORT_INDEX]; 294 295 pInPort->ActualNumPortFormatsSupported = 1; 296 297 //OMX_VIDEO_PARAM_PORTFORMATTYPE INPUT PORT SETTINGS 298 //On input port for index 0 299 SetHeader(&pInPort->VideoParam[0], sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); 300 pInPort->VideoParam[0].nPortIndex = 0; 301 pInPort->VideoParam[0].nIndex = 0; 302 pInPort->VideoParam[0].eCompressionFormat = OMX_VIDEO_CodingAVC; 303 pInPort->VideoParam[0].eColorFormat = OMX_COLOR_FormatUnused; 304 305 pOutPort->ActualNumPortFormatsSupported = 1; 306 307 //OMX_VIDEO_PARAM_PORTFORMATTYPE OUTPUT PORT SETTINGS 308 //On output port for index 0 309 SetHeader(&pOutPort->VideoParam[0], sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); 310 pOutPort->VideoParam[0].nPortIndex = 1; 311 pOutPort->VideoParam[0].nIndex = 0; 312 pOutPort->VideoParam[0].eCompressionFormat = OMX_VIDEO_CodingUnused; 313 pOutPort->VideoParam[0].eColorFormat = OMX_COLOR_FormatYUV420Planar; 314 315 oscl_strncpy((OMX_STRING)iComponentRole, (OMX_STRING)"video_decoder.avc", OMX_MAX_STRINGNAME_SIZE); 316 317 iDecodeReturn = OMX_FALSE; 318 319 if (ipAvcDec) 320 { 321 OSCL_DELETE(ipAvcDec); 322 ipAvcDec = NULL; 323 } 324 325 ipAvcDec = OSCL_NEW(AvcDecoder_OMX, ()); 326 if (ipAvcDec == NULL) 327 { 328 return OMX_ErrorInsufficientResources; 329 } 330 331 oscl_memset(ipAvcDec, 0, sizeof(AvcDecoder_OMX)); 332 333 #if PROXY_INTERFACE 334 335 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSendCommand = BaseComponentSendCommand; 336 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetParameter = BaseComponentGetParameter; 337 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetParameter = BaseComponentSetParameter; 338 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetConfig = BaseComponentGetConfig; 339 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetConfig = BaseComponentSetConfig; 340 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetExtensionIndex = BaseComponentGetExtensionIndex; 341 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetState = BaseComponentGetState; 342 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentUseBuffer = BaseComponentUseBuffer; 343 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentAllocateBuffer = BaseComponentAllocateBuffer; 344 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentFreeBuffer = BaseComponentFreeBuffer; 345 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentEmptyThisBuffer = BaseComponentEmptyThisBuffer; 346 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentFillThisBuffer = BaseComponentFillThisBuffer; 347 348 #endif 349 350 return OMX_ErrorNone; 351 } 352 353 354 /** This function is called by the omx core when the component 355 * is disposed by the IL client with a call to FreeHandle(). 356 * \param Component, the component to be disposed 357 */ 358 359 OMX_ERRORTYPE OpenmaxAvcAO::DestroyComponent() 360 { 361 if (iIsInit != OMX_FALSE) 362 { 363 ComponentDeInit(); 364 } 365 366 //Destroy the base class now 367 DestroyBaseComponent(); 368 369 if (ipAvcDec) 370 { 371 OSCL_DELETE(ipAvcDec); 372 ipAvcDec = NULL; 373 } 374 375 if (ipAppPriv) 376 { 377 ipAppPriv->CompHandle = NULL; 378 379 oscl_free(ipAppPriv); 380 ipAppPriv = NULL; 381 } 382 383 return OMX_ErrorNone; 384 } 385 386 387 /* This function will be called in case of buffer management without marker bit present 388 * The purpose is to copy the current input buffer into a big temporary buffer, so that 389 * an incomplete/partial frame is never passed to the decoder library for decode 390 */ 391 void OpenmaxAvcAO::ComponentBufferMgmtWithoutMarker() 392 { 393 //This common routine has been written in the base class 394 TempInputBufferMgmtWithoutMarker(); 395 } 396 397 OMX_BOOL OpenmaxAvcAO::ParseFullAVCFramesIntoNALs(OMX_BUFFERHEADERTYPE* aInputBuffer) 398 { 399 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : ParseFullAVCFramesIntoNALs IN")); 400 401 ipInputBuffer = aInputBuffer; 402 403 if (iNumInputBuffer == 0) 404 { 405 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentBase : ParseFullAVCFramesIntoNALs ERROR")); 406 return OMX_FALSE; 407 } 408 409 if (iPVCapabilityFlags.iOMXComponentUsesNALStartCodes && !(ipInputBuffer->nFlags & OMX_BUFFERFLAG_EXTRADATA)) 410 { 411 OMX_U32 offset = ipInputBuffer->nOffset; 412 OMX_U32 length = ipInputBuffer->nFilledLen; 413 OMX_U8* pBuffer = ipInputBuffer->pBuffer + offset; 414 OMX_U8* pTemp; 415 int32 nalSize; 416 417 iNumNALs = 0; 418 419 while (length > 0) 420 { 421 if (AVCDEC_SUCCESS != ipAvcDec->GetNextFullNAL_OMX(&pTemp, &nalSize, pBuffer, &length)) 422 { 423 break; 424 } 425 426 pBuffer += nalSize + (int32)(pTemp - pBuffer); 427 428 iNALSizeArray[iNumNALs] = nalSize; 429 430 iNumNALs++; 431 } 432 433 if (iNumNALs > 0) 434 { 435 iCurrNAL = 0; 436 iNALOffset = ipInputBuffer->nOffset + NAL_START_CODE_SIZE; 437 ipFrameDecodeBuffer = ipInputBuffer->pBuffer + iNALOffset; 438 iInputCurrLength = iNALSizeArray[iCurrNAL]; 439 iNALOffset += (iInputCurrLength + NAL_START_CODE_SIZE); // offset for next NAL 440 //capture the timestamp to be send to the corresponding output buffer 441 iFrameTimestamp = ipInputBuffer->nTimeStamp; 442 } 443 else 444 { 445 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentBase : ParseFullAVCFramesIntoNALs ERROR")); 446 return OMX_FALSE; 447 } 448 } 449 // may be a full frame, or may incomplete, therefore don't check for OMX_BUFFERFLAG_ENDOFFRAME 450 else if (ipInputBuffer->nFlags & OMX_BUFFERFLAG_EXTRADATA) 451 { 452 // get extra data from end of buffer 453 OMX_OTHER_EXTRADATATYPE *pExtra; 454 OMX_U32 offset = ipInputBuffer->nOffset + ipInputBuffer->nFilledLen; 455 OMX_U32 allocLen = ipInputBuffer->nAllocLen; 456 OMX_U8* pTemp = ipInputBuffer->pBuffer + offset; 457 458 // align 459 pExtra = (OMX_OTHER_EXTRADATATYPE *)(((OMX_U32) pTemp + 3) & ~3); 460 offset += (OMX_U32) pExtra - (OMX_U32) pTemp; 461 462 while (pExtra->eType != OMX_ExtraDataNone) 463 { 464 if (pExtra->eType == OMX_ExtraDataNALSizeArray) 465 { 466 oscl_memcpy(iNALSizeArray, ((OMX_U8*)pExtra + 20), pExtra->nDataSize); 467 iNumNALs = pExtra->nDataSize >> 2; 468 iCurrNAL = 0; 469 iNALOffset = ipInputBuffer->nOffset; 470 break; 471 } 472 473 offset += pExtra->nSize; 474 if (offset > (allocLen - 20)) 475 { 476 // corrupt data 477 break; 478 } 479 else 480 { 481 pExtra = (OMX_OTHER_EXTRADATATYPE *)((OMX_U8*)pExtra + pExtra->nSize); 482 } 483 } 484 485 if (pExtra->eType != OMX_ExtraDataNALSizeArray) 486 { 487 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentBase : ParseFullAVCFramesIntoNALs ERROR")); 488 return OMX_FALSE; 489 } 490 491 ipFrameDecodeBuffer = ipInputBuffer->pBuffer + iNALOffset; 492 iInputCurrLength = iNALSizeArray[iCurrNAL]; 493 iNALOffset += iInputCurrLength; // offset for next NAL 494 //capture the timestamp to be send to the corresponding output buffer 495 iFrameTimestamp = ipInputBuffer->nTimeStamp; 496 } 497 else if (ipInputBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) 498 { 499 iInputCurrLength = ipInputBuffer->nFilledLen; 500 ipFrameDecodeBuffer = ipInputBuffer->pBuffer + ipInputBuffer->nOffset; 501 //capture the timestamp to be send to the corresponding output buffer 502 iFrameTimestamp = ipInputBuffer->nTimeStamp; 503 } 504 else 505 { 506 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentBase : ParseFullAVCFramesIntoNALs ERROR")); 507 return OMX_FALSE; 508 } 509 510 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : ParseFullAVCFramesIntoNALs OUT")); 511 return OMX_TRUE; 512 } 513 514 515 void OpenmaxAvcAO::ProcessData() 516 { 517 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : ProcessData IN")); 518 if (!iEndOfFrameFlag) 519 { 520 DecodeWithoutMarker(); 521 } 522 else 523 { 524 DecodeWithMarker(); 525 } 526 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : ProcessData OUT")); 527 } 528 529 530 /* Decoding function for input buffers without end of frame flag marked */ 531 void OpenmaxAvcAO::DecodeWithoutMarker() 532 { 533 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithoutMarker IN")); 534 535 QueueType* pInputQueue = ipPorts[OMX_PORT_INPUTPORT_INDEX]->pBufferQueue; 536 QueueType* pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue; 537 ComponentPortType* pOutPort = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]; 538 OMX_COMPONENTTYPE * pHandle = &iOmxComponent; 539 540 OMX_U8* pOutBuffer; 541 OMX_U32 OutputLength; 542 OMX_U8* pTempInBuffer; 543 OMX_U32 TempInLength; 544 OMX_BOOL MarkerFlag = OMX_FALSE; 545 OMX_TICKS TempTimestamp; 546 OMX_BOOL ResizeNeeded = OMX_FALSE; 547 548 OMX_U32 TempInputBufferSize = (2 * sizeof(uint8) * (ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize)); 549 OMX_U32 CurrWidth = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameWidth; 550 OMX_U32 CurrHeight = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameHeight; 551 552 553 if ((!iIsInputBufferEnded) || ((iEndofStream) || (0 != iTempInputBufferLength))) 554 { 555 //Check whether prev output bufer has been released or not 556 if (OMX_TRUE == iNewOutBufRequired) 557 { 558 //Check whether a new output buffer is available or not 559 if (0 == (GetQueueNumElem(pOutputQueue))) 560 { 561 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithoutMarker OUT output buffer unavailable")); 562 //Store the mark data for output buffer, as it will be overwritten next time 563 if (NULL != ipTargetComponent) 564 { 565 ipTempTargetComponent = ipTargetComponent; 566 iTempTargetMarkData = iTargetMarkData; 567 iMarkPropagate = OMX_TRUE; 568 } 569 return; 570 } 571 572 ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue); 573 if (NULL == ipOutputBuffer) 574 { 575 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithoutMarker Error, output buffer dequeue returned NULL, OUT")); 576 return; 577 } 578 579 //Do not proceed if the output buffer can't fit the YUV data 580 if ((ipOutputBuffer->nAllocLen < (OMX_U32)(((CurrWidth + 15)&(~15)) *((CurrHeight + 15)&(~15)) * 3 / 2)) && (OMX_TRUE == ipAvcDec->iAvcActiveFlag)) 581 { 582 ipOutputBuffer->nFilledLen = 0; 583 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 584 ipOutputBuffer = NULL; 585 return; 586 } 587 ipOutputBuffer->nFilledLen = 0; 588 iNewOutBufRequired = OMX_FALSE; 589 } 590 591 592 /* Code for the marking buffer. Takes care of the OMX_CommandMarkBuffer 593 * command and hMarkTargetComponent as given by the specifications 594 */ 595 if (NULL != ipMark) 596 { 597 ipOutputBuffer->hMarkTargetComponent = ipMark->hMarkTargetComponent; 598 ipOutputBuffer->pMarkData = ipMark->pMarkData; 599 ipMark = NULL; 600 } 601 602 if ((OMX_TRUE == iMarkPropagate) && (ipTempTargetComponent != ipTargetComponent)) 603 { 604 ipOutputBuffer->hMarkTargetComponent = ipTempTargetComponent; 605 ipOutputBuffer->pMarkData = iTempTargetMarkData; 606 ipTempTargetComponent = NULL; 607 iMarkPropagate = OMX_FALSE; 608 } 609 else if (ipTargetComponent != NULL) 610 { 611 ipOutputBuffer->hMarkTargetComponent = ipTargetComponent; 612 ipOutputBuffer->pMarkData = iTargetMarkData; 613 ipTargetComponent = NULL; 614 iMarkPropagate = OMX_FALSE; 615 } 616 //Mark buffer code ends here 617 618 pOutBuffer = ipOutputBuffer->pBuffer; 619 OutputLength = 0; 620 621 pTempInBuffer = ipTempInputBuffer + iTempConsumedLength; 622 TempInLength = iTempInputBufferLength; 623 624 //Output buffer is passed as a short pointer 625 iDecodeReturn = ipAvcDec->AvcDecodeVideo_OMX(pOutBuffer, (OMX_U32*) & OutputLength, 626 &(pTempInBuffer), 627 &TempInLength, 628 &(ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam), 629 &iFrameCount, 630 MarkerFlag, &TempTimestamp, &ResizeNeeded); 631 632 ipOutputBuffer->nFilledLen = OutputLength; 633 634 //offset not required in our case, set it to zero 635 ipOutputBuffer->nOffset = 0; 636 637 //Set the timestamp equal to the input buffer timestamp 638 ipOutputBuffer->nTimeStamp = iFrameTimestamp; 639 640 iTempConsumedLength += (iTempInputBufferLength - TempInLength); 641 iTempInputBufferLength = TempInLength; 642 643 //If decoder returned error, report it to the client via a callback 644 if (!iDecodeReturn && OMX_FALSE == ipAvcDec->iAvcActiveFlag) 645 { 646 // initialization error 647 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithoutMarker ErrorBadParameter callback send")); 648 649 (*(ipCallbacks->EventHandler)) 650 (pHandle, 651 iCallbackData, 652 OMX_EventError, 653 OMX_ErrorBadParameter, 654 0, 655 NULL); 656 } 657 else if (!iDecodeReturn && OMX_FALSE == iEndofStream) 658 { 659 // decoding error 660 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithoutMarker ErrorStreamCorrupt callback send")); 661 662 (*(ipCallbacks->EventHandler)) 663 (pHandle, 664 iCallbackData, 665 OMX_EventError, 666 OMX_ErrorStreamCorrupt, 667 0, 668 NULL); 669 } 670 671 672 //Do not decode if big buffer is less than half the size 673 if (TempInLength < (TempInputBufferSize >> 1)) 674 { 675 iIsInputBufferEnded = OMX_TRUE; 676 iNewInBufferRequired = OMX_TRUE; 677 } 678 679 if (ResizeNeeded == OMX_TRUE) 680 { 681 OMX_COMPONENTTYPE* pHandle = (OMX_COMPONENTTYPE*) ipAppPriv->CompHandle; 682 683 iResizePending = OMX_TRUE; 684 (*(ipCallbacks->EventHandler)) 685 (pHandle, 686 iCallbackData, 687 OMX_EventPortSettingsChanged, //The command was completed 688 OMX_PORT_OUTPUTPORT_INDEX, 689 0, 690 NULL); 691 } 692 693 /* If EOS flag has come from the client & there are no more 694 * input buffers to decode, send the callback to the client 695 */ 696 if (OMX_TRUE == iEndofStream) 697 { 698 if ((0 == iTempInputBufferLength) && !iDecodeReturn) 699 { 700 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithoutMarker EOS callback send")); 701 702 (*(ipCallbacks->EventHandler)) 703 (pHandle, 704 iCallbackData, 705 OMX_EventBufferFlag, 706 1, 707 OMX_BUFFERFLAG_EOS, 708 NULL); 709 710 iNewInBufferRequired = OMX_TRUE; 711 iEndofStream = OMX_FALSE; 712 713 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_EOS; 714 715 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 716 ipOutputBuffer = NULL; 717 718 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithoutMarker OUT")); 719 720 return; 721 } 722 } 723 724 //Send the output buffer back when it has some data in it 725 if (ipOutputBuffer->nFilledLen > 0) 726 { 727 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 728 ipOutputBuffer = NULL; 729 } 730 731 /* If there is some more processing left with current buffers, re-schedule the AO 732 * Do not go for more than one round of processing at a time. 733 * This may block the AO longer than required. 734 */ 735 if ((ResizeNeeded == OMX_FALSE) && ((TempInLength != 0) || (GetQueueNumElem(pInputQueue) > 0)) 736 && ((GetQueueNumElem(pOutputQueue) > 0) || (OMX_FALSE == iNewOutBufRequired))) 737 { 738 RunIfNotReady(); 739 } 740 } 741 742 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithoutMarker OUT")); 743 return; 744 } 745 746 747 /* Decoding function for input buffers with end of frame flag marked */ 748 void OpenmaxAvcAO::DecodeWithMarker() 749 { 750 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithMarker IN")); 751 752 OMX_COMPONENTTYPE *pHandle = &iOmxComponent; 753 QueueType* pInputQueue = ipPorts[OMX_PORT_INPUTPORT_INDEX]->pBufferQueue; 754 QueueType* pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue; 755 756 ComponentPortType* pInPort = ipPorts[OMX_PORT_INPUTPORT_INDEX]; 757 ComponentPortType* pOutPort = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]; 758 759 OMX_U8* pOutBuffer; 760 OMX_U32 OutputLength; 761 OMX_BOOL MarkerFlag = OMX_TRUE; 762 OMX_BOOL Status; 763 OMX_BOOL ResizeNeeded = OMX_FALSE; 764 765 OMX_U32 CurrWidth = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameWidth; 766 OMX_U32 CurrHeight = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameHeight; 767 768 if ((!iIsInputBufferEnded) || (iEndofStream)) 769 { 770 //Check whether prev output bufer has been released or not 771 if (OMX_TRUE == iNewOutBufRequired) 772 { 773 //Check whether a new output buffer is available or not 774 if (0 == (GetQueueNumElem(pOutputQueue))) 775 { 776 iNewInBufferRequired = OMX_FALSE; 777 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithMarker OUT output buffer unavailable")); 778 return; 779 } 780 781 ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue); 782 if (NULL == ipOutputBuffer) 783 { 784 iNewInBufferRequired = OMX_FALSE; 785 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithMarker Error, output buffer dequeue returned NULL, OUT")); 786 return; 787 } 788 789 //Do not proceed if the output buffer can't fit the YUV data 790 if ((ipOutputBuffer->nAllocLen < (OMX_U32)(((CurrWidth + 15)&(~15)) *((CurrHeight + 15)&(~15)) * 3 / 2)) && (OMX_TRUE == ipAvcDec->iAvcActiveFlag)) 791 { 792 ipOutputBuffer->nFilledLen = 0; 793 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 794 ipOutputBuffer = NULL; 795 return; 796 } 797 ipOutputBuffer->nFilledLen = 0; 798 iNewOutBufRequired = OMX_FALSE; 799 } 800 801 /* Code for the marking buffer. Takes care of the OMX_CommandMarkBuffer 802 * command and hMarkTargetComponent as given by the specifications 803 */ 804 if (NULL != ipMark) 805 { 806 ipOutputBuffer->hMarkTargetComponent = ipMark->hMarkTargetComponent; 807 ipOutputBuffer->pMarkData = ipMark->pMarkData; 808 ipMark = NULL; 809 } 810 811 if (NULL != ipTargetComponent) 812 { 813 ipOutputBuffer->hMarkTargetComponent = ipTargetComponent; 814 ipOutputBuffer->pMarkData = iTargetMarkData; 815 ipTargetComponent = NULL; 816 817 } 818 //Mark buffer code ends here 819 820 pOutBuffer = ipOutputBuffer->pBuffer; 821 OutputLength = 0; 822 823 if (iInputCurrLength > 0) 824 { 825 //Store the input timestamp into a temp variable 826 ipAvcDec->CurrInputTimestamp = iFrameTimestamp; 827 828 //Output buffer is passed as a short pointer 829 iDecodeReturn = ipAvcDec->AvcDecodeVideo_OMX(pOutBuffer, (OMX_U32*) & OutputLength, 830 &(ipFrameDecodeBuffer), 831 &(iInputCurrLength), 832 &(ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam), 833 &iFrameCount, 834 MarkerFlag, 835 &(ipOutputBuffer->nTimeStamp), &ResizeNeeded); 836 837 ipOutputBuffer->nFilledLen = OutputLength; 838 //offset not required in our case, set it to zero 839 ipOutputBuffer->nOffset = 0; 840 841 if (ResizeNeeded == OMX_TRUE) 842 { 843 OMX_COMPONENTTYPE* pHandle = (OMX_COMPONENTTYPE*) ipAppPriv->CompHandle; 844 845 // set the flag. Do not process any more frames until 846 // IL Client sends PortDisable event (thus starting the procedure for 847 // dynamic port reconfiguration) 848 iResizePending = OMX_TRUE; 849 850 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : Sending the PortSettings Changed Callback")); 851 852 (*(ipCallbacks->EventHandler)) 853 (pHandle, 854 iCallbackData, 855 OMX_EventPortSettingsChanged, //The command was completed 856 OMX_PORT_OUTPUTPORT_INDEX, 857 0, 858 NULL); 859 } 860 861 862 //If decoder returned error, report it to the client via a callback 863 if (!iDecodeReturn && OMX_FALSE == ipAvcDec->iAvcActiveFlag) 864 { 865 // initialization error 866 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithoutMarker ErrorBadParameter callback send")); 867 868 (*(ipCallbacks->EventHandler)) 869 (pHandle, 870 iCallbackData, 871 OMX_EventError, 872 OMX_ErrorBadParameter, 873 0, 874 NULL); 875 } 876 else if (!iDecodeReturn && OMX_FALSE == iEndofStream) 877 { 878 // decode error 879 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithMarker ErrorStreamCorrupt callback send")); 880 881 (*(ipCallbacks->EventHandler)) 882 (pHandle, 883 iCallbackData, 884 OMX_EventError, 885 OMX_ErrorStreamCorrupt, 886 0, 887 NULL); 888 } 889 890 891 if (0 == iInputCurrLength) 892 { 893 if (iPVCapabilityFlags.iOMXComponentUsesFullAVCFrames) 894 { 895 iCurrNAL++; 896 897 if (iCurrNAL < iNumNALs) 898 { 899 ipFrameDecodeBuffer = ipInputBuffer->pBuffer + iNALOffset; 900 iInputCurrLength = iNALSizeArray[iCurrNAL]; 901 902 if (iPVCapabilityFlags.iOMXComponentUsesNALStartCodes) 903 { 904 iNALOffset += (iInputCurrLength + NAL_START_CODE_SIZE); // offset for next NAL 905 } 906 else 907 { 908 iNALOffset += iInputCurrLength; // offset for next NAL 909 } 910 911 iNewInBufferRequired = OMX_FALSE; 912 } 913 else 914 { 915 ipInputBuffer->nFilledLen = 0; 916 ReturnInputBuffer(ipInputBuffer, pInPort); 917 iNewInBufferRequired = OMX_TRUE; 918 iIsInputBufferEnded = OMX_TRUE; 919 ipInputBuffer = NULL; 920 } 921 } 922 else 923 { 924 ipInputBuffer->nFilledLen = 0; 925 ReturnInputBuffer(ipInputBuffer, pInPort); 926 iNewInBufferRequired = OMX_TRUE; 927 iIsInputBufferEnded = OMX_TRUE; 928 ipInputBuffer = NULL; 929 } 930 } 931 else 932 { 933 iNewInBufferRequired = OMX_FALSE; 934 } 935 } 936 else if (iEndofStream == OMX_FALSE) 937 { 938 // it's possible that after partial frame assembly, the input buffer still remains empty (due to 939 // client erroneously sending such buffers). This may cause error in processing/returning buffers 940 // This code adds robustness in the sense that it returns such buffer to the client 941 942 ipInputBuffer->nFilledLen = 0; 943 ReturnInputBuffer(ipInputBuffer, pInPort); 944 ipInputBuffer = NULL; 945 iNewInBufferRequired = OMX_TRUE; 946 iIsInputBufferEnded = OMX_TRUE; 947 } 948 949 950 /* If EOS flag has come from the client & there are no more 951 * input buffers to decode, send the callback to the client*/ 952 if (OMX_TRUE == iEndofStream) 953 { 954 if (!iDecodeReturn) 955 { 956 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithMarker EOS callback send")); 957 958 (*(ipCallbacks->EventHandler)) 959 (pHandle, 960 iCallbackData, 961 OMX_EventBufferFlag, 962 1, 963 OMX_BUFFERFLAG_EOS, 964 NULL); 965 966 iNewInBufferRequired = OMX_TRUE; 967 iEndofStream = OMX_FALSE; 968 969 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_EOS; 970 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 971 ipOutputBuffer = NULL; 972 973 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithMarker OUT")); 974 975 return; 976 } 977 else if (iDecodeReturn) 978 { 979 Status = ipAvcDec->FlushOutput_OMX(pOutBuffer, &OutputLength, &(ipOutputBuffer->nTimeStamp), pOutPort->PortParam.format.video.nFrameWidth, pOutPort->PortParam.format.video.nFrameHeight); 980 ipOutputBuffer->nFilledLen = OutputLength; 981 982 ipOutputBuffer->nOffset = 0; 983 984 if (OMX_FALSE != Status) 985 { 986 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 987 ipOutputBuffer = NULL; 988 989 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithMarker OUT")); 990 RunIfNotReady(); 991 return; 992 } 993 else 994 { 995 iDecodeReturn = OMX_FALSE; 996 RunIfNotReady(); 997 } 998 } 999 } 1000 1001 //Send the output buffer back when it has some data in it 1002 if (ipOutputBuffer->nFilledLen > 0) 1003 { 1004 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 1005 ipOutputBuffer = NULL; 1006 } 1007 1008 1009 /* If there is some more processing left with current buffers, re-schedule the AO 1010 * Do not go for more than one round of processing at a time. 1011 * This may block the AO longer than required. 1012 */ 1013 if ((ResizeNeeded == OMX_FALSE) && ((iInputCurrLength != 0) || (GetQueueNumElem(pInputQueue) > 0)) 1014 && ((GetQueueNumElem(pOutputQueue) > 0) || (OMX_FALSE == iNewOutBufRequired))) 1015 { 1016 RunIfNotReady(); 1017 } 1018 } 1019 1020 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithMarker OUT")); 1021 return; 1022 } 1023 1024 1025 void OpenmaxAvcAO::ComponentGetRolesOfComponent(OMX_STRING* aRoleString) 1026 { 1027 *aRoleString = (OMX_STRING)"video_decoder.avc"; 1028 } 1029 1030 1031 1032 //Component object constructor 1033 OpenmaxAvcAO::OpenmaxAvcAO() 1034 { 1035 ipAvcDec = NULL; 1036 1037 if (!IsAdded()) 1038 { 1039 AddToScheduler(); 1040 } 1041 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : constructed")); 1042 } 1043 1044 1045 //Component object destructor 1046 OpenmaxAvcAO::~OpenmaxAvcAO() 1047 { 1048 if (IsAdded()) 1049 { 1050 RemoveFromScheduler(); 1051 } 1052 1053 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : destructed")); 1054 } 1055 1056 1057 /** The Initialization function 1058 */ 1059 OMX_ERRORTYPE OpenmaxAvcAO::ComponentInit() 1060 { 1061 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : ComponentInit IN")); 1062 1063 OMX_ERRORTYPE Status = OMX_ErrorNone; 1064 1065 if (OMX_TRUE == iIsInit) 1066 { 1067 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : ComponentInit error incorrect operation")); 1068 return OMX_ErrorIncorrectStateOperation; 1069 } 1070 iIsInit = OMX_TRUE; 1071 1072 //avc lib init 1073 if (!iCodecReady) 1074 { 1075 Status = ipAvcDec->AvcDecInit_OMX(); 1076 iCodecReady = OMX_TRUE; 1077 } 1078 1079 iInputCurrLength = 0; 1080 iNumNALs = 0; 1081 iCurrNAL = 0; 1082 iNALOffset = 0; 1083 oscl_memset(iNALSizeArray, 0, MAX_NAL_PER_FRAME * sizeof(uint32)); 1084 //Used in dynamic port reconfiguration 1085 iFrameCount = 0; 1086 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : ComponentInit OUT")); 1087 1088 return Status; 1089 1090 } 1091 1092 /** This function is called upon a transition to the idle or invalid state. 1093 * Also it is called by the AvcComponentDestructor() function 1094 */ 1095 OMX_ERRORTYPE OpenmaxAvcAO::ComponentDeInit() 1096 { 1097 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : ComponentDeInit IN")); 1098 1099 OMX_ERRORTYPE Status = OMX_ErrorNone; 1100 1101 iIsInit = OMX_FALSE; 1102 1103 if (iCodecReady) 1104 { 1105 Status = ipAvcDec->AvcDecDeinit_OMX(); 1106 iCodecReady = OMX_FALSE; 1107 } 1108 1109 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : ComponentDeInit OUT")); 1110 1111 return Status; 1112 1113 } 1114 1115 1116 OMX_ERRORTYPE OpenmaxAvcAO::GetConfig( 1117 OMX_IN OMX_HANDLETYPE hComponent, 1118 OMX_IN OMX_INDEXTYPE nIndex, 1119 OMX_INOUT OMX_PTR pComponentConfigStructure) 1120 { 1121 OSCL_UNUSED_ARG(hComponent); 1122 OSCL_UNUSED_ARG(nIndex); 1123 OSCL_UNUSED_ARG(pComponentConfigStructure); 1124 return OMX_ErrorNotImplemented; 1125 } 1126 1127 /* This routine will reset the decoder library and some of the associated flags*/ 1128 void OpenmaxAvcAO::ResetComponent() 1129 { 1130 // reset decoder 1131 if (ipAvcDec) 1132 { 1133 ipAvcDec->ResetDecoder(); 1134 } 1135 1136 } 1137