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