• 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 "pv_omxdefs.h"
20 #include "omx_mpeg4_component.h"
21 
22 #if PROXY_INTERFACE
23 #include "omx_proxy_interface.h"
24 #endif
25 
26 // Use default DLL entry point
27 #ifndef OSCL_DLL_H_INCLUDED
28 #include "oscl_dll.h"
29 #endif
30 
31 OSCL_DLL_ENTRY_POINT_DEFAULT()
32 
33 static const uint32 mask[33] =
34 {
35     0x00000000, 0x00000001, 0x00000003, 0x00000007,
36     0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
37     0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
38     0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
39     0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
40     0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
41     0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
42     0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
43     0xffffffff
44 };
45 
46 // This function is called by OMX_GetHandle and it creates an instance of the mpeg4 component AO
Mpeg4OmxComponentFactory(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)47 OSCL_EXPORT_REF OMX_ERRORTYPE Mpeg4OmxComponentFactory(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)
48 {
49     OSCL_UNUSED_ARG(aOmxLibName);
50     OSCL_UNUSED_ARG(aOmxLib);
51     OSCL_UNUSED_ARG(aOsclUuid);
52     OSCL_UNUSED_ARG(aRefCount);
53 
54 
55     OpenmaxMpeg4AO* pOpenmaxAOType;
56     OMX_ERRORTYPE Status;
57 
58     // move InitMpeg4OmxComponentFields content to actual constructor
59 
60     pOpenmaxAOType = (OpenmaxMpeg4AO*) OSCL_NEW(OpenmaxMpeg4AO, ());
61 
62     if (NULL == pOpenmaxAOType)
63     {
64         return OMX_ErrorInsufficientResources;
65     }
66 
67     // set decoding mode to H263
68     pOpenmaxAOType->SetDecoderMode(MODE_MPEG4);
69 
70     //Call the construct component to initialize OMX types
71     Status = pOpenmaxAOType->ConstructComponent(pAppData, pProxy);
72 
73     *pHandle = pOpenmaxAOType->GetOmxHandle();
74 
75     return Status;
76     ///////////////////////////////////////////////////////////////////////////////////////
77 }
78 
79 // This function is called by OMX_FreeHandle when component AO needs to be destroyed
Mpeg4OmxComponentDestructor(OMX_IN OMX_HANDLETYPE pHandle,OMX_PTR & aOmxLib,OMX_PTR aOsclUuid,OMX_U32 & aRefCount)80 OSCL_EXPORT_REF OMX_ERRORTYPE Mpeg4OmxComponentDestructor(OMX_IN OMX_HANDLETYPE pHandle, OMX_PTR &aOmxLib, OMX_PTR aOsclUuid, OMX_U32 &aRefCount)
81 {
82     OSCL_UNUSED_ARG(aOmxLib);
83     OSCL_UNUSED_ARG(aOsclUuid);
84     OSCL_UNUSED_ARG(aRefCount);
85 
86     // get pointer to component AO
87     OpenmaxMpeg4AO* pOpenmaxAOType = (OpenmaxMpeg4AO*)((OMX_COMPONENTTYPE*)pHandle)->pComponentPrivate;
88 
89     // clean up decoder, OMX component stuff
90     pOpenmaxAOType->DestroyComponent();
91 
92     // destroy the AO class
93     OSCL_DELETE(pOpenmaxAOType);
94 
95     return OMX_ErrorNone;
96 }
97 
98 // This function is called by OMX_GetHandle and it creates an instance of the h263 component AO
H263OmxComponentFactory(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)99 OSCL_EXPORT_REF OMX_ERRORTYPE H263OmxComponentFactory(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)
100 {
101     OSCL_UNUSED_ARG(aOmxLibName);
102     OSCL_UNUSED_ARG(aOmxLib);
103     OSCL_UNUSED_ARG(aOsclUuid);
104     OSCL_UNUSED_ARG(aRefCount);
105 
106     OpenmaxMpeg4AO* pOpenmaxAOType;
107     OMX_ERRORTYPE Status;
108 
109     // move InitMpeg4OmxComponentFields content to actual constructor
110 
111     pOpenmaxAOType = (OpenmaxMpeg4AO*) OSCL_NEW(OpenmaxMpeg4AO, ());
112 
113     if (NULL == pOpenmaxAOType)
114     {
115         return OMX_ErrorInsufficientResources;
116     }
117 
118     // set decoding mode to H263
119     pOpenmaxAOType->SetDecoderMode(MODE_H263);
120 
121     //Call the construct component to initialize OMX types
122     Status = pOpenmaxAOType->ConstructComponent(pAppData, pProxy);
123 
124     *pHandle = pOpenmaxAOType->GetOmxHandle();
125 
126     return Status;
127     ///////////////////////////////////////////////////////////////////////////////////////
128 }
129 
130 // This function is called by OMX_FreeHandle when component AO needs to be destroyed
H263OmxComponentDestructor(OMX_IN OMX_HANDLETYPE pHandle,OMX_PTR & aOmxLib,OMX_PTR aOsclUuid,OMX_U32 & aRefCount)131 OSCL_EXPORT_REF OMX_ERRORTYPE H263OmxComponentDestructor(OMX_IN OMX_HANDLETYPE pHandle, OMX_PTR &aOmxLib, OMX_PTR aOsclUuid, OMX_U32 &aRefCount)
132 {
133     OSCL_UNUSED_ARG(aOmxLib);
134     OSCL_UNUSED_ARG(aOsclUuid);
135     OSCL_UNUSED_ARG(aRefCount);
136 
137     // get pointer to component AO
138     OpenmaxMpeg4AO* pOpenmaxAOType = (OpenmaxMpeg4AO*)((OMX_COMPONENTTYPE*)pHandle)->pComponentPrivate;
139 
140     // clean up decoder, OMX component stuff
141     pOpenmaxAOType->DestroyComponent();
142 
143     // destroy the AO class
144     OSCL_DELETE(pOpenmaxAOType);
145 
146     return OMX_ErrorNone;
147 }
148 
149 #if (DYNAMIC_LOAD_OMX_M4V_COMPONENT || DYNAMIC_LOAD_OMX_H263_COMPONENT)
150 class Mpeg4H263OmxSharedLibraryInterface: public OsclSharedLibraryInterface,
151         public OmxSharedLibraryInterface
152 
153 {
154     public:
QueryOmxComponentInterface(const OsclUuid & aOmxTypeId,const OsclUuid & aInterfaceId)155         OsclAny *QueryOmxComponentInterface(const OsclUuid& aOmxTypeId, const OsclUuid& aInterfaceId)
156         {
157             if (PV_OMX_M4VDEC_UUID == aOmxTypeId)
158             {
159                 if (PV_OMX_CREATE_INTERFACE == aInterfaceId)
160                 {
161                     return ((OsclAny*)(&Mpeg4OmxComponentFactory));
162                 }
163                 else if (PV_OMX_DESTROY_INTERFACE == aInterfaceId)
164                 {
165                     return ((OsclAny*)(&Mpeg4OmxComponentDestructor));
166                 }
167             }
168             else if (PV_OMX_H263DEC_UUID == aOmxTypeId)
169             {
170                 if (PV_OMX_CREATE_INTERFACE == aInterfaceId)
171                 {
172                     return ((OsclAny*)(&H263OmxComponentFactory));
173                 }
174                 else if (PV_OMX_DESTROY_INTERFACE == aInterfaceId)
175                 {
176                     return ((OsclAny*)(&H263OmxComponentDestructor));
177                 }
178             }
179             return NULL;
180         };
SharedLibraryLookup(const OsclUuid & aInterfaceId)181         OsclAny *SharedLibraryLookup(const OsclUuid& aInterfaceId)
182         {
183             if (aInterfaceId == PV_OMX_SHARED_INTERFACE)
184             {
185                 return OSCL_STATIC_CAST(OmxSharedLibraryInterface*, this);
186             }
187             return NULL;
188         };
Mpeg4H263OmxSharedLibraryInterface()189         Mpeg4H263OmxSharedLibraryInterface() {};
190 };
191 
192 // function to obtain the interface object from the shared library
193 extern "C"
194 {
PVGetInterface()195     OSCL_EXPORT_REF OsclAny* PVGetInterface()
196     {
197         return (OsclAny*) OSCL_NEW(Mpeg4H263OmxSharedLibraryInterface, ());
198     }
199 
PVReleaseInterface(OsclSharedLibraryInterface * aInstance)200     OSCL_EXPORT_REF void PVReleaseInterface(OsclSharedLibraryInterface* aInstance)
201     {
202         Mpeg4H263OmxSharedLibraryInterface* module = (Mpeg4H263OmxSharedLibraryInterface*)aInstance;
203         OSCL_DELETE(module);
204     }
205 }
206 
207 #endif
208 
SetDecoderMode(int mode)209 void OpenmaxMpeg4AO::SetDecoderMode(int mode)
210 {
211     iDecMode = mode;
212 }
213 
214 
215 
216 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
217 
ConstructComponent(OMX_PTR pAppData,OMX_PTR pProxy)218 OMX_ERRORTYPE OpenmaxMpeg4AO::ConstructComponent(OMX_PTR pAppData, OMX_PTR pProxy)
219 {
220     ComponentPortType *pInPort, *pOutPort;
221     OMX_ERRORTYPE Status;
222 
223     iNumPorts = 2;
224     iOmxComponent.nSize = sizeof(OMX_COMPONENTTYPE);
225     iOmxComponent.pComponentPrivate = (OMX_PTR) this;  // pComponentPrivate points to THIS component AO class
226     ipComponentProxy = pProxy;
227     iOmxComponent.pApplicationPrivate = pAppData; // init the App data
228 
229 
230 #if PROXY_INTERFACE
231     iPVCapabilityFlags.iIsOMXComponentMultiThreaded = OMX_TRUE;
232 
233     iOmxComponent.SendCommand = OpenmaxMpeg4AO::BaseComponentProxySendCommand;
234     iOmxComponent.GetParameter = OpenmaxMpeg4AO::BaseComponentProxyGetParameter;
235     iOmxComponent.SetParameter = OpenmaxMpeg4AO::BaseComponentProxySetParameter;
236     iOmxComponent.GetConfig = OpenmaxMpeg4AO::BaseComponentProxyGetConfig;
237     iOmxComponent.SetConfig = OpenmaxMpeg4AO::BaseComponentProxySetConfig;
238     iOmxComponent.GetExtensionIndex = OpenmaxMpeg4AO::BaseComponentProxyGetExtensionIndex;
239     iOmxComponent.GetState = OpenmaxMpeg4AO::BaseComponentProxyGetState;
240     iOmxComponent.UseBuffer = OpenmaxMpeg4AO::BaseComponentProxyUseBuffer;
241     iOmxComponent.AllocateBuffer = OpenmaxMpeg4AO::BaseComponentProxyAllocateBuffer;
242     iOmxComponent.FreeBuffer = OpenmaxMpeg4AO::BaseComponentProxyFreeBuffer;
243     iOmxComponent.EmptyThisBuffer = OpenmaxMpeg4AO::BaseComponentProxyEmptyThisBuffer;
244     iOmxComponent.FillThisBuffer = OpenmaxMpeg4AO::BaseComponentProxyFillThisBuffer;
245 
246 #else
247     iPVCapabilityFlags.iIsOMXComponentMultiThreaded = OMX_FALSE;
248 
249     iOmxComponent.SendCommand = OpenmaxMpeg4AO::BaseComponentSendCommand;
250     iOmxComponent.GetParameter = OpenmaxMpeg4AO::BaseComponentGetParameter;
251     iOmxComponent.SetParameter = OpenmaxMpeg4AO::BaseComponentSetParameter;
252     iOmxComponent.GetConfig = OpenmaxMpeg4AO::BaseComponentGetConfig;
253     iOmxComponent.SetConfig = OpenmaxMpeg4AO::BaseComponentSetConfig;
254     iOmxComponent.GetExtensionIndex = OpenmaxMpeg4AO::BaseComponentGetExtensionIndex;
255     iOmxComponent.GetState = OpenmaxMpeg4AO::BaseComponentGetState;
256     iOmxComponent.UseBuffer = OpenmaxMpeg4AO::BaseComponentUseBuffer;
257     iOmxComponent.AllocateBuffer = OpenmaxMpeg4AO::BaseComponentAllocateBuffer;
258     iOmxComponent.FreeBuffer = OpenmaxMpeg4AO::BaseComponentFreeBuffer;
259     iOmxComponent.EmptyThisBuffer = OpenmaxMpeg4AO::BaseComponentEmptyThisBuffer;
260     iOmxComponent.FillThisBuffer = OpenmaxMpeg4AO::BaseComponentFillThisBuffer;
261 #endif
262 
263     iOmxComponent.SetCallbacks = OpenmaxMpeg4AO::BaseComponentSetCallbacks;
264     iOmxComponent.nVersion.s.nVersionMajor = SPECVERSIONMAJOR;
265     iOmxComponent.nVersion.s.nVersionMinor = SPECVERSIONMINOR;
266     iOmxComponent.nVersion.s.nRevision = SPECREVISION;
267     iOmxComponent.nVersion.s.nStep = SPECSTEP;
268 
269     // PV capability
270     iPVCapabilityFlags.iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE;
271     iPVCapabilityFlags.iOMXComponentSupportsExternalOutputBufferAlloc = OMX_TRUE;
272     iPVCapabilityFlags.iOMXComponentSupportsMovableInputBuffers = OMX_TRUE;
273     iPVCapabilityFlags.iOMXComponentSupportsPartialFrames = OMX_TRUE;
274     iPVCapabilityFlags.iOMXComponentUsesNALStartCodes = OMX_FALSE;
275     iPVCapabilityFlags.iOMXComponentCanHandleIncompleteFrames = OMX_TRUE;
276     iPVCapabilityFlags.iOMXComponentUsesFullAVCFrames = OMX_FALSE;
277 
278     if (ipAppPriv)
279     {
280         oscl_free(ipAppPriv);
281         ipAppPriv = NULL;
282     }
283 
284     ipAppPriv = (ComponentPrivateType*) oscl_malloc(sizeof(ComponentPrivateType));
285 
286     if (NULL == ipAppPriv)
287     {
288         return OMX_ErrorInsufficientResources;
289     }
290 
291     //Construct base class now
292     Status = ConstructBaseComponent(pAppData);
293 
294     if (OMX_ErrorNone != Status)
295     {
296         return Status;
297     }
298 
299     /** Domain specific section for the ports. */
300     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_INPUTPORT_INDEX;
301     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainVideo;
302     if (iDecMode == MODE_MPEG4)
303     {
304         ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.cMIMEType = (OMX_STRING)"video/mpeg4";
305         ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
306 
307     }
308     else if (iDecMode == MODE_H263)
309     {
310         ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.cMIMEType = (OMX_STRING)"video/h263";
311         ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingH263;
312 
313     }
314 
315     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.pNativeRender = 0;
316     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.bFlagErrorConcealment = OMX_FALSE;
317 
318     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.eColorFormat = OMX_COLOR_FormatUnused;
319     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.nFrameWidth = 176;
320     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.nFrameHeight = 144;
321     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.nBitrate = 64000;
322     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.xFramerate = (15 << 16);
323     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.eDir = OMX_DirInput;
324     //Set to a default value, will change later during setparameter call
325     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferCountActual = NUMBER_INPUT_BUFFER_MP4;
326     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferCountMin = 1;
327     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize = INPUT_BUFFER_SIZE_MP4;
328     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE;
329     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE;
330 
331 
332     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX;
333     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainVideo;
334     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.cMIMEType = (OMX_STRING)"raw";
335     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.pNativeRender = 0;
336     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.bFlagErrorConcealment = OMX_FALSE;
337     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
338     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
339     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameWidth = 176; //320; //176;
340     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nStride = 176;
341     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameHeight = 144; //240; //144;
342     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nSliceHeight = 144;
343     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nBitrate = 64000;
344     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.xFramerate = (15 << 16);
345     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDir = OMX_DirOutput;
346     //Set to a default value, will change later during setparameter call
347     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountActual = NUMBER_OUTPUT_BUFFER_MP4;
348     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountMin = 1;
349     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferSize = OUTPUT_BUFFER_SIZE_MP4;
350     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE;
351     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE;
352 
353     if (iDecMode == MODE_MPEG4)
354     {
355         //Default values for mpeg4 video param port
356         ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoMpeg4.nPortIndex = OMX_PORT_INPUTPORT_INDEX;
357         ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoMpeg4.eProfile = OMX_VIDEO_MPEG4ProfileSimple;
358         ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoMpeg4.eLevel = OMX_VIDEO_MPEG4Level3;
359 
360         ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.nPortIndex = OMX_PORT_INPUTPORT_INDEX;
361         ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.nProfileIndex = 0;
362         ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.eProfile = OMX_VIDEO_MPEG4ProfileSimple;
363         ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.eLevel = OMX_VIDEO_MPEG4Level3;
364         oscl_strncpy((OMX_STRING)iComponentRole, (OMX_STRING)"video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE);
365     }
366     else if (iDecMode == MODE_H263)
367     {
368         //Default values for h263 video param port
369         ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoH263.nPortIndex = OMX_PORT_INPUTPORT_INDEX;
370         ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoH263.eProfile = (OMX_VIDEO_H263PROFILETYPE) (OMX_VIDEO_H263ProfileBaseline | OMX_VIDEO_H263ProfileISWV2);
371         ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoH263.eLevel = OMX_VIDEO_H263Level45;
372 
373         ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.nPortIndex = OMX_PORT_INPUTPORT_INDEX;
374         ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.nProfileIndex = 0;
375         ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.eProfile = OMX_VIDEO_H263ProfileBaseline | OMX_VIDEO_H263ProfileISWV2;
376         ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.eLevel = OMX_VIDEO_H263Level45;
377         oscl_strncpy((OMX_STRING)iComponentRole, (OMX_STRING)"video_decoder.h263", OMX_MAX_STRINGNAME_SIZE);
378 
379     }
380 
381     iPortTypesParam.nPorts = 2;
382     iPortTypesParam.nStartPortNumber = 0;
383 
384     pInPort = (ComponentPortType*) ipPorts[OMX_PORT_INPUTPORT_INDEX];
385     pOutPort = (ComponentPortType*) ipPorts[OMX_PORT_OUTPUTPORT_INDEX];
386 
387     pInPort->ActualNumPortFormatsSupported = 1;
388 
389     //OMX_VIDEO_PARAM_PORTFORMATTYPE INPUT PORT SETTINGS
390     //On input port for index 0
391     SetHeader(&pInPort->VideoParam[0], sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
392     pInPort->VideoParam[0].nPortIndex = 0;
393     pInPort->VideoParam[0].nIndex = 0;
394 
395     if (iDecMode == MODE_MPEG4)
396     {
397         pInPort->VideoParam[0].eCompressionFormat = OMX_VIDEO_CodingMPEG4;
398 
399     }
400     else if (iDecMode == MODE_H263)
401     {
402         pInPort->VideoParam[0].eCompressionFormat = OMX_VIDEO_CodingH263;
403     }
404 
405     pInPort->VideoParam[0].eColorFormat = OMX_COLOR_FormatUnused;
406 
407     pOutPort->ActualNumPortFormatsSupported = 1;
408 
409     //OMX_VIDEO_PARAM_PORTFORMATTYPE OUTPUT PORT SETTINGS
410     //On output port for index 0
411     SetHeader(&pOutPort->VideoParam[0], sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
412     pOutPort->VideoParam[0].nPortIndex = 1;
413     pOutPort->VideoParam[0].nIndex = 0;
414     pOutPort->VideoParam[0].eCompressionFormat = OMX_VIDEO_CodingUnused;
415     pOutPort->VideoParam[0].eColorFormat = OMX_COLOR_FormatYUV420Planar;
416 
417 
418     iUseExtTimestamp = OMX_TRUE;
419 
420 
421     if (ipMpegDecoderObject)
422     {
423         OSCL_DELETE(ipMpegDecoderObject);
424         ipMpegDecoderObject = NULL;
425     }
426     ipMpegDecoderObject = OSCL_NEW(Mpeg4Decoder_OMX, ());
427     oscl_memset(ipMpegDecoderObject, 0, sizeof(Mpeg4Decoder_OMX));
428 
429 #if PROXY_INTERFACE
430 
431     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSendCommand = BaseComponentSendCommand;
432     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetParameter = BaseComponentGetParameter;
433     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetParameter = BaseComponentSetParameter;
434     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetConfig = BaseComponentGetConfig;
435     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetConfig = BaseComponentSetConfig;
436     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetExtensionIndex = BaseComponentGetExtensionIndex;
437     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetState = BaseComponentGetState;
438     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentUseBuffer = BaseComponentUseBuffer;
439     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentAllocateBuffer = BaseComponentAllocateBuffer;
440     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentFreeBuffer = BaseComponentFreeBuffer;
441     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentEmptyThisBuffer = BaseComponentEmptyThisBuffer;
442     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentFillThisBuffer = BaseComponentFillThisBuffer;
443 
444 #endif
445 
446     return OMX_ErrorNone;
447 }
448 
449 
450 /** This function is called by the omx core when the component
451     * is disposed by the IL client with a call to FreeHandle().
452     */
453 
DestroyComponent()454 OMX_ERRORTYPE OpenmaxMpeg4AO::DestroyComponent()
455 {
456     if (OMX_FALSE != iIsInit)
457     {
458         ComponentDeInit();
459     }
460 
461     //Destroy the base class now
462     DestroyBaseComponent();
463 
464     if (ipMpegDecoderObject)
465     {
466         OSCL_DELETE(ipMpegDecoderObject);
467         ipMpegDecoderObject = NULL;
468     }
469 
470     if (ipAppPriv)
471     {
472         ipAppPriv->CompHandle = NULL;
473 
474         oscl_free(ipAppPriv);
475         ipAppPriv = NULL;
476     }
477 
478     return OMX_ErrorNone;
479 }
480 
481 
482 
483 /* This function will be called in case of buffer management without marker bit present
484  * The purpose is to copy the current input buffer into a big temporary buffer, so that
485  * an incomplete/partial frame is never passed to the decoder library for decode
486  */
ComponentBufferMgmtWithoutMarker()487 void OpenmaxMpeg4AO::ComponentBufferMgmtWithoutMarker()
488 {
489     //This common routine has been written in the base class
490     TempInputBufferMgmtWithoutMarker();
491 }
492 
493 
ProcessData()494 void OpenmaxMpeg4AO::ProcessData()
495 {
496     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : ProcessData IN"));
497     if (!iEndOfFrameFlag)
498     {
499         DecodeWithoutMarker();
500     }
501     else
502     {
503         DecodeWithMarker();
504     }
505 
506     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : ProcessData OUT"));
507 }
508 
509 
DecodeWithoutMarker()510 void OpenmaxMpeg4AO::DecodeWithoutMarker()
511 {
512     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker IN"));
513 
514     QueueType* pInputQueue = ipPorts[OMX_PORT_INPUTPORT_INDEX]->pBufferQueue;
515     QueueType* pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue;
516     ComponentPortType*  pOutPort = ipPorts[OMX_PORT_OUTPUTPORT_INDEX];
517     OMX_COMPONENTTYPE  *pHandle = &iOmxComponent;
518 
519     OMX_U8*                 pOutBuffer;
520     OMX_U32                 OutputLength;
521     OMX_U8*                 pTempInBuffer;
522     OMX_U32                 TempInLength;
523     OMX_BOOL                DecodeReturn;
524     OMX_BOOL                MarkerFlag = OMX_FALSE;
525     OMX_BOOL                ResizeNeeded = OMX_FALSE;
526 
527     OMX_U32 TempInputBufferSize = (2 * sizeof(uint8) * (ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize));
528 
529     OMX_U32 CurrWidth =  ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameWidth;
530     OMX_U32 CurrHeight = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameHeight;
531 
532     if ((!iIsInputBufferEnded) || iEndofStream)
533     {
534         //Check whether a new output buffer is available or not
535         if (0 == (GetQueueNumElem(pOutputQueue)))
536         {
537             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker OUT output buffer unavailable"));
538             //Store the mark data for output buffer, as it will be overwritten next time
539             if (NULL != ipTargetComponent)
540             {
541                 ipTempTargetComponent = ipTargetComponent;
542                 iTempTargetMarkData = iTargetMarkData;
543                 iMarkPropagate = OMX_TRUE;
544             }
545             return;
546         }
547 
548         ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue);
549         if (NULL == ipOutputBuffer)
550         {
551             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker Error, output buffer dequeue returned NULL, OUT"));
552             return;
553         }
554 
555         //Do not proceed if the output buffer can't fit the YUV data
556         if ((ipOutputBuffer->nAllocLen < (OMX_U32)((((CurrWidth + 15) >> 4) << 4) *(((CurrHeight + 15) >> 4) << 4) * 3 / 2)) && (OMX_TRUE == ipMpegDecoderObject->Mpeg4InitCompleteFlag))
557         {
558             ipOutputBuffer->nFilledLen = 0;
559             ReturnOutputBuffer(ipOutputBuffer, pOutPort);
560             ipOutputBuffer = NULL;
561             return;
562         }
563 
564         ipOutputBuffer->nFilledLen = 0;
565 
566 
567         /* Code for the marking buffer. Takes care of the OMX_CommandMarkBuffer
568          * command and hMarkTargetComponent as given by the specifications
569          */
570         if (ipMark != NULL)
571         {
572             ipOutputBuffer->hMarkTargetComponent = ipMark->hMarkTargetComponent;
573             ipOutputBuffer->pMarkData = ipMark->pMarkData;
574             ipMark = NULL;
575         }
576 
577         if ((OMX_TRUE == iMarkPropagate) && (ipTempTargetComponent != ipTargetComponent))
578         {
579             ipOutputBuffer->hMarkTargetComponent = ipTempTargetComponent;
580             ipOutputBuffer->pMarkData = iTempTargetMarkData;
581             ipTempTargetComponent = NULL;
582             iMarkPropagate = OMX_FALSE;
583         }
584         else if (ipTargetComponent != NULL)
585         {
586             ipOutputBuffer->hMarkTargetComponent = ipTargetComponent;
587             ipOutputBuffer->pMarkData = iTargetMarkData;
588             ipTargetComponent = NULL;
589             iMarkPropagate = OMX_FALSE;
590 
591         }
592         //Mark buffer code ends here
593 
594         pOutBuffer = ipOutputBuffer->pBuffer;
595         OutputLength = 0;
596 
597         pTempInBuffer = ipTempInputBuffer + iTempConsumedLength;
598         TempInLength = iTempInputBufferLength;
599 
600         //Output buffer is passed as a short pointer
601         DecodeReturn = ipMpegDecoderObject->Mp4DecodeVideo(pOutBuffer, (OMX_U32*) & OutputLength,
602                        &(pTempInBuffer),
603                        &TempInLength,
604                        &(ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam),
605                        &iFrameCount,
606                        MarkerFlag,
607                        &ResizeNeeded);
608 
609         ipOutputBuffer->nFilledLen = OutputLength;
610 
611         //offset not required in our case, set it to zero
612         ipOutputBuffer->nOffset = 0;
613 
614         //If decoder returned error, report it to the client via a callback
615         if (!DecodeReturn && OMX_FALSE == ipMpegDecoderObject->Mpeg4InitCompleteFlag)
616         {
617             // initialization error, stop playback
618             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker ErrorBadParameter callback send"));
619 
620             (*(ipCallbacks->EventHandler))
621             (pHandle,
622              iCallbackData,
623              OMX_EventError,
624              OMX_ErrorBadParameter,
625              0,
626              NULL);
627         }
628         else if (!DecodeReturn && OMX_FALSE == iEndofStream)
629         {
630             // decoding error
631             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker ErrorStreamCorrupt callback send"));
632 
633             (*(ipCallbacks->EventHandler))
634             (pHandle,
635              iCallbackData,
636              OMX_EventError,
637              OMX_ErrorStreamCorrupt,
638              0,
639              NULL);
640         }
641 
642 
643         if (ResizeNeeded == OMX_TRUE)
644         {
645             // send port settings changed event
646             OMX_COMPONENTTYPE* pHandle = (OMX_COMPONENTTYPE*) ipAppPriv->CompHandle;
647 
648             // set the flag to disable further processing until Client reacts to this
649             //  by doing dynamic port reconfiguration
650             iResizePending = OMX_TRUE;
651 
652             (*(ipCallbacks->EventHandler))
653             (pHandle,
654              iCallbackData,
655              OMX_EventPortSettingsChanged, //The command was completed
656              OMX_PORT_OUTPUTPORT_INDEX,
657              0,
658              NULL);
659 
660         }
661         //Set the timestamp equal to the input buffer timestamp
662         ipOutputBuffer->nTimeStamp = iFrameTimestamp;
663 
664         iTempConsumedLength += (iTempInputBufferLength - TempInLength);
665         iTempInputBufferLength = TempInLength;
666 
667         //Do not decode if big buffer is less than half the size
668         if (TempInLength < (TempInputBufferSize >> 1))
669         {
670             iIsInputBufferEnded = OMX_TRUE;
671             iNewInBufferRequired = OMX_TRUE;
672         }
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) || (!DecodeReturn))
681             {
682                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : 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                 ReturnOutputBuffer(ipOutputBuffer, pOutPort);
697                 ipOutputBuffer = NULL;
698 
699                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker OUT"));
700 
701                 return;
702             }
703         }
704 
705         //Send the output buffer back after decode
706         ReturnOutputBuffer(ipOutputBuffer, pOutPort);
707         ipOutputBuffer = NULL;
708 
709         /* If there is some more processing left with current buffers, re-schedule the AO
710          * Do not go for more than one round of processing at a time.
711          * This may block the AO longer than required.
712          */
713         if ((TempInLength != 0 || GetQueueNumElem(pInputQueue) > 0) && (GetQueueNumElem(pOutputQueue) > 0) && (ResizeNeeded == OMX_FALSE))
714         {
715             RunIfNotReady();
716         }
717     }
718 
719     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker OUT"));
720     return;
721 }
722 
723 
DecodeWithMarker()724 void OpenmaxMpeg4AO::DecodeWithMarker()
725 {
726     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithMarker IN"));
727 
728     QueueType* pInputQueue = ipPorts[OMX_PORT_INPUTPORT_INDEX]->pBufferQueue;
729     QueueType* pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue;
730 
731     ComponentPortType*  pInPort = ipPorts[OMX_PORT_INPUTPORT_INDEX];
732     ComponentPortType*  pOutPort = ipPorts[OMX_PORT_OUTPUTPORT_INDEX];
733 
734     OMX_U8*                 pOutBuffer;
735     OMX_U32                 OutputLength;
736     OMX_BOOL                DecodeReturn = OMX_FALSE;
737     OMX_BOOL                MarkerFlag = OMX_TRUE;
738     OMX_COMPONENTTYPE *     pHandle = &iOmxComponent;
739     OMX_BOOL                ResizeNeeded = OMX_FALSE;
740 
741     OMX_U32 CurrWidth =  ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameWidth;
742     OMX_U32 CurrHeight = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameHeight;
743 
744     if ((!iIsInputBufferEnded) || (iEndofStream))
745     {
746         //Check whether a new output buffer is available or not
747         if (0 == (GetQueueNumElem(pOutputQueue)))
748         {
749             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithMarker OUT output buffer unavailable"));
750             iNewInBufferRequired = OMX_FALSE;
751             return;
752         }
753 
754         ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue);
755         if (NULL == ipOutputBuffer)
756         {
757             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithMarker Error, output buffer dequeue returned NULL, OUT"));
758             iNewInBufferRequired = OMX_FALSE;
759             return;
760         }
761 
762         //Do not proceed if the output buffer can't fit the YUV data
763         if ((ipOutputBuffer->nAllocLen < (OMX_U32)((((CurrWidth + 15) >> 4) << 4) *(((CurrHeight + 15) >> 4) << 4) * 3 / 2)) && (OMX_TRUE == ipMpegDecoderObject->Mpeg4InitCompleteFlag))
764         {
765             ipOutputBuffer->nFilledLen = 0;
766             ReturnOutputBuffer(ipOutputBuffer, pOutPort);
767             ipOutputBuffer = NULL;
768             return;
769         }
770         ipOutputBuffer->nFilledLen = 0;
771 
772         /* Code for the marking buffer. Takes care of the OMX_CommandMarkBuffer
773          * command and hMarkTargetComponent as given by the specifications
774          */
775         if (ipMark != NULL)
776         {
777             ipOutputBuffer->hMarkTargetComponent = ipMark->hMarkTargetComponent;
778             ipOutputBuffer->pMarkData = ipMark->pMarkData;
779             ipMark = NULL;
780         }
781 
782         if (ipTargetComponent != NULL)
783         {
784             ipOutputBuffer->hMarkTargetComponent = ipTargetComponent;
785             ipOutputBuffer->pMarkData = iTargetMarkData;
786             ipTargetComponent = NULL;
787 
788         }
789         //Mark buffer code ends here
790 
791         if (iInputCurrLength > 0)
792         {
793             pOutBuffer = ipOutputBuffer->pBuffer;
794             OutputLength = 0;
795 
796             //Output buffer is passed as a short pointer
797             DecodeReturn = ipMpegDecoderObject->Mp4DecodeVideo(pOutBuffer, (OMX_U32*) & OutputLength,
798                            &(ipFrameDecodeBuffer),
799                            &(iInputCurrLength),
800                            &(ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam),
801                            &iFrameCount,
802                            MarkerFlag,
803                            &ResizeNeeded);
804 
805             ipOutputBuffer->nFilledLen = OutputLength;
806             //offset not required in our case, set it to zero
807             ipOutputBuffer->nOffset = 0;
808 
809             //If decoder returned error, report it to the client via a callback
810             if (!DecodeReturn && OMX_FALSE == ipMpegDecoderObject->Mpeg4InitCompleteFlag)
811             {
812                 // initialization error, stop playback
813                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker ErrorBadParameter callback send"));
814 
815                 (*(ipCallbacks->EventHandler))
816                 (pHandle,
817                  iCallbackData,
818                  OMX_EventError,
819                  OMX_ErrorBadParameter,
820                  0,
821                  NULL);
822             }
823             else if (!DecodeReturn && OMX_FALSE == iEndofStream)
824             {
825                 // decode error
826                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithMarker ErrorStreamCorrupt callback send"));
827 
828                 (*(ipCallbacks->EventHandler))
829                 (pHandle,
830                  iCallbackData,
831                  OMX_EventError,
832                  OMX_ErrorStreamCorrupt,
833                  0,
834                  NULL);
835             }
836 
837             if (ResizeNeeded == OMX_TRUE)
838             {
839                 // send port settings changed event
840                 OMX_COMPONENTTYPE* pHandle = (OMX_COMPONENTTYPE*) ipAppPriv->CompHandle;
841 
842                 iResizePending = OMX_TRUE;
843                 (*(ipCallbacks->EventHandler))
844                 (pHandle,
845                  iCallbackData,
846                  OMX_EventPortSettingsChanged, //The command was completed
847                  OMX_PORT_OUTPUTPORT_INDEX,
848                  0,
849                  NULL);
850 
851             }
852             //Set the timestamp equal to the input buffer timestamp
853             if (OMX_TRUE == iUseExtTimestamp)
854             {
855                 ipOutputBuffer->nTimeStamp = iFrameTimestamp;
856             }
857 
858             /* Discard the input frame if it is with the marker bit & decoder fails*/
859             if (iInputCurrLength == 0 || !DecodeReturn)
860             {
861                 ipInputBuffer->nFilledLen = 0;
862                 ReturnInputBuffer(ipInputBuffer, pInPort);
863                 ipInputBuffer = NULL;
864                 iNewInBufferRequired = OMX_TRUE;
865                 iIsInputBufferEnded = OMX_TRUE;
866                 iUseExtTimestamp = OMX_TRUE;
867                 iInputCurrLength = 0;
868             }
869             else
870             {
871                 iNewInBufferRequired = OMX_FALSE;
872                 iIsInputBufferEnded = OMX_FALSE;
873                 iUseExtTimestamp = OMX_FALSE;
874             }
875         }
876         else if (iEndofStream == OMX_FALSE)
877         {
878             // it's possible that after partial frame assembly, the input buffer still remains empty (due to
879             // client erroneously sending such buffers). This code adds robustness in the sense that it returns such buffer to the client
880 
881             ipInputBuffer->nFilledLen = 0;
882             ReturnInputBuffer(ipInputBuffer, pInPort);
883             ipInputBuffer = NULL;
884             iNewInBufferRequired = OMX_TRUE;
885             iIsInputBufferEnded = OMX_TRUE;
886             iUseExtTimestamp = OMX_TRUE;
887         }
888 
889 
890 
891 
892         /* If EOS flag has come from the client & there are no more
893          * input buffers to decode, send the callback to the client
894          */
895         if (OMX_TRUE == iEndofStream)
896         {
897             if (!DecodeReturn)
898             {
899                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithMarker EOS callback send"));
900 
901                 (*(ipCallbacks->EventHandler))
902                 (pHandle,
903                  iCallbackData,
904                  OMX_EventBufferFlag,
905                  1,
906                  OMX_BUFFERFLAG_EOS,
907                  NULL);
908 
909                 iNewInBufferRequired = OMX_TRUE;
910                 //Mark this flag false once the callback has been send back
911                 iEndofStream = OMX_FALSE;
912 
913                 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_EOS;
914                 ReturnOutputBuffer(ipOutputBuffer, pOutPort);
915                 ipOutputBuffer = NULL;
916 
917                 if ((iNumInputBuffer != 0) && (NULL != ipInputBuffer))
918                 {
919                     ReturnInputBuffer(ipInputBuffer, pInPort);
920                     ipInputBuffer = NULL;
921                     iIsInputBufferEnded = OMX_TRUE;
922                     iInputCurrLength = 0;
923                 }
924 
925                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithMarker OUT"));
926                 return;
927             }
928 
929         }
930 
931         //Send the output buffer back after decode
932         ReturnOutputBuffer(ipOutputBuffer, pOutPort);
933         ipOutputBuffer = NULL;
934 
935 
936         /* If there is some more processing left with current buffers, re-schedule the AO
937          * Do not go for more than one round of processing at a time.
938          * This may block the AO longer than required.
939          */
940         if ((iInputCurrLength != 0 || GetQueueNumElem(pInputQueue) > 0)
941                 && (GetQueueNumElem(pOutputQueue) > 0) && (ResizeNeeded == OMX_FALSE))
942         {
943             RunIfNotReady();
944         }
945     }
946 
947     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithMarker OUT"));
948     return;
949 }
950 
951 
952 //Not implemented & supported in case of base profile components
953 
ComponentGetRolesOfComponent(OMX_STRING * aRoleString)954 void OpenmaxMpeg4AO::ComponentGetRolesOfComponent(OMX_STRING* aRoleString)
955 {
956     *aRoleString = (OMX_STRING)"video_decoder.mpeg4";
957 }
958 
959 
960 //Component constructor
OpenmaxMpeg4AO()961 OpenmaxMpeg4AO::OpenmaxMpeg4AO()
962 {
963     iUseExtTimestamp = OMX_TRUE;
964     ipMpegDecoderObject = NULL;
965 
966     if (!IsAdded())
967     {
968         AddToScheduler();
969     }
970 
971     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : constructed"));
972 }
973 
974 
975 //Active object destructor
~OpenmaxMpeg4AO()976 OpenmaxMpeg4AO::~OpenmaxMpeg4AO()
977 {
978     if (IsAdded())
979     {
980         RemoveFromScheduler();
981     }
982 
983     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : destructed"));
984 }
985 
986 
987 /** The Initialization function
988  */
ComponentInit()989 OMX_ERRORTYPE OpenmaxMpeg4AO::ComponentInit()
990 {
991     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : ComponentInit IN"));
992 
993     OMX_ERRORTYPE Status = OMX_ErrorNone;
994 
995     if (OMX_TRUE == iIsInit)
996     {
997         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : ComponentInit error incorrect operation"));
998         return OMX_ErrorIncorrectStateOperation;
999     }
1000     iIsInit = OMX_TRUE;
1001 
1002 
1003     if (!iCodecReady)
1004     {
1005         //Call the init routine here in case of H263 mode, without waiting for buffers
1006 
1007         if (iDecMode == MODE_H263)
1008         {
1009             OMX_S32 Width, Height, Size = 0;
1010             OMX_U8* Buff = NULL;
1011 
1012             //Pass dummy pointers during initializations
1013             if (OMX_TRUE != ipMpegDecoderObject->InitializeVideoDecode(&Width, &Height, &Buff, &Size, iDecMode))
1014             {
1015                 Status = OMX_ErrorInsufficientResources;
1016             }
1017 
1018             ipMpegDecoderObject->Mpeg4InitCompleteFlag = OMX_TRUE;
1019         }
1020         else
1021         {
1022             //mp4 lib init
1023             Status = ipMpegDecoderObject->Mp4DecInit();
1024         }
1025 
1026         iCodecReady = OMX_TRUE;
1027     }
1028 
1029     iUseExtTimestamp = OMX_TRUE;
1030     iInputCurrLength = 0;
1031 
1032     //Used in dynamic port reconfiguration
1033     iFrameCount = 0;
1034     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : ComponentInit OUT"));
1035 
1036     return Status;
1037 
1038 }
1039 
1040 /** This function is called upon a transition to the idle or invalid state.
1041  *  Also it is called by the ComponentDestructor() function
1042  */
ComponentDeInit()1043 OMX_ERRORTYPE OpenmaxMpeg4AO::ComponentDeInit()
1044 {
1045     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : ComponentDeInit IN"));
1046 
1047     OMX_ERRORTYPE Status = OMX_ErrorNone;
1048 
1049     iIsInit = OMX_FALSE;
1050 
1051     if (iCodecReady)
1052     {
1053         Status = ipMpegDecoderObject->Mp4DecDeinit();
1054         iCodecReady = OMX_FALSE;
1055     }
1056 
1057     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : ComponentDeInit OUT"));
1058 
1059     return Status;
1060 
1061 }
1062 
GetConfig(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_INDEXTYPE nIndex,OMX_INOUT OMX_PTR pComponentConfigStructure)1063 OMX_ERRORTYPE OpenmaxMpeg4AO::GetConfig(
1064     OMX_IN  OMX_HANDLETYPE hComponent,
1065     OMX_IN  OMX_INDEXTYPE nIndex,
1066     OMX_INOUT OMX_PTR pComponentConfigStructure)
1067 {
1068     OSCL_UNUSED_ARG(hComponent);
1069     OSCL_UNUSED_ARG(nIndex);
1070     OSCL_UNUSED_ARG(pComponentConfigStructure);
1071     return OMX_ErrorNotImplemented;
1072 }
1073 
1074 
ReAllocatePartialAssemblyBuffers(OMX_BUFFERHEADERTYPE * aInputBufferHdr)1075 OMX_ERRORTYPE OpenmaxMpeg4AO::ReAllocatePartialAssemblyBuffers(OMX_BUFFERHEADERTYPE* aInputBufferHdr)
1076 {
1077 
1078     // check if there is enough data in the buffer to read the information that we need
1079     if (aInputBufferHdr->nFilledLen >= MINIMUM_H263_SHORT_HEADER_SIZE)
1080     {
1081         OMX_U8 *pInputBuffer = (aInputBufferHdr->pBuffer + aInputBufferHdr->nOffset);
1082 
1083         if (MODE_H263 == iDecMode)
1084         {
1085             OMX_BOOL Status = OMX_TRUE;
1086 
1087             Status = DecodeH263Header(pInputBuffer, &iInputCurrBufferSize);
1088 
1089             // Re-allocate the partial frame buffer in case the stream is not corrupted,
1090             // otherwise leave the buffer size as it is
1091             if (OMX_TRUE == Status)
1092             {
1093                 if (NULL != ipInputCurrBuffer)
1094                 {
1095                     ipInputCurrBuffer = (OMX_U8*) oscl_realloc(ipInputCurrBuffer, iInputCurrBufferSize);
1096                     if (NULL == ipInputCurrBuffer)
1097                     {
1098                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentBase : DoStateSet error insufficient resources"));
1099                         return OMX_ErrorInsufficientResources;
1100                     }
1101                 }
1102 
1103                 //Used when the buffers are not marked with EndOfFrame flag
1104                 if (NULL != ipTempInputBuffer)
1105                 {
1106                     ipTempInputBuffer = (OMX_U8*) oscl_realloc(ipTempInputBuffer, iInputCurrBufferSize);
1107                     if (NULL == ipTempInputBuffer)
1108                     {
1109                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentBase : DoStateSet error insufficient resources"));
1110                         return OMX_ErrorInsufficientResources;
1111                     }
1112                 }
1113             }
1114         }
1115 
1116         return OMX_ErrorNone;
1117     }
1118     else
1119     {
1120         return OMX_ErrorInsufficientResources;
1121     }
1122 
1123 }
1124 
DecodeH263Header(OMX_U8 * aInputBuffer,OMX_U32 * aBufferSize)1125 OMX_BOOL OpenmaxMpeg4AO::DecodeH263Header(OMX_U8* aInputBuffer,
1126         OMX_U32* aBufferSize)
1127 {
1128     uint32 codeword;
1129     int32   extended_PTYPE = 0;
1130     int32 UFEP = 0;
1131     int32 custom_PFMT = 0;
1132 
1133     //Reset the data bit position to the start of the stream
1134     iH263DataBitPos = 0;
1135     iH263BitPos = 0;
1136     //BitBuf contains the first 4 bytes of the aInputBuffer
1137     iH263BitBuf = (aInputBuffer[0] << 24) | (aInputBuffer[1] << 16) | (aInputBuffer[2] << 8) | aInputBuffer[3];
1138 
1139     ReadBits(aInputBuffer, 22, &codeword);
1140     if (codeword !=  0x20)
1141     {
1142         return OMX_FALSE;
1143     }
1144 
1145     ReadBits(aInputBuffer, 8, &codeword);
1146 
1147     ReadBits(aInputBuffer, 1, &codeword);
1148     if (codeword == 0) return OMX_FALSE;
1149 
1150     ReadBits(aInputBuffer, 1, &codeword);
1151     if (codeword == 1) return OMX_FALSE;
1152 
1153     ReadBits(aInputBuffer, 1, &codeword);
1154     if (codeword == 1) return OMX_FALSE;
1155 
1156     ReadBits(aInputBuffer, 1, &codeword);
1157     if (codeword == 1) return OMX_FALSE;
1158 
1159     ReadBits(aInputBuffer, 1, &codeword);
1160     if (codeword == 1) return OMX_FALSE;
1161 
1162     /* source format */
1163     ReadBits(aInputBuffer, 3, &codeword);
1164     switch (codeword)
1165     {
1166         case 1:
1167             *aBufferSize = 32000;
1168             break;
1169 
1170         case 2:
1171             *aBufferSize = 32000;
1172             break;
1173 
1174         case 3:
1175             *aBufferSize = 128000;
1176             break;
1177 
1178         case 4:
1179             *aBufferSize = 256000;
1180             break;
1181 
1182         case 5:
1183             *aBufferSize = 512000;
1184             break;
1185 
1186         case 7:
1187             extended_PTYPE = 1;
1188             break;
1189         default:
1190             /* Msg("H.263 source format not legal\n"); */
1191             return OMX_FALSE;
1192     }
1193 
1194     if (extended_PTYPE == 0)
1195     {
1196         return OMX_TRUE;
1197     }
1198 
1199     /* source format */
1200     ReadBits(aInputBuffer, 3, &codeword);
1201     UFEP = codeword;
1202     if (UFEP == 1)
1203     {
1204         ReadBits(aInputBuffer, 3, &codeword);
1205         switch (codeword)
1206         {
1207             case 1:
1208                 *aBufferSize = 32000;
1209                 break;
1210 
1211             case 2:
1212                 *aBufferSize = 32000;
1213                 break;
1214 
1215             case 3:
1216                 *aBufferSize = 128000;
1217                 break;
1218 
1219             case 4:
1220                 *aBufferSize = 256000;
1221                 break;
1222 
1223             case 5:
1224                 *aBufferSize = 512000;
1225                 break;
1226 
1227             case 6:
1228                 custom_PFMT = 1;
1229                 break;
1230             default:
1231                 /* Msg("H.263 source format not legal\n"); */
1232                 return OMX_FALSE;
1233         }
1234         if (custom_PFMT == 0)
1235         {
1236             return OMX_TRUE;
1237         }
1238 
1239 
1240         ReadBits(aInputBuffer, 1, &codeword);
1241         ReadBits(aInputBuffer, 1, &codeword);
1242         if (codeword) return OMX_FALSE;
1243         ReadBits(aInputBuffer, 1, &codeword);
1244         if (codeword) return OMX_FALSE;
1245         ReadBits(aInputBuffer, 1, &codeword);
1246         if (codeword) return OMX_FALSE;
1247         ReadBits(aInputBuffer, 3, &codeword);
1248         ReadBits(aInputBuffer, 3, &codeword);
1249         if (codeword) return OMX_FALSE;             /* RPS, ISD, AIV */
1250         ReadBits(aInputBuffer, 1, &codeword);
1251         ReadBits(aInputBuffer, 4, &codeword);
1252         if (codeword != 8) return OMX_FALSE;
1253     }
1254 
1255     if (UFEP == 0 || UFEP == 1)
1256     {
1257         ReadBits(aInputBuffer, 3, &codeword);
1258         if (codeword > 1) return OMX_FALSE;
1259         ReadBits(aInputBuffer, 1, &codeword);
1260         if (codeword) return OMX_FALSE;
1261         ReadBits(aInputBuffer, 1, &codeword);
1262         if (codeword) return OMX_FALSE;
1263         ReadBits(aInputBuffer, 1, &codeword);
1264         ReadBits(aInputBuffer, 3, &codeword);
1265         if (codeword != 1) return OMX_FALSE;
1266     }
1267     else
1268     {
1269         return OMX_FALSE;
1270     }
1271 
1272     ReadBits(aInputBuffer, 1, &codeword);
1273     if (codeword) return OMX_FALSE; /* CPM */
1274     if (custom_PFMT == 1 && UFEP == 1)
1275     {
1276         OMX_U32 DisplayWidth, Width, DisplayHeight, Height, Resolution;
1277 
1278         ReadBits(aInputBuffer, 4, &codeword);
1279         if (codeword == 0) return OMX_FALSE;
1280         if (codeword == 0xf)
1281         {
1282             ReadBits(aInputBuffer, 8, &codeword);
1283             ReadBits(aInputBuffer, 8, &codeword);
1284         }
1285         ReadBits(aInputBuffer, 9, &codeword);
1286         DisplayWidth = (codeword + 1) << 2;
1287         Width = (DisplayWidth + 15) & -16;
1288 
1289         ReadBits(aInputBuffer, 1, &codeword);
1290         if (codeword != 1) return OMX_FALSE;
1291         ReadBits(aInputBuffer, 9, &codeword);
1292         if (codeword == 0) return OMX_FALSE;
1293         DisplayHeight = codeword << 2;
1294         Height = (DisplayHeight + 15) & -16;
1295 
1296         Resolution = Width * Height;
1297 
1298         if (Resolution <= 25344)        //25344 = 176x144 (QCIF)
1299         {
1300             *aBufferSize = 32000;
1301         }
1302         else if (Resolution <= 101376)  //101376 = 352x288 (CIF)
1303         {
1304             *aBufferSize = 128000;
1305         }
1306         else if (Resolution <= 405504)  //405504 = 704*576 (4CIF)
1307         {
1308             *aBufferSize = 256000;
1309         }
1310         else                            //1408x1152 (16CIF)
1311         {
1312             //This is the max buffer size that we want to allocate
1313             *aBufferSize = 512000;
1314         }
1315     }
1316 
1317     return OMX_TRUE;
1318 }
1319 
1320 
ReadBits(OMX_U8 * aStream,uint8 aNumBits,uint32 * aOutData)1321 void OpenmaxMpeg4AO::ReadBits(OMX_U8* aStream,           /* Input Stream */
1322                               uint8 aNumBits,                     /* nr of bits to read */
1323                               uint32* aOutData                 /* output target */
1324                              )
1325 {
1326     uint8 *bits;
1327     uint32 dataBitPos = iH263DataBitPos;
1328     uint32 bitPos = iH263BitPos;
1329     uint32 dataBytePos;
1330 
1331     if (aNumBits > (32 - bitPos))    /* not enough bits */
1332     {
1333         dataBytePos = dataBitPos >> 3;    /* Byte Aligned Position */
1334         bitPos = dataBitPos & 7; /* update bit position */
1335         bits = &aStream[dataBytePos];
1336         iH263BitBuf = (bits[0] << 24) | (bits[1] << 16) | (bits[2] << 8) | bits[3];
1337     }
1338 
1339     iH263DataBitPos += aNumBits;
1340     iH263BitPos      = (unsigned char)(bitPos + aNumBits);
1341 
1342     *aOutData = (iH263BitBuf >> (32 - iH263BitPos)) & mask[(uint16)aNumBits];
1343 
1344     return;
1345 }
1346 
1347