blob: efda2b130505ffc99ae84748f852fac75dffdb5a [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 "oscl_base.h"
#include "pv_omxdefs.h"
#include "omx_mpeg4_component.h"
#if PROXY_INTERFACE
#include "omx_proxy_interface.h"
#endif
// Use default DLL entry point
#ifndef OSCL_DLL_H_INCLUDED
#include "oscl_dll.h"
#endif
OSCL_DLL_ENTRY_POINT_DEFAULT()
static const uint32 mask[33] =
{
0x00000000, 0x00000001, 0x00000003, 0x00000007,
0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
0xffffffff
};
// This function is called by OMX_GetHandle and it creates an instance of the mpeg4 component AO
OSCL_EXPORT_REF OMX_ERRORTYPE Mpeg4OmxComponentFactory(OMX_OUT OMX_HANDLETYPE* pHandle, OMX_IN OMX_PTR pAppData, OMX_IN 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);
OpenmaxMpeg4AO* pOpenmaxAOType;
OMX_ERRORTYPE Status;
// move InitMpeg4OmxComponentFields content to actual constructor
pOpenmaxAOType = (OpenmaxMpeg4AO*) OSCL_NEW(OpenmaxMpeg4AO, ());
if (NULL == pOpenmaxAOType)
{
return OMX_ErrorInsufficientResources;
}
// set decoding mode to H263
pOpenmaxAOType->SetDecoderMode(MODE_MPEG4);
//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
OSCL_EXPORT_REF OMX_ERRORTYPE Mpeg4OmxComponentDestructor(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
OpenmaxMpeg4AO* pOpenmaxAOType = (OpenmaxMpeg4AO*)((OMX_COMPONENTTYPE*)pHandle)->pComponentPrivate;
// clean up decoder, OMX component stuff
pOpenmaxAOType->DestroyComponent();
// destroy the AO class
OSCL_DELETE(pOpenmaxAOType);
return OMX_ErrorNone;
}
// This function is called by OMX_GetHandle and it creates an instance of the h263 component AO
OSCL_EXPORT_REF OMX_ERRORTYPE H263OmxComponentFactory(OMX_OUT OMX_HANDLETYPE* pHandle, OMX_IN OMX_PTR pAppData, OMX_IN 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);
OpenmaxMpeg4AO* pOpenmaxAOType;
OMX_ERRORTYPE Status;
// move InitMpeg4OmxComponentFields content to actual constructor
pOpenmaxAOType = (OpenmaxMpeg4AO*) OSCL_NEW(OpenmaxMpeg4AO, ());
if (NULL == pOpenmaxAOType)
{
return OMX_ErrorInsufficientResources;
}
// set decoding mode to H263
pOpenmaxAOType->SetDecoderMode(MODE_H263);
//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
OSCL_EXPORT_REF OMX_ERRORTYPE H263OmxComponentDestructor(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
OpenmaxMpeg4AO* pOpenmaxAOType = (OpenmaxMpeg4AO*)((OMX_COMPONENTTYPE*)pHandle)->pComponentPrivate;
// clean up decoder, OMX component stuff
pOpenmaxAOType->DestroyComponent();
// destroy the AO class
OSCL_DELETE(pOpenmaxAOType);
return OMX_ErrorNone;
}
#if (DYNAMIC_LOAD_OMX_M4V_COMPONENT || DYNAMIC_LOAD_OMX_H263_COMPONENT)
class Mpeg4H263OmxSharedLibraryInterface: public OsclSharedLibraryInterface,
public OmxSharedLibraryInterface
{
public:
OsclAny *QueryOmxComponentInterface(const OsclUuid& aOmxTypeId, const OsclUuid& aInterfaceId)
{
if (PV_OMX_M4VDEC_UUID == aOmxTypeId)
{
if (PV_OMX_CREATE_INTERFACE == aInterfaceId)
{
return ((OsclAny*)(&Mpeg4OmxComponentFactory));
}
else if (PV_OMX_DESTROY_INTERFACE == aInterfaceId)
{
return ((OsclAny*)(&Mpeg4OmxComponentDestructor));
}
}
else if (PV_OMX_H263DEC_UUID == aOmxTypeId)
{
if (PV_OMX_CREATE_INTERFACE == aInterfaceId)
{
return ((OsclAny*)(&H263OmxComponentFactory));
}
else if (PV_OMX_DESTROY_INTERFACE == aInterfaceId)
{
return ((OsclAny*)(&H263OmxComponentDestructor));
}
}
return NULL;
};
OsclAny *SharedLibraryLookup(const OsclUuid& aInterfaceId)
{
if (aInterfaceId == PV_OMX_SHARED_INTERFACE)
{
return OSCL_STATIC_CAST(OmxSharedLibraryInterface*, this);
}
return NULL;
};
Mpeg4H263OmxSharedLibraryInterface() {};
};
// function to obtain the interface object from the shared library
extern "C"
{
OSCL_EXPORT_REF OsclAny* PVGetInterface()
{
return (OsclAny*) OSCL_NEW(Mpeg4H263OmxSharedLibraryInterface, ());
}
OSCL_EXPORT_REF void PVReleaseInterface(OsclSharedLibraryInterface* aInstance)
{
Mpeg4H263OmxSharedLibraryInterface* module = (Mpeg4H263OmxSharedLibraryInterface*)aInstance;
OSCL_DELETE(module);
}
}
#endif
void OpenmaxMpeg4AO::SetDecoderMode(int mode)
{
iDecMode = mode;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE OpenmaxMpeg4AO::ConstructComponent(OMX_PTR pAppData, OMX_PTR pProxy)
{
ComponentPortType *pInPort, *pOutPort;
OMX_ERRORTYPE Status;
iNumPorts = 2;
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 = OpenmaxMpeg4AO::BaseComponentProxySendCommand;
iOmxComponent.GetParameter = OpenmaxMpeg4AO::BaseComponentProxyGetParameter;
iOmxComponent.SetParameter = OpenmaxMpeg4AO::BaseComponentProxySetParameter;
iOmxComponent.GetConfig = OpenmaxMpeg4AO::BaseComponentProxyGetConfig;
iOmxComponent.SetConfig = OpenmaxMpeg4AO::BaseComponentProxySetConfig;
iOmxComponent.GetExtensionIndex = OpenmaxMpeg4AO::BaseComponentProxyGetExtensionIndex;
iOmxComponent.GetState = OpenmaxMpeg4AO::BaseComponentProxyGetState;
iOmxComponent.UseBuffer = OpenmaxMpeg4AO::BaseComponentProxyUseBuffer;
iOmxComponent.AllocateBuffer = OpenmaxMpeg4AO::BaseComponentProxyAllocateBuffer;
iOmxComponent.FreeBuffer = OpenmaxMpeg4AO::BaseComponentProxyFreeBuffer;
iOmxComponent.EmptyThisBuffer = OpenmaxMpeg4AO::BaseComponentProxyEmptyThisBuffer;
iOmxComponent.FillThisBuffer = OpenmaxMpeg4AO::BaseComponentProxyFillThisBuffer;
#else
iPVCapabilityFlags.iIsOMXComponentMultiThreaded = OMX_FALSE;
iOmxComponent.SendCommand = OpenmaxMpeg4AO::BaseComponentSendCommand;
iOmxComponent.GetParameter = OpenmaxMpeg4AO::BaseComponentGetParameter;
iOmxComponent.SetParameter = OpenmaxMpeg4AO::BaseComponentSetParameter;
iOmxComponent.GetConfig = OpenmaxMpeg4AO::BaseComponentGetConfig;
iOmxComponent.SetConfig = OpenmaxMpeg4AO::BaseComponentSetConfig;
iOmxComponent.GetExtensionIndex = OpenmaxMpeg4AO::BaseComponentGetExtensionIndex;
iOmxComponent.GetState = OpenmaxMpeg4AO::BaseComponentGetState;
iOmxComponent.UseBuffer = OpenmaxMpeg4AO::BaseComponentUseBuffer;
iOmxComponent.AllocateBuffer = OpenmaxMpeg4AO::BaseComponentAllocateBuffer;
iOmxComponent.FreeBuffer = OpenmaxMpeg4AO::BaseComponentFreeBuffer;
iOmxComponent.EmptyThisBuffer = OpenmaxMpeg4AO::BaseComponentEmptyThisBuffer;
iOmxComponent.FillThisBuffer = OpenmaxMpeg4AO::BaseComponentFillThisBuffer;
#endif
iOmxComponent.SetCallbacks = OpenmaxMpeg4AO::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. */
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_INPUTPORT_INDEX;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainVideo;
if (iDecMode == MODE_MPEG4)
{
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.cMIMEType = (OMX_STRING)"video/mpeg4";
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
}
else if (iDecMode == MODE_H263)
{
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.cMIMEType = (OMX_STRING)"video/h263";
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingH263;
}
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.pNativeRender = 0;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.bFlagErrorConcealment = OMX_FALSE;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.eColorFormat = OMX_COLOR_FormatUnused;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.nFrameWidth = 176;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.nFrameHeight = 144;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.nBitrate = 64000;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.video.xFramerate = (15 << 16);
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_MP4;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferCountMin = 1;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize = INPUT_BUFFER_SIZE_MP4;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainVideo;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.cMIMEType = (OMX_STRING)"raw";
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.pNativeRender = 0;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.bFlagErrorConcealment = OMX_FALSE;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameWidth = 176; //320; //176;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nStride = 176;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameHeight = 144; //240; //144;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nSliceHeight = 144;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nBitrate = 64000;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.xFramerate = (15 << 16);
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_MP4;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountMin = 1;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferSize = OUTPUT_BUFFER_SIZE_MP4;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE;
ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE;
if (iDecMode == MODE_MPEG4)
{
//Default values for mpeg4 video param port
ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoMpeg4.nPortIndex = OMX_PORT_INPUTPORT_INDEX;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoMpeg4.eProfile = OMX_VIDEO_MPEG4ProfileSimple;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoMpeg4.eLevel = OMX_VIDEO_MPEG4Level3;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.nPortIndex = OMX_PORT_INPUTPORT_INDEX;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.nProfileIndex = 0;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.eProfile = OMX_VIDEO_MPEG4ProfileSimple;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.eLevel = OMX_VIDEO_MPEG4Level3;
oscl_strncpy((OMX_STRING)iComponentRole, (OMX_STRING)"video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE);
}
else if (iDecMode == MODE_H263)
{
//Default values for h263 video param port
ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoH263.nPortIndex = OMX_PORT_INPUTPORT_INDEX;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoH263.eProfile = (OMX_VIDEO_H263PROFILETYPE) (OMX_VIDEO_H263ProfileBaseline | OMX_VIDEO_H263ProfileISWV2);
ipPorts[OMX_PORT_INPUTPORT_INDEX]->VideoH263.eLevel = OMX_VIDEO_H263Level45;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.nPortIndex = OMX_PORT_INPUTPORT_INDEX;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.nProfileIndex = 0;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.eProfile = OMX_VIDEO_H263ProfileBaseline | OMX_VIDEO_H263ProfileISWV2;
ipPorts[OMX_PORT_INPUTPORT_INDEX]->ProfileLevel.eLevel = OMX_VIDEO_H263Level45;
oscl_strncpy((OMX_STRING)iComponentRole, (OMX_STRING)"video_decoder.h263", OMX_MAX_STRINGNAME_SIZE);
}
iPortTypesParam.nPorts = 2;
iPortTypesParam.nStartPortNumber = 0;
pInPort = (ComponentPortType*) ipPorts[OMX_PORT_INPUTPORT_INDEX];
pOutPort = (ComponentPortType*) ipPorts[OMX_PORT_OUTPUTPORT_INDEX];
pInPort->ActualNumPortFormatsSupported = 1;
//OMX_VIDEO_PARAM_PORTFORMATTYPE INPUT PORT SETTINGS
//On input port for index 0
SetHeader(&pInPort->VideoParam[0], sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
pInPort->VideoParam[0].nPortIndex = 0;
pInPort->VideoParam[0].nIndex = 0;
if (iDecMode == MODE_MPEG4)
{
pInPort->VideoParam[0].eCompressionFormat = OMX_VIDEO_CodingMPEG4;
}
else if (iDecMode == MODE_H263)
{
pInPort->VideoParam[0].eCompressionFormat = OMX_VIDEO_CodingH263;
}
pInPort->VideoParam[0].eColorFormat = OMX_COLOR_FormatUnused;
pOutPort->ActualNumPortFormatsSupported = 1;
//OMX_VIDEO_PARAM_PORTFORMATTYPE OUTPUT PORT SETTINGS
//On output port for index 0
SetHeader(&pOutPort->VideoParam[0], sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
pOutPort->VideoParam[0].nPortIndex = 1;
pOutPort->VideoParam[0].nIndex = 0;
pOutPort->VideoParam[0].eCompressionFormat = OMX_VIDEO_CodingUnused;
pOutPort->VideoParam[0].eColorFormat = OMX_COLOR_FormatYUV420Planar;
iUseExtTimestamp = OMX_TRUE;
if (ipMpegDecoderObject)
{
OSCL_DELETE(ipMpegDecoderObject);
ipMpegDecoderObject = NULL;
}
ipMpegDecoderObject = OSCL_NEW(Mpeg4Decoder_OMX, ());
oscl_memset(ipMpegDecoderObject, 0, sizeof(Mpeg4Decoder_OMX));
#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().
*/
OMX_ERRORTYPE OpenmaxMpeg4AO::DestroyComponent()
{
if (OMX_FALSE != iIsInit)
{
ComponentDeInit();
}
//Destroy the base class now
DestroyBaseComponent();
if (ipMpegDecoderObject)
{
OSCL_DELETE(ipMpegDecoderObject);
ipMpegDecoderObject = NULL;
}
if (ipAppPriv)
{
ipAppPriv->CompHandle = NULL;
oscl_free(ipAppPriv);
ipAppPriv = NULL;
}
return OMX_ErrorNone;
}
/* This function will be called in case of buffer management without marker bit present
* The purpose is to copy the current input buffer into a big temporary buffer, so that
* an incomplete/partial frame is never passed to the decoder library for decode
*/
void OpenmaxMpeg4AO::ComponentBufferMgmtWithoutMarker()
{
//This common routine has been written in the base class
TempInputBufferMgmtWithoutMarker();
}
void OpenmaxMpeg4AO::ProcessData()
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : ProcessData IN"));
if (!iEndOfFrameFlag)
{
DecodeWithoutMarker();
}
else
{
DecodeWithMarker();
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : ProcessData OUT"));
}
void OpenmaxMpeg4AO::DecodeWithoutMarker()
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker IN"));
QueueType* pInputQueue = ipPorts[OMX_PORT_INPUTPORT_INDEX]->pBufferQueue;
QueueType* pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue;
ComponentPortType* pOutPort = ipPorts[OMX_PORT_OUTPUTPORT_INDEX];
OMX_COMPONENTTYPE *pHandle = &iOmxComponent;
OMX_U8* pOutBuffer;
OMX_U32 OutputLength;
OMX_U8* pTempInBuffer;
OMX_U32 TempInLength;
OMX_BOOL DecodeReturn;
OMX_BOOL MarkerFlag = OMX_FALSE;
OMX_BOOL ResizeNeeded = OMX_FALSE;
OMX_U32 TempInputBufferSize = (2 * sizeof(uint8) * (ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize));
OMX_U32 CurrWidth = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameWidth;
OMX_U32 CurrHeight = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameHeight;
if ((!iIsInputBufferEnded) || iEndofStream)
{
//Check whether a new output buffer is available or not
if (0 == (GetQueueNumElem(pOutputQueue)))
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker OUT output buffer unavailable"));
//Store the mark data for output buffer, as it will be overwritten next time
if (NULL != ipTargetComponent)
{
ipTempTargetComponent = ipTargetComponent;
iTempTargetMarkData = iTargetMarkData;
iMarkPropagate = OMX_TRUE;
}
return;
}
ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue);
if (NULL == ipOutputBuffer)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker Error, output buffer dequeue returned NULL, OUT"));
return;
}
//Do not proceed if the output buffer can't fit the YUV data
if ((ipOutputBuffer->nAllocLen < (OMX_U32)((((CurrWidth + 15) >> 4) << 4) *(((CurrHeight + 15) >> 4) << 4) * 3 / 2)) && (OMX_TRUE == ipMpegDecoderObject->Mpeg4InitCompleteFlag))
{
ipOutputBuffer->nFilledLen = 0;
ReturnOutputBuffer(ipOutputBuffer, pOutPort);
ipOutputBuffer = NULL;
return;
}
ipOutputBuffer->nFilledLen = 0;
/* 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 ((OMX_TRUE == iMarkPropagate) && (ipTempTargetComponent != ipTargetComponent))
{
ipOutputBuffer->hMarkTargetComponent = ipTempTargetComponent;
ipOutputBuffer->pMarkData = iTempTargetMarkData;
ipTempTargetComponent = NULL;
iMarkPropagate = OMX_FALSE;
}
else if (ipTargetComponent != NULL)
{
ipOutputBuffer->hMarkTargetComponent = ipTargetComponent;
ipOutputBuffer->pMarkData = iTargetMarkData;
ipTargetComponent = NULL;
iMarkPropagate = OMX_FALSE;
}
//Mark buffer code ends here
pOutBuffer = ipOutputBuffer->pBuffer;
OutputLength = 0;
pTempInBuffer = ipTempInputBuffer + iTempConsumedLength;
TempInLength = iTempInputBufferLength;
//Output buffer is passed as a short pointer
DecodeReturn = ipMpegDecoderObject->Mp4DecodeVideo(pOutBuffer, (OMX_U32*) & OutputLength,
&(pTempInBuffer),
&TempInLength,
&(ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam),
&iFrameCount,
MarkerFlag,
&ResizeNeeded);
ipOutputBuffer->nFilledLen = OutputLength;
//offset not required in our case, set it to zero
ipOutputBuffer->nOffset = 0;
//If decoder returned error, report it to the client via a callback
if (!DecodeReturn && OMX_FALSE == ipMpegDecoderObject->Mpeg4InitCompleteFlag)
{
// initialization error, stop playback
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker ErrorBadParameter callback send"));
(*(ipCallbacks->EventHandler))
(pHandle,
iCallbackData,
OMX_EventError,
OMX_ErrorBadParameter,
0,
NULL);
}
else if (!DecodeReturn && OMX_FALSE == iEndofStream)
{
// decoding error
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker ErrorStreamCorrupt callback send"));
(*(ipCallbacks->EventHandler))
(pHandle,
iCallbackData,
OMX_EventError,
OMX_ErrorStreamCorrupt,
0,
NULL);
}
if (ResizeNeeded == OMX_TRUE)
{
// send port settings changed event
OMX_COMPONENTTYPE* pHandle = (OMX_COMPONENTTYPE*) ipAppPriv->CompHandle;
// set the flag to disable further processing until Client reacts to this
// by doing dynamic port reconfiguration
iResizePending = OMX_TRUE;
(*(ipCallbacks->EventHandler))
(pHandle,
iCallbackData,
OMX_EventPortSettingsChanged, //The command was completed
OMX_PORT_OUTPUTPORT_INDEX,
0,
NULL);
}
//Set the timestamp equal to the input buffer timestamp
ipOutputBuffer->nTimeStamp = iFrameTimestamp;
iTempConsumedLength += (iTempInputBufferLength - TempInLength);
iTempInputBufferLength = TempInLength;
//Do not decode if big buffer is less than half the size
if (TempInLength < (TempInputBufferSize >> 1))
{
iIsInputBufferEnded = OMX_TRUE;
iNewInBufferRequired = OMX_TRUE;
}
/* 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 == iTempInputBufferLength) || (!DecodeReturn))
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker EOS callback send"));
(*(ipCallbacks->EventHandler))
(pHandle,
iCallbackData,
OMX_EventBufferFlag,
1,
OMX_BUFFERFLAG_EOS,
NULL);
iNewInBufferRequired = OMX_TRUE;
iEndofStream = OMX_FALSE;
ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_EOS;
ReturnOutputBuffer(ipOutputBuffer, pOutPort);
ipOutputBuffer = NULL;
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker OUT"));
return;
}
}
//Send the output buffer back after decode
ReturnOutputBuffer(ipOutputBuffer, pOutPort);
ipOutputBuffer = NULL;
/* 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 ((TempInLength != 0 || GetQueueNumElem(pInputQueue) > 0) && (GetQueueNumElem(pOutputQueue) > 0) && (ResizeNeeded == OMX_FALSE))
{
RunIfNotReady();
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker OUT"));
return;
}
void OpenmaxMpeg4AO::DecodeWithMarker()
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithMarker IN"));
QueueType* pInputQueue = ipPorts[OMX_PORT_INPUTPORT_INDEX]->pBufferQueue;
QueueType* pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue;
ComponentPortType* pInPort = ipPorts[OMX_PORT_INPUTPORT_INDEX];
ComponentPortType* pOutPort = ipPorts[OMX_PORT_OUTPUTPORT_INDEX];
OMX_U8* pOutBuffer;
OMX_U32 OutputLength;
OMX_BOOL DecodeReturn = OMX_FALSE;
OMX_BOOL MarkerFlag = OMX_TRUE;
OMX_COMPONENTTYPE * pHandle = &iOmxComponent;
OMX_BOOL ResizeNeeded = OMX_FALSE;
OMX_U32 CurrWidth = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameWidth;
OMX_U32 CurrHeight = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.video.nFrameHeight;
if ((!iIsInputBufferEnded) || (iEndofStream))
{
//Check whether a new output buffer is available or not
if (0 == (GetQueueNumElem(pOutputQueue)))
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithMarker OUT output buffer unavailable"));
iNewInBufferRequired = OMX_FALSE;
return;
}
ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue);
if (NULL == ipOutputBuffer)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithMarker Error, output buffer dequeue returned NULL, OUT"));
iNewInBufferRequired = OMX_FALSE;
return;
}
//Do not proceed if the output buffer can't fit the YUV data
if ((ipOutputBuffer->nAllocLen < (OMX_U32)((((CurrWidth + 15) >> 4) << 4) *(((CurrHeight + 15) >> 4) << 4) * 3 / 2)) && (OMX_TRUE == ipMpegDecoderObject->Mpeg4InitCompleteFlag))
{
ipOutputBuffer->nFilledLen = 0;
ReturnOutputBuffer(ipOutputBuffer, pOutPort);
ipOutputBuffer = NULL;
return;
}
ipOutputBuffer->nFilledLen = 0;
/* 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 (iInputCurrLength > 0)
{
pOutBuffer = ipOutputBuffer->pBuffer;
OutputLength = 0;
//Output buffer is passed as a short pointer
DecodeReturn = ipMpegDecoderObject->Mp4DecodeVideo(pOutBuffer, (OMX_U32*) & OutputLength,
&(ipFrameDecodeBuffer),
&(iInputCurrLength),
&(ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam),
&iFrameCount,
MarkerFlag,
&ResizeNeeded);
ipOutputBuffer->nFilledLen = OutputLength;
//offset not required in our case, set it to zero
ipOutputBuffer->nOffset = 0;
//If decoder returned error, report it to the client via a callback
if (!DecodeReturn && OMX_FALSE == ipMpegDecoderObject->Mpeg4InitCompleteFlag)
{
// initialization error, stop playback
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithoutMarker ErrorBadParameter callback send"));
(*(ipCallbacks->EventHandler))
(pHandle,
iCallbackData,
OMX_EventError,
OMX_ErrorBadParameter,
0,
NULL);
}
else if (!DecodeReturn && OMX_FALSE == iEndofStream)
{
// decode error
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithMarker ErrorStreamCorrupt callback send"));
(*(ipCallbacks->EventHandler))
(pHandle,
iCallbackData,
OMX_EventError,
OMX_ErrorStreamCorrupt,
0,
NULL);
}
if (ResizeNeeded == OMX_TRUE)
{
// send port settings changed event
OMX_COMPONENTTYPE* pHandle = (OMX_COMPONENTTYPE*) ipAppPriv->CompHandle;
iResizePending = OMX_TRUE;
(*(ipCallbacks->EventHandler))
(pHandle,
iCallbackData,
OMX_EventPortSettingsChanged, //The command was completed
OMX_PORT_OUTPUTPORT_INDEX,
0,
NULL);
}
//Set the timestamp equal to the input buffer timestamp
if (OMX_TRUE == iUseExtTimestamp)
{
ipOutputBuffer->nTimeStamp = iFrameTimestamp;
}
/* Discard the input frame if it is with the marker bit & decoder fails*/
if (iInputCurrLength == 0 || !DecodeReturn)
{
ipInputBuffer->nFilledLen = 0;
ReturnInputBuffer(ipInputBuffer, pInPort);
ipInputBuffer = NULL;
iNewInBufferRequired = OMX_TRUE;
iIsInputBufferEnded = OMX_TRUE;
iUseExtTimestamp = OMX_TRUE;
iInputCurrLength = 0;
}
else
{
iNewInBufferRequired = OMX_FALSE;
iIsInputBufferEnded = OMX_FALSE;
iUseExtTimestamp = OMX_FALSE;
}
}
else if (iEndofStream == OMX_FALSE)
{
// it's possible that after partial frame assembly, the input buffer still remains empty (due to
// client erroneously sending such buffers). This code adds robustness in the sense that it returns such buffer to the client
ipInputBuffer->nFilledLen = 0;
ReturnInputBuffer(ipInputBuffer, pInPort);
ipInputBuffer = NULL;
iNewInBufferRequired = OMX_TRUE;
iIsInputBufferEnded = OMX_TRUE;
iUseExtTimestamp = OMX_TRUE;
}
/* 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 (!DecodeReturn)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithMarker EOS callback send"));
(*(ipCallbacks->EventHandler))
(pHandle,
iCallbackData,
OMX_EventBufferFlag,
1,
OMX_BUFFERFLAG_EOS,
NULL);
iNewInBufferRequired = OMX_TRUE;
//Mark this flag false once the callback has been send back
iEndofStream = OMX_FALSE;
ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_EOS;
ReturnOutputBuffer(ipOutputBuffer, pOutPort);
ipOutputBuffer = NULL;
if ((iNumInputBuffer != 0) && (NULL != ipInputBuffer))
{
ReturnInputBuffer(ipInputBuffer, pInPort);
ipInputBuffer = NULL;
iIsInputBufferEnded = OMX_TRUE;
iInputCurrLength = 0;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithMarker OUT"));
return;
}
}
//Send the output buffer back after decode
ReturnOutputBuffer(ipOutputBuffer, pOutPort);
ipOutputBuffer = NULL;
/* 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 ((iInputCurrLength != 0 || GetQueueNumElem(pInputQueue) > 0)
&& (GetQueueNumElem(pOutputQueue) > 0) && (ResizeNeeded == OMX_FALSE))
{
RunIfNotReady();
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : DecodeWithMarker OUT"));
return;
}
//Not implemented & supported in case of base profile components
void OpenmaxMpeg4AO::ComponentGetRolesOfComponent(OMX_STRING* aRoleString)
{
*aRoleString = (OMX_STRING)"video_decoder.mpeg4";
}
//Component constructor
OpenmaxMpeg4AO::OpenmaxMpeg4AO()
{
iUseExtTimestamp = OMX_TRUE;
ipMpegDecoderObject = NULL;
if (!IsAdded())
{
AddToScheduler();
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : constructed"));
}
//Active object destructor
OpenmaxMpeg4AO::~OpenmaxMpeg4AO()
{
if (IsAdded())
{
RemoveFromScheduler();
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : destructed"));
}
/** The Initialization function
*/
OMX_ERRORTYPE OpenmaxMpeg4AO::ComponentInit()
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : ComponentInit IN"));
OMX_ERRORTYPE Status = OMX_ErrorNone;
if (OMX_TRUE == iIsInit)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : ComponentInit error incorrect operation"));
return OMX_ErrorIncorrectStateOperation;
}
iIsInit = OMX_TRUE;
if (!iCodecReady)
{
//Call the init routine here in case of H263 mode, without waiting for buffers
if (iDecMode == MODE_H263)
{
OMX_S32 Width, Height, Size = 0;
OMX_U8* Buff = NULL;
//Pass dummy pointers during initializations
if (OMX_TRUE != ipMpegDecoderObject->InitializeVideoDecode(&Width, &Height, &Buff, &Size, iDecMode))
{
Status = OMX_ErrorInsufficientResources;
}
ipMpegDecoderObject->Mpeg4InitCompleteFlag = OMX_TRUE;
}
else
{
//mp4 lib init
Status = ipMpegDecoderObject->Mp4DecInit();
}
iCodecReady = OMX_TRUE;
}
iUseExtTimestamp = OMX_TRUE;
iInputCurrLength = 0;
//Used in dynamic port reconfiguration
iFrameCount = 0;
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : ComponentInit OUT"));
return Status;
}
/** This function is called upon a transition to the idle or invalid state.
* Also it is called by the ComponentDestructor() function
*/
OMX_ERRORTYPE OpenmaxMpeg4AO::ComponentDeInit()
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : ComponentDeInit IN"));
OMX_ERRORTYPE Status = OMX_ErrorNone;
iIsInit = OMX_FALSE;
if (iCodecReady)
{
Status = ipMpegDecoderObject->Mp4DecDeinit();
iCodecReady = OMX_FALSE;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OpenmaxMpeg4AO : ComponentDeInit OUT"));
return Status;
}
OMX_ERRORTYPE OpenmaxMpeg4AO::GetConfig(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nIndex,
OMX_INOUT OMX_PTR pComponentConfigStructure)
{
OSCL_UNUSED_ARG(hComponent);
OSCL_UNUSED_ARG(nIndex);
OSCL_UNUSED_ARG(pComponentConfigStructure);
return OMX_ErrorNotImplemented;
}
OMX_ERRORTYPE OpenmaxMpeg4AO::ReAllocatePartialAssemblyBuffers(OMX_BUFFERHEADERTYPE* aInputBufferHdr)
{
// check if there is enough data in the buffer to read the information that we need
if (aInputBufferHdr->nFilledLen >= MINIMUM_H263_SHORT_HEADER_SIZE)
{
OMX_U8 *pInputBuffer = (aInputBufferHdr->pBuffer + aInputBufferHdr->nOffset);
if (MODE_H263 == iDecMode)
{
OMX_BOOL Status = OMX_TRUE;
Status = DecodeH263Header(pInputBuffer, &iInputCurrBufferSize);
// Re-allocate the partial frame buffer in case the stream is not corrupted,
// otherwise leave the buffer size as it is
if (OMX_TRUE == Status)
{
if (NULL != ipInputCurrBuffer)
{
ipInputCurrBuffer = (OMX_U8*) oscl_realloc(ipInputCurrBuffer, iInputCurrBufferSize);
if (NULL == ipInputCurrBuffer)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentBase : DoStateSet error insufficient resources"));
return OMX_ErrorInsufficientResources;
}
}
//Used when the buffers are not marked with EndOfFrame flag
if (NULL != ipTempInputBuffer)
{
ipTempInputBuffer = (OMX_U8*) oscl_realloc(ipTempInputBuffer, iInputCurrBufferSize);
if (NULL == ipTempInputBuffer)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentBase : DoStateSet error insufficient resources"));
return OMX_ErrorInsufficientResources;
}
}
}
}
return OMX_ErrorNone;
}
else
{
return OMX_ErrorInsufficientResources;
}
}
OMX_BOOL OpenmaxMpeg4AO::DecodeH263Header(OMX_U8* aInputBuffer,
OMX_U32* aBufferSize)
{
uint32 codeword;
int32 extended_PTYPE = 0;
int32 UFEP = 0;
int32 custom_PFMT = 0;
//Reset the data bit position to the start of the stream
iH263DataBitPos = 0;
iH263BitPos = 0;
//BitBuf contains the first 4 bytes of the aInputBuffer
iH263BitBuf = (aInputBuffer[0] << 24) | (aInputBuffer[1] << 16) | (aInputBuffer[2] << 8) | aInputBuffer[3];
ReadBits(aInputBuffer, 22, &codeword);
if (codeword != 0x20)
{
return OMX_FALSE;
}
ReadBits(aInputBuffer, 8, &codeword);
ReadBits(aInputBuffer, 1, &codeword);
if (codeword == 0) return OMX_FALSE;
ReadBits(aInputBuffer, 1, &codeword);
if (codeword == 1) return OMX_FALSE;
ReadBits(aInputBuffer, 1, &codeword);
if (codeword == 1) return OMX_FALSE;
ReadBits(aInputBuffer, 1, &codeword);
if (codeword == 1) return OMX_FALSE;
ReadBits(aInputBuffer, 1, &codeword);
if (codeword == 1) return OMX_FALSE;
/* source format */
ReadBits(aInputBuffer, 3, &codeword);
switch (codeword)
{
case 1:
*aBufferSize = 32000;
break;
case 2:
*aBufferSize = 32000;
break;
case 3:
*aBufferSize = 128000;
break;
case 4:
*aBufferSize = 256000;
break;
case 5:
*aBufferSize = 512000;
break;
case 7:
extended_PTYPE = 1;
break;
default:
/* Msg("H.263 source format not legal\n"); */
return OMX_FALSE;
}
if (extended_PTYPE == 0)
{
return OMX_TRUE;
}
/* source format */
ReadBits(aInputBuffer, 3, &codeword);
UFEP = codeword;
if (UFEP == 1)
{
ReadBits(aInputBuffer, 3, &codeword);
switch (codeword)
{
case 1:
*aBufferSize = 32000;
break;
case 2:
*aBufferSize = 32000;
break;
case 3:
*aBufferSize = 128000;
break;
case 4:
*aBufferSize = 256000;
break;
case 5:
*aBufferSize = 512000;
break;
case 6:
custom_PFMT = 1;
break;
default:
/* Msg("H.263 source format not legal\n"); */
return OMX_FALSE;
}
if (custom_PFMT == 0)
{
return OMX_TRUE;
}
ReadBits(aInputBuffer, 1, &codeword);
ReadBits(aInputBuffer, 1, &codeword);
if (codeword) return OMX_FALSE;
ReadBits(aInputBuffer, 1, &codeword);
if (codeword) return OMX_FALSE;
ReadBits(aInputBuffer, 1, &codeword);
if (codeword) return OMX_FALSE;
ReadBits(aInputBuffer, 3, &codeword);
ReadBits(aInputBuffer, 3, &codeword);
if (codeword) return OMX_FALSE; /* RPS, ISD, AIV */
ReadBits(aInputBuffer, 1, &codeword);
ReadBits(aInputBuffer, 4, &codeword);
if (codeword != 8) return OMX_FALSE;
}
if (UFEP == 0 || UFEP == 1)
{
ReadBits(aInputBuffer, 3, &codeword);
if (codeword > 1) return OMX_FALSE;
ReadBits(aInputBuffer, 1, &codeword);
if (codeword) return OMX_FALSE;
ReadBits(aInputBuffer, 1, &codeword);
if (codeword) return OMX_FALSE;
ReadBits(aInputBuffer, 1, &codeword);
ReadBits(aInputBuffer, 3, &codeword);
if (codeword != 1) return OMX_FALSE;
}
else
{
return OMX_FALSE;
}
ReadBits(aInputBuffer, 1, &codeword);
if (codeword) return OMX_FALSE; /* CPM */
if (custom_PFMT == 1 && UFEP == 1)
{
OMX_U32 DisplayWidth, Width, DisplayHeight, Height, Resolution;
ReadBits(aInputBuffer, 4, &codeword);
if (codeword == 0) return OMX_FALSE;
if (codeword == 0xf)
{
ReadBits(aInputBuffer, 8, &codeword);
ReadBits(aInputBuffer, 8, &codeword);
}
ReadBits(aInputBuffer, 9, &codeword);
DisplayWidth = (codeword + 1) << 2;
Width = (DisplayWidth + 15) & -16;
ReadBits(aInputBuffer, 1, &codeword);
if (codeword != 1) return OMX_FALSE;
ReadBits(aInputBuffer, 9, &codeword);
if (codeword == 0) return OMX_FALSE;
DisplayHeight = codeword << 2;
Height = (DisplayHeight + 15) & -16;
Resolution = Width * Height;
if (Resolution <= 25344) //25344 = 176x144 (QCIF)
{
*aBufferSize = 32000;
}
else if (Resolution <= 101376) //101376 = 352x288 (CIF)
{
*aBufferSize = 128000;
}
else if (Resolution <= 405504) //405504 = 704*576 (4CIF)
{
*aBufferSize = 256000;
}
else //1408x1152 (16CIF)
{
//This is the max buffer size that we want to allocate
*aBufferSize = 512000;
}
}
return OMX_TRUE;
}
void OpenmaxMpeg4AO::ReadBits(OMX_U8* aStream, /* Input Stream */
uint8 aNumBits, /* nr of bits to read */
uint32* aOutData /* output target */
)
{
uint8 *bits;
uint32 dataBitPos = iH263DataBitPos;
uint32 bitPos = iH263BitPos;
uint32 dataBytePos;
if (aNumBits > (32 - bitPos)) /* not enough bits */
{
dataBytePos = dataBitPos >> 3; /* Byte Aligned Position */
bitPos = dataBitPos & 7; /* update bit position */
bits = &aStream[dataBytePos];
iH263BitBuf = (bits[0] << 24) | (bits[1] << 16) | (bits[2] << 8) | bits[3];
}
iH263DataBitPos += aNumBits;
iH263BitPos = (unsigned char)(bitPos + aNumBits);
*aOutData = (iH263BitBuf >> (32 - iH263BitPos)) & mask[(uint16)aNumBits];
return;
}