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