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