blob: a1dd9ad0216ecf52f110150534930267db4db45d [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
* -------------------------------------------------------------------
*/
#include "omx_amrenc_component.h"
#if PROXY_INTERFACE
#include "omx_proxy_interface.h"
#endif
// This function is called by OMX_GetHandle and it creates an instance of the amr component AO
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)
{
OSCL_UNUSED_ARG(aOmxLibName);
OSCL_UNUSED_ARG(aOmxLib);
OSCL_UNUSED_ARG(aOsclUuid);
OSCL_UNUSED_ARG(aRefCount);
OmxComponentAmrEncoderAO* pOpenmaxAOType;
OMX_ERRORTYPE Status;
// move InitAmrOmxComponentFields content to actual constructor
pOpenmaxAOType = (OmxComponentAmrEncoderAO*) OSCL_NEW(OmxComponentAmrEncoderAO, ());
if (NULL == pOpenmaxAOType)
{
return OMX_ErrorInsufficientResources;
}
//Call the construct component to initialize OMX types
Status = pOpenmaxAOType->ConstructComponent(pAppData, pProxy);
*pHandle = pOpenmaxAOType->GetOmxHandle();
return Status;
///////////////////////////////////////////////////////////////////////////////////////
}
// This function is called by OMX_FreeHandle when component AO needs to be destroyed
OMX_ERRORTYPE AmrEncOmxComponentDestructor(OMX_IN OMX_HANDLETYPE pHandle, OMX_PTR &aOmxLib, OMX_PTR aOsclUuid, OMX_U32 &aRefCount)
{
OSCL_UNUSED_ARG(aOmxLib);
OSCL_UNUSED_ARG(aOsclUuid);
OSCL_UNUSED_ARG(aRefCount);
// get pointer to component AO
OmxComponentAmrEncoderAO* pOpenmaxAOType = (OmxComponentAmrEncoderAO*)((OMX_COMPONENTTYPE*)pHandle)->pComponentPrivate;
// clean up encoder, OMX component stuff
pOpenmaxAOType->DestroyComponent();
// destroy the AO class
OSCL_DELETE(pOpenmaxAOType);
return OMX_ErrorNone;
}
#if DYNAMIC_LOAD_OMX_AMRENC_COMPONENT
class AmrEncOmxSharedLibraryInterface: public OsclSharedLibraryInterface,
public OmxSharedLibraryInterface
{
public:
OsclAny *QueryOmxComponentInterface(const OsclUuid& aOmxTypeId, const OsclUuid& aInterfaceId)
{
if (PV_OMX_AMRENC_UUID == aOmxTypeId)
{
if (PV_OMX_CREATE_INTERFACE == aInterfaceId)
{
return ((OsclAny*)(&AmrEncOmxComponentFactory));
}
else if (PV_OMX_DESTROY_INTERFACE == aInterfaceId)
{
return ((OsclAny*)(&AmrEncOmxComponentDestructor));
}
}
return NULL;
};
OsclAny *SharedLibraryLookup(const OsclUuid& aInterfaceId)
{
if (aInterfaceId == PV_OMX_SHARED_INTERFACE)
{
return OSCL_STATIC_CAST(OmxSharedLibraryInterface*, this);
}
return NULL;
};
AmrEncOmxSharedLibraryInterface() {};
};
// function to obtain the interface object from the shared library
extern "C"
{
OSCL_EXPORT_REF OsclAny* PVGetInterface()
{
return (OsclAny*) OSCL_NEW(AmrEncOmxSharedLibraryInterface, ());
}
OSCL_EXPORT_REF void PVReleaseInterface(OsclSharedLibraryInterface* aInstance)
{
AmrEncOmxSharedLibraryInterface* module = (AmrEncOmxSharedLibraryInterface*)aInstance;
OSCL_DELETE(module);
}
}
#endif
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE OmxComponentAmrEncoderAO::ConstructComponent(OMX_PTR pAppData, OMX_PTR pProxy)
{
ComponentPortType* pInPort, *pOutPort;
OMX_ERRORTYPE Status;
iNumPorts = 2;
iCompressedFormatPortNum = OMX_PORT_OUTPUTPORT_INDEX;
iOmxComponent.nSize = sizeof(OMX_COMPONENTTYPE);
iOmxComponent.pComponentPrivate = (OMX_PTR) this; // pComponentPrivate points to THIS component AO class
ipComponentProxy = pProxy;
iOmxComponent.pApplicationPrivate = pAppData; // init the App data
#if PROXY_INTERFACE
iPVCapabilityFlags.iIsOMXComponentMultiThreaded = OMX_TRUE;
iOmxComponent.SendCommand = OmxComponentAmrEncoderAO::BaseComponentProxySendCommand;
iOmxComponent.GetParameter = OmxComponentAmrEncoderAO::BaseComponentProxyGetParameter;
iOmxComponent.SetParameter = OmxComponentAmrEncoderAO::BaseComponentProxySetParameter;
iOmxComponent.GetConfig = OmxComponentAmrEncoderAO::BaseComponentProxyGetConfig;
iOmxComponent.SetConfig = OmxComponentAmrEncoderAO::BaseComponentProxySetConfig;
iOmxComponent.GetExtensionIndex = OmxComponentAmrEncoderAO::BaseComponentProxyGetExtensionIndex;
iOmxComponent.GetState = OmxComponentAmrEncoderAO::BaseComponentProxyGetState;
iOmxComponent.UseBuffer = OmxComponentAmrEncoderAO::BaseComponentProxyUseBuffer;
iOmxComponent.AllocateBuffer = OmxComponentAmrEncoderAO::BaseComponentProxyAllocateBuffer;
iOmxComponent.FreeBuffer = OmxComponentAmrEncoderAO::BaseComponentProxyFreeBuffer;
iOmxComponent.EmptyThisBuffer = OmxComponentAmrEncoderAO::BaseComponentProxyEmptyThisBuffer;
iOmxComponent.FillThisBuffer = OmxComponentAmrEncoderAO::BaseComponentProxyFillThisBuffer;
#else
iPVCapabilityFlags.iIsOMXComponentMultiThreaded = OMX_FALSE;
iOmxComponent.SendCommand = OmxComponentAmrEncoderAO::BaseComponentSendCommand;
iOmxComponent.GetParameter = OmxComponentAmrEncoderAO::BaseComponentGetParameter;
iOmxComponent.SetParameter = OmxComponentAmrEncoderAO::BaseComponentSetParameter;
iOmxComponent.GetConfig = OmxComponentAmrEncoderAO::BaseComponentGetConfig;
iOmxComponent.SetConfig = OmxComponentAmrEncoderAO::BaseComponentSetConfig;
iOmxComponent.GetExtensionIndex = OmxComponentAmrEncoderAO::BaseComponentGetExtensionIndex;
iOmxComponent.GetState = OmxComponentAmrEncoderAO::BaseComponentGetState;
iOmxComponent.UseBuffer = OmxComponentAmrEncoderAO::BaseComponentUseBuffer;
iOmxComponent.AllocateBuffer = OmxComponentAmrEncoderAO::BaseComponentAllocateBuffer;
iOmxComponent.FreeBuffer = OmxComponentAmrEncoderAO::BaseComponentFreeBuffer;
iOmxComponent.EmptyThisBuffer = OmxComponentAmrEncoderAO::BaseComponentEmptyThisBuffer;
iOmxComponent.FillThisBuffer = OmxComponentAmrEncoderAO::BaseComponentFillThisBuffer;
#endif
iOmxComponent.SetCallbacks = OmxComponentAmrEncoderAO::BaseComponentSetCallbacks;
iOmxComponent.nVersion.s.nVersionMajor = SPECVERSIONMAJOR;
iOmxComponent.nVersion.s.nVersionMinor = SPECVERSIONMINOR;
iOmxComponent.nVersion.s.nRevision = SPECREVISION;
iOmxComponent.nVersion.s.nStep = SPECSTEP;
// PV capability
iPVCapabilityFlags.iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE;
iPVCapabilityFlags.iOMXComponentSupportsExternalOutputBufferAlloc = OMX_TRUE;
iPVCapabilityFlags.iOMXComponentSupportsMovableInputBuffers = OMX_TRUE;
iPVCapabilityFlags.iOMXComponentSupportsPartialFrames = OMX_TRUE;
iPVCapabilityFlags.iOMXComponentUsesNALStartCodes = OMX_FALSE;
iPVCapabilityFlags.iOMXComponentCanHandleIncompleteFrames = OMX_TRUE;
iPVCapabilityFlags.iOMXComponentUsesFullAVCFrames = OMX_FALSE;
if (ipAppPriv)
{
oscl_free(ipAppPriv);
ipAppPriv = NULL;
}
ipAppPriv = (ComponentPrivateType*) oscl_malloc(sizeof(ComponentPrivateType));
if (NULL == ipAppPriv)
{
return OMX_ErrorInsufficientResources;
}
//Construct base class now
Status = ConstructBaseComponent(pAppData);
if (OMX_ErrorNone != Status)
{
return Status;
}
/** Domain specific section for the ports */
/* Input port is raw/pcm for AMR encoder */
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_INPUTPORT_INDEX;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainAudio;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.cMIMEType = (OMX_STRING)"raw";
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.pNativeRender = 0;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.bFlagErrorConcealment = OMX_FALSE;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.eDir = OMX_DirInput;
//Set to a default value, will change later during setparameter call
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferCountActual = NUMBER_INPUT_BUFFER_AMR_ENC;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferCountMin = 1;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize = INPUT_BUFFER_SIZE_AMR_ENC;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE;
/* Output port is amr format for AMR encoder */
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainAudio;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.cMIMEType = (OMX_STRING)"audio/mpeg";
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.pNativeRender = 0;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.bFlagErrorConcealment = OMX_FALSE;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.eEncoding = OMX_AUDIO_CodingAMR;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDir = OMX_DirOutput;
//Set to a default value, will change later during setparameter call
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountActual = NUMBER_OUTPUT_BUFFER_AMR_ENC;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountMin = 1;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferSize = OUTPUT_BUFFER_SIZE_AMR_ENC;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE;
//Default values for PCM input audio param port
ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.nPortIndex = OMX_PORT_INPUTPORT_INDEX;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.nChannels = 1;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.eNumData = OMX_NumericalDataSigned;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.bInterleaved = OMX_TRUE;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.nBitPerSample = 16;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.nSamplingRate = 8000;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.ePCMMode = OMX_AUDIO_PCMModeLinear;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
//Default values for AMR output audio param port
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioAmrParam.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioAmrParam.nChannels = 1;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioAmrParam.nBitRate = 0;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioAmrParam.eAMRBandMode = OMX_AUDIO_AMRBandModeNB7; //AMRNB Mode 7 = 12200 bps
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioAmrParam.eAMRDTXMode = OMX_AUDIO_AMRDTXModeOnVAD1;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioAmrParam.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; //PVMF_AMR_IETF
iPortTypesParam.nPorts = 2;
iPortTypesParam.nStartPortNumber = 0;
pInPort = (ComponentPortType*) ipPorts[OMX_PORT_INPUTPORT_INDEX];
pOutPort = (ComponentPortType*) ipPorts[OMX_PORT_OUTPUTPORT_INDEX];
SetHeader(&pInPort->AudioParam, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE));
pInPort->AudioParam.nPortIndex = 0;
pInPort->AudioParam.nIndex = 0;
pInPort->AudioParam.eEncoding = OMX_AUDIO_CodingPCM;
SetHeader(&pOutPort->AudioParam, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE));
pOutPort->AudioParam.nPortIndex = 1;
pOutPort->AudioParam.nIndex = 0;
pOutPort->AudioParam.eEncoding = OMX_AUDIO_CodingAMR;
oscl_strncpy((OMX_STRING)iComponentRole, (OMX_STRING)"audio_encoder.amrnb", OMX_MAX_STRINGNAME_SIZE);
iInputBufferRemainingBytes = 0;
if (ipAmrEnc)
{
OSCL_DELETE(ipAmrEnc);
ipAmrEnc = NULL;
}
ipAmrEnc = OSCL_NEW(OmxAmrEncoder, ());
if (NULL == ipAmrEnc)
{
return OMX_ErrorInsufficientResources;
}
#if PROXY_INTERFACE
((ProxyApplication_OMX*)ipComponentProxy)->ComponentSendCommand = BaseComponentSendCommand;
((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetParameter = BaseComponentGetParameter;
((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetParameter = BaseComponentSetParameter;
((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetConfig = BaseComponentGetConfig;
((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetConfig = BaseComponentSetConfig;
((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetExtensionIndex = BaseComponentGetExtensionIndex;
((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetState = BaseComponentGetState;
((ProxyApplication_OMX*)ipComponentProxy)->ComponentUseBuffer = BaseComponentUseBuffer;
((ProxyApplication_OMX*)ipComponentProxy)->ComponentAllocateBuffer = BaseComponentAllocateBuffer;
((ProxyApplication_OMX*)ipComponentProxy)->ComponentFreeBuffer = BaseComponentFreeBuffer;
((ProxyApplication_OMX*)ipComponentProxy)->ComponentEmptyThisBuffer = BaseComponentEmptyThisBuffer;
((ProxyApplication_OMX*)ipComponentProxy)->ComponentFillThisBuffer = BaseComponentFillThisBuffer;
#endif
return OMX_ErrorNone;
}
/** This function is called by the omx core when the component
* is disposed by the IL client with a call to FreeHandle().
* \param Component, the component to be disposed
*/
OMX_ERRORTYPE OmxComponentAmrEncoderAO::DestroyComponent()
{
if (iIsInit != OMX_FALSE)
{
ComponentDeInit();
}
//Destroy the base class now
DestroyBaseComponent();
if (ipAmrEnc)
{
OSCL_DELETE(ipAmrEnc);
ipAmrEnc = NULL;
}
if (ipAppPriv)
{
ipAppPriv->CompHandle = NULL;
oscl_free(ipAppPriv);
ipAppPriv = NULL;
}
return OMX_ErrorNone;
}
/* This routine will extract the input timestamp from the input buffer */
void OmxComponentAmrEncoderAO::SyncWithInputTimestamp()
{
// this is called when new input buffer is received
// and checked against internally kept (Current) timestamp
// TODO:
// If there is unprocessed data from previous buffer - need to adjust timestamp - but
// timestamp adjustment should only be done once (if multiple PCM input buffers are received - prior to doing further processing)
}
void OmxComponentAmrEncoderAO::ProcessData()
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ProcessData IN"));
QueueType* pInputQueue = ipPorts[OMX_PORT_INPUTPORT_INDEX]->pBufferQueue;
QueueType* pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue;
ComponentPortType* pInPort = (ComponentPortType*) ipPorts[OMX_PORT_INPUTPORT_INDEX];
ComponentPortType* pOutPort = ipPorts[OMX_PORT_OUTPUTPORT_INDEX];
OMX_COMPONENTTYPE* pHandle = &iOmxComponent;
OMX_U8* pOutBuffer;
OMX_U32 OutputLength;
OMX_S32 EncodeReturn;
OMX_U32 RemainderInputBytes = 0;
OMX_TICKS OutputTimeStamp;
OMX_U32 TempInputBufferSize = (2 * sizeof(uint8) * (ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize));
OMX_U32 AllocNumberOutputFrames;
OMX_U32 ExtraInputBytes = 0;
if ((!iIsInputBufferEnded) || iEndofStream)
{
//Check whether prev output bufer has been released or not
if (OMX_TRUE == iNewOutBufRequired)
{
//Check whether a new output buffer is available or not
if (0 == (GetQueueNumElem(pOutputQueue)))
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ProcessData OUT output buffer unavailable"));
return;
}
ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue);
OSCL_ASSERT(NULL != ipOutputBuffer);
if (NULL == ipOutputBuffer)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "OmxComponentAmrEncoderAO : ProcessData ERROR - OUT buffer cannot be dequeued"));
return;
}
ipOutputBuffer->nFilledLen = 0;
iNewOutBufRequired = OMX_FALSE;
//At the first frame count, detrermine the output parameters
if (0 == iFrameCount)
{
//How many frames can be accomodated in the output buffer
AllocNumberOutputFrames = ipOutputBuffer->nAllocLen / MAX_AMR_FRAME_SIZE;
iActualNumberOutputFrames = omx_min(AllocNumberOutputFrames, iMaxNumberOutputFrames);
/* Keep the minimum of the two:
-frames accomodated and
-maximum frames defined by component */
iOutputFrameLength = iActualNumberOutputFrames * MAX_AMR_FRAME_SIZE;
}
}
/* Code for the marking buffer. Takes care of the OMX_CommandMarkBuffer
* command and hMarkTargetComponent as given by the specifications
*/
if (ipMark != NULL)
{
ipOutputBuffer->hMarkTargetComponent = ipMark->hMarkTargetComponent;
ipOutputBuffer->pMarkData = ipMark->pMarkData;
ipMark = NULL;
}
if (ipTargetComponent != NULL)
{
ipOutputBuffer->hMarkTargetComponent = ipTargetComponent;
ipOutputBuffer->pMarkData = iTargetMarkData;
ipTargetComponent = NULL;
}
//Mark buffer code ends here
if ((iTempInputBufferLength > 0) &&
((iInputCurrLength + iTempInputBufferLength) <= TempInputBufferSize))
{
oscl_memcpy(&ipTempInputBuffer[iTempInputBufferLength], ipFrameDecodeBuffer, iInputCurrLength);
iInputCurrLength += iTempInputBufferLength;
iTempInputBufferLength = 0;
ipFrameDecodeBuffer = ipTempInputBuffer;
}
//If the number of output buffers to be produced from the current iInputCurrLength
//are more than our requirement, send only the required data for encoding
if (iInputCurrLength / iInputFrameLength > iActualNumberOutputFrames)
{
ExtraInputBytes = iInputCurrLength - (iInputFrameLength * iActualNumberOutputFrames);
iInputCurrLength -= ExtraInputBytes;
}
else
{
/* Before sending the input buffer to the encoder, ensure that the data is multiple
* of one amr input frame length*/
RemainderInputBytes = iInputCurrLength % iInputFrameLength;
iInputCurrLength -= RemainderInputBytes;
}
pOutBuffer = &ipOutputBuffer->pBuffer[ipOutputBuffer->nFilledLen];
OutputLength = 0;
EncodeReturn = ipAmrEnc->AmrEncodeFrame(pOutBuffer,
&OutputLength,
ipFrameDecodeBuffer,
iInputCurrLength,
iCurrentTimestamp,
&OutputTimeStamp);
//Attach the timestamp to the output buffer only when we have fetched the new output buffer
//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
if (0 == ipOutputBuffer->nFilledLen)
{
ipOutputBuffer->nTimeStamp = OutputTimeStamp;
}
ipOutputBuffer->nFilledLen += OutputLength;
//offset not required in our case, set it to zero
ipOutputBuffer->nOffset = 0;
//It has to be incremented atleast one time, so that 'equality with zero' checks added above hold true only once
iFrameCount++;
/* If EOS flag has come from the client & there are no more
* input buffers to decode, send the callback to the client
*/
if (OMX_TRUE == iEndofStream)
{
if ((0 == iInputCurrLength) || (OMX_TRUE != EncodeReturn))
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ProcessData EOS callback send"));
(*(ipCallbacks->EventHandler))
(pHandle,
iCallbackData,
OMX_EventBufferFlag,
1,
OMX_BUFFERFLAG_EOS,
NULL);
iEndofStream = OMX_FALSE;
ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_EOS;
ReturnOutputBuffer(ipOutputBuffer, pOutPort);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ProcessData OUT"));
return;
}
}
if (OMX_TRUE == EncodeReturn)
{
//Do not return the input buffer in case it has more than one frame data to encode
if (ExtraInputBytes > 0)
{
ipFrameDecodeBuffer += iInputCurrLength;
iInputCurrLength = ExtraInputBytes;
}
else
{
/* If there are some remainder bytes out of the last buffer, copy into a temp buffer
* to be used in next decode cycle and return the existing input buffer*/
if (RemainderInputBytes > 0)
{
oscl_memmove(ipTempInputBuffer, &ipFrameDecodeBuffer[iInputCurrLength], RemainderInputBytes);
iTempInputBufferLength = RemainderInputBytes;
}
//Input bytes consumed now, return the buffer
ipInputBuffer->nFilledLen = 0;
ReturnInputBuffer(ipInputBuffer, pInPort);
iIsInputBufferEnded = OMX_TRUE;
iInputCurrLength = 0;
}
}
//In case of error, discard the bitstream and report data corruption error via callback
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ProcessData ErrorStreamCorrupt callback send"));
ipInputBuffer->nFilledLen = 0;
ReturnInputBuffer(ipInputBuffer, pInPort);
iIsInputBufferEnded = OMX_TRUE;
iInputCurrLength = 0;
(*(ipCallbacks->EventHandler))
(pHandle,
iCallbackData,
OMX_EventError,
OMX_ErrorStreamCorrupt,
0,
NULL);
}
/* Send the output buffer back when it has the following conditions as true:
1) Output buffer contain desired number of frames, calculated above
2) Output buffer can no longer hold the desired number of frames that
we will encode in next encode call
*/
if ((ipOutputBuffer->nFilledLen >= iOutputFrameLength)
|| (ipOutputBuffer->nAllocLen - ipOutputBuffer->nFilledLen) < iOutputFrameLength)
{
//Attach the end of frame flag while sending out the output buffer
ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
ReturnOutputBuffer(ipOutputBuffer, pOutPort);
}
/* If there is some more processing left with current buffers, re-schedule the AO
* Do not go for more than one round of processing at a time.
* This may block the AO longer than required.
*/
if (((ipInputBuffer->nFilledLen != 0) || (GetQueueNumElem(pInputQueue) > 0))
&& ((GetQueueNumElem(pOutputQueue) > 0) || (OMX_FALSE == iNewOutBufRequired)))
{
RunIfNotReady();
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ProcessData OUT"));
return;
}
//Not implemented & supported in case of base profile components
void OmxComponentAmrEncoderAO::ComponentGetRolesOfComponent(OMX_STRING* aRoleString)
{
*aRoleString = (OMX_STRING)"audio_encoder.amr";
}
//Component constructor
OmxComponentAmrEncoderAO::OmxComponentAmrEncoderAO()
{
ipAmrEnc = NULL;
iInputFrameLength = 0;
iOutputFrameLength = 0;
iActualNumberOutputFrames = 0;
iMaxNumberOutputFrames = 0;
if (!IsAdded())
{
AddToScheduler();
}
iCurrentTimestamp = 0;
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : constructed"));
}
//Active object destructor
OmxComponentAmrEncoderAO::~OmxComponentAmrEncoderAO()
{
if (IsAdded())
{
RemoveFromScheduler();
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : destructed"));
}
/** The Initialization function
*/
OMX_ERRORTYPE OmxComponentAmrEncoderAO::ComponentInit()
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ComponentInit IN"));
OMX_BOOL Status = OMX_TRUE;
if (OMX_TRUE == iIsInit)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ComponentInit error incorrect operation"));
return OMX_ErrorIncorrectStateOperation;
}
iIsInit = OMX_TRUE;
//amr encoder lib init
if (!iCodecReady)
{
Status = ipAmrEnc->AmrEncInit(ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode,
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioAmrParam,
&iInputFrameLength, &iMaxNumberOutputFrames);
iCodecReady = OMX_TRUE;
}
iInputCurrLength = 0;
//Used in dynamic port reconfiguration
iFrameCount = 0;
if (OMX_TRUE == Status)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ComponentInit OUT"));
return OMX_ErrorNone;
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : Error ComponentInit, OUT"));
return OMX_ErrorInvalidComponent;
}
}
/** This function is called upon a transition to the idle or invalid state.
* Also it is called by the ComponentDestructor() function
*/
OMX_ERRORTYPE OmxComponentAmrEncoderAO::ComponentDeInit()
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ComponentDeInit IN"));
iIsInit = OMX_FALSE;
if (iCodecReady)
{
ipAmrEnc->AmrEncDeinit();
iCodecReady = OMX_FALSE;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ComponentDeInit OUT"));
return OMX_ErrorNone;
}
/* A component specific routine called from BufferMgmtWithoutMarker */
void OmxComponentAmrEncoderAO::ProcessInBufferFlag()
{
iIsInputBufferEnded = OMX_FALSE;
}