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