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