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 19 #include "omx_avcenc_component.h" 20 21 #if PROXY_INTERFACE 22 #include "omx_proxy_interface.h" 23 #endif 24 25 const uint8 NAL_START_CODE[4] = {0, 0, 0, 1}; 26 27 #define CONFIG_SIZE_AND_VERSION(param) \ 28 param.nSize=sizeof(param); \ 29 param.nVersion.s.nVersionMajor = SPECVERSIONMAJOR; \ 30 param.nVersion.s.nVersionMinor = SPECVERSIONMINOR; \ 31 param.nVersion.s.nRevision = SPECREVISION; \ 32 param.nVersion.s.nStep = SPECSTEP; 33 34 // This function is called by OMX_GetHandle and it creates an instance of the avc component AO 35 OMX_ERRORTYPE AvcEncOmxComponentFactory(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) 36 { 37 OSCL_UNUSED_ARG(aOmxLibName); 38 OSCL_UNUSED_ARG(aOmxLib); 39 OSCL_UNUSED_ARG(aOsclUuid); 40 OSCL_UNUSED_ARG(aRefCount); 41 42 43 OmxComponentAvcEncAO* pOpenmaxAOType; 44 OMX_ERRORTYPE Status; 45 46 // move InitAvcOmxComponentFields content to actual constructor 47 48 pOpenmaxAOType = (OmxComponentAvcEncAO*) OSCL_NEW(OmxComponentAvcEncAO, ()); 49 50 if (NULL == pOpenmaxAOType) 51 { 52 return OMX_ErrorInsufficientResources; 53 } 54 55 //Call the construct component to initialize OMX types 56 Status = pOpenmaxAOType->ConstructComponent(pAppData, pProxy); 57 58 *pHandle = pOpenmaxAOType->GetOmxHandle(); 59 60 return Status; 61 } 62 63 64 // This function is called by OMX_FreeHandle when component AO needs to be destroyed 65 OMX_ERRORTYPE AvcEncOmxComponentDestructor(OMX_IN OMX_HANDLETYPE pHandle, OMX_PTR &aOmxLib, OMX_PTR aOsclUuid, OMX_U32 &aRefCount) 66 { 67 OSCL_UNUSED_ARG(aOmxLib); 68 OSCL_UNUSED_ARG(aOsclUuid); 69 OSCL_UNUSED_ARG(aRefCount); 70 71 // get pointer to component AO 72 OmxComponentAvcEncAO* pOpenmaxAOType = (OmxComponentAvcEncAO*)((OMX_COMPONENTTYPE*)pHandle)->pComponentPrivate; 73 74 // clean up decoder, OMX component stuff 75 pOpenmaxAOType->DestroyComponent(); 76 77 // destroy the AO class 78 OSCL_DELETE(pOpenmaxAOType); 79 80 return OMX_ErrorNone; 81 } 82 83 #if DYNAMIC_LOAD_OMX_AVCENC_COMPONENT 84 85 class AvcEncOmxSharedLibraryInterface: public OsclSharedLibraryInterface, 86 public OmxSharedLibraryInterface 87 88 { 89 public: 90 OsclAny *QueryOmxComponentInterface(const OsclUuid& aOmxTypeId, const OsclUuid& aInterfaceId) 91 { 92 if (PV_OMX_AVCENC_UUID == aOmxTypeId) 93 { 94 if (PV_OMX_CREATE_INTERFACE == aInterfaceId) 95 { 96 return ((OsclAny*)(&AvcEncOmxComponentFactory)); 97 } 98 else if (PV_OMX_DESTROY_INTERFACE == aInterfaceId) 99 { 100 return ((OsclAny*)(&AvcEncOmxComponentDestructor)); 101 } 102 } 103 return NULL; 104 }; 105 106 OsclAny *SharedLibraryLookup(const OsclUuid& aInterfaceId) 107 { 108 if (aInterfaceId == PV_OMX_SHARED_INTERFACE) 109 { 110 return OSCL_STATIC_CAST(OmxSharedLibraryInterface*, this); 111 } 112 return NULL; 113 }; 114 115 AvcEncOmxSharedLibraryInterface() {}; 116 }; 117 118 // function to obtain the interface object from the shared library 119 extern "C" 120 { 121 OSCL_EXPORT_REF OsclAny* PVGetInterface() 122 { 123 return (OsclAny*) OSCL_NEW(AvcEncOmxSharedLibraryInterface, ()); 124 } 125 126 OSCL_EXPORT_REF void PVReleaseInterface(OsclSharedLibraryInterface* aInstance) 127 { 128 AvcEncOmxSharedLibraryInterface* module = (AvcEncOmxSharedLibraryInterface*)aInstance; 129 OSCL_DELETE(module); 130 } 131 } 132 133 #endif 134 135 136 OMX_ERRORTYPE OmxComponentAvcEncAO::ConstructComponent(OMX_PTR pAppData, OMX_PTR pProxy) 137 { 138 ComponentPortType *pInPort, *pOutPort; 139 OMX_ERRORTYPE Status; 140 141 iNumPorts = 2; 142 iCompressedFormatPortNum = OMX_PORT_OUTPUTPORT_INDEX; 143 iOmxComponent.nSize = sizeof(OMX_COMPONENTTYPE); 144 iOmxComponent.pComponentPrivate = (OMX_PTR) this; // pComponentPrivate points to THIS component AO class 145 ipComponentProxy = pProxy; 146 iOmxComponent.pApplicationPrivate = pAppData; // init the App data 147 148 oscl_memset((void *)iNALSizeArray, 0, MAX_NAL_PER_FRAME * sizeof(int32)); 149 iNALCount = 0; 150 iNALSizeSum = 0; 151 iEndOfOutputFrame = OMX_FALSE; 152 153 #if PROXY_INTERFACE 154 iPVCapabilityFlags.iIsOMXComponentMultiThreaded = OMX_TRUE; 155 156 iOmxComponent.SendCommand = OmxComponentAvcEncAO::BaseComponentProxySendCommand; 157 iOmxComponent.GetParameter = OmxComponentAvcEncAO::BaseComponentProxyGetParameter; 158 iOmxComponent.SetParameter = OmxComponentAvcEncAO::BaseComponentProxySetParameter; 159 iOmxComponent.GetConfig = OmxComponentAvcEncAO::BaseComponentProxyGetConfig; 160 iOmxComponent.SetConfig = OmxComponentAvcEncAO::BaseComponentProxySetConfig; 161 iOmxComponent.GetExtensionIndex = OmxComponentAvcEncAO::BaseComponentProxyGetExtensionIndex; 162 iOmxComponent.GetState = OmxComponentAvcEncAO::BaseComponentProxyGetState; 163 iOmxComponent.UseBuffer = OmxComponentAvcEncAO::BaseComponentProxyUseBuffer; 164 iOmxComponent.AllocateBuffer = OmxComponentAvcEncAO::BaseComponentProxyAllocateBuffer; 165 iOmxComponent.FreeBuffer = OmxComponentAvcEncAO::BaseComponentProxyFreeBuffer; 166 iOmxComponent.EmptyThisBuffer = OmxComponentAvcEncAO::BaseComponentProxyEmptyThisBuffer; 167 iOmxComponent.FillThisBuffer = OmxComponentAvcEncAO::BaseComponentProxyFillThisBuffer; 168 169 #else 170 iPVCapabilityFlags.iIsOMXComponentMultiThreaded = OMX_FALSE; 171 172 iOmxComponent.SendCommand = OmxComponentAvcEncAO::BaseComponentSendCommand; 173 iOmxComponent.GetParameter = OmxComponentAvcEncAO::BaseComponentGetParameter; 174 iOmxComponent.SetParameter = OmxComponentAvcEncAO::BaseComponentSetParameter; 175 iOmxComponent.GetConfig = OmxComponentAvcEncAO::BaseComponentGetConfig; 176 iOmxComponent.SetConfig = OmxComponentAvcEncAO::BaseComponentSetConfig; 177 iOmxComponent.GetExtensionIndex = OmxComponentAvcEncAO::BaseComponentGetExtensionIndex; 178 iOmxComponent.GetState = OmxComponentAvcEncAO::BaseComponentGetState; 179 iOmxComponent.UseBuffer = OmxComponentAvcEncAO::BaseComponentUseBuffer; 180 iOmxComponent.AllocateBuffer = OmxComponentAvcEncAO::BaseComponentAllocateBuffer; 181 iOmxComponent.FreeBuffer = OmxComponentAvcEncAO::BaseComponentFreeBuffer; 182 iOmxComponent.EmptyThisBuffer = OmxComponentAvcEncAO::BaseComponentEmptyThisBuffer; 183 iOmxComponent.FillThisBuffer = OmxComponentAvcEncAO::BaseComponentFillThisBuffer; 184 #endif 185 186 iOmxComponent.SetCallbacks = OmxComponentAvcEncAO::BaseComponentSetCallbacks; 187 iOmxComponent.nVersion.s.nVersionMajor = SPECVERSIONMAJOR; 188 iOmxComponent.nVersion.s.nVersionMinor = SPECVERSIONMINOR; 189 iOmxComponent.nVersion.s.nRevision = SPECREVISION; 190 iOmxComponent.nVersion.s.nStep = SPECSTEP; 191 192 // PV capability 193 #if defined(TEST_FULL_AVC_FRAME_MODE) 194 /* output buffers based on frame boundaries instead of NAL boundaries and specify NAL boundaries through 195 * through OMX_EXTRADATA structures appended on the end of the buffer 196 */ 197 iPVCapabilityFlags.iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE; 198 iPVCapabilityFlags.iOMXComponentSupportsExternalOutputBufferAlloc = OMX_TRUE; 199 iPVCapabilityFlags.iOMXComponentSupportsMovableInputBuffers = OMX_TRUE; 200 iPVCapabilityFlags.iOMXComponentSupportsPartialFrames = OMX_TRUE; 201 iPVCapabilityFlags.iOMXComponentUsesNALStartCodes = OMX_FALSE; 202 iPVCapabilityFlags.iOMXComponentCanHandleIncompleteFrames = OMX_TRUE; 203 iPVCapabilityFlags.iOMXComponentUsesFullAVCFrames = OMX_TRUE; 204 #elif defined(TEST_FULL_AVC_FRAME_MODE_SC) 205 /* output buffers based on frame boundaries instead of NAL boundaries and specify NAL boundaries 206 * with NAL start codes 207 */ 208 iPVCapabilityFlags.iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE; 209 iPVCapabilityFlags.iOMXComponentSupportsExternalOutputBufferAlloc = OMX_TRUE; 210 iPVCapabilityFlags.iOMXComponentSupportsMovableInputBuffers = OMX_TRUE; 211 iPVCapabilityFlags.iOMXComponentSupportsPartialFrames = OMX_TRUE; 212 iPVCapabilityFlags.iOMXComponentUsesNALStartCodes = OMX_TRUE; 213 iPVCapabilityFlags.iOMXComponentCanHandleIncompleteFrames = OMX_TRUE; 214 iPVCapabilityFlags.iOMXComponentUsesFullAVCFrames = OMX_TRUE; 215 #else 216 iPVCapabilityFlags.iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE; 217 iPVCapabilityFlags.iOMXComponentSupportsExternalOutputBufferAlloc = OMX_TRUE; 218 iPVCapabilityFlags.iOMXComponentSupportsMovableInputBuffers = OMX_TRUE; 219 iPVCapabilityFlags.iOMXComponentSupportsPartialFrames = OMX_TRUE; 220 iPVCapabilityFlags.iOMXComponentUsesNALStartCodes = OMX_FALSE; 221 iPVCapabilityFlags.iOMXComponentCanHandleIncompleteFrames = OMX_TRUE; 222 iPVCapabilityFlags.iOMXComponentUsesFullAVCFrames = OMX_FALSE; 223 #endif 224 225 if (ipAppPriv) 226 { 227 oscl_free(ipAppPriv); 228 ipAppPriv = NULL; 229 } 230 231 ipAppPriv = (ComponentPrivateType*) oscl_malloc(sizeof(ComponentPrivateType)); 232 if (NULL == ipAppPriv) 233 { 234 return OMX_ErrorInsufficientResources; 235 } 236 237 //Construct base class now 238 Status = ConstructBaseComponent(pAppData); 239 240 if (OMX_ErrorNone != Status) 241 { 242 return Status; 243 } 244 245 /** Domain specific section for input raw port */ //OMX_PARAM_PORTDEFINITIONTYPE 246 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_INPUTPORT_INDEX; 247 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainVideo; 248 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.cMIMEType = (OMX_STRING)"raw"; 249 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; 250 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.pNativeRender = 0; 251 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.bFlagErrorConcealment = OMX_FALSE; 252 253 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar; 254 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.nFrameWidth = 176; 255 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.nFrameHeight = 144; 256 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.nBitrate = 64000; 257 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.xFramerate = (15 << 16); 258 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.eDir = OMX_DirInput; 259 //Set to a default value, will change later during setparameter call 260 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferCountActual = NUMBER_INPUT_BUFFER_AVCENC; 261 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferCountMin = 1; 262 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize = INPUT_BUFFER_SIZE_AVCENC; 263 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE; 264 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE; 265 266 267 /** Domain specific section for output avc port */ 268 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 269 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainVideo; 270 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.cMIMEType = (OMX_STRING)"video/avc"; 271 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; 272 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.pNativeRender = 0; 273 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.bFlagErrorConcealment = OMX_FALSE; 274 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.eColorFormat = OMX_COLOR_FormatUnused; 275 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameWidth = 176; 276 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameHeight = 144; 277 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nBitrate = 64000; 278 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.xFramerate = (15 << 16); 279 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDir = OMX_DirOutput; 280 //Set to a default value, will change later during setparameter call 281 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountActual = NUMBER_OUTPUT_BUFFER_AVCENC; 282 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountMin = 1; 283 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferSize = OUTPUT_BUFFER_SIZE_AVCENC; 284 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE; 285 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE; 286 287 288 //OMX_VIDEO_PARAM_AVCTYPE //Default values for avc video output param port 289 oscl_memset(&ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoAvc, 0, sizeof(OMX_VIDEO_PARAM_AVCTYPE)); 290 SetHeader(&ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoAvc, sizeof(OMX_VIDEO_PARAM_AVCTYPE)); 291 292 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoAvc.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 293 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoAvc.eProfile = OMX_VIDEO_AVCProfileBaseline; 294 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoAvc.eLevel = OMX_VIDEO_AVCLevel1b; 295 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoAvc.nPFrames = 0xFFFFFFFF; //Default value 296 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoAvc.nBFrames = 0; //No support for B frames 297 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoAvc.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 298 299 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoAvc.nRefFrames = 1; //Only support this value 300 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoAvc.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; 301 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoAvc.bEnableFMO = OMX_FALSE; //Default value is false 302 303 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoAvc.bFrameMBsOnly = OMX_TRUE; 304 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoAvc.bMBAFF = OMX_FALSE; 305 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoAvc.bEntropyCodingCABAC = OMX_FALSE; 306 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoAvc.bWeightedPPrediction = OMX_FALSE; 307 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoAvc.bDirect8x8Inference = OMX_FALSE; 308 309 310 //OMX_VIDEO_PARAM_PROFILELEVELTYPE structure 311 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->ProfileLevel.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 312 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->ProfileLevel.nProfileIndex = 0; 313 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->ProfileLevel.eProfile = OMX_VIDEO_AVCProfileBaseline; 314 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->ProfileLevel.eLevel = OMX_VIDEO_AVCLevel1b; 315 316 317 iPortTypesParam.nPorts = 2; 318 iPortTypesParam.nStartPortNumber = 0; 319 320 pInPort = (ComponentPortType*) ipPorts[OMX_PORT_INPUTPORT_INDEX]; 321 pOutPort = (ComponentPortType*) ipPorts[OMX_PORT_OUTPUTPORT_INDEX]; 322 323 pInPort->ActualNumPortFormatsSupported = 4; 324 325 //OMX_VIDEO_PARAM_PORTFORMATTYPE INPUT PORT SETTINGS 326 //On input port for index 0 327 SetHeader(&pInPort->VideoParam[0], sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); 328 pInPort->VideoParam[0].nPortIndex = OMX_PORT_INPUTPORT_INDEX; 329 pInPort->VideoParam[0].nIndex = 0; 330 pInPort->VideoParam[0].eCompressionFormat = OMX_VIDEO_CodingUnused; 331 pInPort->VideoParam[0].eColorFormat = OMX_COLOR_FormatYUV420Planar; 332 pInPort->VideoParam[0].xFramerate = (15 << 16); 333 334 //On input port for index 1 335 SetHeader(&pInPort->VideoParam[1], sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); 336 pInPort->VideoParam[1].nPortIndex = OMX_PORT_INPUTPORT_INDEX; 337 pInPort->VideoParam[1].nIndex = 1; 338 pInPort->VideoParam[1].eCompressionFormat = OMX_VIDEO_CodingUnused; 339 pInPort->VideoParam[1].eColorFormat = OMX_COLOR_Format24bitRGB888; 340 pInPort->VideoParam[1].xFramerate = (15 << 16); 341 342 //On input port for index 2 343 SetHeader(&pInPort->VideoParam[2], sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); 344 pInPort->VideoParam[2].nPortIndex = OMX_PORT_INPUTPORT_INDEX; 345 pInPort->VideoParam[2].nIndex = 2; 346 pInPort->VideoParam[2].eCompressionFormat = OMX_VIDEO_CodingUnused; 347 pInPort->VideoParam[2].eColorFormat = OMX_COLOR_Format12bitRGB444; 348 pInPort->VideoParam[2].xFramerate = (15 << 16); 349 350 //On input port for index 3 351 SetHeader(&pInPort->VideoParam[3], sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); 352 pInPort->VideoParam[3].nPortIndex = OMX_PORT_INPUTPORT_INDEX; 353 pInPort->VideoParam[3].nIndex = 3; 354 pInPort->VideoParam[3].eCompressionFormat = OMX_VIDEO_CodingUnused; 355 pInPort->VideoParam[3].eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; 356 pInPort->VideoParam[3].xFramerate = (15 << 16); 357 358 pOutPort->ActualNumPortFormatsSupported = 1; 359 360 //OMX_VIDEO_PARAM_PORTFORMATTYPE OUTPUT PORT SETTINGS 361 //On output port for index 0 362 SetHeader(&pOutPort->VideoParam[0], sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); 363 pOutPort->VideoParam[0].nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 364 pOutPort->VideoParam[0].nIndex = 0; 365 pOutPort->VideoParam[0].eColorFormat = OMX_COLOR_FormatUnused; 366 pOutPort->VideoParam[0].eCompressionFormat = OMX_VIDEO_CodingAVC; 367 pOutPort->VideoParam[0].xFramerate = (15 << 16); 368 369 370 //OMX_CONFIG_ROTATIONTYPE SETTINGS ON INPUT PORT 371 SetHeader(&pInPort->VideoOrientationType, sizeof(OMX_CONFIG_ROTATIONTYPE)); 372 pInPort->VideoOrientationType.nPortIndex = OMX_PORT_INPUTPORT_INDEX; 373 pInPort->VideoOrientationType.nRotation = -1; //For all the YUV formats that are other than RGB 374 375 376 //OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE settings of output port 377 oscl_memset(&pOutPort->VideoErrorCorrection, 0, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); 378 SetHeader(&pOutPort->VideoErrorCorrection, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); 379 pOutPort->VideoErrorCorrection.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 380 pOutPort->VideoErrorCorrection.bEnableDataPartitioning = OMX_FALSE; 381 382 383 //OMX_VIDEO_PARAM_BITRATETYPE settings of output port 384 SetHeader(&pOutPort->VideoRateType, sizeof(OMX_VIDEO_PARAM_BITRATETYPE)); 385 pOutPort->VideoRateType.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 386 pOutPort->VideoRateType.eControlRate = OMX_Video_ControlRateConstant; 387 pOutPort->VideoRateType.nTargetBitrate = 64000; 388 389 390 //OMX_CONFIG_FRAMERATETYPE default seetings (specified in khronos conformance test) 391 SetHeader(&pOutPort->VideoConfigFrameRateType, sizeof(OMX_CONFIG_FRAMERATETYPE)); 392 pOutPort->VideoConfigFrameRateType.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 393 pOutPort->VideoConfigFrameRateType.xEncodeFramerate = (15 << 16); 394 395 //OMX_VIDEO_CONFIG_BITRATETYPE default settings (specified in khronos conformance test) 396 SetHeader(&pOutPort->VideoConfigBitRateType, sizeof(OMX_VIDEO_CONFIG_BITRATETYPE)); 397 pOutPort->VideoConfigBitRateType.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 398 pOutPort->VideoConfigBitRateType.nEncodeBitrate = 64000; 399 400 401 //OMX_VIDEO_PARAM_QUANTIZATIONTYPE settings of output port 402 SetHeader(&pOutPort->VideoQuantType, sizeof(OMX_VIDEO_PARAM_QUANTIZATIONTYPE)); 403 pOutPort->VideoQuantType.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 404 pOutPort->VideoQuantType.nQpI = 0; //Not required by encoder 405 pOutPort->VideoQuantType.nQpP = 0; //Default is 0 406 pOutPort->VideoQuantType.nQpB = 0; //Not required by encoder 407 408 409 //OMX_VIDEO_PARAM_VBSMCTYPE settings of output port 410 oscl_memset(&pOutPort->VideoBlockMotionSize, 0, sizeof(OMX_VIDEO_PARAM_VBSMCTYPE)); 411 SetHeader(&pOutPort->VideoBlockMotionSize, sizeof(OMX_VIDEO_PARAM_VBSMCTYPE)); 412 pOutPort->VideoBlockMotionSize.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 413 pOutPort->VideoBlockMotionSize.b16x16 = OMX_TRUE; //Encoder only support this mode 414 415 416 //OMX_VIDEO_PARAM_MOTIONVECTORTYPE settings of output port 417 oscl_memset(&pOutPort->VideoMotionVector, 0, sizeof(OMX_VIDEO_PARAM_MOTIONVECTORTYPE)); 418 SetHeader(&pOutPort->VideoMotionVector, sizeof(OMX_VIDEO_PARAM_MOTIONVECTORTYPE)); 419 pOutPort->VideoMotionVector.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 420 pOutPort->VideoMotionVector.eAccuracy = OMX_Video_MotionVectorQuarterPel; 421 pOutPort->VideoMotionVector.bUnrestrictedMVs = OMX_TRUE; //Only support true 422 pOutPort->VideoMotionVector.sXSearchRange = 16; 423 pOutPort->VideoMotionVector.sYSearchRange = 16; 424 425 426 //OMX_VIDEO_PARAM_INTRAREFRESHTYPE settings of output port 427 oscl_memset(&pOutPort->VideoIntraRefresh, 0, sizeof(OMX_VIDEO_PARAM_INTRAREFRESHTYPE)); 428 SetHeader(&pOutPort->VideoIntraRefresh, sizeof(OMX_VIDEO_PARAM_INTRAREFRESHTYPE)); 429 pOutPort->VideoIntraRefresh.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 430 pOutPort->VideoIntraRefresh.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic; 431 pOutPort->VideoIntraRefresh.nCirMBs = 0; 432 433 //OMX_VIDEO_PARAM_AVCSLICEFMO settings on output port 434 oscl_memset(&pOutPort->AvcSliceFMO, 0, sizeof(OMX_VIDEO_PARAM_AVCSLICEFMO)); 435 SetHeader(&pOutPort->AvcSliceFMO, sizeof(OMX_VIDEO_PARAM_AVCSLICEFMO)); 436 pOutPort->AvcSliceFMO.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 437 pOutPort->AvcSliceFMO.eSliceMode = OMX_VIDEO_SLICEMODE_AVCDefault; 438 pOutPort->AvcSliceFMO.nNumSliceGroups = 1; 439 pOutPort->AvcSliceFMO.nSliceGroupMapType = 1; //Only support map type of 1 440 441 442 //OMX_CONFIG_INTRAREFRESHVOPTYPE settings of output port 443 oscl_memset(&pOutPort->VideoIFrame, 0, sizeof(OMX_CONFIG_INTRAREFRESHVOPTYPE)); 444 SetHeader(&pOutPort->VideoIFrame, sizeof(OMX_CONFIG_INTRAREFRESHVOPTYPE)); 445 pOutPort->VideoIFrame.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 446 pOutPort->VideoIFrame.IntraRefreshVOP = OMX_FALSE; 447 448 oscl_strncpy((OMX_STRING)iComponentRole, (OMX_STRING)"video_encoder.avc", OMX_MAX_STRINGNAME_SIZE); 449 450 451 //Construct the encoder object 452 if (ipAvcEncoderObject) 453 { 454 OSCL_DELETE(ipAvcEncoderObject); 455 ipAvcEncoderObject = NULL; 456 } 457 458 ipAvcEncoderObject = OSCL_NEW(AvcEncoder_OMX, ()); 459 460 #if PROXY_INTERFACE 461 462 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSendCommand = BaseComponentSendCommand; 463 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetParameter = BaseComponentGetParameter; 464 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetParameter = BaseComponentSetParameter; 465 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetConfig = BaseComponentGetConfig; 466 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetConfig = BaseComponentSetConfig; 467 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetExtensionIndex = BaseComponentGetExtensionIndex; 468 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetState = BaseComponentGetState; 469 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentUseBuffer = BaseComponentUseBuffer; 470 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentAllocateBuffer = BaseComponentAllocateBuffer; 471 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentFreeBuffer = BaseComponentFreeBuffer; 472 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentEmptyThisBuffer = BaseComponentEmptyThisBuffer; 473 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentFillThisBuffer = BaseComponentFillThisBuffer; 474 475 #endif 476 477 return OMX_ErrorNone; 478 } 479 480 481 /** This function is called by the omx core when the component 482 * is disposed by the IL client with a call to FreeHandle(). 483 */ 484 485 OMX_ERRORTYPE OmxComponentAvcEncAO::DestroyComponent() 486 { 487 if (OMX_FALSE != iIsInit) 488 { 489 ComponentDeInit(); 490 } 491 492 //Destroy the base class now 493 DestroyBaseComponent(); 494 495 if (ipAvcEncoderObject) 496 { 497 OSCL_DELETE(ipAvcEncoderObject); 498 ipAvcEncoderObject = NULL; 499 } 500 501 if (ipAppPriv) 502 { 503 ipAppPriv->CompHandle = NULL; 504 505 oscl_free(ipAppPriv); 506 ipAppPriv = NULL; 507 } 508 509 return OMX_ErrorNone; 510 } 511 512 513 void OmxComponentAvcEncAO::ProcessData() 514 { 515 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : ProcessData IN")); 516 517 QueueType* pInputQueue = ipPorts[OMX_PORT_INPUTPORT_INDEX]->pBufferQueue; 518 QueueType* pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue; 519 520 ComponentPortType* pInPort = ipPorts[OMX_PORT_INPUTPORT_INDEX]; 521 522 OMX_U8* pOutBuffer; 523 OMX_U32 OutputLength; 524 AVCEnc_Status EncodeReturn = AVCENC_SUCCESS; 525 OMX_COMPONENTTYPE* pHandle = &iOmxComponent; 526 527 if ((!iIsInputBufferEnded) || (iEndofStream)) 528 { 529 //Check whether prev output bufer has been released or not 530 if (OMX_TRUE == iNewOutBufRequired) 531 { 532 //Check whether a new output buffer is available or not 533 534 if (0 == (GetQueueNumElem(pOutputQueue))) 535 { 536 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : ProcessData OUT output buffer unavailable")); 537 return; 538 } 539 540 ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue); 541 542 OSCL_ASSERT(NULL != ipOutputBuffer); 543 if (ipOutputBuffer == NULL) 544 { 545 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "OmxComponentAvcEncAO : ProcessData ERR OUT output buffer cannot be dequeued")); 546 return; 547 } 548 ipOutputBuffer->nFilledLen = 0; 549 iNewOutBufRequired = OMX_FALSE; 550 551 oscl_memset((void *)iNALSizeArray, 0, iNALCount * sizeof(int32)); 552 iNALCount = 0; 553 iNALSizeSum = 0; 554 555 if (iPVCapabilityFlags.iOMXComponentUsesNALStartCodes) 556 { 557 oscl_memcpy(ipOutputBuffer->pBuffer + ipOutputBuffer->nOffset + ipOutputBuffer->nFilledLen, &NAL_START_CODE, sizeof(uint8) * 4); 558 ipOutputBuffer->nFilledLen += 4; 559 iNALSizeSum += 4; 560 } 561 562 563 /* If some output data was left to be send from the last processing due to 564 * unavailability of required number of output buffers, 565 * copy it now and send back before processing new input frame */ 566 if (iInternalOutBufFilledLen > 0) 567 { 568 if (OMX_FALSE == CopyDataToOutputBuffer()) 569 { 570 //We fell short of output buffers, exit now and wait for some more buffers to get queued 571 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : ProcessData OUT output buffer unavailable")); 572 return; 573 } 574 else 575 { 576 ManageFrameBoundaries(); 577 578 //Dequeue new output buffer to continue encoding the next frame 579 if (0 == (GetQueueNumElem(pOutputQueue))) 580 { 581 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : ProcessData OUT output buffer unavailable")); 582 return; 583 } 584 ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue); 585 586 OSCL_ASSERT(NULL != ipOutputBuffer); 587 if (ipOutputBuffer == NULL) 588 { 589 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "OmxComponentAvcEncAO : ProcessData OUT ERR output buffer cannot be dequeued")); 590 return; 591 } 592 593 594 ipOutputBuffer->nFilledLen = 0; 595 iNewOutBufRequired = OMX_FALSE; 596 } 597 } 598 } 599 600 /* Code for the marking buffer. Takes care of the OMX_CommandMarkBuffer 601 * command and hMarkTargetComponent as given by the specifications 602 */ 603 if (ipMark != NULL) 604 { 605 ipOutputBuffer->hMarkTargetComponent = ipMark->hMarkTargetComponent; 606 ipOutputBuffer->pMarkData = ipMark->pMarkData; 607 ipMark = NULL; 608 } 609 610 if (ipTargetComponent != NULL) 611 { 612 ipOutputBuffer->hMarkTargetComponent = ipTargetComponent; 613 ipOutputBuffer->pMarkData = iTargetMarkData; 614 ipTargetComponent = NULL; 615 616 } 617 //Mark buffer code ends here 618 619 //Call the encoder only if there is some data to encode 620 if (iInputCurrLength > 0) 621 { 622 OMX_S32 filledLength = ipOutputBuffer->nOffset + ipOutputBuffer->nFilledLen; 623 pOutBuffer = ipOutputBuffer->pBuffer + (OMX_U32)filledLength; 624 625 if (iPVCapabilityFlags.iOMXComponentUsesFullAVCFrames && !iPVCapabilityFlags.iOMXComponentUsesNALStartCodes) 626 { 627 OutputLength = (OMX_U32)(((OMX_S32)ipOutputBuffer->nAllocLen - filledLength - (46 + 4 * (iNALCount + 1))) > 0) ? (ipOutputBuffer->nAllocLen - filledLength - (46 + 4 * (iNALCount + 1))) : 0; 628 // (20 + 4 * (iNALCount + 1) + 20 + 6) is size of extra data 629 } 630 else 631 { 632 OutputLength = (OMX_U32)(((OMX_S32)ipOutputBuffer->nAllocLen - filledLength) > 0) ? (ipOutputBuffer->nAllocLen - filledLength) : 0; 633 } 634 635 //Output buffer is passed as a short pointer 636 EncodeReturn = ipAvcEncoderObject->AvcEncodeVideo(pOutBuffer, 637 &OutputLength, 638 &iBufferOverRun, 639 &ipInternalOutBuffer, 640 ipFrameDecodeBuffer, 641 &iInputCurrLength, 642 iFrameTimestamp, 643 &iOutputTimeStamp, 644 &iSyncFlag); 645 646 //Chk whether output data has been generated or not 647 if (OutputLength > 0) 648 { 649 //offset not required in our case, set it to zero 650 ipOutputBuffer->nOffset = 0; 651 ipOutputBuffer->nTimeStamp = iOutputTimeStamp; 652 653 if (OMX_FALSE == iBufferOverRun) 654 { 655 //No internal buffer is maintained 656 ipOutputBuffer->nFilledLen += OutputLength; 657 } 658 else 659 { 660 iInternalOutBufFilledLen = OutputLength; 661 iBufferOverRun = OMX_FALSE; 662 CopyDataToOutputBuffer(); 663 664 } //else loop of if (OMX_FALSE == iMantainOutInternalBuffer) 665 } //if (OutputLength > 0) loop 666 667 //If encoder returned error in case of frame skip/corrupt frame, report it to the client via a callback 668 if (((AVCENC_SKIPPED_PICTURE == EncodeReturn) || (AVCENC_FAIL == EncodeReturn)) 669 && (OMX_FALSE == iEndofStream)) 670 { 671 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : Frame skipped, ProcessData ErrorStreamCorrupt callback send")); 672 673 (*(ipCallbacks->EventHandler)) 674 (pHandle, 675 iCallbackData, 676 OMX_EventError, 677 OMX_ErrorStreamCorrupt, 678 0, 679 NULL); 680 } 681 682 //Return the input buffer that has been consumed fully 683 if ((AVCENC_PICTURE_READY == EncodeReturn) || 684 (AVCENC_SKIPPED_PICTURE == EncodeReturn) || 685 (AVCENC_FAIL == EncodeReturn)) 686 { 687 ipInputBuffer->nFilledLen = 0; 688 ReturnInputBuffer(ipInputBuffer, pInPort); 689 ipInputBuffer = NULL; 690 691 iIsInputBufferEnded = OMX_TRUE; 692 iInputCurrLength = 0; 693 694 iFrameCount++; 695 } 696 697 if (AVCENC_PICTURE_READY == EncodeReturn) 698 { 699 iEndOfOutputFrame = OMX_TRUE; 700 } 701 } 702 703 704 /* If EOS flag has come from the client & there are no more 705 * input buffers to decode, send the callback to the client 706 */ 707 if (OMX_TRUE == iEndofStream) 708 { 709 if (((0 == iInputCurrLength) || (AVCENC_FAIL == EncodeReturn)) && 710 (0 == iInternalOutBufFilledLen)) 711 { 712 713 (*(ipCallbacks->EventHandler)) 714 (pHandle, 715 iCallbackData, 716 OMX_EventBufferFlag, 717 1, 718 OMX_BUFFERFLAG_EOS, 719 NULL); 720 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : ProcessData EOS callback sent")); 721 722 ManageFrameBoundaries(); 723 724 //Mark this flag false once the callback has been send back 725 iEndofStream = OMX_FALSE; 726 727 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : ProcessData OUT")); 728 return; 729 } 730 731 } 732 733 if (!iPVCapabilityFlags.iOMXComponentUsesNALStartCodes) 734 { 735 if (iEndOfOutputFrame || ((ipOutputBuffer->nFilledLen > 0) && (OMX_FALSE == iNewOutBufRequired))) 736 { 737 ManageFrameBoundaries(); 738 } 739 } 740 else if (ipOutputBuffer->nFilledLen > 4) // therefore only if more than just start code in buffer 741 { 742 if (iEndOfOutputFrame || (OMX_FALSE == iNewOutBufRequired)) 743 { 744 ManageFrameBoundaries(); 745 } 746 } 747 748 749 /* If there is some more processing left with current buffers, re-schedule the AO 750 * Do not go for more than one round of processing at a time. 751 * This may block the AO longer than required. 752 */ 753 if ((iInputCurrLength != 0 || GetQueueNumElem(pInputQueue) > 0) 754 && (GetQueueNumElem(pOutputQueue) > 0)) 755 { 756 RunIfNotReady(); 757 } 758 } 759 760 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : ProcessData OUT")); 761 } 762 763 764 OMX_BOOL OmxComponentAvcEncAO::CopyDataToOutputBuffer() 765 { 766 ComponentPortType* pOutPort = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]; 767 QueueType* pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue; 768 769 while (iInternalOutBufFilledLen > 0) 770 { 771 if (ipOutputBuffer->nAllocLen >= iInternalOutBufFilledLen) 772 { 773 //Pack the whole data into the output buffer Alloc length data in one buffer and return it 774 oscl_memcpy(ipOutputBuffer->pBuffer, ipInternalOutBuffer, iInternalOutBufFilledLen); 775 ipOutputBuffer->nFilledLen = iInternalOutBufFilledLen; 776 777 } 778 else 779 { 780 oscl_memcpy(ipOutputBuffer->pBuffer, ipInternalOutBuffer, ipOutputBuffer->nAllocLen); 781 ipOutputBuffer->nFilledLen = ipOutputBuffer->nAllocLen; 782 } 783 784 iInternalOutBufFilledLen -= ipOutputBuffer->nFilledLen; 785 ipInternalOutBuffer += ipOutputBuffer->nFilledLen; 786 787 788 if (0 != iInternalOutBufFilledLen) 789 { 790 //Mark the sync Flag in every piece of IDR NAL 791 if (OMX_TRUE == iSyncFlag) 792 { 793 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; 794 } 795 //Return the partial output buffer and try to fetch a new output buffer for filling the remaining data 796 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 797 798 //Check whether a new output buffer is available or not 799 if (0 == (GetQueueNumElem(pOutputQueue))) 800 { 801 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : CopyDatatoOutputBuffer OUT output buffer unavailable")); 802 return OMX_FALSE; 803 } 804 805 ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue); 806 807 OSCL_ASSERT(NULL != ipOutputBuffer); 808 if (ipOutputBuffer == NULL) 809 { 810 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "OmxComponentAvcEncAO : CopyDatatoOutputBuffer ERR OUT output buffer cannot be dequeued")); 811 return OMX_FALSE; 812 } 813 814 ipOutputBuffer->nFilledLen = 0; 815 ipOutputBuffer->nTimeStamp = iOutputTimeStamp; 816 ipOutputBuffer->nOffset = 0; 817 iNewOutBufRequired = OMX_FALSE; 818 } 819 } //while (iInternalOutBufFilledLen > 0) 820 821 return OMX_TRUE; 822 823 } 824 825 826 //Not implemented & supported in case of base profile components 827 828 void OmxComponentAvcEncAO::ComponentGetRolesOfComponent(OMX_STRING* aRoleString) 829 { 830 *aRoleString = (OMX_STRING)"video_encoder.avc"; 831 } 832 833 834 //Component constructor 835 OmxComponentAvcEncAO::OmxComponentAvcEncAO() 836 { 837 ipAvcEncoderObject = NULL; 838 ipInternalOutBuffer = NULL; 839 iInternalOutBufFilledLen = 0; 840 iSyncFlag = OMX_FALSE; 841 iBufferOverRun = OMX_FALSE; 842 843 if (!IsAdded()) 844 { 845 AddToScheduler(); 846 } 847 848 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : constructed")); 849 } 850 851 852 //Active object destructor 853 OmxComponentAvcEncAO::~OmxComponentAvcEncAO() 854 { 855 if (IsAdded()) 856 { 857 RemoveFromScheduler(); 858 } 859 860 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : destructed")); 861 } 862 863 864 OMX_ERRORTYPE OmxComponentAvcEncAO::SetConfig( 865 OMX_IN OMX_HANDLETYPE hComponent, 866 OMX_IN OMX_INDEXTYPE nIndex, 867 OMX_IN OMX_PTR pComponentConfigStructure) 868 { 869 OSCL_UNUSED_ARG(hComponent); 870 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : SetConfig IN")); 871 872 OMX_U32 PortIndex; 873 874 OMX_ERRORTYPE ErrorType = OMX_ErrorNone; 875 OMX_CONFIG_INTRAREFRESHVOPTYPE* pAvcIFrame; 876 OMX_VIDEO_CONFIG_BITRATETYPE* pBitRateType; 877 OMX_CONFIG_FRAMERATETYPE* pFrameRateType; 878 879 880 881 if (NULL == pComponentConfigStructure) 882 { 883 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : SetConfig error bad parameter")); 884 return OMX_ErrorBadParameter; 885 } 886 887 switch (nIndex) 888 { 889 case OMX_IndexConfigVideoIntraVOPRefresh: 890 { 891 pAvcIFrame = (OMX_CONFIG_INTRAREFRESHVOPTYPE*) pComponentConfigStructure; 892 PortIndex = pAvcIFrame->nPortIndex; 893 894 if (PortIndex != iCompressedFormatPortNum) 895 { 896 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : SetConfig error invalid port index")); 897 return OMX_ErrorBadPortIndex; 898 } 899 900 /*Check Structure Header*/ 901 ErrorType = CheckHeader(pAvcIFrame, sizeof(OMX_CONFIG_INTRAREFRESHVOPTYPE)); 902 if (ErrorType != OMX_ErrorNone) 903 { 904 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : SetConfig error param check failed")); 905 return ErrorType; 906 } 907 908 //Call the RequestI frame routine of the encoder in case of setconfig call 909 if (OMX_TRUE == pAvcIFrame->IntraRefreshVOP) 910 { 911 ipAvcEncoderObject->AvcRequestIFrame(); 912 913 } 914 } 915 break; 916 917 case OMX_IndexConfigVideoBitrate: 918 { 919 pBitRateType = (OMX_VIDEO_CONFIG_BITRATETYPE*) pComponentConfigStructure; 920 PortIndex = pBitRateType->nPortIndex; 921 922 if (PortIndex != iCompressedFormatPortNum) 923 { 924 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : SetConfig error invalid port index")); 925 return OMX_ErrorBadPortIndex; 926 } 927 928 /*Check Structure Header*/ 929 ErrorType = CheckHeader(pBitRateType, sizeof(OMX_VIDEO_CONFIG_BITRATETYPE)); 930 if (ErrorType != OMX_ErrorNone) 931 { 932 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : SetConfig error param check failed")); 933 return ErrorType; 934 } 935 936 //Call the corresponding routine of the encoder in case of setconfig call 937 if (OMX_FALSE == (ipAvcEncoderObject->AvcUpdateBitRate(pBitRateType->nEncodeBitrate))) 938 { 939 return OMX_ErrorBadParameter; 940 941 } 942 943 ipPorts[PortIndex]->VideoConfigBitRateType.nEncodeBitrate = pBitRateType->nEncodeBitrate; 944 } 945 break; 946 947 case OMX_IndexConfigVideoFramerate: 948 { 949 pFrameRateType = (OMX_CONFIG_FRAMERATETYPE*) pComponentConfigStructure; 950 PortIndex = pFrameRateType->nPortIndex; 951 952 if (PortIndex != iCompressedFormatPortNum) 953 { 954 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : SetConfig error invalid port index")); 955 return OMX_ErrorBadPortIndex; 956 } 957 958 /*Check Structure Header*/ 959 ErrorType = CheckHeader(pFrameRateType, sizeof(OMX_CONFIG_FRAMERATETYPE)); 960 if (ErrorType != OMX_ErrorNone) 961 { 962 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : SetConfig error param check failed")); 963 return ErrorType; 964 } 965 966 //Call the corresponding routine of the encoder in case of setconfig call 967 if (OMX_FALSE == (ipAvcEncoderObject->AvcUpdateFrameRate(pFrameRateType->xEncodeFramerate))) 968 { 969 return OMX_ErrorBadParameter; 970 } 971 972 ipPorts[PortIndex]->VideoConfigFrameRateType.xEncodeFramerate = pFrameRateType->xEncodeFramerate; 973 } 974 break; 975 976 default: 977 { 978 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : SetConfig error Unsupported Index")); 979 return OMX_ErrorUnsupportedIndex; 980 } 981 break; 982 } 983 984 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : SetConfig OUT")); 985 return OMX_ErrorNone; 986 987 } 988 989 990 991 /** The Initialization function 992 */ 993 OMX_ERRORTYPE OmxComponentAvcEncAO::ComponentInit() 994 { 995 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : ComponentInit IN")); 996 997 OMX_ERRORTYPE Status = OMX_ErrorNone; 998 999 if (OMX_TRUE == iIsInit) 1000 { 1001 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : ComponentInit error incorrect operation")); 1002 return OMX_ErrorIncorrectStateOperation; 1003 } 1004 iIsInit = OMX_TRUE; 1005 1006 1007 if (!iCodecReady) 1008 { 1009 iCodecReady = OMX_TRUE; 1010 } 1011 1012 //Verify the parameters and return failure in case they cannot be supported by our encoder 1013 OMX_VIDEO_PARAM_AVCTYPE* pAvcParam = (OMX_VIDEO_PARAM_AVCTYPE*) & ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoAvc; 1014 OMX_VIDEO_PARAM_AVCSLICEFMO* pAvcSliceFMO = (OMX_VIDEO_PARAM_AVCSLICEFMO*) & ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AvcSliceFMO; 1015 1016 //FMO enabled is not supported in the encoder 1017 if ((pAvcParam->nBFrames > 0) || 1018 (0 == (pAvcParam->nAllowedPictureTypes & 1019 (OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP))) || 1020 (OMX_FALSE == pAvcParam->bFrameMBsOnly) || 1021 (OMX_TRUE == pAvcParam->bMBAFF) || 1022 (OMX_TRUE == pAvcParam->bEntropyCodingCABAC) || 1023 (OMX_TRUE == pAvcParam->bWeightedPPrediction) || 1024 (OMX_TRUE == pAvcParam->bDirect8x8Inference) || 1025 (OMX_TRUE == pAvcParam->bEnableFMO) || 1026 (1 != pAvcSliceFMO->nSliceGroupMapType)) 1027 { 1028 return OMX_ErrorUnsupportedSetting; 1029 } 1030 1031 1032 //Library init routine 1033 Status = ipAvcEncoderObject->AvcEncInit( 1034 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video, 1035 ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoOrientationType, 1036 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video, 1037 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoAvc, 1038 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoRateType, 1039 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoQuantType, 1040 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoMotionVector, 1041 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoIntraRefresh, 1042 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->VideoBlockMotionSize); 1043 1044 iInputCurrLength = 0; 1045 1046 //Used in dynamic port reconfiguration 1047 iFrameCount = 0; 1048 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : ComponentInit OUT")); 1049 1050 return Status; 1051 1052 } 1053 1054 /** This function is called upon a transition to the idle or invalid state. 1055 * Also it is called by the ComponentDestructor() function 1056 */ 1057 OMX_ERRORTYPE OmxComponentAvcEncAO::ComponentDeInit() 1058 { 1059 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : ComponentDeInit IN")); 1060 1061 OMX_ERRORTYPE Status = OMX_ErrorNone; 1062 1063 iIsInit = OMX_FALSE; 1064 1065 if (iCodecReady) 1066 { 1067 Status = ipAvcEncoderObject->AvcEncDeinit(); 1068 iCodecReady = OMX_FALSE; 1069 } 1070 1071 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAvcEncAO : ComponentDeInit OUT")); 1072 1073 return Status; 1074 1075 } 1076 1077 /* A component specific routine called from BufferMgmtWithoutMarker */ 1078 void OmxComponentAvcEncAO::ProcessInBufferFlag() 1079 { 1080 iIsInputBufferEnded = OMX_FALSE; 1081 } 1082 1083 ///////////////////////////////////////////////////////////////////////////// 1084 OMX_BOOL OmxComponentAvcEncAO::AppendExtraDataToBuffer(OMX_BUFFERHEADERTYPE* aOutputBuffer, 1085 OMX_EXTRADATATYPE aType, 1086 OMX_U8* aExtraData, 1087 OMX_U8 aDataLength) 1088 1089 { 1090 // This function is used to append AVC NAL info to the buffer using the OMX_EXTRADATA_TYPE structure, when 1091 // a component requires buffers with full AVC frames rather than just NALs 1092 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, 1093 (0, "OmxComponentAvcEncAO::AppendExtraDataToBuffer() In")); 1094 1095 1096 if ((aType != OMX_ExtraDataNone) && (aExtraData != NULL) && (aOutputBuffer->pBuffer != NULL)) 1097 { 1098 const uint32 sizeOfExtraDataStruct = 20; // 20 is the number of bytes for the OMX_OTHER_EXTRADATATYPE structure (minus the data hint member) 1099 1100 OMX_OTHER_EXTRADATATYPE extra; 1101 OMX_OTHER_EXTRADATATYPE terminator; 1102 1103 CONFIG_SIZE_AND_VERSION(extra); 1104 CONFIG_SIZE_AND_VERSION(terminator); 1105 1106 extra.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 1107 terminator.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 1108 1109 extra.eType = aType; 1110 extra.nSize = (sizeOfExtraDataStruct + aDataLength + 3) & ~3; // size + padding for byte alignment 1111 extra.nDataSize = aDataLength; 1112 1113 // fill in fields for terminator 1114 terminator.eType = OMX_ExtraDataNone; 1115 terminator.nDataSize = 0; 1116 1117 // make sure there is enough room in the buffer 1118 if (aOutputBuffer->nAllocLen < (aOutputBuffer->nOffset + aOutputBuffer->nFilledLen + sizeOfExtraDataStruct + aDataLength + terminator.nSize + 6)) 1119 { 1120 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1121 (0, "OmxComponentAvcEncAO::AppendExtraDataToBuffer() - Error (not enough room in buffer) appending extra data to Buffer 0x%x, TS=%d", aOutputBuffer->pBuffer, iOutputTimeStamp)); 1122 1123 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1124 (0, "OmxComponentAvcEncAO::AppendExtraDataToBuffer() Out")); 1125 1126 return OMX_FALSE; 1127 } 1128 1129 // copy extra data into buffer 1130 // need to align to 4 bytes 1131 OMX_U8* buffer = aOutputBuffer->pBuffer + aOutputBuffer->nOffset + aOutputBuffer->nFilledLen; 1132 buffer = (OMX_U8*)(((OMX_U32) buffer + 3) & ~3); 1133 1134 oscl_memcpy(buffer, &extra, sizeOfExtraDataStruct); 1135 oscl_memcpy(buffer + sizeOfExtraDataStruct, aExtraData, aDataLength); 1136 buffer += extra.nSize; 1137 1138 oscl_memcpy(buffer, &terminator, terminator.nSize); 1139 1140 // flag buffer 1141 aOutputBuffer->nFlags |= OMX_BUFFERFLAG_EXTRADATA; 1142 1143 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1144 (0, "OmxComponentAvcEncAO::AppendExtraDataToBuffer() - Appending extra data to Buffer 0x%x, TS=%d", aOutputBuffer->pBuffer, iOutputTimeStamp)); 1145 1146 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1147 (0, "OmxComponentAvcEncAO::AppendExtraDataToBuffer() Out")); 1148 1149 return OMX_TRUE; 1150 } 1151 else 1152 { 1153 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1154 (0, "OmxComponentAvcEncAO::AppendExtraDataToBuffer() Out")); 1155 1156 return OMX_FALSE; 1157 } 1158 } 1159 1160 void OmxComponentAvcEncAO::ManageFrameBoundaries() 1161 { 1162 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, 1163 (0, "OmxComponentAvcEncAO::ManageFrameBoundaries() In")); 1164 1165 ComponentPortType* pOutPort = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]; 1166 1167 if (!iPVCapabilityFlags.iOMXComponentUsesFullAVCFrames || !ipAvcEncoderObject->GetSpsPpsHeaderFlag()) 1168 { 1169 if (iPVCapabilityFlags.iOMXComponentUsesNALStartCodes && ipOutputBuffer->nFilledLen == 4) 1170 { 1171 ipOutputBuffer->nFilledLen = 0; 1172 } 1173 1174 1175 //Attach the end of frame flag while sending out the last piece of output buffer 1176 if (iEndofStream) 1177 { 1178 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_EOS; 1179 } 1180 else 1181 { 1182 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; 1183 } 1184 1185 if (OMX_TRUE == iSyncFlag) 1186 { 1187 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; 1188 iSyncFlag = OMX_FALSE; 1189 } 1190 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 1191 } 1192 else /* append extra data structure to buffer if iOMXComponentUsesFullAVCFrames is set and the buffer does not contain SPS or PPS NALs */ 1193 { 1194 OMX_U32 CurrNALSize = ipOutputBuffer->nFilledLen - iNALSizeSum; 1195 if (CurrNALSize > 0) 1196 { 1197 if (iPVCapabilityFlags.iOMXComponentUsesNALStartCodes && !iEndOfOutputFrame && !iEndofStream) 1198 { 1199 oscl_memcpy(ipOutputBuffer->pBuffer + ipOutputBuffer->nOffset + ipOutputBuffer->nFilledLen, &NAL_START_CODE, sizeof(uint8) * 4); 1200 ipOutputBuffer->nFilledLen += 4; 1201 iNALSizeSum += 4; 1202 } 1203 1204 iNALSizeArray[iNALCount] = CurrNALSize; 1205 iNALSizeSum += iNALSizeArray[iNALCount]; 1206 iNALCount++; 1207 } 1208 1209 if (iEndOfOutputFrame || iEndofStream) 1210 { 1211 if (!iPVCapabilityFlags.iOMXComponentUsesNALStartCodes) 1212 { 1213 if (OMX_FALSE == AppendExtraDataToBuffer(ipOutputBuffer, (OMX_EXTRADATATYPE) OMX_ExtraDataNALSizeArray, (OMX_U8*) iNALSizeArray, sizeof(uint32) * iNALCount)) 1214 { 1215 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; 1216 1217 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1218 (0, "OmxComponentAvcEncAO::ManageFrameBoundaries() - Error appending extra data to Buffer 0x%x, TS=%d, returning anyway with data corrupt flag", ipOutputBuffer->pBuffer, iOutputTimeStamp)); 1219 } 1220 } 1221 else if (0 == iNALCount) 1222 { 1223 iNALSizeSum = 0; 1224 ipOutputBuffer->nFilledLen = 0; 1225 } 1226 1227 //Attach the end of frame flag while sending out the last piece of output buffer 1228 if (iEndOfOutputFrame) 1229 { 1230 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; 1231 } 1232 1233 //Attach the end of stream flag 1234 if (iEndofStream) 1235 { 1236 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_EOS; 1237 } 1238 1239 if (OMX_TRUE == iSyncFlag) 1240 { 1241 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; 1242 iSyncFlag = OMX_FALSE; 1243 } 1244 1245 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 1246 1247 oscl_memset((void *)iNALSizeArray, 0, iNALCount * sizeof(int32)); 1248 iNALCount = 0; 1249 iNALSizeSum = 0; 1250 1251 iEndOfOutputFrame = OMX_FALSE; 1252 } 1253 } 1254 1255 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, 1256 (0, "OmxComponentAvcEncAO::ManageFrameBoundaries() Out")); 1257 } 1258 1259