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
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)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
AvcEncOmxComponentDestructor(OMX_IN OMX_HANDLETYPE pHandle,OMX_PTR & aOmxLib,OMX_PTR aOsclUuid,OMX_U32 & aRefCount)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:
QueryOmxComponentInterface(const OsclUuid & aOmxTypeId,const OsclUuid & aInterfaceId)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
SharedLibraryLookup(const OsclUuid & aInterfaceId)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
AvcEncOmxSharedLibraryInterface()115 AvcEncOmxSharedLibraryInterface() {};
116 };
117
118 // function to obtain the interface object from the shared library
119 extern "C"
120 {
PVGetInterface()121 OSCL_EXPORT_REF OsclAny* PVGetInterface()
122 {
123 return (OsclAny*) OSCL_NEW(AvcEncOmxSharedLibraryInterface, ());
124 }
125
PVReleaseInterface(OsclSharedLibraryInterface * aInstance)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
ConstructComponent(OMX_PTR pAppData,OMX_PTR pProxy)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
DestroyComponent()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
ProcessData()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
CopyDataToOutputBuffer()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
ComponentGetRolesOfComponent(OMX_STRING * aRoleString)828 void OmxComponentAvcEncAO::ComponentGetRolesOfComponent(OMX_STRING* aRoleString)
829 {
830 *aRoleString = (OMX_STRING)"video_encoder.avc";
831 }
832
833
834 //Component constructor
OmxComponentAvcEncAO()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
~OmxComponentAvcEncAO()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
SetConfig(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_INDEXTYPE nIndex,OMX_IN OMX_PTR pComponentConfigStructure)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 */
ComponentInit()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 */
ComponentDeInit()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 */
ProcessInBufferFlag()1078 void OmxComponentAvcEncAO::ProcessInBufferFlag()
1079 {
1080 iIsInputBufferEnded = OMX_FALSE;
1081 }
1082
1083 /////////////////////////////////////////////////////////////////////////////
AppendExtraDataToBuffer(OMX_BUFFERHEADERTYPE * aOutputBuffer,OMX_EXTRADATATYPE aType,OMX_U8 * aExtraData,OMX_U8 aDataLength)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
ManageFrameBoundaries()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