• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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