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_mpeg4_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 OSCL_DLL_ENTRY_POINT_DEFAULT() 32 33 static const uint32 mask[33] = 34 { 35 0x00000000, 0x00000001, 0x00000003, 0x00000007, 36 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, 37 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, 38 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 39 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, 40 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, 41 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, 42 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, 43 0xffffffff 44 }; 45 46 // This function is called by OMX_GetHandle and it creates an instance of the mpeg4 component AO 47 OSCL_EXPORT_REF OMX_ERRORTYPE Mpeg4OmxComponentFactory(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) 48 { 49 OSCL_UNUSED_ARG(aOmxLibName); 50 OSCL_UNUSED_ARG(aOmxLib); 51 OSCL_UNUSED_ARG(aOsclUuid); 52 OSCL_UNUSED_ARG(aRefCount); 53 54 55 OpenmaxMpeg4AO* pOpenmaxAOType; 56 OMX_ERRORTYPE Status; 57 58 // move InitMpeg4OmxComponentFields content to actual constructor 59 60 pOpenmaxAOType = (OpenmaxMpeg4AO*) OSCL_NEW(OpenmaxMpeg4AO, ()); 61 62 if (NULL == pOpenmaxAOType) 63 { 64 return OMX_ErrorInsufficientResources; 65 } 66 67 // set decoding mode to H263 68 pOpenmaxAOType->SetDecoderMode(MODE_MPEG4); 69 70 //Call the construct component to initialize OMX types 71 Status = pOpenmaxAOType->ConstructComponent(pAppData, pProxy); 72 73 *pHandle = pOpenmaxAOType->GetOmxHandle(); 74 75 return Status; 76 /////////////////////////////////////////////////////////////////////////////////////// 77 } 78 79 // This function is called by OMX_FreeHandle when component AO needs to be destroyed 80 OSCL_EXPORT_REF OMX_ERRORTYPE Mpeg4OmxComponentDestructor(OMX_IN OMX_HANDLETYPE pHandle, OMX_PTR &aOmxLib, OMX_PTR aOsclUuid, OMX_U32 &aRefCount) 81 { 82 OSCL_UNUSED_ARG(aOmxLib); 83 OSCL_UNUSED_ARG(aOsclUuid); 84 OSCL_UNUSED_ARG(aRefCount); 85 86 // get pointer to component AO 87 OpenmaxMpeg4AO* pOpenmaxAOType = (OpenmaxMpeg4AO*)((OMX_COMPONENTTYPE*)pHandle)->pComponentPrivate; 88 89 // clean up decoder, OMX component stuff 90 pOpenmaxAOType->DestroyComponent(); 91 92 // destroy the AO class 93 OSCL_DELETE(pOpenmaxAOType); 94 95 return OMX_ErrorNone; 96 } 97 98 // This function is called by OMX_GetHandle and it creates an instance of the h263 component AO 99 OSCL_EXPORT_REF OMX_ERRORTYPE H263OmxComponentFactory(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) 100 { 101 OSCL_UNUSED_ARG(aOmxLibName); 102 OSCL_UNUSED_ARG(aOmxLib); 103 OSCL_UNUSED_ARG(aOsclUuid); 104 OSCL_UNUSED_ARG(aRefCount); 105 106 OpenmaxMpeg4AO* pOpenmaxAOType; 107 OMX_ERRORTYPE Status; 108 109 // move InitMpeg4OmxComponentFields content to actual constructor 110 111 pOpenmaxAOType = (OpenmaxMpeg4AO*) OSCL_NEW(OpenmaxMpeg4AO, ()); 112 113 if (NULL == pOpenmaxAOType) 114 { 115 return OMX_ErrorInsufficientResources; 116 } 117 118 // set decoding mode to H263 119 pOpenmaxAOType->SetDecoderMode(MODE_H263); 120 121 //Call the construct component to initialize OMX types 122 Status = pOpenmaxAOType->ConstructComponent(pAppData, pProxy); 123 124 *pHandle = pOpenmaxAOType->GetOmxHandle(); 125 126 return Status; 127 /////////////////////////////////////////////////////////////////////////////////////// 128 } 129 130 // This function is called by OMX_FreeHandle when component AO needs to be destroyed 131 OSCL_EXPORT_REF OMX_ERRORTYPE H263OmxComponentDestructor(OMX_IN OMX_HANDLETYPE pHandle, OMX_PTR &aOmxLib, OMX_PTR aOsclUuid, OMX_U32 &aRefCount) 132 { 133 OSCL_UNUSED_ARG(aOmxLib); 134 OSCL_UNUSED_ARG(aOsclUuid); 135 OSCL_UNUSED_ARG(aRefCount); 136 137 // get pointer to component AO 138 OpenmaxMpeg4AO* pOpenmaxAOType = (OpenmaxMpeg4AO*)((OMX_COMPONENTTYPE*)pHandle)->pComponentPrivate; 139 140 // clean up decoder, OMX component stuff 141 pOpenmaxAOType->DestroyComponent(); 142 143 // destroy the AO class 144 OSCL_DELETE(pOpenmaxAOType); 145 146 return OMX_ErrorNone; 147 } 148 149 #if (DYNAMIC_LOAD_OMX_M4V_COMPONENT || DYNAMIC_LOAD_OMX_H263_COMPONENT) 150 class Mpeg4H263OmxSharedLibraryInterface: public OsclSharedLibraryInterface, 151 public OmxSharedLibraryInterface 152 153 { 154 public: 155 OsclAny *QueryOmxComponentInterface(const OsclUuid& aOmxTypeId, const OsclUuid& aInterfaceId) 156 { 157 if (PV_OMX_M4VDEC_UUID == aOmxTypeId) 158 { 159 if (PV_OMX_CREATE_INTERFACE == aInterfaceId) 160 { 161 return ((OsclAny*)(&Mpeg4OmxComponentFactory)); 162 } 163 else if (PV_OMX_DESTROY_INTERFACE == aInterfaceId) 164 { 165 return ((OsclAny*)(&Mpeg4OmxComponentDestructor)); 166 } 167 } 168 else if (PV_OMX_H263DEC_UUID == aOmxTypeId) 169 { 170 if (PV_OMX_CREATE_INTERFACE == aInterfaceId) 171 { 172 return ((OsclAny*)(&H263OmxComponentFactory)); 173 } 174 else if (PV_OMX_DESTROY_INTERFACE == aInterfaceId) 175 { 176 return ((OsclAny*)(&H263OmxComponentDestructor)); 177 } 178 } 179 return NULL; 180 }; 181 OsclAny *SharedLibraryLookup(const OsclUuid& aInterfaceId) 182 { 183 if (aInterfaceId == PV_OMX_SHARED_INTERFACE) 184 { 185 return OSCL_STATIC_CAST(OmxSharedLibraryInterface*, this); 186 } 187 return NULL; 188 }; 189 Mpeg4H263OmxSharedLibraryInterface() {}; 190 }; 191 192 // function to obtain the interface object from the shared library 193 extern "C" 194 { 195 OSCL_EXPORT_REF OsclAny* PVGetInterface() 196 { 197 return (OsclAny*) OSCL_NEW(Mpeg4H263OmxSharedLibraryInterface, ()); 198 } 199 200 OSCL_EXPORT_REF void PVReleaseInterface(OsclSharedLibraryInterface* aInstance) 201 { 202 Mpeg4H263OmxSharedLibraryInterface* module = (Mpeg4H263OmxSharedLibraryInterface*)aInstance; 203 OSCL_DELETE(module); 204 } 205 } 206 207 #endif 208 209 void OpenmaxMpeg4AO::SetDecoderMode(int mode) 210 { 211 iDecMode = mode; 212 } 213 214 215 216 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 217 218 OMX_ERRORTYPE OpenmaxMpeg4AO::ConstructComponent(OMX_PTR pAppData, OMX_PTR pProxy) 219 { 220 ComponentPortType *pInPort, *pOutPort; 221 OMX_ERRORTYPE Status; 222 223 iNumPorts = 2; 224 iOmxComponent.nSize = sizeof(OMX_COMPONENTTYPE); 225 iOmxComponent.pComponentPrivate = (OMX_PTR) this; // pComponentPrivate points to THIS component AO class 226 ipComponentProxy = pProxy; 227 iOmxComponent.pApplicationPrivate = pAppData; // init the App data 228 229 230 #if PROXY_INTERFACE 231 iPVCapabilityFlags.iIsOMXComponentMultiThreaded = OMX_TRUE; 232 233 iOmxComponent.SendCommand = OpenmaxMpeg4AO::BaseComponentProxySendCommand; 234 iOmxComponent.GetParameter = OpenmaxMpeg4AO::BaseComponentProxyGetParameter; 235 iOmxComponent.SetParameter = OpenmaxMpeg4AO::BaseComponentProxySetParameter; 236 iOmxComponent.GetConfig = OpenmaxMpeg4AO::BaseComponentProxyGetConfig; 237 iOmxComponent.SetConfig = OpenmaxMpeg4AO::BaseComponentProxySetConfig; 238 iOmxComponent.GetExtensionIndex = OpenmaxMpeg4AO::BaseComponentProxyGetExtensionIndex; 239 iOmxComponent.GetState = OpenmaxMpeg4AO::BaseComponentProxyGetState; 240 iOmxComponent.UseBuffer = OpenmaxMpeg4AO::BaseComponentProxyUseBuffer; 241 iOmxComponent.AllocateBuffer = OpenmaxMpeg4AO::BaseComponentProxyAllocateBuffer; 242 iOmxComponent.FreeBuffer = OpenmaxMpeg4AO::BaseComponentProxyFreeBuffer; 243 iOmxComponent.EmptyThisBuffer = OpenmaxMpeg4AO::BaseComponentProxyEmptyThisBuffer; 244 iOmxComponent.FillThisBuffer = OpenmaxMpeg4AO::BaseComponentProxyFillThisBuffer; 245 246 #else 247 iPVCapabilityFlags.iIsOMXComponentMultiThreaded = OMX_FALSE; 248 249 iOmxComponent.SendCommand = OpenmaxMpeg4AO::BaseComponentSendCommand; 250 iOmxComponent.GetParameter = OpenmaxMpeg4AO::BaseComponentGetParameter; 251 iOmxComponent.SetParameter = OpenmaxMpeg4AO::BaseComponentSetParameter; 252 iOmxComponent.GetConfig = OpenmaxMpeg4AO::BaseComponentGetConfig; 253 iOmxComponent.SetConfig = OpenmaxMpeg4AO::BaseComponentSetConfig; 254 iOmxComponent.GetExtensionIndex = OpenmaxMpeg4AO::BaseComponentGetExtensionIndex; 255 iOmxComponent.GetState = OpenmaxMpeg4AO::BaseComponentGetState; 256 iOmxComponent.UseBuffer = OpenmaxMpeg4AO::BaseComponentUseBuffer; 257 iOmxComponent.AllocateBuffer = OpenmaxMpeg4AO::BaseComponentAllocateBuffer; 258 iOmxComponent.FreeBuffer = OpenmaxMpeg4AO::BaseComponentFreeBuffer; 259 iOmxComponent.EmptyThisBuffer = OpenmaxMpeg4AO::BaseComponentEmptyThisBuffer; 260 iOmxComponent.FillThisBuffer = OpenmaxMpeg4AO::BaseComponentFillThisBuffer; 261 #endif 262 263 iOmxComponent.SetCallbacks = OpenmaxMpeg4AO::BaseComponentSetCallbacks; 264 iOmxComponent.nVersion.s.nVersionMajor = SPECVERSIONMAJOR; 265 iOmxComponent.nVersion.s.nVersionMinor = SPECVERSIONMINOR; 266 iOmxComponent.nVersion.s.nRevision = SPECREVISION; 267 iOmxComponent.nVersion.s.nStep = SPECSTEP; 268 269 // PV capability 270 iPVCapabilityFlags.iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE; 271 iPVCapabilityFlags.iOMXComponentSupportsExternalOutputBufferAlloc = OMX_TRUE; 272 iPVCapabilityFlags.iOMXComponentSupportsMovableInputBuffers = OMX_TRUE; 273 iPVCapabilityFlags.iOMXComponentSupportsPartialFrames = OMX_TRUE; 274 iPVCapabilityFlags.iOMXComponentUsesNALStartCodes = OMX_FALSE; 275 iPVCapabilityFlags.iOMXComponentCanHandleIncompleteFrames = OMX_TRUE; 276 iPVCapabilityFlags.iOMXComponentUsesFullAVCFrames = OMX_FALSE; 277 278 if (ipAppPriv) 279 { 280 oscl_free(ipAppPriv); 281 ipAppPriv = NULL; 282 } 283 284 ipAppPriv = (ComponentPrivateType*) oscl_malloc(sizeof(ComponentPrivateType)); 285 286 if (NULL == ipAppPriv) 287 { 288 return OMX_ErrorInsufficientResources; 289 } 290 291 //Construct base class now 292 Status = ConstructBaseComponent(pAppData); 293 294 if (OMX_ErrorNone != Status) 295 { 296 return Status; 297 } 298 299 /** Domain specific section for the ports. */ 300 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_INPUTPORT_INDEX; 301 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainVideo; 302 if (iDecMode == MODE_MPEG4) 303 { 304 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.cMIMEType = (OMX_STRING)"video/mpeg4"; 305 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4; 306 307 } 308 else if (iDecMode == MODE_H263) 309 { 310 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.cMIMEType = (OMX_STRING)"video/h263"; 311 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingH263; 312 313 } 314 315 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.pNativeRender = 0; 316 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.bFlagErrorConcealment = OMX_FALSE; 317 318 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.eColorFormat = OMX_COLOR_FormatUnused; 319 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.nFrameWidth = 176; 320 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.nFrameHeight = 144; 321 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.nBitrate = 64000; 322 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.xFramerate = (15 << 16); 323 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.eDir = OMX_DirInput; 324 //Set to a default value, will change later during setparameter call 325 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferCountActual = NUMBER_INPUT_BUFFER_MP4; 326 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferCountMin = 1; 327 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize = INPUT_BUFFER_SIZE_MP4; 328 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE; 329 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE; 330 331 332 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 333 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainVideo; 334 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.cMIMEType = (OMX_STRING)"raw"; 335 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.pNativeRender = 0; 336 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.bFlagErrorConcealment = OMX_FALSE; 337 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; 338 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar; 339 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameWidth = 176; //320; //176; 340 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nStride = 176; 341 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameHeight = 144; //240; //144; 342 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nSliceHeight = 144; 343 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nBitrate = 64000; 344 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.xFramerate = (15 << 16); 345 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDir = OMX_DirOutput; 346 //Set to a default value, will change later during setparameter call 347 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountActual = NUMBER_OUTPUT_BUFFER_MP4; 348 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountMin = 1; 349 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferSize = OUTPUT_BUFFER_SIZE_MP4; 350 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE; 351 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE; 352 353 if (iDecMode == MODE_MPEG4) 354 { 355 //Default values for mpeg4 video param port 356 ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoMpeg4.nPortIndex = OMX_PORT_INPUTPORT_INDEX; 357 ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoMpeg4.eProfile = OMX_VIDEO_MPEG4ProfileSimple; 358 ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoMpeg4.eLevel = OMX_VIDEO_MPEG4Level3; 359 360 ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.nPortIndex = OMX_PORT_INPUTPORT_INDEX; 361 ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.nProfileIndex = 0; 362 ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.eProfile = OMX_VIDEO_MPEG4ProfileSimple; 363 ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.eLevel = OMX_VIDEO_MPEG4Level3; 364 oscl_strncpy((OMX_STRING)iComponentRole, (OMX_STRING)"video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE); 365 } 366 else if (iDecMode == MODE_H263) 367 { 368 //Default values for h263 video param port 369 ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoH263.nPortIndex = OMX_PORT_INPUTPORT_INDEX; 370 ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoH263.eProfile = (OMX_VIDEO_H263PROFILETYPE) (OMX_VIDEO_H263ProfileBaseline | OMX_VIDEO_H263ProfileISWV2); 371 ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoH263.eLevel = OMX_VIDEO_H263Level45; 372 373 ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.nPortIndex = OMX_PORT_INPUTPORT_INDEX; 374 ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.nProfileIndex = 0; 375 ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.eProfile = OMX_VIDEO_H263ProfileBaseline | OMX_VIDEO_H263ProfileISWV2; 376 ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.eLevel = OMX_VIDEO_H263Level45; 377 oscl_strncpy((OMX_STRING)iComponentRole, (OMX_STRING)"video_decoder.h263", OMX_MAX_STRINGNAME_SIZE); 378 379 } 380 381 iPortTypesParam.nPorts = 2; 382 iPortTypesParam.nStartPortNumber = 0; 383 384 pInPort = (ComponentPortType*) ipPorts[OMX_PORT_INPUTPORT_INDEX]; 385 pOutPort = (ComponentPortType*) ipPorts[OMX_PORT_OUTPUTPORT_INDEX]; 386 387 pInPort->ActualNumPortFormatsSupported = 1; 388 389 //OMX_VIDEO_PARAM_PORTFORMATTYPE INPUT PORT SETTINGS 390 //On input port for index 0 391 SetHeader(&pInPort->VideoParam[0], sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); 392 pInPort->VideoParam[0].nPortIndex = 0; 393 pInPort->VideoParam[0].nIndex = 0; 394 395 if (iDecMode == MODE_MPEG4) 396 { 397 pInPort->VideoParam[0].eCompressionFormat = OMX_VIDEO_CodingMPEG4; 398 399 } 400 else if (iDecMode == MODE_H263) 401 { 402 pInPort->VideoParam[0].eCompressionFormat = OMX_VIDEO_CodingH263; 403 } 404 405 pInPort->VideoParam[0].eColorFormat = OMX_COLOR_FormatUnused; 406 407 pOutPort->ActualNumPortFormatsSupported = 1; 408 409 //OMX_VIDEO_PARAM_PORTFORMATTYPE OUTPUT PORT SETTINGS 410 //On output port for index 0 411 SetHeader(&pOutPort->VideoParam[0], sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); 412 pOutPort->VideoParam[0].nPortIndex = 1; 413 pOutPort->VideoParam[0].nIndex = 0; 414 pOutPort->VideoParam[0].eCompressionFormat = OMX_VIDEO_CodingUnused; 415 pOutPort->VideoParam[0].eColorFormat = OMX_COLOR_FormatYUV420Planar; 416 417 418 iUseExtTimestamp = OMX_TRUE; 419 420 421 if (ipMpegDecoderObject) 422 { 423 OSCL_DELETE(ipMpegDecoderObject); 424 ipMpegDecoderObject = NULL; 425 } 426 ipMpegDecoderObject = OSCL_NEW(Mpeg4Decoder_OMX, ()); 427 oscl_memset(ipMpegDecoderObject, 0, sizeof(Mpeg4Decoder_OMX)); 428 429 #if PROXY_INTERFACE 430 431 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSendCommand = BaseComponentSendCommand; 432 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetParameter = BaseComponentGetParameter; 433 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetParameter = BaseComponentSetParameter; 434 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetConfig = BaseComponentGetConfig; 435 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetConfig = BaseComponentSetConfig; 436 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetExtensionIndex = BaseComponentGetExtensionIndex; 437 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetState = BaseComponentGetState; 438 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentUseBuffer = BaseComponentUseBuffer; 439 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentAllocateBuffer = BaseComponentAllocateBuffer; 440 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentFreeBuffer = BaseComponentFreeBuffer; 441 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentEmptyThisBuffer = BaseComponentEmptyThisBuffer; 442 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentFillThisBuffer = BaseComponentFillThisBuffer; 443 444 #endif 445 446 return OMX_ErrorNone; 447 } 448 449 450 /** This function is called by the omx core when the component 451 * is disposed by the IL client with a call to FreeHandle(). 452 */ 453 454 OMX_ERRORTYPE OpenmaxMpeg4AO::DestroyComponent() 455 { 456 if (OMX_FALSE != iIsInit) 457 { 458 ComponentDeInit(); 459 } 460 461 //Destroy the base class now 462 DestroyBaseComponent(); 463 464 if (ipMpegDecoderObject) 465 { 466 OSCL_DELETE(ipMpegDecoderObject); 467 ipMpegDecoderObject = NULL; 468 } 469 470 if (ipAppPriv) 471 { 472 ipAppPriv->CompHandle = NULL; 473 474 oscl_free(ipAppPriv); 475 ipAppPriv = NULL; 476 } 477 478 return OMX_ErrorNone; 479 } 480 481 482 483 /* This function will be called in case of buffer management without marker bit present 484 * The purpose is to copy the current input buffer into a big temporary buffer, so that 485 * an incomplete/partial frame is never passed to the decoder library for decode 486 */ 487 void OpenmaxMpeg4AO::ComponentBufferMgmtWithoutMarker() 488 { 489 //This common routine has been written in the base class 490 TempInputBufferMgmtWithoutMarker(); 491 } 492 493 494 void OpenmaxMpeg4AO::ProcessData() 495 { 496 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : ProcessData IN")); 497 if (!iEndOfFrameFlag) 498 { 499 DecodeWithoutMarker(); 500 } 501 else 502 { 503 DecodeWithMarker(); 504 } 505 506 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : ProcessData OUT")); 507 } 508 509 510 void OpenmaxMpeg4AO::DecodeWithoutMarker() 511 { 512 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker IN")); 513 514 QueueType* pInputQueue = ipPorts[OMX_PORT_INPUTPORT_INDEX]->pBufferQueue; 515 QueueType* pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue; 516 ComponentPortType* pOutPort = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]; 517 OMX_COMPONENTTYPE *pHandle = &iOmxComponent; 518 519 OMX_U8* pOutBuffer; 520 OMX_U32 OutputLength; 521 OMX_U8* pTempInBuffer; 522 OMX_U32 TempInLength; 523 OMX_BOOL DecodeReturn; 524 OMX_BOOL MarkerFlag = OMX_FALSE; 525 OMX_BOOL ResizeNeeded = OMX_FALSE; 526 527 OMX_U32 TempInputBufferSize = (2 * sizeof(uint8) * (ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize)); 528 529 OMX_U32 CurrWidth = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameWidth; 530 OMX_U32 CurrHeight = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameHeight; 531 532 if ((!iIsInputBufferEnded) || iEndofStream) 533 { 534 //Check whether a new output buffer is available or not 535 if (0 == (GetQueueNumElem(pOutputQueue))) 536 { 537 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker OUT output buffer unavailable")); 538 //Store the mark data for output buffer, as it will be overwritten next time 539 if (NULL != ipTargetComponent) 540 { 541 ipTempTargetComponent = ipTargetComponent; 542 iTempTargetMarkData = iTargetMarkData; 543 iMarkPropagate = OMX_TRUE; 544 } 545 return; 546 } 547 548 ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue); 549 if (NULL == ipOutputBuffer) 550 { 551 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker Error, output buffer dequeue returned NULL, OUT")); 552 return; 553 } 554 555 //Do not proceed if the output buffer can't fit the YUV data 556 if ((ipOutputBuffer->nAllocLen < (OMX_U32)((((CurrWidth + 15) >> 4) << 4) *(((CurrHeight + 15) >> 4) << 4) * 3 / 2)) && (OMX_TRUE == ipMpegDecoderObject->Mpeg4InitCompleteFlag)) 557 { 558 ipOutputBuffer->nFilledLen = 0; 559 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 560 ipOutputBuffer = NULL; 561 return; 562 } 563 564 ipOutputBuffer->nFilledLen = 0; 565 566 567 /* Code for the marking buffer. Takes care of the OMX_CommandMarkBuffer 568 * command and hMarkTargetComponent as given by the specifications 569 */ 570 if (ipMark != NULL) 571 { 572 ipOutputBuffer->hMarkTargetComponent = ipMark->hMarkTargetComponent; 573 ipOutputBuffer->pMarkData = ipMark->pMarkData; 574 ipMark = NULL; 575 } 576 577 if ((OMX_TRUE == iMarkPropagate) && (ipTempTargetComponent != ipTargetComponent)) 578 { 579 ipOutputBuffer->hMarkTargetComponent = ipTempTargetComponent; 580 ipOutputBuffer->pMarkData = iTempTargetMarkData; 581 ipTempTargetComponent = NULL; 582 iMarkPropagate = OMX_FALSE; 583 } 584 else if (ipTargetComponent != NULL) 585 { 586 ipOutputBuffer->hMarkTargetComponent = ipTargetComponent; 587 ipOutputBuffer->pMarkData = iTargetMarkData; 588 ipTargetComponent = NULL; 589 iMarkPropagate = OMX_FALSE; 590 591 } 592 //Mark buffer code ends here 593 594 pOutBuffer = ipOutputBuffer->pBuffer; 595 OutputLength = 0; 596 597 pTempInBuffer = ipTempInputBuffer + iTempConsumedLength; 598 TempInLength = iTempInputBufferLength; 599 600 //Output buffer is passed as a short pointer 601 DecodeReturn = ipMpegDecoderObject->Mp4DecodeVideo(pOutBuffer, (OMX_U32*) & OutputLength, 602 &(pTempInBuffer), 603 &TempInLength, 604 &(ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam), 605 &iFrameCount, 606 MarkerFlag, 607 &ResizeNeeded); 608 609 ipOutputBuffer->nFilledLen = OutputLength; 610 611 //offset not required in our case, set it to zero 612 ipOutputBuffer->nOffset = 0; 613 614 //If decoder returned error, report it to the client via a callback 615 if (!DecodeReturn && OMX_FALSE == ipMpegDecoderObject->Mpeg4InitCompleteFlag) 616 { 617 // initialization error, stop playback 618 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker ErrorBadParameter callback send")); 619 620 (*(ipCallbacks->EventHandler)) 621 (pHandle, 622 iCallbackData, 623 OMX_EventError, 624 OMX_ErrorBadParameter, 625 0, 626 NULL); 627 } 628 else if (!DecodeReturn && OMX_FALSE == iEndofStream) 629 { 630 // decoding error 631 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker ErrorStreamCorrupt callback send")); 632 633 (*(ipCallbacks->EventHandler)) 634 (pHandle, 635 iCallbackData, 636 OMX_EventError, 637 OMX_ErrorStreamCorrupt, 638 0, 639 NULL); 640 } 641 642 643 if (ResizeNeeded == OMX_TRUE) 644 { 645 // send port settings changed event 646 OMX_COMPONENTTYPE* pHandle = (OMX_COMPONENTTYPE*) ipAppPriv->CompHandle; 647 648 // set the flag to disable further processing until Client reacts to this 649 // by doing dynamic port reconfiguration 650 iResizePending = OMX_TRUE; 651 652 (*(ipCallbacks->EventHandler)) 653 (pHandle, 654 iCallbackData, 655 OMX_EventPortSettingsChanged, //The command was completed 656 OMX_PORT_OUTPUTPORT_INDEX, 657 0, 658 NULL); 659 660 } 661 //Set the timestamp equal to the input buffer timestamp 662 ipOutputBuffer->nTimeStamp = iFrameTimestamp; 663 664 iTempConsumedLength += (iTempInputBufferLength - TempInLength); 665 iTempInputBufferLength = TempInLength; 666 667 //Do not decode if big buffer is less than half the size 668 if (TempInLength < (TempInputBufferSize >> 1)) 669 { 670 iIsInputBufferEnded = OMX_TRUE; 671 iNewInBufferRequired = OMX_TRUE; 672 } 673 674 675 /* If EOS flag has come from the client & there are no more 676 * input buffers to decode, send the callback to the client 677 */ 678 if (OMX_TRUE == iEndofStream) 679 { 680 if ((0 == iTempInputBufferLength) || (!DecodeReturn)) 681 { 682 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker EOS callback send")); 683 684 (*(ipCallbacks->EventHandler)) 685 (pHandle, 686 iCallbackData, 687 OMX_EventBufferFlag, 688 1, 689 OMX_BUFFERFLAG_EOS, 690 NULL); 691 692 iNewInBufferRequired = OMX_TRUE; 693 iEndofStream = OMX_FALSE; 694 695 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_EOS; 696 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 697 ipOutputBuffer = NULL; 698 699 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker OUT")); 700 701 return; 702 } 703 } 704 705 //Send the output buffer back after decode 706 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 707 ipOutputBuffer = NULL; 708 709 /* If there is some more processing left with current buffers, re-schedule the AO 710 * Do not go for more than one round of processing at a time. 711 * This may block the AO longer than required. 712 */ 713 if ((TempInLength != 0 || GetQueueNumElem(pInputQueue) > 0) && (GetQueueNumElem(pOutputQueue) > 0) && (ResizeNeeded == OMX_FALSE)) 714 { 715 RunIfNotReady(); 716 } 717 } 718 719 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker OUT")); 720 return; 721 } 722 723 724 void OpenmaxMpeg4AO::DecodeWithMarker() 725 { 726 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithMarker IN")); 727 728 QueueType* pInputQueue = ipPorts[OMX_PORT_INPUTPORT_INDEX]->pBufferQueue; 729 QueueType* pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue; 730 731 ComponentPortType* pInPort = ipPorts[OMX_PORT_INPUTPORT_INDEX]; 732 ComponentPortType* pOutPort = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]; 733 734 OMX_U8* pOutBuffer; 735 OMX_U32 OutputLength; 736 OMX_BOOL DecodeReturn = OMX_FALSE; 737 OMX_BOOL MarkerFlag = OMX_TRUE; 738 OMX_COMPONENTTYPE * pHandle = &iOmxComponent; 739 OMX_BOOL ResizeNeeded = OMX_FALSE; 740 741 OMX_U32 CurrWidth = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameWidth; 742 OMX_U32 CurrHeight = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameHeight; 743 744 if ((!iIsInputBufferEnded) || (iEndofStream)) 745 { 746 //Check whether a new output buffer is available or not 747 if (0 == (GetQueueNumElem(pOutputQueue))) 748 { 749 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithMarker OUT output buffer unavailable")); 750 iNewInBufferRequired = OMX_FALSE; 751 return; 752 } 753 754 ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue); 755 if (NULL == ipOutputBuffer) 756 { 757 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithMarker Error, output buffer dequeue returned NULL, OUT")); 758 iNewInBufferRequired = OMX_FALSE; 759 return; 760 } 761 762 //Do not proceed if the output buffer can't fit the YUV data 763 if ((ipOutputBuffer->nAllocLen < (OMX_U32)((((CurrWidth + 15) >> 4) << 4) *(((CurrHeight + 15) >> 4) << 4) * 3 / 2)) && (OMX_TRUE == ipMpegDecoderObject->Mpeg4InitCompleteFlag)) 764 { 765 ipOutputBuffer->nFilledLen = 0; 766 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 767 ipOutputBuffer = NULL; 768 return; 769 } 770 ipOutputBuffer->nFilledLen = 0; 771 772 /* Code for the marking buffer. Takes care of the OMX_CommandMarkBuffer 773 * command and hMarkTargetComponent as given by the specifications 774 */ 775 if (ipMark != NULL) 776 { 777 ipOutputBuffer->hMarkTargetComponent = ipMark->hMarkTargetComponent; 778 ipOutputBuffer->pMarkData = ipMark->pMarkData; 779 ipMark = NULL; 780 } 781 782 if (ipTargetComponent != NULL) 783 { 784 ipOutputBuffer->hMarkTargetComponent = ipTargetComponent; 785 ipOutputBuffer->pMarkData = iTargetMarkData; 786 ipTargetComponent = NULL; 787 788 } 789 //Mark buffer code ends here 790 791 if (iInputCurrLength > 0) 792 { 793 pOutBuffer = ipOutputBuffer->pBuffer; 794 OutputLength = 0; 795 796 //Output buffer is passed as a short pointer 797 DecodeReturn = ipMpegDecoderObject->Mp4DecodeVideo(pOutBuffer, (OMX_U32*) & OutputLength, 798 &(ipFrameDecodeBuffer), 799 &(iInputCurrLength), 800 &(ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam), 801 &iFrameCount, 802 MarkerFlag, 803 &ResizeNeeded); 804 805 ipOutputBuffer->nFilledLen = OutputLength; 806 //offset not required in our case, set it to zero 807 ipOutputBuffer->nOffset = 0; 808 809 //If decoder returned error, report it to the client via a callback 810 if (!DecodeReturn && OMX_FALSE == ipMpegDecoderObject->Mpeg4InitCompleteFlag) 811 { 812 // initialization error, stop playback 813 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker ErrorBadParameter callback send")); 814 815 (*(ipCallbacks->EventHandler)) 816 (pHandle, 817 iCallbackData, 818 OMX_EventError, 819 OMX_ErrorBadParameter, 820 0, 821 NULL); 822 } 823 else if (!DecodeReturn && OMX_FALSE == iEndofStream) 824 { 825 // decode error 826 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithMarker ErrorStreamCorrupt callback send")); 827 828 (*(ipCallbacks->EventHandler)) 829 (pHandle, 830 iCallbackData, 831 OMX_EventError, 832 OMX_ErrorStreamCorrupt, 833 0, 834 NULL); 835 } 836 837 if (ResizeNeeded == OMX_TRUE) 838 { 839 // send port settings changed event 840 OMX_COMPONENTTYPE* pHandle = (OMX_COMPONENTTYPE*) ipAppPriv->CompHandle; 841 842 iResizePending = OMX_TRUE; 843 (*(ipCallbacks->EventHandler)) 844 (pHandle, 845 iCallbackData, 846 OMX_EventPortSettingsChanged, //The command was completed 847 OMX_PORT_OUTPUTPORT_INDEX, 848 0, 849 NULL); 850 851 } 852 //Set the timestamp equal to the input buffer timestamp 853 if (OMX_TRUE == iUseExtTimestamp) 854 { 855 ipOutputBuffer->nTimeStamp = iFrameTimestamp; 856 } 857 858 /* Discard the input frame if it is with the marker bit & decoder fails*/ 859 if (iInputCurrLength == 0 || !DecodeReturn) 860 { 861 ipInputBuffer->nFilledLen = 0; 862 ReturnInputBuffer(ipInputBuffer, pInPort); 863 ipInputBuffer = NULL; 864 iNewInBufferRequired = OMX_TRUE; 865 iIsInputBufferEnded = OMX_TRUE; 866 iUseExtTimestamp = OMX_TRUE; 867 iInputCurrLength = 0; 868 } 869 else 870 { 871 iNewInBufferRequired = OMX_FALSE; 872 iIsInputBufferEnded = OMX_FALSE; 873 iUseExtTimestamp = OMX_FALSE; 874 } 875 } 876 else if (iEndofStream == OMX_FALSE) 877 { 878 // it's possible that after partial frame assembly, the input buffer still remains empty (due to 879 // client erroneously sending such buffers). This code adds robustness in the sense that it returns such buffer to the client 880 881 ipInputBuffer->nFilledLen = 0; 882 ReturnInputBuffer(ipInputBuffer, pInPort); 883 ipInputBuffer = NULL; 884 iNewInBufferRequired = OMX_TRUE; 885 iIsInputBufferEnded = OMX_TRUE; 886 iUseExtTimestamp = OMX_TRUE; 887 } 888 889 890 891 892 /* If EOS flag has come from the client & there are no more 893 * input buffers to decode, send the callback to the client 894 */ 895 if (OMX_TRUE == iEndofStream) 896 { 897 if (!DecodeReturn) 898 { 899 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithMarker EOS callback send")); 900 901 (*(ipCallbacks->EventHandler)) 902 (pHandle, 903 iCallbackData, 904 OMX_EventBufferFlag, 905 1, 906 OMX_BUFFERFLAG_EOS, 907 NULL); 908 909 iNewInBufferRequired = OMX_TRUE; 910 //Mark this flag false once the callback has been send back 911 iEndofStream = OMX_FALSE; 912 913 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_EOS; 914 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 915 ipOutputBuffer = NULL; 916 917 if ((iNumInputBuffer != 0) && (NULL != ipInputBuffer)) 918 { 919 ReturnInputBuffer(ipInputBuffer, pInPort); 920 ipInputBuffer = NULL; 921 iIsInputBufferEnded = OMX_TRUE; 922 iInputCurrLength = 0; 923 } 924 925 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithMarker OUT")); 926 return; 927 } 928 929 } 930 931 //Send the output buffer back after decode 932 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 933 ipOutputBuffer = NULL; 934 935 936 /* If there is some more processing left with current buffers, re-schedule the AO 937 * Do not go for more than one round of processing at a time. 938 * This may block the AO longer than required. 939 */ 940 if ((iInputCurrLength != 0 || GetQueueNumElem(pInputQueue) > 0) 941 && (GetQueueNumElem(pOutputQueue) > 0) && (ResizeNeeded == OMX_FALSE)) 942 { 943 RunIfNotReady(); 944 } 945 } 946 947 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithMarker OUT")); 948 return; 949 } 950 951 952 //Not implemented & supported in case of base profile components 953 954 void OpenmaxMpeg4AO::ComponentGetRolesOfComponent(OMX_STRING* aRoleString) 955 { 956 *aRoleString = (OMX_STRING)"video_decoder.mpeg4"; 957 } 958 959 960 //Component constructor 961 OpenmaxMpeg4AO::OpenmaxMpeg4AO() 962 { 963 iUseExtTimestamp = OMX_TRUE; 964 ipMpegDecoderObject = NULL; 965 966 if (!IsAdded()) 967 { 968 AddToScheduler(); 969 } 970 971 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : constructed")); 972 } 973 974 975 //Active object destructor 976 OpenmaxMpeg4AO::~OpenmaxMpeg4AO() 977 { 978 if (IsAdded()) 979 { 980 RemoveFromScheduler(); 981 } 982 983 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : destructed")); 984 } 985 986 987 /** The Initialization function 988 */ 989 OMX_ERRORTYPE OpenmaxMpeg4AO::ComponentInit() 990 { 991 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : ComponentInit IN")); 992 993 OMX_ERRORTYPE Status = OMX_ErrorNone; 994 995 if (OMX_TRUE == iIsInit) 996 { 997 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : ComponentInit error incorrect operation")); 998 return OMX_ErrorIncorrectStateOperation; 999 } 1000 iIsInit = OMX_TRUE; 1001 1002 1003 if (!iCodecReady) 1004 { 1005 //Call the init routine here in case of H263 mode, without waiting for buffers 1006 1007 if (iDecMode == MODE_H263) 1008 { 1009 OMX_S32 Width, Height, Size = 0; 1010 OMX_U8* Buff = NULL; 1011 1012 //Pass dummy pointers during initializations 1013 if (OMX_TRUE != ipMpegDecoderObject->InitializeVideoDecode(&Width, &Height, &Buff, &Size, iDecMode)) 1014 { 1015 Status = OMX_ErrorInsufficientResources; 1016 } 1017 1018 ipMpegDecoderObject->Mpeg4InitCompleteFlag = OMX_TRUE; 1019 } 1020 else 1021 { 1022 //mp4 lib init 1023 Status = ipMpegDecoderObject->Mp4DecInit(); 1024 } 1025 1026 iCodecReady = OMX_TRUE; 1027 } 1028 1029 iUseExtTimestamp = OMX_TRUE; 1030 iInputCurrLength = 0; 1031 1032 //Used in dynamic port reconfiguration 1033 iFrameCount = 0; 1034 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : ComponentInit OUT")); 1035 1036 return Status; 1037 1038 } 1039 1040 /** This function is called upon a transition to the idle or invalid state. 1041 * Also it is called by the ComponentDestructor() function 1042 */ 1043 OMX_ERRORTYPE OpenmaxMpeg4AO::ComponentDeInit() 1044 { 1045 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : ComponentDeInit IN")); 1046 1047 OMX_ERRORTYPE Status = OMX_ErrorNone; 1048 1049 iIsInit = OMX_FALSE; 1050 1051 if (iCodecReady) 1052 { 1053 Status = ipMpegDecoderObject->Mp4DecDeinit(); 1054 iCodecReady = OMX_FALSE; 1055 } 1056 1057 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : ComponentDeInit OUT")); 1058 1059 return Status; 1060 1061 } 1062 1063 OMX_ERRORTYPE OpenmaxMpeg4AO::GetConfig( 1064 OMX_IN OMX_HANDLETYPE hComponent, 1065 OMX_IN OMX_INDEXTYPE nIndex, 1066 OMX_INOUT OMX_PTR pComponentConfigStructure) 1067 { 1068 OSCL_UNUSED_ARG(hComponent); 1069 OSCL_UNUSED_ARG(nIndex); 1070 OSCL_UNUSED_ARG(pComponentConfigStructure); 1071 return OMX_ErrorNotImplemented; 1072 } 1073 1074 1075 OMX_ERRORTYPE OpenmaxMpeg4AO::ReAllocatePartialAssemblyBuffers(OMX_BUFFERHEADERTYPE* aInputBufferHdr) 1076 { 1077 1078 // check if there is enough data in the buffer to read the information that we need 1079 if (aInputBufferHdr->nFilledLen >= MINIMUM_H263_SHORT_HEADER_SIZE) 1080 { 1081 OMX_U8 *pInputBuffer = (aInputBufferHdr->pBuffer + aInputBufferHdr->nOffset); 1082 1083 if (MODE_H263 == iDecMode) 1084 { 1085 OMX_BOOL Status = OMX_TRUE; 1086 1087 Status = DecodeH263Header(pInputBuffer, &iInputCurrBufferSize); 1088 1089 // Re-allocate the partial frame buffer in case the stream is not corrupted, 1090 // otherwise leave the buffer size as it is 1091 if (OMX_TRUE == Status) 1092 { 1093 if (NULL != ipInputCurrBuffer) 1094 { 1095 ipInputCurrBuffer = (OMX_U8*) oscl_realloc(ipInputCurrBuffer, iInputCurrBufferSize); 1096 if (NULL == ipInputCurrBuffer) 1097 { 1098 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentBase : DoStateSet error insufficient resources")); 1099 return OMX_ErrorInsufficientResources; 1100 } 1101 } 1102 1103 //Used when the buffers are not marked with EndOfFrame flag 1104 if (NULL != ipTempInputBuffer) 1105 { 1106 ipTempInputBuffer = (OMX_U8*) oscl_realloc(ipTempInputBuffer, iInputCurrBufferSize); 1107 if (NULL == ipTempInputBuffer) 1108 { 1109 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentBase : DoStateSet error insufficient resources")); 1110 return OMX_ErrorInsufficientResources; 1111 } 1112 } 1113 } 1114 } 1115 1116 return OMX_ErrorNone; 1117 } 1118 else 1119 { 1120 return OMX_ErrorInsufficientResources; 1121 } 1122 1123 } 1124 1125 OMX_BOOL OpenmaxMpeg4AO::DecodeH263Header(OMX_U8* aInputBuffer, 1126 OMX_U32* aBufferSize) 1127 { 1128 uint32 codeword; 1129 int32 extended_PTYPE = 0; 1130 int32 UFEP = 0; 1131 int32 custom_PFMT = 0; 1132 1133 //Reset the data bit position to the start of the stream 1134 iH263DataBitPos = 0; 1135 iH263BitPos = 0; 1136 //BitBuf contains the first 4 bytes of the aInputBuffer 1137 iH263BitBuf = (aInputBuffer[0] << 24) | (aInputBuffer[1] << 16) | (aInputBuffer[2] << 8) | aInputBuffer[3]; 1138 1139 ReadBits(aInputBuffer, 22, &codeword); 1140 if (codeword != 0x20) 1141 { 1142 return OMX_FALSE; 1143 } 1144 1145 ReadBits(aInputBuffer, 8, &codeword); 1146 1147 ReadBits(aInputBuffer, 1, &codeword); 1148 if (codeword == 0) return OMX_FALSE; 1149 1150 ReadBits(aInputBuffer, 1, &codeword); 1151 if (codeword == 1) return OMX_FALSE; 1152 1153 ReadBits(aInputBuffer, 1, &codeword); 1154 if (codeword == 1) return OMX_FALSE; 1155 1156 ReadBits(aInputBuffer, 1, &codeword); 1157 if (codeword == 1) return OMX_FALSE; 1158 1159 ReadBits(aInputBuffer, 1, &codeword); 1160 if (codeword == 1) return OMX_FALSE; 1161 1162 /* source format */ 1163 ReadBits(aInputBuffer, 3, &codeword); 1164 switch (codeword) 1165 { 1166 case 1: 1167 *aBufferSize = 32000; 1168 break; 1169 1170 case 2: 1171 *aBufferSize = 32000; 1172 break; 1173 1174 case 3: 1175 *aBufferSize = 128000; 1176 break; 1177 1178 case 4: 1179 *aBufferSize = 256000; 1180 break; 1181 1182 case 5: 1183 *aBufferSize = 512000; 1184 break; 1185 1186 case 7: 1187 extended_PTYPE = 1; 1188 break; 1189 default: 1190 /* Msg("H.263 source format not legal\n"); */ 1191 return OMX_FALSE; 1192 } 1193 1194 if (extended_PTYPE == 0) 1195 { 1196 return OMX_TRUE; 1197 } 1198 1199 /* source format */ 1200 ReadBits(aInputBuffer, 3, &codeword); 1201 UFEP = codeword; 1202 if (UFEP == 1) 1203 { 1204 ReadBits(aInputBuffer, 3, &codeword); 1205 switch (codeword) 1206 { 1207 case 1: 1208 *aBufferSize = 32000; 1209 break; 1210 1211 case 2: 1212 *aBufferSize = 32000; 1213 break; 1214 1215 case 3: 1216 *aBufferSize = 128000; 1217 break; 1218 1219 case 4: 1220 *aBufferSize = 256000; 1221 break; 1222 1223 case 5: 1224 *aBufferSize = 512000; 1225 break; 1226 1227 case 6: 1228 custom_PFMT = 1; 1229 break; 1230 default: 1231 /* Msg("H.263 source format not legal\n"); */ 1232 return OMX_FALSE; 1233 } 1234 if (custom_PFMT == 0) 1235 { 1236 return OMX_TRUE; 1237 } 1238 1239 1240 ReadBits(aInputBuffer, 1, &codeword); 1241 ReadBits(aInputBuffer, 1, &codeword); 1242 if (codeword) return OMX_FALSE; 1243 ReadBits(aInputBuffer, 1, &codeword); 1244 if (codeword) return OMX_FALSE; 1245 ReadBits(aInputBuffer, 1, &codeword); 1246 if (codeword) return OMX_FALSE; 1247 ReadBits(aInputBuffer, 3, &codeword); 1248 ReadBits(aInputBuffer, 3, &codeword); 1249 if (codeword) return OMX_FALSE; /* RPS, ISD, AIV */ 1250 ReadBits(aInputBuffer, 1, &codeword); 1251 ReadBits(aInputBuffer, 4, &codeword); 1252 if (codeword != 8) return OMX_FALSE; 1253 } 1254 1255 if (UFEP == 0 || UFEP == 1) 1256 { 1257 ReadBits(aInputBuffer, 3, &codeword); 1258 if (codeword > 1) return OMX_FALSE; 1259 ReadBits(aInputBuffer, 1, &codeword); 1260 if (codeword) return OMX_FALSE; 1261 ReadBits(aInputBuffer, 1, &codeword); 1262 if (codeword) return OMX_FALSE; 1263 ReadBits(aInputBuffer, 1, &codeword); 1264 ReadBits(aInputBuffer, 3, &codeword); 1265 if (codeword != 1) return OMX_FALSE; 1266 } 1267 else 1268 { 1269 return OMX_FALSE; 1270 } 1271 1272 ReadBits(aInputBuffer, 1, &codeword); 1273 if (codeword) return OMX_FALSE; /* CPM */ 1274 if (custom_PFMT == 1 && UFEP == 1) 1275 { 1276 OMX_U32 DisplayWidth, Width, DisplayHeight, Height, Resolution; 1277 1278 ReadBits(aInputBuffer, 4, &codeword); 1279 if (codeword == 0) return OMX_FALSE; 1280 if (codeword == 0xf) 1281 { 1282 ReadBits(aInputBuffer, 8, &codeword); 1283 ReadBits(aInputBuffer, 8, &codeword); 1284 } 1285 ReadBits(aInputBuffer, 9, &codeword); 1286 DisplayWidth = (codeword + 1) << 2; 1287 Width = (DisplayWidth + 15) & -16; 1288 1289 ReadBits(aInputBuffer, 1, &codeword); 1290 if (codeword != 1) return OMX_FALSE; 1291 ReadBits(aInputBuffer, 9, &codeword); 1292 if (codeword == 0) return OMX_FALSE; 1293 DisplayHeight = codeword << 2; 1294 Height = (DisplayHeight + 15) & -16; 1295 1296 Resolution = Width * Height; 1297 1298 if (Resolution <= 25344) //25344 = 176x144 (QCIF) 1299 { 1300 *aBufferSize = 32000; 1301 } 1302 else if (Resolution <= 101376) //101376 = 352x288 (CIF) 1303 { 1304 *aBufferSize = 128000; 1305 } 1306 else if (Resolution <= 405504) //405504 = 704*576 (4CIF) 1307 { 1308 *aBufferSize = 256000; 1309 } 1310 else //1408x1152 (16CIF) 1311 { 1312 //This is the max buffer size that we want to allocate 1313 *aBufferSize = 512000; 1314 } 1315 } 1316 1317 return OMX_TRUE; 1318 } 1319 1320 1321 void OpenmaxMpeg4AO::ReadBits(OMX_U8* aStream, /* Input Stream */ 1322 uint8 aNumBits, /* nr of bits to read */ 1323 uint32* aOutData /* output target */ 1324 ) 1325 { 1326 uint8 *bits; 1327 uint32 dataBitPos = iH263DataBitPos; 1328 uint32 bitPos = iH263BitPos; 1329 uint32 dataBytePos; 1330 1331 if (aNumBits > (32 - bitPos)) /* not enough bits */ 1332 { 1333 dataBytePos = dataBitPos >> 3; /* Byte Aligned Position */ 1334 bitPos = dataBitPos & 7; /* update bit position */ 1335 bits = &aStream[dataBytePos]; 1336 iH263BitBuf = (bits[0] << 24) | (bits[1] << 16) | (bits[2] << 8) | bits[3]; 1337 } 1338 1339 iH263DataBitPos += aNumBits; 1340 iH263BitPos = (unsigned char)(bitPos + aNumBits); 1341 1342 *aOutData = (iH263BitBuf >> (32 - iH263BitPos)) & mask[(uint16)aNumBits]; 1343 1344 return; 1345 } 1346 1347