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 
     19 #include "omx_amrenc_component.h"
     20 
     21 #if PROXY_INTERFACE
     22 #include "omx_proxy_interface.h"
     23 #endif
     24 
     25 
     26 
     27 // This function is called by OMX_GetHandle and it creates an instance of the amr component AO
     28 OMX_ERRORTYPE AmrEncOmxComponentFactory(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)
     29 {
     30     OSCL_UNUSED_ARG(aOmxLibName);
     31     OSCL_UNUSED_ARG(aOmxLib);
     32     OSCL_UNUSED_ARG(aOsclUuid);
     33     OSCL_UNUSED_ARG(aRefCount);
     34 
     35     OmxComponentAmrEncoderAO* pOpenmaxAOType;
     36     OMX_ERRORTYPE Status;
     37 
     38     // move InitAmrOmxComponentFields content to actual constructor
     39 
     40     pOpenmaxAOType = (OmxComponentAmrEncoderAO*) OSCL_NEW(OmxComponentAmrEncoderAO, ());
     41 
     42     if (NULL == pOpenmaxAOType)
     43     {
     44         return OMX_ErrorInsufficientResources;
     45     }
     46 
     47     //Call the construct component to initialize OMX types
     48     Status = pOpenmaxAOType->ConstructComponent(pAppData, pProxy);
     49 
     50     *pHandle = pOpenmaxAOType->GetOmxHandle();
     51 
     52     return Status;
     53     ///////////////////////////////////////////////////////////////////////////////////////
     54 }
     55 
     56 // This function is called by OMX_FreeHandle when component AO needs to be destroyed
     57 OMX_ERRORTYPE AmrEncOmxComponentDestructor(OMX_IN OMX_HANDLETYPE pHandle, OMX_PTR &aOmxLib, OMX_PTR aOsclUuid, OMX_U32 &aRefCount)
     58 {
     59     OSCL_UNUSED_ARG(aOmxLib);
     60     OSCL_UNUSED_ARG(aOsclUuid);
     61     OSCL_UNUSED_ARG(aRefCount);
     62 
     63     // get pointer to component AO
     64     OmxComponentAmrEncoderAO* pOpenmaxAOType = (OmxComponentAmrEncoderAO*)((OMX_COMPONENTTYPE*)pHandle)->pComponentPrivate;
     65 
     66     // clean up encoder, OMX component stuff
     67     pOpenmaxAOType->DestroyComponent();
     68 
     69     // destroy the AO class
     70     OSCL_DELETE(pOpenmaxAOType);
     71 
     72     return OMX_ErrorNone;
     73 }
     74 
     75 #if DYNAMIC_LOAD_OMX_AMRENC_COMPONENT
     76 class AmrEncOmxSharedLibraryInterface:  public OsclSharedLibraryInterface,
     77         public OmxSharedLibraryInterface
     78 
     79 {
     80     public:
     81         OsclAny *QueryOmxComponentInterface(const OsclUuid& aOmxTypeId, const OsclUuid& aInterfaceId)
     82         {
     83             if (PV_OMX_AMRENC_UUID == aOmxTypeId)
     84             {
     85                 if (PV_OMX_CREATE_INTERFACE == aInterfaceId)
     86                 {
     87                     return ((OsclAny*)(&AmrEncOmxComponentFactory));
     88                 }
     89                 else if (PV_OMX_DESTROY_INTERFACE == aInterfaceId)
     90                 {
     91                     return ((OsclAny*)(&AmrEncOmxComponentDestructor));
     92                 }
     93             }
     94             return NULL;
     95         };
     96 
     97         OsclAny *SharedLibraryLookup(const OsclUuid& aInterfaceId)
     98         {
     99             if (aInterfaceId == PV_OMX_SHARED_INTERFACE)
    100             {
    101                 return OSCL_STATIC_CAST(OmxSharedLibraryInterface*, this);
    102             }
    103             return NULL;
    104         };
    105 
    106         AmrEncOmxSharedLibraryInterface() {};
    107 };
    108 
    109 // function to obtain the interface object from the shared library
    110 extern "C"
    111 {
    112     OSCL_EXPORT_REF OsclAny* PVGetInterface()
    113     {
    114         return (OsclAny*) OSCL_NEW(AmrEncOmxSharedLibraryInterface, ());
    115     }
    116 
    117     OSCL_EXPORT_REF void PVReleaseInterface(OsclSharedLibraryInterface* aInstance)
    118     {
    119         AmrEncOmxSharedLibraryInterface* module = (AmrEncOmxSharedLibraryInterface*)aInstance;
    120         OSCL_DELETE(module);
    121     }
    122 }
    123 
    124 #endif
    125 
    126 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    127 
    128 OMX_ERRORTYPE OmxComponentAmrEncoderAO::ConstructComponent(OMX_PTR pAppData, OMX_PTR pProxy)
    129 {
    130     ComponentPortType* pInPort, *pOutPort;
    131     OMX_ERRORTYPE Status;
    132 
    133     iNumPorts = 2;
    134     iCompressedFormatPortNum = OMX_PORT_OUTPUTPORT_INDEX;
    135     iOmxComponent.nSize = sizeof(OMX_COMPONENTTYPE);
    136     iOmxComponent.pComponentPrivate = (OMX_PTR) this;  // pComponentPrivate points to THIS component AO class
    137     ipComponentProxy = pProxy;
    138     iOmxComponent.pApplicationPrivate = pAppData; // init the App data
    139 
    140 
    141 #if PROXY_INTERFACE
    142     iPVCapabilityFlags.iIsOMXComponentMultiThreaded = OMX_TRUE;
    143 
    144     iOmxComponent.SendCommand = OmxComponentAmrEncoderAO::BaseComponentProxySendCommand;
    145     iOmxComponent.GetParameter = OmxComponentAmrEncoderAO::BaseComponentProxyGetParameter;
    146     iOmxComponent.SetParameter = OmxComponentAmrEncoderAO::BaseComponentProxySetParameter;
    147     iOmxComponent.GetConfig = OmxComponentAmrEncoderAO::BaseComponentProxyGetConfig;
    148     iOmxComponent.SetConfig = OmxComponentAmrEncoderAO::BaseComponentProxySetConfig;
    149     iOmxComponent.GetExtensionIndex = OmxComponentAmrEncoderAO::BaseComponentProxyGetExtensionIndex;
    150     iOmxComponent.GetState = OmxComponentAmrEncoderAO::BaseComponentProxyGetState;
    151     iOmxComponent.UseBuffer = OmxComponentAmrEncoderAO::BaseComponentProxyUseBuffer;
    152     iOmxComponent.AllocateBuffer = OmxComponentAmrEncoderAO::BaseComponentProxyAllocateBuffer;
    153     iOmxComponent.FreeBuffer = OmxComponentAmrEncoderAO::BaseComponentProxyFreeBuffer;
    154     iOmxComponent.EmptyThisBuffer = OmxComponentAmrEncoderAO::BaseComponentProxyEmptyThisBuffer;
    155     iOmxComponent.FillThisBuffer = OmxComponentAmrEncoderAO::BaseComponentProxyFillThisBuffer;
    156 
    157 #else
    158     iPVCapabilityFlags.iIsOMXComponentMultiThreaded = OMX_FALSE;
    159 
    160     iOmxComponent.SendCommand = OmxComponentAmrEncoderAO::BaseComponentSendCommand;
    161     iOmxComponent.GetParameter = OmxComponentAmrEncoderAO::BaseComponentGetParameter;
    162     iOmxComponent.SetParameter = OmxComponentAmrEncoderAO::BaseComponentSetParameter;
    163     iOmxComponent.GetConfig = OmxComponentAmrEncoderAO::BaseComponentGetConfig;
    164     iOmxComponent.SetConfig = OmxComponentAmrEncoderAO::BaseComponentSetConfig;
    165     iOmxComponent.GetExtensionIndex = OmxComponentAmrEncoderAO::BaseComponentGetExtensionIndex;
    166     iOmxComponent.GetState = OmxComponentAmrEncoderAO::BaseComponentGetState;
    167     iOmxComponent.UseBuffer = OmxComponentAmrEncoderAO::BaseComponentUseBuffer;
    168     iOmxComponent.AllocateBuffer = OmxComponentAmrEncoderAO::BaseComponentAllocateBuffer;
    169     iOmxComponent.FreeBuffer = OmxComponentAmrEncoderAO::BaseComponentFreeBuffer;
    170     iOmxComponent.EmptyThisBuffer = OmxComponentAmrEncoderAO::BaseComponentEmptyThisBuffer;
    171     iOmxComponent.FillThisBuffer = OmxComponentAmrEncoderAO::BaseComponentFillThisBuffer;
    172 #endif
    173 
    174     iOmxComponent.SetCallbacks = OmxComponentAmrEncoderAO::BaseComponentSetCallbacks;
    175     iOmxComponent.nVersion.s.nVersionMajor = SPECVERSIONMAJOR;
    176     iOmxComponent.nVersion.s.nVersionMinor = SPECVERSIONMINOR;
    177     iOmxComponent.nVersion.s.nRevision = SPECREVISION;
    178     iOmxComponent.nVersion.s.nStep = SPECSTEP;
    179 
    180     // PV capability
    181     iPVCapabilityFlags.iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE;
    182     iPVCapabilityFlags.iOMXComponentSupportsExternalOutputBufferAlloc = OMX_TRUE;
    183     iPVCapabilityFlags.iOMXComponentSupportsMovableInputBuffers = OMX_TRUE;
    184     iPVCapabilityFlags.iOMXComponentSupportsPartialFrames = OMX_TRUE;
    185     iPVCapabilityFlags.iOMXComponentUsesNALStartCodes = OMX_FALSE;
    186     iPVCapabilityFlags.iOMXComponentCanHandleIncompleteFrames = OMX_TRUE;
    187     iPVCapabilityFlags.iOMXComponentUsesFullAVCFrames = OMX_FALSE;
    188 
    189     if (ipAppPriv)
    190     {
    191         oscl_free(ipAppPriv);
    192         ipAppPriv = NULL;
    193     }
    194 
    195     ipAppPriv = (ComponentPrivateType*) oscl_malloc(sizeof(ComponentPrivateType));
    196     if (NULL == ipAppPriv)
    197     {
    198         return OMX_ErrorInsufficientResources;
    199     }
    200 
    201     //Construct base class now
    202     Status = ConstructBaseComponent(pAppData);
    203 
    204     if (OMX_ErrorNone != Status)
    205     {
    206         return Status;
    207     }
    208 
    209     /** Domain specific section for the ports */
    210     /* Input port is raw/pcm for AMR encoder */
    211     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_INPUTPORT_INDEX;
    212     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainAudio;
    213     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.cMIMEType = (OMX_STRING)"raw";
    214     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.pNativeRender = 0;
    215     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.bFlagErrorConcealment = OMX_FALSE;
    216     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
    217     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.eDir = OMX_DirInput;
    218     //Set to a default value, will change later during setparameter call
    219     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferCountActual = NUMBER_INPUT_BUFFER_AMR_ENC;
    220     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferCountMin = 1;
    221     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize = INPUT_BUFFER_SIZE_AMR_ENC;
    222     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE;
    223     ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE;
    224 
    225 
    226     /* Output port is amr format for AMR encoder */
    227     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX;
    228     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainAudio;
    229     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.cMIMEType = (OMX_STRING)"audio/mpeg";
    230     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.pNativeRender = 0;
    231     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.bFlagErrorConcealment = OMX_FALSE;
    232     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.eEncoding = OMX_AUDIO_CodingAMR;
    233     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDir = OMX_DirOutput;
    234     //Set to a default value, will change later during setparameter call
    235     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountActual = NUMBER_OUTPUT_BUFFER_AMR_ENC;
    236     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountMin = 1;
    237     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferSize = OUTPUT_BUFFER_SIZE_AMR_ENC;
    238     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE;
    239     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE;
    240 
    241     //Default values for PCM input audio param port
    242     ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.nPortIndex = OMX_PORT_INPUTPORT_INDEX;
    243     ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.nChannels = 1;
    244     ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.eNumData = OMX_NumericalDataSigned;
    245     ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.bInterleaved = OMX_TRUE;
    246     ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.nBitPerSample = 16;
    247     ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.nSamplingRate = 8000;
    248     ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.ePCMMode = OMX_AUDIO_PCMModeLinear;
    249     ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
    250     ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
    251 
    252     //Default values for AMR output audio param port
    253     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioAmrParam.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX;
    254     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioAmrParam.nChannels = 1;
    255     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioAmrParam.nBitRate = 0;
    256     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioAmrParam.eAMRBandMode = OMX_AUDIO_AMRBandModeNB7;  //AMRNB Mode 7 = 12200 bps
    257     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioAmrParam.eAMRDTXMode = OMX_AUDIO_AMRDTXModeOnVAD1;
    258     ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioAmrParam.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;    //PVMF_AMR_IETF
    259 
    260     iPortTypesParam.nPorts = 2;
    261     iPortTypesParam.nStartPortNumber = 0;
    262 
    263     pInPort = (ComponentPortType*) ipPorts[OMX_PORT_INPUTPORT_INDEX];
    264     pOutPort = (ComponentPortType*) ipPorts[OMX_PORT_OUTPUTPORT_INDEX];
    265 
    266     SetHeader(&pInPort->AudioParam, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE));
    267     pInPort->AudioParam.nPortIndex = 0;
    268     pInPort->AudioParam.nIndex = 0;
    269     pInPort->AudioParam.eEncoding = OMX_AUDIO_CodingPCM;
    270 
    271     SetHeader(&pOutPort->AudioParam, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE));
    272     pOutPort->AudioParam.nPortIndex = 1;
    273     pOutPort->AudioParam.nIndex = 0;
    274     pOutPort->AudioParam.eEncoding = OMX_AUDIO_CodingAMR;
    275 
    276     oscl_strncpy((OMX_STRING)iComponentRole, (OMX_STRING)"audio_encoder.amrnb", OMX_MAX_STRINGNAME_SIZE);
    277 
    278     iInputBufferRemainingBytes = 0;
    279 
    280     if (ipAmrEnc)
    281     {
    282         OSCL_DELETE(ipAmrEnc);
    283         ipAmrEnc = NULL;
    284     }
    285 
    286     ipAmrEnc = OSCL_NEW(OmxAmrEncoder, ());
    287     if (NULL == ipAmrEnc)
    288     {
    289         return OMX_ErrorInsufficientResources;
    290     }
    291 
    292 
    293 
    294 #if PROXY_INTERFACE
    295 
    296     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSendCommand = BaseComponentSendCommand;
    297     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetParameter = BaseComponentGetParameter;
    298     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetParameter = BaseComponentSetParameter;
    299     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetConfig = BaseComponentGetConfig;
    300     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetConfig = BaseComponentSetConfig;
    301     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetExtensionIndex = BaseComponentGetExtensionIndex;
    302     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetState = BaseComponentGetState;
    303     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentUseBuffer = BaseComponentUseBuffer;
    304     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentAllocateBuffer = BaseComponentAllocateBuffer;
    305     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentFreeBuffer = BaseComponentFreeBuffer;
    306     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentEmptyThisBuffer = BaseComponentEmptyThisBuffer;
    307     ((ProxyApplication_OMX*)ipComponentProxy)->ComponentFillThisBuffer = BaseComponentFillThisBuffer;
    308 
    309 #endif
    310     return OMX_ErrorNone;
    311 }
    312 
    313 
    314 /** This function is called by the omx core when the component
    315     * is disposed by the IL client with a call to FreeHandle().
    316     * \param Component, the component to be disposed
    317     */
    318 
    319 OMX_ERRORTYPE OmxComponentAmrEncoderAO::DestroyComponent()
    320 {
    321     if (iIsInit != OMX_FALSE)
    322     {
    323         ComponentDeInit();
    324     }
    325 
    326     //Destroy the base class now
    327     DestroyBaseComponent();
    328 
    329     if (ipAmrEnc)
    330     {
    331         OSCL_DELETE(ipAmrEnc);
    332         ipAmrEnc = NULL;
    333     }
    334 
    335     if (ipAppPriv)
    336     {
    337         ipAppPriv->CompHandle = NULL;
    338 
    339         oscl_free(ipAppPriv);
    340         ipAppPriv = NULL;
    341     }
    342 
    343     return OMX_ErrorNone;
    344 }
    345 
    346 
    347 
    348 /* This routine will extract the input timestamp from the input buffer */
    349 void OmxComponentAmrEncoderAO::SyncWithInputTimestamp()
    350 {
    351     // this is called when new input buffer is received
    352     // and checked against internally kept (Current) timestamp
    353 // TODO:
    354 // If there is unprocessed data from previous buffer - need to adjust timestamp - but
    355 // timestamp adjustment should only be done once (if multiple PCM input buffers are received - prior to doing further processing)
    356 
    357 
    358 }
    359 
    360 
    361 void OmxComponentAmrEncoderAO::ProcessData()
    362 {
    363     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ProcessData IN"));
    364 
    365     QueueType* pInputQueue  = ipPorts[OMX_PORT_INPUTPORT_INDEX]->pBufferQueue;
    366     QueueType* pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue;
    367 
    368     ComponentPortType* pInPort  = (ComponentPortType*) ipPorts[OMX_PORT_INPUTPORT_INDEX];
    369     ComponentPortType* pOutPort = ipPorts[OMX_PORT_OUTPUTPORT_INDEX];
    370     OMX_COMPONENTTYPE* pHandle  = &iOmxComponent;
    371 
    372     OMX_U8*  pOutBuffer;
    373     OMX_U32  OutputLength;
    374     OMX_S32  EncodeReturn;
    375     OMX_U32  RemainderInputBytes = 0;
    376     OMX_TICKS OutputTimeStamp;
    377 
    378     OMX_U32 TempInputBufferSize = (2 * sizeof(uint8) * (ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize));
    379 
    380     OMX_U32 AllocNumberOutputFrames;
    381     OMX_U32 ExtraInputBytes = 0;
    382 
    383     if ((!iIsInputBufferEnded) || iEndofStream)
    384     {
    385         //Check whether prev output bufer has been released or not
    386         if (OMX_TRUE == iNewOutBufRequired)
    387         {
    388             //Check whether a new output buffer is available or not
    389             if (0 == (GetQueueNumElem(pOutputQueue)))
    390             {
    391                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ProcessData OUT output buffer unavailable"));
    392                 return;
    393             }
    394 
    395             ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue);
    396 
    397             OSCL_ASSERT(NULL != ipOutputBuffer);
    398             if (NULL == ipOutputBuffer)
    399             {
    400                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "OmxComponentAmrEncoderAO : ProcessData ERROR - OUT buffer cannot be dequeued"));
    401 
    402                 return;
    403             }
    404 
    405             ipOutputBuffer->nFilledLen = 0;
    406             iNewOutBufRequired = OMX_FALSE;
    407 
    408             //At the first frame count, detrermine the output parameters
    409             if (0 == iFrameCount)
    410             {
    411                 //How many frames can be accomodated in the output buffer
    412                 AllocNumberOutputFrames = ipOutputBuffer->nAllocLen / MAX_AMR_FRAME_SIZE;
    413                 iActualNumberOutputFrames = omx_min(AllocNumberOutputFrames, iMaxNumberOutputFrames);
    414 
    415                 /* Keep the minimum of the two:
    416                     -frames accomodated and
    417                     -maximum frames defined by component */
    418                 iOutputFrameLength = iActualNumberOutputFrames * MAX_AMR_FRAME_SIZE;
    419             }
    420         }
    421 
    422         /* Code for the marking buffer. Takes care of the OMX_CommandMarkBuffer
    423          * command and hMarkTargetComponent as given by the specifications
    424          */
    425         if (ipMark != NULL)
    426         {
    427             ipOutputBuffer->hMarkTargetComponent = ipMark->hMarkTargetComponent;
    428             ipOutputBuffer->pMarkData = ipMark->pMarkData;
    429             ipMark = NULL;
    430         }
    431 
    432         if (ipTargetComponent != NULL)
    433         {
    434             ipOutputBuffer->hMarkTargetComponent = ipTargetComponent;
    435             ipOutputBuffer->pMarkData = iTargetMarkData;
    436             ipTargetComponent = NULL;
    437 
    438         }
    439         //Mark buffer code ends here
    440 
    441 
    442         if ((iTempInputBufferLength > 0) &&
    443                 ((iInputCurrLength + iTempInputBufferLength) <= TempInputBufferSize))
    444         {
    445             oscl_memcpy(&ipTempInputBuffer[iTempInputBufferLength], ipFrameDecodeBuffer, iInputCurrLength);
    446             iInputCurrLength += iTempInputBufferLength;
    447             iTempInputBufferLength = 0;
    448             ipFrameDecodeBuffer = ipTempInputBuffer;
    449         }
    450 
    451 
    452         //If the number of output buffers to be produced from the current iInputCurrLength
    453         //are more than our requirement, send only the required data for encoding
    454         if (iInputCurrLength / iInputFrameLength > iActualNumberOutputFrames)
    455         {
    456             ExtraInputBytes = iInputCurrLength - (iInputFrameLength * iActualNumberOutputFrames);
    457             iInputCurrLength -= ExtraInputBytes;
    458         }
    459         else
    460         {
    461             /* Before sending the input buffer to the encoder, ensure that the data is multiple
    462              * of one amr input frame length*/
    463             RemainderInputBytes = iInputCurrLength % iInputFrameLength;
    464             iInputCurrLength -= RemainderInputBytes;
    465         }
    466 
    467 
    468         pOutBuffer = &ipOutputBuffer->pBuffer[ipOutputBuffer->nFilledLen];
    469         OutputLength = 0;
    470 
    471         EncodeReturn = ipAmrEnc->AmrEncodeFrame(pOutBuffer,
    472                                                 &OutputLength,
    473                                                 ipFrameDecodeBuffer,
    474                                                 iInputCurrLength,
    475                                                 iCurrentTimestamp,
    476                                                 &OutputTimeStamp);
    477 
    478 
    479         //Attach the timestamp to the output buffer only when we have fetched the new output buffer
    480         //If we are reusing the same output buffer again, no need to modify the previous timestamp, as it should be of the first frame in that buffer
    481 
    482         if (0 == ipOutputBuffer->nFilledLen)
    483         {
    484             ipOutputBuffer->nTimeStamp = OutputTimeStamp;
    485         }
    486 
    487 
    488         ipOutputBuffer->nFilledLen += OutputLength;
    489         //offset not required in our case, set it to zero
    490         ipOutputBuffer->nOffset = 0;
    491 
    492         //It has to be incremented atleast one time, so that 'equality with zero' checks added above hold true only once
    493         iFrameCount++;
    494 
    495 
    496         /* If EOS flag has come from the client & there are no more
    497          * input buffers to decode, send the callback to the client
    498          */
    499         if (OMX_TRUE == iEndofStream)
    500         {
    501             if ((0 == iInputCurrLength) || (OMX_TRUE != EncodeReturn))
    502             {
    503                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ProcessData EOS callback send"));
    504 
    505                 (*(ipCallbacks->EventHandler))
    506                 (pHandle,
    507                  iCallbackData,
    508                  OMX_EventBufferFlag,
    509                  1,
    510                  OMX_BUFFERFLAG_EOS,
    511                  NULL);
    512 
    513                 iEndofStream = OMX_FALSE;
    514 
    515                 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_EOS;
    516 
    517                 ReturnOutputBuffer(ipOutputBuffer, pOutPort);
    518                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ProcessData OUT"));
    519 
    520                 return;
    521             }
    522         }
    523 
    524 
    525         if (OMX_TRUE == EncodeReturn)
    526         {
    527             //Do not return the input buffer in case it has more than one frame data to encode
    528             if (ExtraInputBytes > 0)
    529             {
    530                 ipFrameDecodeBuffer += iInputCurrLength;
    531                 iInputCurrLength = ExtraInputBytes;
    532             }
    533             else
    534             {
    535 
    536                 /* If there are some remainder bytes out of the last buffer, copy into a temp buffer
    537                  * to be used in next decode cycle and return the existing input buffer*/
    538                 if (RemainderInputBytes > 0)
    539                 {
    540                     oscl_memmove(ipTempInputBuffer, &ipFrameDecodeBuffer[iInputCurrLength], RemainderInputBytes);
    541                     iTempInputBufferLength = RemainderInputBytes;
    542                 }
    543 
    544                 //Input bytes consumed now, return the buffer
    545                 ipInputBuffer->nFilledLen = 0;
    546                 ReturnInputBuffer(ipInputBuffer, pInPort);
    547                 iIsInputBufferEnded = OMX_TRUE;
    548                 iInputCurrLength = 0;
    549 
    550             }
    551         }
    552         //In case of error, discard the bitstream and report data corruption error via callback
    553         else
    554         {
    555             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ProcessData ErrorStreamCorrupt callback send"));
    556 
    557             ipInputBuffer->nFilledLen = 0;
    558             ReturnInputBuffer(ipInputBuffer, pInPort);
    559             iIsInputBufferEnded = OMX_TRUE;
    560             iInputCurrLength = 0;
    561 
    562 
    563             (*(ipCallbacks->EventHandler))
    564             (pHandle,
    565              iCallbackData,
    566              OMX_EventError,
    567              OMX_ErrorStreamCorrupt,
    568              0,
    569              NULL);
    570         }
    571 
    572 
    573         /* Send the output buffer back when it has the following conditions as true:
    574         1) Output buffer contain desired number of frames, calculated above
    575         2) Output buffer can no longer hold the desired number of frames that
    576            we will encode in next encode call
    577         */
    578         if ((ipOutputBuffer->nFilledLen >= iOutputFrameLength)
    579                 || (ipOutputBuffer->nAllocLen - ipOutputBuffer->nFilledLen) < iOutputFrameLength)
    580         {
    581             //Attach the end of frame flag while sending out the output buffer
    582             ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
    583             ReturnOutputBuffer(ipOutputBuffer, pOutPort);
    584         }
    585 
    586 
    587         /* If there is some more processing left with current buffers, re-schedule the AO
    588          * Do not go for more than one round of processing at a time.
    589          * This may block the AO longer than required.
    590          */
    591         if (((ipInputBuffer->nFilledLen != 0) || (GetQueueNumElem(pInputQueue) > 0))
    592                 && ((GetQueueNumElem(pOutputQueue) > 0) || (OMX_FALSE == iNewOutBufRequired)))
    593         {
    594             RunIfNotReady();
    595         }
    596     }
    597 
    598     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ProcessData OUT"));
    599     return;
    600 }
    601 
    602 
    603 //Not implemented & supported in case of base profile components
    604 
    605 void OmxComponentAmrEncoderAO::ComponentGetRolesOfComponent(OMX_STRING* aRoleString)
    606 {
    607     *aRoleString = (OMX_STRING)"audio_encoder.amr";
    608 }
    609 
    610 
    611 //Component constructor
    612 OmxComponentAmrEncoderAO::OmxComponentAmrEncoderAO()
    613 {
    614     ipAmrEnc = NULL;
    615     iInputFrameLength = 0;
    616     iOutputFrameLength = 0;
    617     iActualNumberOutputFrames = 0;
    618     iMaxNumberOutputFrames = 0;
    619 
    620     if (!IsAdded())
    621     {
    622         AddToScheduler();
    623     }
    624 
    625     iCurrentTimestamp = 0;
    626     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : constructed"));
    627 }
    628 
    629 
    630 //Active object destructor
    631 OmxComponentAmrEncoderAO::~OmxComponentAmrEncoderAO()
    632 {
    633     if (IsAdded())
    634     {
    635         RemoveFromScheduler();
    636     }
    637 
    638     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : destructed"));
    639 }
    640 
    641 
    642 /** The Initialization function
    643  */
    644 OMX_ERRORTYPE OmxComponentAmrEncoderAO::ComponentInit()
    645 {
    646     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ComponentInit IN"));
    647 
    648     OMX_BOOL Status = OMX_TRUE;
    649 
    650     if (OMX_TRUE == iIsInit)
    651     {
    652         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ComponentInit error incorrect operation"));
    653         return OMX_ErrorIncorrectStateOperation;
    654     }
    655     iIsInit = OMX_TRUE;
    656 
    657     //amr encoder lib init
    658     if (!iCodecReady)
    659     {
    660         Status = ipAmrEnc->AmrEncInit(ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode,
    661                                       ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioAmrParam,
    662                                       &iInputFrameLength, &iMaxNumberOutputFrames);
    663 
    664         iCodecReady = OMX_TRUE;
    665     }
    666 
    667     iInputCurrLength = 0;
    668 
    669     //Used in dynamic port reconfiguration
    670     iFrameCount = 0;
    671 
    672     if (OMX_TRUE == Status)
    673     {
    674         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ComponentInit OUT"));
    675         return OMX_ErrorNone;
    676     }
    677     else
    678     {
    679         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : Error ComponentInit, OUT"));
    680         return OMX_ErrorInvalidComponent;
    681     }
    682 }
    683 
    684 
    685 
    686 /** This function is called upon a transition to the idle or invalid state.
    687  *  Also it is called by the ComponentDestructor() function
    688  */
    689 OMX_ERRORTYPE OmxComponentAmrEncoderAO::ComponentDeInit()
    690 {
    691     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ComponentDeInit IN"));
    692 
    693     iIsInit = OMX_FALSE;
    694 
    695     if (iCodecReady)
    696     {
    697         ipAmrEnc->AmrEncDeinit();
    698         iCodecReady = OMX_FALSE;
    699     }
    700 
    701     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ComponentDeInit OUT"));
    702 
    703     return OMX_ErrorNone;
    704 
    705 }
    706 
    707 
    708 /* A component specific routine called from BufferMgmtWithoutMarker */
    709 void OmxComponentAmrEncoderAO::ProcessInBufferFlag()
    710 {
    711     iIsInputBufferEnded = OMX_FALSE;
    712 }
    713