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