• 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_mp3_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 
OSCL_DLL_ENTRY_POINT_DEFAULT()33 OSCL_DLL_ENTRY_POINT_DEFAULT()
34 
35 // This function is called by OMX_GetHandle and it creates an instance of the mp3 component AO
36 OSCL_EXPORT_REF OMX_ERRORTYPE Mp3OmxComponentFactory(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)
37 {
38     OSCL_UNUSED_ARG(aOmxLibName);
39     OSCL_UNUSED_ARG(aOmxLib);
40     OSCL_UNUSED_ARG(aOsclUuid);
41     OSCL_UNUSED_ARG(aRefCount);
42 
43     OpenmaxMp3AO* pOpenmaxAOType;
44     OMX_ERRORTYPE Status;
45 
46     // move InitMp3OmxComponentFields content to actual constructor
47 
48     pOpenmaxAOType = (OpenmaxMp3AO*) OSCL_NEW(OpenmaxMp3AO, ());
49 
50     if (NULL == pOpenmaxAOType)
51     {
52         return OMX_ErrorInsufficientResources;
53     }
54 
55     //Call the construct component to initialize OMX types
56     Status = pOpenmaxAOType->ConstructComponent(pAppData, pProxy);
57 
58     *pHandle = pOpenmaxAOType->GetOmxHandle();
59 
60     return Status;
61     ///////////////////////////////////////////////////////////////////////////////////////
62 }
63 
64 // This function is called by OMX_FreeHandle when component AO needs to be destroyed
Mp3OmxComponentDestructor(OMX_IN OMX_HANDLETYPE pHandle,OMX_PTR & aOmxLib,OMX_PTR aOsclUuid,OMX_U32 & aRefCount)65 OSCL_EXPORT_REF OMX_ERRORTYPE Mp3OmxComponentDestructor(OMX_IN OMX_HANDLETYPE pHandle, OMX_PTR &aOmxLib, OMX_PTR aOsclUuid, OMX_U32 &aRefCount)
66 {
67     OSCL_UNUSED_ARG(aOmxLib);
68     OSCL_UNUSED_ARG(aOsclUuid);
69     OSCL_UNUSED_ARG(aRefCount);
70 
71     // get pointer to component AO
72     OpenmaxMp3AO* pOpenmaxAOType = (OpenmaxMp3AO*)((OMX_COMPONENTTYPE*)pHandle)->pComponentPrivate;
73 
74     // clean up decoder, OMX component stuff
75     pOpenmaxAOType->DestroyComponent();
76 
77     // destroy the AO class
78     OSCL_DELETE(pOpenmaxAOType);
79 
80     return OMX_ErrorNone;
81 }
82 #if DYNAMIC_LOAD_OMX_MP3_COMPONENT
83 class Mp3OmxSharedLibraryInterface: public OsclSharedLibraryInterface,
84         public OmxSharedLibraryInterface
85 {
86     public:
QueryOmxComponentInterface(const OsclUuid & aOmxTypeId,const OsclUuid & aInterfaceId)87         OsclAny *QueryOmxComponentInterface(const OsclUuid& aOmxTypeId, const OsclUuid& aInterfaceId)
88         {
89             if (PV_OMX_MP3DEC_UUID == aOmxTypeId)
90             {
91                 if (PV_OMX_CREATE_INTERFACE == aInterfaceId)
92                 {
93                     return ((OsclAny*)(&Mp3OmxComponentFactory));
94                 }
95                 else if (PV_OMX_DESTROY_INTERFACE == aInterfaceId)
96                 {
97                     return ((OsclAny*)(&Mp3OmxComponentDestructor));
98                 }
99             }
100             return NULL;
101         };
SharedLibraryLookup(const OsclUuid & aInterfaceId)102         OsclAny *SharedLibraryLookup(const OsclUuid& aInterfaceId)
103         {
104             if (aInterfaceId == PV_OMX_SHARED_INTERFACE)
105             {
106                 return OSCL_STATIC_CAST(OmxSharedLibraryInterface*, this);
107             }
108             return NULL;
109         };
110 
Mp3OmxSharedLibraryInterface()111         Mp3OmxSharedLibraryInterface() {};
112 };
113 
114 // function to obtain the interface object from the shared library
115 extern "C"
116 {
PVGetInterface()117     OSCL_EXPORT_REF OsclAny* PVGetInterface()
118     {
119         return (OsclAny*) OSCL_NEW(Mp3OmxSharedLibraryInterface, ());
120     }
121 
PVReleaseInterface(OsclSharedLibraryInterface * aInstance)122     OSCL_EXPORT_REF void PVReleaseInterface(OsclSharedLibraryInterface* aInstance)
123     {
124         Mp3OmxSharedLibraryInterface* module = (Mp3OmxSharedLibraryInterface*)aInstance;
125         OSCL_DELETE(module);
126     }
127 }
128 
129 #endif
130 
131 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
132 
ConstructComponent(OMX_PTR pAppData,OMX_PTR pProxy)133 OMX_ERRORTYPE OpenmaxMp3AO::ConstructComponent(OMX_PTR pAppData, OMX_PTR pProxy)
134 {
135     ComponentPortType* pInPort, *pOutPort;
136     OMX_ERRORTYPE Status;
137 
138     iNumPorts = 2;
139     iOmxComponent.nSize = sizeof(OMX_COMPONENTTYPE);
140     iOmxComponent.pComponentPrivate = (OMX_PTR) this;  // pComponentPrivate points to THIS component AO class
141     iOmxComponent.pApplicationPrivate = pAppData; // init the App data
142 
143     ipComponentProxy = pProxy;
144 
145 
146 #if PROXY_INTERFACE
147     iPVCapabilityFlags.iIsOMXComponentMultiThreaded = OMX_TRUE;
148 
149     iOmxComponent.SendCommand = OpenmaxMp3AO::BaseComponentProxySendCommand;
150     iOmxComponent.GetParameter = OpenmaxMp3AO::BaseComponentProxyGetParameter;
151     iOmxComponent.SetParameter = OpenmaxMp3AO::BaseComponentProxySetParameter;
152     iOmxComponent.GetConfig = OpenmaxMp3AO::BaseComponentProxyGetConfig;
153     iOmxComponent.SetConfig = OpenmaxMp3AO::BaseComponentProxySetConfig;
154     iOmxComponent.GetExtensionIndex = OpenmaxMp3AO::BaseComponentProxyGetExtensionIndex;
155     iOmxComponent.GetState = OpenmaxMp3AO::BaseComponentProxyGetState;
156     iOmxComponent.UseBuffer = OpenmaxMp3AO::BaseComponentProxyUseBuffer;
157     iOmxComponent.AllocateBuffer = OpenmaxMp3AO::BaseComponentProxyAllocateBuffer;
158     iOmxComponent.FreeBuffer = OpenmaxMp3AO::BaseComponentProxyFreeBuffer;
159     iOmxComponent.EmptyThisBuffer = OpenmaxMp3AO::BaseComponentProxyEmptyThisBuffer;
160     iOmxComponent.FillThisBuffer = OpenmaxMp3AO::BaseComponentProxyFillThisBuffer;
161 
162 #else
163     iPVCapabilityFlags.iIsOMXComponentMultiThreaded = OMX_FALSE;
164 
165     iOmxComponent.SendCommand = OpenmaxMp3AO::BaseComponentSendCommand;
166     iOmxComponent.GetParameter = OpenmaxMp3AO::BaseComponentGetParameter;
167     iOmxComponent.SetParameter = OpenmaxMp3AO::BaseComponentSetParameter;
168     iOmxComponent.GetConfig = OpenmaxMp3AO::BaseComponentGetConfig;
169     iOmxComponent.SetConfig = OpenmaxMp3AO::BaseComponentSetConfig;
170     iOmxComponent.GetExtensionIndex = OpenmaxMp3AO::BaseComponentGetExtensionIndex;
171     iOmxComponent.GetState = OpenmaxMp3AO::BaseComponentGetState;
172     iOmxComponent.UseBuffer = OpenmaxMp3AO::BaseComponentUseBuffer;
173     iOmxComponent.AllocateBuffer = OpenmaxMp3AO::BaseComponentAllocateBuffer;
174     iOmxComponent.FreeBuffer = OpenmaxMp3AO::BaseComponentFreeBuffer;
175     iOmxComponent.EmptyThisBuffer = OpenmaxMp3AO::BaseComponentEmptyThisBuffer;
176     iOmxComponent.FillThisBuffer = OpenmaxMp3AO::BaseComponentFillThisBuffer;
177 #endif
178 
179     iOmxComponent.SetCallbacks = OpenmaxMp3AO::BaseComponentSetCallbacks;
180     iOmxComponent.nVersion.s.nVersionMajor = SPECVERSIONMAJOR;
181     iOmxComponent.nVersion.s.nVersionMinor = SPECVERSIONMINOR;
182     iOmxComponent.nVersion.s.nRevision = SPECREVISION;
183     iOmxComponent.nVersion.s.nStep = SPECSTEP;
184 
185     // PV capability
186     iPVCapabilityFlags.iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE;
187     iPVCapabilityFlags.iOMXComponentSupportsExternalOutputBufferAlloc = OMX_TRUE;
188     iPVCapabilityFlags.iOMXComponentSupportsMovableInputBuffers = OMX_TRUE;
189     iPVCapabilityFlags.iOMXComponentSupportsPartialFrames = OMX_TRUE;
190     iPVCapabilityFlags.iOMXComponentUsesNALStartCodes = OMX_FALSE;
191     iPVCapabilityFlags.iOMXComponentCanHandleIncompleteFrames = OMX_TRUE;
192     iPVCapabilityFlags.iOMXComponentUsesFullAVCFrames = OMX_FALSE;
193 
194     if (ipAppPriv)
195     {
196         oscl_free(ipAppPriv);
197         ipAppPriv = NULL;
198     }
199 
200     ipAppPriv = (ComponentPrivateType*) oscl_malloc(sizeof(ComponentPrivateType));
201     if (NULL == ipAppPriv)
202     {
203         return OMX_ErrorInsufficientResources;
204     }
205 
206     //Construct base class now
207     Status = ConstructBaseComponent(pAppData);
208 
209     if (OMX_ErrorNone != Status)
210     {
211         return Status;
212     }
213 
214     /** Domain specific section for the ports. */
215     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_INPUTPORT_INDEX;
216     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainAudio;
217     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.cMIMEType = (OMX_STRING)"audio/mpeg";
218     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.pNativeRender = 0;
219     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.bFlagErrorConcealment = OMX_FALSE;
220     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.eEncoding = OMX_AUDIO_CodingMP3;
221     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.eDir = OMX_DirInput;
222     //Set to a default value, will change later during setparameter call
223     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferCountActual = NUMBER_INPUT_BUFFER_MP3;
224     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferCountMin = 1;
225     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize = INPUT_BUFFER_SIZE_MP3;
226     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE;
227     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE;
228 
229 
230     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX;
231     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainAudio;
232     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.cMIMEType = (OMX_STRING)"raw";
233     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.pNativeRender = 0;
234     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.bFlagErrorConcealment = OMX_FALSE;
235     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
236     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDir = OMX_DirOutput;
237     //Set to a default value, will change later during setparameter call
238     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountActual = NUMBER_OUTPUT_BUFFER_MP3;
239     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountMin = 1;
240     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferSize = OUTPUT_BUFFER_SIZE_MP3 * 6;
241     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE;
242     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE;
243 
244     //Default values for Mp3 audio param port
245     ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioMp3Param.nPortIndex = OMX_PORT_INPUTPORT_INDEX;
246     ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioMp3Param.nChannels = 2;
247     ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioMp3Param.nBitRate = 0;
248     ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioMp3Param.nSampleRate = 44100;
249     ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioMp3Param.nAudioBandWidth = 0;
250     ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioMp3Param.eChannelMode = OMX_AUDIO_ChannelModeStereo;
251     ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioMp3Param.eFormat = OMX_AUDIO_MP3StreamFormatMP1Layer3;
252 
253     ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioEqualizerType.nPortIndex = OMX_PORT_INPUTPORT_INDEX;
254     ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioEqualizerType.sBandIndex.nMin = 0;
255     //Taken these value from from mp3 decoder component
256     ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioEqualizerType.sBandIndex.nValue = (e_equalization) flat;
257     ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioEqualizerType.sBandIndex.nMax = (e_equalization) flat_;
258 
259 
260     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX;
261     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.nChannels = 2;
262     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.eNumData = OMX_NumericalDataSigned;
263     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.bInterleaved = OMX_TRUE;
264     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.nBitPerSample = 16;
265     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.nSamplingRate = 44100;
266     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.ePCMMode = OMX_AUDIO_PCMModeLinear;
267     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
268     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
269 
270     iPortTypesParam.nPorts = 2;
271     iPortTypesParam.nStartPortNumber = 0;
272 
273     pInPort = (ComponentPortType*) ipPorts[OMX_PORT_INPUTPORT_INDEX];
274     pOutPort = (ComponentPortType*) ipPorts[OMX_PORT_OUTPUTPORT_INDEX];
275 
276     SetHeader(&pInPort->AudioParam, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE));
277     pInPort->AudioParam.nPortIndex = 0;
278     pInPort->AudioParam.nIndex = 0;
279     pInPort->AudioParam.eEncoding = OMX_AUDIO_CodingMP3;
280 
281     SetHeader(&pOutPort->AudioParam, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE));
282     pOutPort->AudioParam.nPortIndex = 1;
283     pOutPort->AudioParam.nIndex = 0;
284     pOutPort->AudioParam.eEncoding = OMX_AUDIO_CodingPCM;
285 
286     oscl_strncpy((OMX_STRING)iComponentRole, (OMX_STRING)"audio_decoder.mp3", OMX_MAX_STRINGNAME_SIZE);
287 
288     iOutputFrameLength = OUTPUT_BUFFER_SIZE_MP3;
289 
290     if (ipMp3Dec)
291     {
292         OSCL_DELETE(ipMp3Dec);
293         ipMp3Dec = NULL;
294     }
295 
296     ipMp3Dec = OSCL_NEW(Mp3Decoder, ());
297     if (ipMp3Dec == NULL)
298     {
299         return OMX_ErrorInsufficientResources;
300     }
301 
302     oscl_memset(ipMp3Dec, 0, sizeof(Mp3Decoder));
303 
304     iSamplesPerFrame = DEFAULT_SAMPLES_PER_FRAME_MP3;
305     iOutputMicroSecPerFrame = iCurrentFrameTS.GetFrameDuration();
306 
307 #if PROXY_INTERFACE
308 
309     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSendCommand = BaseComponentSendCommand;
310     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetParameter = BaseComponentGetParameter;
311     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetParameter = BaseComponentSetParameter;
312     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetConfig = BaseComponentGetConfig;
313     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetConfig = BaseComponentSetConfig;
314     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetExtensionIndex = BaseComponentGetExtensionIndex;
315     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetState = BaseComponentGetState;
316     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentUseBuffer = BaseComponentUseBuffer;
317     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentAllocateBuffer = BaseComponentAllocateBuffer;
318     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentFreeBuffer = BaseComponentFreeBuffer;
319     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentEmptyThisBuffer = BaseComponentEmptyThisBuffer;
320     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentFillThisBuffer = BaseComponentFillThisBuffer;
321 
322 #endif
323     return OMX_ErrorNone;
324 }
325 
326 
327 /** This function is called by the omx core when the component
328     * is disposed by the IL client with a call to FreeHandle().
329     */
330 
DestroyComponent()331 OMX_ERRORTYPE OpenmaxMp3AO::DestroyComponent()
332 {
333     if (iIsInit != OMX_FALSE)
334     {
335         ComponentDeInit();
336     }
337 
338     //Destroy the base class now
339     DestroyBaseComponent();
340 
341     if (ipMp3Dec)
342     {
343         OSCL_DELETE(ipMp3Dec);
344         ipMp3Dec = NULL;
345     }
346 
347     if (ipAppPriv)
348     {
349         ipAppPriv->CompHandle = NULL;
350 
351         oscl_free(ipAppPriv);
352         ipAppPriv = NULL;
353     }
354 
355     return OMX_ErrorNone;
356 }
357 
358 
SyncWithInputTimestamp()359 void OpenmaxMp3AO::SyncWithInputTimestamp()
360 {
361     //Do not check for silence insertion if the clip is repositioned
362     if (OMX_FALSE == iRepositionFlag)
363     {
364         CheckForSilenceInsertion();
365     }
366 
367     /* Set the current timestamp equal to input buffer timestamp in case of
368      * a) All input frames
369      * b) First frame after repositioning */
370     if (OMX_FALSE == iSilenceInsertionInProgress || OMX_TRUE == iRepositionFlag)
371     {
372         // Set the current timestamp equal to input buffer timestamp
373         iCurrentFrameTS.SetFromInputTimestamp(iFrameTimestamp);
374 
375         //Reset the flag back to false, once timestamp has been updated from input frame
376         if (OMX_TRUE == iRepositionFlag)
377         {
378             iRepositionFlag = OMX_FALSE;
379         }
380     }
381 }
382 
ResetComponent()383 void OpenmaxMp3AO::ResetComponent()
384 {
385     // reset decoder
386     if (ipMp3Dec)
387     {
388         ipMp3Dec->ResetDecoder();
389         //Set this length to zero for flushing the current input buffer
390         ipMp3Dec->iInputUsedLength = 0;
391         //ipMp3Dec->iInitFlag = 0;
392     }
393 }
394 
395 
ProcessInBufferFlag()396 void OpenmaxMp3AO::ProcessInBufferFlag()
397 {
398     iIsInputBufferEnded = OMX_FALSE;
399 }
400 
401 
ProcessData()402 void OpenmaxMp3AO::ProcessData()
403 {
404     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : ProcessData IN"));
405 
406     QueueType* pInputQueue  = ipPorts[OMX_PORT_INPUTPORT_INDEX]->pBufferQueue;
407     QueueType* pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue;
408 
409     ComponentPortType* pInPort = (ComponentPortType*) ipPorts[OMX_PORT_INPUTPORT_INDEX];
410     ComponentPortType* pOutPort = ipPorts[OMX_PORT_OUTPUTPORT_INDEX];
411     OMX_COMPONENTTYPE* pHandle = &iOmxComponent;
412 
413     OMX_U8* pOutBuffer;
414     OMX_U32 OutputLength;
415     OMX_S32 DecodeReturn;
416     OMX_BOOL ResizeNeeded = OMX_FALSE;
417 
418     OMX_U32 TempInputBufferSize = (2 * sizeof(uint8) * (ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize));
419 
420     if ((!iIsInputBufferEnded) || iEndofStream)
421     {
422         if (OMX_TRUE == iSilenceInsertionInProgress)
423         {
424             DoSilenceInsertion();
425             //If the flag is still true, come back to this routine again
426             if (OMX_TRUE == iSilenceInsertionInProgress)
427             {
428                 return;
429             }
430         }
431 
432         //Check whether prev output bufer has been released or not
433         if (OMX_TRUE == iNewOutBufRequired)
434         {
435             //Check whether a new output buffer is available or not
436             if (0 == (GetQueueNumElem(pOutputQueue)))
437             {
438                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : ProcessData OUT output buffer unavailable"));
439                 return;
440             }
441 
442             ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue);
443             if (NULL == ipOutputBuffer)
444             {
445                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : ProcessData Error, Output Buffer Dequeue returned NULL, OUT"));
446                 return;
447             }
448             ipOutputBuffer->nFilledLen = 0;
449             iNewOutBufRequired = OMX_FALSE;
450 
451             //Set the current timestamp to the output buffer timestamp
452             ipOutputBuffer->nTimeStamp = iCurrentFrameTS.GetConvertedTs();
453 
454             // Copy the output buffer that was stored locally before dynamic port reconfiguration
455             // in the new omx buffer received.
456             if (OMX_TRUE == iSendOutBufferAfterPortReconfigFlag)
457             {
458                 if ((ipTempOutBufferForPortReconfig)
459                         && (iSizeOutBufferForPortReconfig <= ipOutputBuffer->nAllocLen))
460                 {
461                     oscl_memcpy(ipOutputBuffer->pBuffer, ipTempOutBufferForPortReconfig, iSizeOutBufferForPortReconfig);
462                     ipOutputBuffer->nFilledLen = iSizeOutBufferForPortReconfig;
463                     ipOutputBuffer->nTimeStamp = iTimestampOutBufferForPortReconfig;
464                 }
465 
466                 iSendOutBufferAfterPortReconfigFlag = OMX_FALSE;
467 
468                 //Send the output buffer back only when it has become full
469                 if ((ipOutputBuffer->nAllocLen - ipOutputBuffer->nFilledLen) < iOutputFrameLength)
470                 {
471                     ReturnOutputBuffer(ipOutputBuffer, pOutPort);
472                 }
473 
474                 //Free the temp output buffer
475                 if (ipTempOutBufferForPortReconfig)
476                 {
477                     oscl_free(ipTempOutBufferForPortReconfig);
478                     ipTempOutBufferForPortReconfig = NULL;
479                     iSizeOutBufferForPortReconfig = 0;
480                 }
481 
482                 //Dequeue new output buffer if required to continue decoding the next frame
483                 if (OMX_TRUE == iNewOutBufRequired)
484                 {
485                     if (0 == (GetQueueNumElem(pOutputQueue)))
486                     {
487                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : ProcessData OUT, output buffer unavailable"));
488                         return;
489                     }
490 
491                     ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue);
492                     if (NULL == ipOutputBuffer)
493                     {
494                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : ProcessData Error, Output Buffer Dequeue returned NULL, OUT"));
495                         return;
496                     }
497 
498                     ipOutputBuffer->nFilledLen = 0;
499                     iNewOutBufRequired = OMX_FALSE;
500 
501                     ipOutputBuffer->nTimeStamp = iCurrentFrameTS.GetConvertedTs();
502                 }
503             }
504         }
505 
506         /* Code for the marking buffer. Takes care of the OMX_CommandMarkBuffer
507          * command and hMarkTargetComponent as given by the specifications
508          */
509         if (ipMark != NULL)
510         {
511             ipOutputBuffer->hMarkTargetComponent = ipMark->hMarkTargetComponent;
512             ipOutputBuffer->pMarkData = ipMark->pMarkData;
513             ipMark = NULL;
514         }
515 
516         if (ipTargetComponent != NULL)
517         {
518             ipOutputBuffer->hMarkTargetComponent = ipTargetComponent;
519             ipOutputBuffer->pMarkData = iTargetMarkData;
520             ipTargetComponent = NULL;
521 
522         }
523         //Mark buffer code ends here
524 
525         pOutBuffer = &ipOutputBuffer->pBuffer[ipOutputBuffer->nFilledLen];
526         OutputLength = (ipOutputBuffer->nAllocLen - ipOutputBuffer->nFilledLen) >> 1;
527 
528         /* Copy the left-over data from last input buffer that is stored in temporary
529          * buffer to the next incoming buffer.
530          */
531         if (iTempInputBufferLength > 0 &&
532                 ((iInputCurrLength + iTempInputBufferLength) < TempInputBufferSize))
533         {
534             oscl_memcpy(&ipTempInputBuffer[iTempInputBufferLength], ipFrameDecodeBuffer, iInputCurrLength);
535             iInputCurrLength += iTempInputBufferLength;
536             iTempInputBufferLength = 0;
537             ipFrameDecodeBuffer = ipTempInputBuffer;
538         }
539 
540         //Output buffer is passed as a short pointer
541         DecodeReturn = ipMp3Dec->Mp3DecodeAudio((OMX_S16*) pOutBuffer,
542                                                 (OMX_U32*) & OutputLength,
543                                                 &(ipFrameDecodeBuffer),
544                                                 &iInputCurrLength,
545                                                 &iFrameCount,
546                                                 &(ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode),
547                                                 &(ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioMp3Param),
548                                                 iEndOfFrameFlag,
549                                                 &ResizeNeeded);
550 
551         if (ResizeNeeded == OMX_TRUE)
552         {
553             if (0 != OutputLength)
554             {
555                 iOutputFrameLength = OutputLength * 2;
556 
557                 //Update the timestamp
558                 iSamplesPerFrame = OutputLength / ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.nChannels;
559 
560                 iCurrentFrameTS.SetParameters(ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioPcmMode.nSamplingRate, iSamplesPerFrame);
561                 iOutputMicroSecPerFrame = iCurrentFrameTS.GetFrameDuration();
562 
563             }
564 
565             // set the flag to disable further processing until Client reacts to this
566             //  by doing dynamic port reconfiguration
567             iResizePending = OMX_TRUE;
568 
569             /* Do not return the output buffer generated yet, store it locally
570              * and wait for the dynamic port reconfig to complete */
571             if ((NULL == ipTempOutBufferForPortReconfig))
572             {
573                 ipTempOutBufferForPortReconfig = (OMX_U8*) oscl_malloc(sizeof(uint8) * OutputLength * 2);
574                 if (NULL == ipTempOutBufferForPortReconfig)
575                 {
576                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : ProcessData error, insufficient resources"));
577                     return;
578                 }
579             }
580 
581             //Copy the omx output buffer to the temporary internal buffer
582             oscl_memcpy(ipTempOutBufferForPortReconfig, pOutBuffer, OutputLength * 2);
583             iSizeOutBufferForPortReconfig = OutputLength * 2;
584 
585             //Set the current timestamp to the output buffer timestamp for the first output frame
586             //Later it will be done at the time of dequeue
587             iTimestampOutBufferForPortReconfig = iCurrentFrameTS.GetConvertedTs();
588 
589             iCurrentFrameTS.UpdateTimestamp(iSamplesPerFrame);
590             //Make this length 0 so that no output buffer is returned by the component
591             OutputLength = 0;
592 
593             // send port settings changed event
594             OMX_COMPONENTTYPE* pHandle = (OMX_COMPONENTTYPE*) ipAppPriv->CompHandle;
595 
596             (*(ipCallbacks->EventHandler))
597             (pHandle,
598              iCallbackData,
599              OMX_EventPortSettingsChanged, //The command was completed
600              OMX_PORT_OUTPUTPORT_INDEX,
601              0,
602              NULL);
603         }
604 
605         ipOutputBuffer->nFilledLen += OutputLength * 2;
606         //offset not required in our case, set it to zero
607         ipOutputBuffer->nOffset = 0;
608 
609         if (OutputLength > 0)
610         {
611             iCurrentFrameTS.UpdateTimestamp(iSamplesPerFrame);
612         }
613 
614         /* If EOS flag has come from the client & there are no more
615          * input buffers to decode, send the callback to the client
616          */
617         if (OMX_TRUE == iEndofStream)
618         {
619             /* Changed the condition here. If EOS has come and decoder can't decode
620              * the buffer, do not wait for buffer length to become zero and return
621              * the callback as the current buffer may contain partial frame and
622              * no other data is going to come now
623              */
624             if (MP3DEC_SUCCESS != DecodeReturn)
625             {
626                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : ProcessData EOS callback send"));
627 
628                 (*(ipCallbacks->EventHandler))
629                 (pHandle,
630                  iCallbackData,
631                  OMX_EventBufferFlag,
632                  1,
633                  OMX_BUFFERFLAG_EOS,
634                  NULL);
635 
636                 iEndofStream = OMX_FALSE;
637 
638                 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_EOS;
639 
640                 ReturnOutputBuffer(ipOutputBuffer, pOutPort);
641                 ipOutputBuffer = NULL;
642 
643                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : ProcessData OUT"));
644 
645                 return;
646             }
647         }
648 
649 
650         if (MP3DEC_SUCCESS == DecodeReturn)
651         {
652             ipInputBuffer->nFilledLen = iInputCurrLength;
653         }
654         else if ((MP3DEC_INCOMPLETE_FRAME == DecodeReturn) ||
655                  (MP3DEC_OUTPUT_BUFFER_TOO_SMALL == DecodeReturn))
656         {
657             /* If decoder returns MP4AUDEC_INCOMPLETE_FRAME,
658              * this indicates the input buffer contains less than a frame data
659              * Copy it to a temp buffer to be used in next decode call
660              */
661             oscl_memcpy(ipTempInputBuffer, ipFrameDecodeBuffer, iInputCurrLength);
662             iTempInputBufferLength = iInputCurrLength;
663 
664             ipInputBuffer->nFilledLen = 0;
665             iInputCurrLength = 0;
666         }
667         else
668         {
669             //bitstream error, discard the current data as it can't be decoded further
670             ipInputBuffer->nFilledLen = 0;
671             iInputCurrLength = 0;
672 
673             //Report it to the client via a callback
674             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : ProcessData ErrorStreamCorrupt callback send"));
675 
676             (*(ipCallbacks->EventHandler))
677             (pHandle,
678              iCallbackData,
679              OMX_EventError,
680              OMX_ErrorStreamCorrupt,
681              0,
682              NULL);
683 
684         }
685 
686         //Return the input buffer if it has been consumed fully by the decoder
687         if (0 == ipInputBuffer->nFilledLen)
688         {
689             ReturnInputBuffer(ipInputBuffer, pInPort);
690             ipInputBuffer = NULL;
691             iIsInputBufferEnded = OMX_TRUE;
692             iInputCurrLength = 0;
693         }
694 
695         /*
696          *  Send the output buffer back when it has become full
697          *  or when there is not room to hold next decoded output
698          */
699         if ((ipOutputBuffer->nAllocLen - ipOutputBuffer->nFilledLen) < (iOutputFrameLength) ||
700                 (MP3DEC_OUTPUT_BUFFER_TOO_SMALL == DecodeReturn))
701         {
702             ReturnOutputBuffer(ipOutputBuffer, pOutPort);
703             ipOutputBuffer = NULL;
704         }
705 
706         /* If there is some more processing left with current buffers, re-schedule the AO
707          * Do not go for more than one round of processing at a time.
708          * This may block the AO longer than required.
709          */
710         if (((iInputCurrLength != 0 || GetQueueNumElem(pInputQueue) > 0)
711                 && (GetQueueNumElem(pOutputQueue) > 0) && (ResizeNeeded == OMX_FALSE))
712                 || (OMX_TRUE == iEndofStream))
713         {
714             RunIfNotReady();
715         }
716     }
717 
718     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : ProcessData OUT"));
719     return;
720 }
721 
722 
ComponentGetRolesOfComponent(OMX_STRING * aRoleString)723 void OpenmaxMp3AO::ComponentGetRolesOfComponent(OMX_STRING* aRoleString)
724 {
725     *aRoleString = (OMX_STRING)"audio_decoder.mp3";
726 }
727 
728 
729 //Active object constructor
OpenmaxMp3AO()730 OpenmaxMp3AO::OpenmaxMp3AO()
731 {
732     ipMp3Dec = NULL;
733 
734     if (!IsAdded())
735     {
736         AddToScheduler();
737     }
738 
739     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : constructed"));
740 }
741 
742 
743 //Active object destructor
~OpenmaxMp3AO()744 OpenmaxMp3AO::~OpenmaxMp3AO()
745 {
746     if (IsAdded())
747     {
748         RemoveFromScheduler();
749     }
750 
751     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : destructed"));
752 }
753 
754 
755 /** The Initialization function
756  */
ComponentInit()757 OMX_ERRORTYPE OpenmaxMp3AO::ComponentInit()
758 {
759     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : ComponentInit IN"));
760 
761     OMX_BOOL Status = OMX_FALSE;
762 
763     if (OMX_TRUE == iIsInit)
764     {
765         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : ComponentInit error incorrect operation"));
766         return OMX_ErrorIncorrectStateOperation;
767     }
768     iIsInit = OMX_TRUE;
769 
770     //Mp3 lib init
771     if (!iCodecReady)
772     {
773         Status = ipMp3Dec->Mp3DecInit(&(ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioEqualizerType));
774         iCodecReady = OMX_TRUE;
775     }
776 
777     iInputCurrLength = 0;
778     //Used in dynamic port reconfiguration
779     iFrameCount = 0;
780 
781     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : ComponentInit OUT"));
782 
783     if (OMX_TRUE == Status)
784     {
785         return OMX_ErrorNone;
786     }
787     else
788     {
789         return OMX_ErrorInvalidComponent;
790     }
791 }
792 
793 /** This function is called upon a transition to the idle or invalid state.
794  *  Also it is called by the Mp3ComponentDestructor() function
795  */
ComponentDeInit()796 OMX_ERRORTYPE OpenmaxMp3AO::ComponentDeInit()
797 {
798     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : ComponentDeInit IN"));
799 
800     iIsInit = OMX_FALSE;
801 
802     if (iCodecReady)
803     {
804         ipMp3Dec->Mp3DecDeinit();
805         iCodecReady = OMX_FALSE;
806     }
807 
808     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : ComponentDeInit OUT"));
809 
810     return OMX_ErrorNone;
811 
812 }
813 
814 
815 //Check whether silence insertion is required here or not
CheckForSilenceInsertion()816 void OpenmaxMp3AO::CheckForSilenceInsertion()
817 {
818 
819     OMX_TICKS CurrTimestamp, TimestampGap;
820     //Set the flag to false by default
821     iSilenceInsertionInProgress = OMX_FALSE;
822 
823     CurrTimestamp = iCurrentFrameTS.GetCurrentTimestamp();
824     TimestampGap = iFrameTimestamp - CurrTimestamp;
825 
826     if ((TimestampGap > OMX_HALFRANGE_THRESHOLD) || (TimestampGap < iOutputMicroSecPerFrame && iFrameCount > 0))
827     {
828         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : CheckForSilenceInsertion OUT - No need to insert silence"));
829         return;
830     }
831 
832     //Silence insertion needed, mark the flag to true
833     if (iFrameCount > 0)
834     {
835         iSilenceInsertionInProgress = OMX_TRUE;
836         //Determine the number of silence frames to insert
837         if (0 != iOutputMicroSecPerFrame)
838         {
839             iSilenceFramesNeeded = TimestampGap / iOutputMicroSecPerFrame;
840         }
841         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : CheckForSilenceInsertion OUT - Silence Insertion required here"));
842     }
843 
844     return;
845 }
846 
847 //Currently we are doing zero frame insertion in this routine
DoSilenceInsertion()848 void OpenmaxMp3AO::DoSilenceInsertion()
849 {
850     QueueType* pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue;
851     ComponentPortType* pOutPort = ipPorts[OMX_PORT_OUTPUTPORT_INDEX];
852     OMX_U8* pOutBuffer = NULL;
853 
854 
855     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : DoSilenceInsertion IN"));
856 
857     while (iSilenceFramesNeeded > 0)
858     {
859         //Check whether prev output bufer has been consumed or not
860         if (OMX_TRUE == iNewOutBufRequired)
861         {
862             //Check whether a new output buffer is available or not
863             if (0 == (GetQueueNumElem(pOutputQueue)))
864             {
865                 //Resume Silence insertion next time when component will be called
866                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : DoSilenceInsertion OUT output buffer unavailable"));
867                 iSilenceInsertionInProgress = OMX_TRUE;
868                 return;
869             }
870 
871             ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue);
872             if (NULL == ipOutputBuffer)
873             {
874                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : DoSilenceInsertion Error, Output Buffer Dequeue returned NULL, OUT"));
875                 iSilenceInsertionInProgress = OMX_TRUE;
876                 return;
877             }
878             ipOutputBuffer->nFilledLen = 0;
879             iNewOutBufRequired = OMX_FALSE;
880 
881             //Set the current timestamp to the output buffer timestamp
882             ipOutputBuffer->nTimeStamp = iCurrentFrameTS.GetConvertedTs();
883         }
884 
885 
886         pOutBuffer = &ipOutputBuffer->pBuffer[ipOutputBuffer->nFilledLen];
887         oscl_memset(pOutBuffer, 0, iOutputFrameLength);
888 
889         ipOutputBuffer->nFilledLen += iOutputFrameLength;
890         ipOutputBuffer->nOffset = 0;
891         iCurrentFrameTS.UpdateTimestamp(iSamplesPerFrame);
892 
893         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : DoSilenceInsertion - One frame of zeros inserted"));
894 
895         //Send the output buffer back when it has become full
896         if ((ipOutputBuffer->nAllocLen - ipOutputBuffer->nFilledLen) < iOutputFrameLength)
897         {
898             ReturnOutputBuffer(ipOutputBuffer, pOutPort);
899             ipOutputBuffer = NULL;
900         }
901 
902         // Decrement the silence frame counter
903         --iSilenceFramesNeeded;
904     }
905 
906     /* Completed Silence insertion successfully, now consider the input buffer already dequeued
907      * for decoding & update the timestamps */
908 
909     iSilenceInsertionInProgress = OMX_FALSE;
910     iCurrentFrameTS.SetFromInputTimestamp(iFrameTimestamp);
911     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMp3AO : DoSilenceInsertion OUT - Done successfully"));
912 
913     return;
914 }
915 
916 
GetConfig(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_INDEXTYPE nIndex,OMX_INOUT OMX_PTR pComponentConfigStructure)917 OMX_ERRORTYPE OpenmaxMp3AO::GetConfig(
918     OMX_IN  OMX_HANDLETYPE hComponent,
919     OMX_IN  OMX_INDEXTYPE nIndex,
920     OMX_INOUT OMX_PTR pComponentConfigStructure)
921 {
922     OSCL_UNUSED_ARG(hComponent);
923     OSCL_UNUSED_ARG(nIndex);
924     OSCL_UNUSED_ARG(pComponentConfigStructure);
925     return OMX_ErrorNotImplemented;
926 }
927