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