• 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.nStride = 176;
266     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameHeight = 144;
267     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nSliceHeight = 144;
268     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nBitrate = 64000;
269     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.xFramerate = (15 << 16);
270     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDir = OMX_DirOutput;
271     //Set to a default value, will change later during setparameter call
272     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountActual = NUMBER_OUTPUT_BUFFER_AVC
273             ;
274     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountMin = 1;
275     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferSize = OUTPUT_BUFFER_SIZE_AVC; //just use QCIF (as default)
276     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE;
277     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE;
278 
279     //Default values for Avc video param port
280     ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoAvc.nPortIndex = OMX_PORT_INPUTPORT_INDEX;
281     ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoAvc.eProfile = OMX_VIDEO_AVCProfileBaseline;
282     ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoAvc.eLevel = OMX_VIDEO_AVCLevel1;
283 
284     ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.nPortIndex = OMX_PORT_INPUTPORT_INDEX;
285     ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.nProfileIndex = 0;
286     ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.eProfile = OMX_VIDEO_AVCProfileBaseline;
287     ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.eLevel = OMX_VIDEO_AVCLevel1;
288 
289     iPortTypesParam.nPorts = 2;
290     iPortTypesParam.nStartPortNumber = 0;
291 
292     pInPort = (ComponentPortType*) ipPorts[OMX_PORT_INPUTPORT_INDEX];
293     pOutPort = (ComponentPortType*) ipPorts[OMX_PORT_OUTPUTPORT_INDEX];
294 
295     pInPort->ActualNumPortFormatsSupported = 1;
296 
297     //OMX_VIDEO_PARAM_PORTFORMATTYPE INPUT PORT SETTINGS
298     //On input port for index 0
299     SetHeader(&pInPort->VideoParam[0], sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
300     pInPort->VideoParam[0].nPortIndex = 0;
301     pInPort->VideoParam[0].nIndex = 0;
302     pInPort->VideoParam[0].eCompressionFormat = OMX_VIDEO_CodingAVC;
303     pInPort->VideoParam[0].eColorFormat = OMX_COLOR_FormatUnused;
304 
305     pOutPort->ActualNumPortFormatsSupported = 1;
306 
307     //OMX_VIDEO_PARAM_PORTFORMATTYPE OUTPUT PORT SETTINGS
308     //On output port for index 0
309     SetHeader(&pOutPort->VideoParam[0], sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
310     pOutPort->VideoParam[0].nPortIndex = 1;
311     pOutPort->VideoParam[0].nIndex = 0;
312     pOutPort->VideoParam[0].eCompressionFormat = OMX_VIDEO_CodingUnused;
313     pOutPort->VideoParam[0].eColorFormat = OMX_COLOR_FormatYUV420Planar;
314 
315     oscl_strncpy((OMX_STRING)iComponentRole, (OMX_STRING)"video_decoder.avc", OMX_MAX_STRINGNAME_SIZE);
316 
317     iDecodeReturn = OMX_FALSE;
318 
319     if (ipAvcDec)
320     {
321         OSCL_DELETE(ipAvcDec);
322         ipAvcDec = NULL;
323     }
324 
325     ipAvcDec = OSCL_NEW(AvcDecoder_OMX, ());
326     if (ipAvcDec == NULL)
327     {
328         return OMX_ErrorInsufficientResources;
329     }
330 
331     oscl_memset(ipAvcDec, 0, sizeof(AvcDecoder_OMX));
332 
333 #if PROXY_INTERFACE
334 
335     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSendCommand = BaseComponentSendCommand;
336     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetParameter = BaseComponentGetParameter;
337     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetParameter = BaseComponentSetParameter;
338     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetConfig = BaseComponentGetConfig;
339     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetConfig = BaseComponentSetConfig;
340     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetExtensionIndex = BaseComponentGetExtensionIndex;
341     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetState = BaseComponentGetState;
342     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentUseBuffer = BaseComponentUseBuffer;
343     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentAllocateBuffer = BaseComponentAllocateBuffer;
344     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentFreeBuffer = BaseComponentFreeBuffer;
345     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentEmptyThisBuffer = BaseComponentEmptyThisBuffer;
346     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentFillThisBuffer = BaseComponentFillThisBuffer;
347 
348 #endif
349 
350     return OMX_ErrorNone;
351 }
352 
353 
354 /** This function is called by the omx core when the component
355     * is disposed by the IL client with a call to FreeHandle().
356     * \param Component, the component to be disposed
357     */
358 
DestroyComponent()359 OMX_ERRORTYPE OpenmaxAvcAO::DestroyComponent()
360 {
361     if (iIsInit != OMX_FALSE)
362     {
363         ComponentDeInit();
364     }
365 
366     //Destroy the base class now
367     DestroyBaseComponent();
368 
369     if (ipAvcDec)
370     {
371         OSCL_DELETE(ipAvcDec);
372         ipAvcDec = NULL;
373     }
374 
375     if (ipAppPriv)
376     {
377         ipAppPriv->CompHandle = NULL;
378 
379         oscl_free(ipAppPriv);
380         ipAppPriv = NULL;
381     }
382 
383     return OMX_ErrorNone;
384 }
385 
386 
387 /* This function will be called in case of buffer management without marker bit present
388  * The purpose is to copy the current input buffer into a big temporary buffer, so that
389  * an incomplete/partial frame is never passed to the decoder library for decode
390  */
ComponentBufferMgmtWithoutMarker()391 void OpenmaxAvcAO::ComponentBufferMgmtWithoutMarker()
392 {
393     //This common routine has been written in the base class
394     TempInputBufferMgmtWithoutMarker();
395 }
396 
ParseFullAVCFramesIntoNALs(OMX_BUFFERHEADERTYPE * aInputBuffer)397 OMX_BOOL OpenmaxAvcAO::ParseFullAVCFramesIntoNALs(OMX_BUFFERHEADERTYPE* aInputBuffer)
398 {
399     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : ParseFullAVCFramesIntoNALs IN"));
400 
401     ipInputBuffer = aInputBuffer;
402 
403     if (iNumInputBuffer == 0)
404     {
405         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentBase : ParseFullAVCFramesIntoNALs ERROR"));
406         return OMX_FALSE;
407     }
408 
409     if (iPVCapabilityFlags.iOMXComponentUsesNALStartCodes && !(ipInputBuffer->nFlags & OMX_BUFFERFLAG_EXTRADATA))
410     {
411         OMX_U32 offset = ipInputBuffer->nOffset;
412         OMX_U32 length = ipInputBuffer->nFilledLen;
413         OMX_U8* pBuffer = ipInputBuffer->pBuffer + offset;
414         OMX_U8* pTemp;
415         int32 nalSize;
416 
417         iNumNALs = 0;
418 
419         while (length > 0)
420         {
421             if (AVCDEC_SUCCESS != ipAvcDec->GetNextFullNAL_OMX(&pTemp, &nalSize, pBuffer, &length))
422             {
423                 break;
424             }
425 
426             pBuffer += nalSize + (int32)(pTemp - pBuffer);
427 
428             iNALSizeArray[iNumNALs] = nalSize;
429 
430             iNumNALs++;
431         }
432 
433         if (iNumNALs > 0)
434         {
435             iCurrNAL = 0;
436             iNALOffset = ipInputBuffer->nOffset + NAL_START_CODE_SIZE;
437             ipFrameDecodeBuffer = ipInputBuffer->pBuffer + iNALOffset;
438             iInputCurrLength = iNALSizeArray[iCurrNAL];
439             iNALOffset += (iInputCurrLength + NAL_START_CODE_SIZE); // offset for next NAL
440             //capture the timestamp to be send to the corresponding output buffer
441             iFrameTimestamp = ipInputBuffer->nTimeStamp;
442         }
443         else
444         {
445             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentBase : ParseFullAVCFramesIntoNALs ERROR"));
446             return OMX_FALSE;
447         }
448     }
449     // may be a full frame, or may incomplete, therefore don't check for OMX_BUFFERFLAG_ENDOFFRAME
450     else if (ipInputBuffer->nFlags & OMX_BUFFERFLAG_EXTRADATA)
451     {
452         // get extra data from end of buffer
453         OMX_OTHER_EXTRADATATYPE *pExtra;
454         OMX_U32 offset = ipInputBuffer->nOffset + ipInputBuffer->nFilledLen;
455         OMX_U32 allocLen = ipInputBuffer->nAllocLen;
456         OMX_U8* pTemp = ipInputBuffer->pBuffer + offset;
457 
458         // align
459         pExtra = (OMX_OTHER_EXTRADATATYPE *)(((OMX_U32) pTemp + 3) & ~3);
460         offset += (OMX_U32) pExtra - (OMX_U32) pTemp;
461 
462         while (pExtra->eType != OMX_ExtraDataNone)
463         {
464             if (pExtra->eType == OMX_ExtraDataNALSizeArray)
465             {
466                 oscl_memcpy(iNALSizeArray, ((OMX_U8*)pExtra + 20), pExtra->nDataSize);
467                 iNumNALs = pExtra->nDataSize >> 2;
468                 iCurrNAL = 0;
469                 iNALOffset = ipInputBuffer->nOffset;
470                 break;
471             }
472 
473             offset += pExtra->nSize;
474             if (offset > (allocLen - 20))
475             {
476                 // corrupt data
477                 break;
478             }
479             else
480             {
481                 pExtra = (OMX_OTHER_EXTRADATATYPE *)((OMX_U8*)pExtra + pExtra->nSize);
482             }
483         }
484 
485         if (pExtra->eType != OMX_ExtraDataNALSizeArray)
486         {
487             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentBase : ParseFullAVCFramesIntoNALs ERROR"));
488             return OMX_FALSE;
489         }
490 
491         ipFrameDecodeBuffer = ipInputBuffer->pBuffer + iNALOffset;
492         iInputCurrLength = iNALSizeArray[iCurrNAL];
493         iNALOffset += iInputCurrLength; // offset for next NAL
494         //capture the timestamp to be send to the corresponding output buffer
495         iFrameTimestamp = ipInputBuffer->nTimeStamp;
496     }
497     else if (ipInputBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)
498     {
499         iInputCurrLength = ipInputBuffer->nFilledLen;
500         ipFrameDecodeBuffer = ipInputBuffer->pBuffer + ipInputBuffer->nOffset;
501         //capture the timestamp to be send to the corresponding output buffer
502         iFrameTimestamp = ipInputBuffer->nTimeStamp;
503     }
504     else
505     {
506         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentBase : ParseFullAVCFramesIntoNALs ERROR"));
507         return OMX_FALSE;
508     }
509 
510     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : ParseFullAVCFramesIntoNALs OUT"));
511     return OMX_TRUE;
512 }
513 
514 
ProcessData()515 void OpenmaxAvcAO::ProcessData()
516 {
517     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : ProcessData IN"));
518     if (!iEndOfFrameFlag)
519     {
520         DecodeWithoutMarker();
521     }
522     else
523     {
524         DecodeWithMarker();
525     }
526     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : ProcessData OUT"));
527 }
528 
529 
530 /* Decoding function for input buffers without end of frame flag marked */
DecodeWithoutMarker()531 void OpenmaxAvcAO::DecodeWithoutMarker()
532 {
533     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithoutMarker IN"));
534 
535     QueueType*              pInputQueue  = ipPorts[OMX_PORT_INPUTPORT_INDEX]->pBufferQueue;
536     QueueType*              pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue;
537     ComponentPortType*  pOutPort =     ipPorts[OMX_PORT_OUTPUTPORT_INDEX];
538     OMX_COMPONENTTYPE *     pHandle =      &iOmxComponent;
539 
540     OMX_U8*                 pOutBuffer;
541     OMX_U32                 OutputLength;
542     OMX_U8*                 pTempInBuffer;
543     OMX_U32                 TempInLength;
544     OMX_BOOL                MarkerFlag = OMX_FALSE;
545     OMX_TICKS               TempTimestamp;
546     OMX_BOOL                ResizeNeeded = OMX_FALSE;
547 
548     OMX_U32 TempInputBufferSize = (2 * sizeof(uint8) * (ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize));
549     OMX_U32 CurrWidth =  ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameWidth;
550     OMX_U32 CurrHeight = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameHeight;
551 
552 
553     if ((!iIsInputBufferEnded) || ((iEndofStream) || (0 != iTempInputBufferLength)))
554     {
555         //Check whether prev output bufer has been released or not
556         if (OMX_TRUE == iNewOutBufRequired)
557         {
558             //Check whether a new output buffer is available or not
559             if (0 == (GetQueueNumElem(pOutputQueue)))
560             {
561                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithoutMarker OUT output buffer unavailable"));
562                 //Store the mark data for output buffer, as it will be overwritten next time
563                 if (NULL != ipTargetComponent)
564                 {
565                     ipTempTargetComponent = ipTargetComponent;
566                     iTempTargetMarkData = iTargetMarkData;
567                     iMarkPropagate = OMX_TRUE;
568                 }
569                 return;
570             }
571 
572             ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue);
573             if (NULL == ipOutputBuffer)
574             {
575                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithoutMarker Error, output buffer dequeue returned NULL, OUT"));
576                 return;
577             }
578 
579             //Do not proceed if the output buffer can't fit the YUV data
580             if ((ipOutputBuffer->nAllocLen < (OMX_U32)(((CurrWidth + 15)&(~15)) *((CurrHeight + 15)&(~15)) * 3 / 2)) && (OMX_TRUE == ipAvcDec->iAvcActiveFlag))
581             {
582                 ipOutputBuffer->nFilledLen = 0;
583                 ReturnOutputBuffer(ipOutputBuffer, pOutPort);
584                 ipOutputBuffer = NULL;
585                 return;
586             }
587             ipOutputBuffer->nFilledLen = 0;
588             iNewOutBufRequired = OMX_FALSE;
589         }
590 
591 
592         /* Code for the marking buffer. Takes care of the OMX_CommandMarkBuffer
593          * command and hMarkTargetComponent as given by the specifications
594          */
595         if (NULL != ipMark)
596         {
597             ipOutputBuffer->hMarkTargetComponent = ipMark->hMarkTargetComponent;
598             ipOutputBuffer->pMarkData = ipMark->pMarkData;
599             ipMark = NULL;
600         }
601 
602         if ((OMX_TRUE == iMarkPropagate) && (ipTempTargetComponent != ipTargetComponent))
603         {
604             ipOutputBuffer->hMarkTargetComponent = ipTempTargetComponent;
605             ipOutputBuffer->pMarkData = iTempTargetMarkData;
606             ipTempTargetComponent = NULL;
607             iMarkPropagate = OMX_FALSE;
608         }
609         else if (ipTargetComponent != NULL)
610         {
611             ipOutputBuffer->hMarkTargetComponent = ipTargetComponent;
612             ipOutputBuffer->pMarkData = iTargetMarkData;
613             ipTargetComponent = NULL;
614             iMarkPropagate = OMX_FALSE;
615         }
616         //Mark buffer code ends here
617 
618         pOutBuffer = ipOutputBuffer->pBuffer;
619         OutputLength = 0;
620 
621         pTempInBuffer = ipTempInputBuffer + iTempConsumedLength;
622         TempInLength = iTempInputBufferLength;
623 
624         //Output buffer is passed as a short pointer
625         iDecodeReturn = ipAvcDec->AvcDecodeVideo_OMX(pOutBuffer, (OMX_U32*) & OutputLength,
626                         &(pTempInBuffer),
627                         &TempInLength,
628                         &(ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam),
629                         &iFrameCount,
630                         MarkerFlag, &TempTimestamp, &ResizeNeeded);
631 
632         ipOutputBuffer->nFilledLen = OutputLength;
633 
634         //offset not required in our case, set it to zero
635         ipOutputBuffer->nOffset = 0;
636 
637         //Set the timestamp equal to the input buffer timestamp
638         ipOutputBuffer->nTimeStamp = iFrameTimestamp;
639 
640         iTempConsumedLength += (iTempInputBufferLength - TempInLength);
641         iTempInputBufferLength = TempInLength;
642 
643         //If decoder returned error, report it to the client via a callback
644         if (!iDecodeReturn && OMX_FALSE == ipAvcDec->iAvcActiveFlag)
645         {
646             // initialization error
647             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithoutMarker ErrorBadParameter callback send"));
648 
649             (*(ipCallbacks->EventHandler))
650             (pHandle,
651              iCallbackData,
652              OMX_EventError,
653              OMX_ErrorBadParameter,
654              0,
655              NULL);
656         }
657         else if (!iDecodeReturn && OMX_FALSE == iEndofStream)
658         {
659             // decoding error
660             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithoutMarker ErrorStreamCorrupt callback send"));
661 
662             (*(ipCallbacks->EventHandler))
663             (pHandle,
664              iCallbackData,
665              OMX_EventError,
666              OMX_ErrorStreamCorrupt,
667              0,
668              NULL);
669         }
670 
671 
672         //Do not decode if big buffer is less than half the size
673         if (TempInLength < (TempInputBufferSize >> 1))
674         {
675             iIsInputBufferEnded = OMX_TRUE;
676             iNewInBufferRequired = OMX_TRUE;
677         }
678 
679         if (ResizeNeeded == OMX_TRUE)
680         {
681             OMX_COMPONENTTYPE* pHandle = (OMX_COMPONENTTYPE*) ipAppPriv->CompHandle;
682 
683             iResizePending = OMX_TRUE;
684             (*(ipCallbacks->EventHandler))
685             (pHandle,
686              iCallbackData,
687              OMX_EventPortSettingsChanged, //The command was completed
688              OMX_PORT_OUTPUTPORT_INDEX,
689              0,
690              NULL);
691         }
692 
693         /* If EOS flag has come from the client & there are no more
694          * input buffers to decode, send the callback to the client
695          */
696         if (OMX_TRUE == iEndofStream)
697         {
698             if ((0 == iTempInputBufferLength) && !iDecodeReturn)
699             {
700                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithoutMarker EOS callback send"));
701 
702                 (*(ipCallbacks->EventHandler))
703                 (pHandle,
704                  iCallbackData,
705                  OMX_EventBufferFlag,
706                  1,
707                  OMX_BUFFERFLAG_EOS,
708                  NULL);
709 
710                 iNewInBufferRequired = OMX_TRUE;
711                 iEndofStream = OMX_FALSE;
712 
713                 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_EOS;
714 
715                 ReturnOutputBuffer(ipOutputBuffer, pOutPort);
716                 ipOutputBuffer = NULL;
717 
718                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithoutMarker OUT"));
719 
720                 return;
721             }
722         }
723 
724         //Send the output buffer back when it has some data in it
725         if (ipOutputBuffer->nFilledLen > 0)
726         {
727             ReturnOutputBuffer(ipOutputBuffer, pOutPort);
728             ipOutputBuffer = NULL;
729         }
730 
731         /* If there is some more processing left with current buffers, re-schedule the AO
732          * Do not go for more than one round of processing at a time.
733          * This may block the AO longer than required.
734          */
735         if ((ResizeNeeded == OMX_FALSE) && ((TempInLength != 0) || (GetQueueNumElem(pInputQueue) > 0))
736                 && ((GetQueueNumElem(pOutputQueue) > 0) || (OMX_FALSE == iNewOutBufRequired)))
737         {
738             RunIfNotReady();
739         }
740     }
741 
742     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithoutMarker OUT"));
743     return;
744 }
745 
746 
747 /* Decoding function for input buffers with end of frame flag marked */
DecodeWithMarker()748 void OpenmaxAvcAO::DecodeWithMarker()
749 {
750     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithMarker IN"));
751 
752     OMX_COMPONENTTYPE  *pHandle = &iOmxComponent;
753     QueueType* pInputQueue = ipPorts[OMX_PORT_INPUTPORT_INDEX]->pBufferQueue;
754     QueueType* pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue;
755 
756     ComponentPortType*  pInPort = ipPorts[OMX_PORT_INPUTPORT_INDEX];
757     ComponentPortType*  pOutPort = ipPorts[OMX_PORT_OUTPUTPORT_INDEX];
758 
759     OMX_U8*                 pOutBuffer;
760     OMX_U32                 OutputLength;
761     OMX_BOOL                MarkerFlag = OMX_TRUE;
762     OMX_BOOL                Status;
763     OMX_BOOL                ResizeNeeded = OMX_FALSE;
764 
765     OMX_U32 CurrWidth =  ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameWidth;
766     OMX_U32 CurrHeight = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameHeight;
767 
768     if ((!iIsInputBufferEnded) || (iEndofStream))
769     {
770         //Check whether prev output bufer has been released or not
771         if (OMX_TRUE == iNewOutBufRequired)
772         {
773             //Check whether a new output buffer is available or not
774             if (0 == (GetQueueNumElem(pOutputQueue)))
775             {
776                 iNewInBufferRequired = OMX_FALSE;
777                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithMarker OUT output buffer unavailable"));
778                 return;
779             }
780 
781             ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue);
782             if (NULL == ipOutputBuffer)
783             {
784                 iNewInBufferRequired = OMX_FALSE;
785                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithMarker Error, output buffer dequeue returned NULL, OUT"));
786                 return;
787             }
788 
789             //Do not proceed if the output buffer can't fit the YUV data
790             if ((ipOutputBuffer->nAllocLen < (OMX_U32)(((CurrWidth + 15)&(~15)) *((CurrHeight + 15)&(~15)) * 3 / 2)) && (OMX_TRUE == ipAvcDec->iAvcActiveFlag))
791             {
792                 ipOutputBuffer->nFilledLen = 0;
793                 ReturnOutputBuffer(ipOutputBuffer, pOutPort);
794                 ipOutputBuffer = NULL;
795                 return;
796             }
797             ipOutputBuffer->nFilledLen = 0;
798             iNewOutBufRequired = OMX_FALSE;
799         }
800 
801         /* Code for the marking buffer. Takes care of the OMX_CommandMarkBuffer
802          * command and hMarkTargetComponent as given by the specifications
803          */
804         if (NULL != ipMark)
805         {
806             ipOutputBuffer->hMarkTargetComponent = ipMark->hMarkTargetComponent;
807             ipOutputBuffer->pMarkData = ipMark->pMarkData;
808             ipMark = NULL;
809         }
810 
811         if (NULL != ipTargetComponent)
812         {
813             ipOutputBuffer->hMarkTargetComponent = ipTargetComponent;
814             ipOutputBuffer->pMarkData = iTargetMarkData;
815             ipTargetComponent = NULL;
816 
817         }
818         //Mark buffer code ends here
819 
820         pOutBuffer = ipOutputBuffer->pBuffer;
821         OutputLength = 0;
822 
823         if (iInputCurrLength > 0)
824         {
825             //Store the input timestamp into a temp variable
826             ipAvcDec->CurrInputTimestamp = iFrameTimestamp;
827 
828             //Output buffer is passed as a short pointer
829             iDecodeReturn = ipAvcDec->AvcDecodeVideo_OMX(pOutBuffer, (OMX_U32*) & OutputLength,
830                             &(ipFrameDecodeBuffer),
831                             &(iInputCurrLength),
832                             &(ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam),
833                             &iFrameCount,
834                             MarkerFlag,
835                             &(ipOutputBuffer->nTimeStamp), &ResizeNeeded);
836 
837             ipOutputBuffer->nFilledLen = OutputLength;
838             //offset not required in our case, set it to zero
839             ipOutputBuffer->nOffset = 0;
840 
841             if (ResizeNeeded == OMX_TRUE)
842             {
843                 OMX_COMPONENTTYPE* pHandle = (OMX_COMPONENTTYPE*) ipAppPriv->CompHandle;
844 
845                 // set the flag. Do not process any more frames until
846                 // IL Client sends PortDisable event (thus starting the procedure for
847                 // dynamic port reconfiguration)
848                 iResizePending = OMX_TRUE;
849 
850                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : Sending the PortSettings Changed Callback"));
851 
852                 (*(ipCallbacks->EventHandler))
853                 (pHandle,
854                  iCallbackData,
855                  OMX_EventPortSettingsChanged, //The command was completed
856                  OMX_PORT_OUTPUTPORT_INDEX,
857                  0,
858                  NULL);
859             }
860 
861 
862             //If decoder returned error, report it to the client via a callback
863             if (!iDecodeReturn && OMX_FALSE == ipAvcDec->iAvcActiveFlag)
864             {
865                 // initialization error
866                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithoutMarker ErrorBadParameter callback send"));
867 
868                 (*(ipCallbacks->EventHandler))
869                 (pHandle,
870                  iCallbackData,
871                  OMX_EventError,
872                  OMX_ErrorBadParameter,
873                  0,
874                  NULL);
875             }
876             else if (!iDecodeReturn && OMX_FALSE == iEndofStream)
877             {
878                 // decode error
879                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithMarker ErrorStreamCorrupt callback send"));
880 
881                 (*(ipCallbacks->EventHandler))
882                 (pHandle,
883                  iCallbackData,
884                  OMX_EventError,
885                  OMX_ErrorStreamCorrupt,
886                  0,
887                  NULL);
888             }
889 
890 
891             if (0 == iInputCurrLength)
892             {
893                 if (iPVCapabilityFlags.iOMXComponentUsesFullAVCFrames)
894                 {
895                     iCurrNAL++;
896 
897                     if (iCurrNAL < iNumNALs)
898                     {
899                         ipFrameDecodeBuffer = ipInputBuffer->pBuffer + iNALOffset;
900                         iInputCurrLength = iNALSizeArray[iCurrNAL];
901 
902                         if (iPVCapabilityFlags.iOMXComponentUsesNALStartCodes)
903                         {
904                             iNALOffset += (iInputCurrLength + NAL_START_CODE_SIZE); // offset for next NAL
905                         }
906                         else
907                         {
908                             iNALOffset += iInputCurrLength; // offset for next NAL
909                         }
910 
911                         iNewInBufferRequired = OMX_FALSE;
912                     }
913                     else
914                     {
915                         ipInputBuffer->nFilledLen = 0;
916                         ReturnInputBuffer(ipInputBuffer, pInPort);
917                         iNewInBufferRequired = OMX_TRUE;
918                         iIsInputBufferEnded = OMX_TRUE;
919                         ipInputBuffer = NULL;
920                     }
921                 }
922                 else
923                 {
924                     ipInputBuffer->nFilledLen = 0;
925                     ReturnInputBuffer(ipInputBuffer, pInPort);
926                     iNewInBufferRequired = OMX_TRUE;
927                     iIsInputBufferEnded = OMX_TRUE;
928                     ipInputBuffer = NULL;
929                 }
930             }
931             else
932             {
933                 iNewInBufferRequired = OMX_FALSE;
934             }
935         }
936         else if (iEndofStream == OMX_FALSE)
937         {
938             // it's possible that after partial frame assembly, the input buffer still remains empty (due to
939             // client erroneously sending such buffers). This may cause error in processing/returning buffers
940             // This code adds robustness in the sense that it returns such buffer to the client
941 
942             ipInputBuffer->nFilledLen = 0;
943             ReturnInputBuffer(ipInputBuffer, pInPort);
944             ipInputBuffer = NULL;
945             iNewInBufferRequired = OMX_TRUE;
946             iIsInputBufferEnded = OMX_TRUE;
947         }
948 
949 
950         /* If EOS flag has come from the client & there are no more
951          * input buffers to decode, send the callback to the client*/
952         if (OMX_TRUE == iEndofStream)
953         {
954             if (!iDecodeReturn)
955             {
956                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithMarker EOS callback send"));
957 
958                 (*(ipCallbacks->EventHandler))
959                 (pHandle,
960                  iCallbackData,
961                  OMX_EventBufferFlag,
962                  1,
963                  OMX_BUFFERFLAG_EOS,
964                  NULL);
965 
966                 iNewInBufferRequired = OMX_TRUE;
967                 iEndofStream = OMX_FALSE;
968 
969                 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_EOS;
970                 ReturnOutputBuffer(ipOutputBuffer, pOutPort);
971                 ipOutputBuffer = NULL;
972 
973                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithMarker OUT"));
974 
975                 return;
976             }
977             else if (iDecodeReturn)
978             {
979                 Status = ipAvcDec->FlushOutput_OMX(pOutBuffer, &OutputLength, &(ipOutputBuffer->nTimeStamp), pOutPort->PortParam.format.video.nFrameWidth, pOutPort->PortParam.format.video.nFrameHeight);
980                 ipOutputBuffer->nFilledLen = OutputLength;
981 
982                 ipOutputBuffer->nOffset = 0;
983 
984                 if (OMX_FALSE != Status)
985                 {
986                     ReturnOutputBuffer(ipOutputBuffer, pOutPort);
987                     ipOutputBuffer = NULL;
988 
989                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithMarker OUT"));
990                     RunIfNotReady();
991                     return;
992                 }
993                 else
994                 {
995                     iDecodeReturn = OMX_FALSE;
996                     RunIfNotReady();
997                 }
998             }
999         }
1000 
1001         //Send the output buffer back when it has some data in it
1002         if (ipOutputBuffer->nFilledLen > 0)
1003         {
1004             ReturnOutputBuffer(ipOutputBuffer, pOutPort);
1005             ipOutputBuffer = NULL;
1006         }
1007 
1008 
1009         /* If there is some more processing left with current buffers, re-schedule the AO
1010          * Do not go for more than one round of processing at a time.
1011          * This may block the AO longer than required.
1012          */
1013         if ((ResizeNeeded == OMX_FALSE) && ((iInputCurrLength != 0) || (GetQueueNumElem(pInputQueue) > 0))
1014                 && ((GetQueueNumElem(pOutputQueue) > 0) || (OMX_FALSE == iNewOutBufRequired)))
1015         {
1016             RunIfNotReady();
1017         }
1018     }
1019 
1020     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : DecodeWithMarker OUT"));
1021     return;
1022 }
1023 
1024 
ComponentGetRolesOfComponent(OMX_STRING * aRoleString)1025 void OpenmaxAvcAO::ComponentGetRolesOfComponent(OMX_STRING* aRoleString)
1026 {
1027     *aRoleString = (OMX_STRING)"video_decoder.avc";
1028 }
1029 
1030 
1031 
1032 //Component object constructor
OpenmaxAvcAO()1033 OpenmaxAvcAO::OpenmaxAvcAO()
1034 {
1035     ipAvcDec = NULL;
1036 
1037     if (!IsAdded())
1038     {
1039         AddToScheduler();
1040     }
1041     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : constructed"));
1042 }
1043 
1044 
1045 //Component object destructor
~OpenmaxAvcAO()1046 OpenmaxAvcAO::~OpenmaxAvcAO()
1047 {
1048     if (IsAdded())
1049     {
1050         RemoveFromScheduler();
1051     }
1052 
1053     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : destructed"));
1054 }
1055 
1056 
1057 /** The Initialization function
1058  */
ComponentInit()1059 OMX_ERRORTYPE OpenmaxAvcAO::ComponentInit()
1060 {
1061     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : ComponentInit IN"));
1062 
1063     OMX_ERRORTYPE Status = OMX_ErrorNone;
1064 
1065     if (OMX_TRUE == iIsInit)
1066     {
1067         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : ComponentInit error incorrect operation"));
1068         return OMX_ErrorIncorrectStateOperation;
1069     }
1070     iIsInit = OMX_TRUE;
1071 
1072     //avc lib init
1073     if (!iCodecReady)
1074     {
1075         Status = ipAvcDec->AvcDecInit_OMX();
1076         iCodecReady = OMX_TRUE;
1077     }
1078 
1079     iInputCurrLength = 0;
1080     iNumNALs = 0;
1081     iCurrNAL = 0;
1082     iNALOffset = 0;
1083     oscl_memset(iNALSizeArray, 0, MAX_NAL_PER_FRAME * sizeof(uint32));
1084     //Used in dynamic port reconfiguration
1085     iFrameCount = 0;
1086     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : ComponentInit OUT"));
1087 
1088     return Status;
1089 
1090 }
1091 
1092 /** This function is called upon a transition to the idle or invalid state.
1093  *  Also it is called by the AvcComponentDestructor() function
1094  */
ComponentDeInit()1095 OMX_ERRORTYPE OpenmaxAvcAO::ComponentDeInit()
1096 {
1097     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : ComponentDeInit IN"));
1098 
1099     OMX_ERRORTYPE Status = OMX_ErrorNone;
1100 
1101     iIsInit = OMX_FALSE;
1102 
1103     if (iCodecReady)
1104     {
1105         Status = ipAvcDec->AvcDecDeinit_OMX();
1106         iCodecReady = OMX_FALSE;
1107     }
1108 
1109     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxAvcAO : ComponentDeInit OUT"));
1110 
1111     return Status;
1112 
1113 }
1114 
1115 
GetConfig(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_INDEXTYPE nIndex,OMX_INOUT OMX_PTR pComponentConfigStructure)1116 OMX_ERRORTYPE OpenmaxAvcAO::GetConfig(
1117     OMX_IN  OMX_HANDLETYPE hComponent,
1118     OMX_IN  OMX_INDEXTYPE nIndex,
1119     OMX_INOUT OMX_PTR pComponentConfigStructure)
1120 {
1121     OSCL_UNUSED_ARG(hComponent);
1122     OSCL_UNUSED_ARG(nIndex);
1123     OSCL_UNUSED_ARG(pComponentConfigStructure);
1124     return OMX_ErrorNotImplemented;
1125 }
1126 
1127 /* This routine will reset the decoder library and some of the associated flags*/
ResetComponent()1128 void OpenmaxAvcAO::ResetComponent()
1129 {
1130     // reset decoder
1131     if (ipAvcDec)
1132     {
1133         ipAvcDec->ResetDecoder();
1134     }
1135 
1136 }
1137