blob: 607e18d637b71242e8e86c16d08ceb049aae0325 [file] [log] [blame]
/*--------------------------------------------------------------------------
Copyright (c) 2010, Code Aurora Forum. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Code Aurora nor
the names of its contributors may be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------*/
/*========================================================================
Include Files
==========================================================================*/
#include "venctest_Encoder.h"
#include "venctest_Debug.h"
#include "venctest_Signal.h"
#include "venctest_Pmem.h"
#include "venctest_SignalQueue.h"
#include "venctest_StatsThread.h"
#include "OMX_Component.h"
#include "OMX_QCOMExtns.h"
#define OMX_SPEC_VERSION 0x00000101
#define OMX_INIT_STRUCT(_s_, _name_) \
memset((_s_), 0x0, sizeof(_name_)); \
(_s_)->nSize = sizeof(_name_); \
(_s_)->nVersion.nVersion = OMX_SPEC_VERSION
namespace venctest
{
static const OMX_U32 PORT_INDEX_IN = 0;
static const OMX_U32 PORT_INDEX_OUT = 1;
struct CmdType
{
OMX_EVENTTYPE eEvent;
OMX_COMMANDTYPE eCmd;
OMX_U32 sCmdData;
OMX_ERRORTYPE eResult;
};
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
Encoder::Encoder()
{
VENC_TEST_MSG_ERROR("Should not be here this is a private constructor");
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
Encoder::Encoder(EmptyDoneCallbackType pEmptyDoneFn,
FillDoneCallbackType pFillDoneFn,
OMX_PTR pAppData,
OMX_VIDEO_CODINGTYPE eCodec)
: m_pSignalQueue(new SignalQueue(32, sizeof(CmdType))),
m_pInMem(0),
m_pOutMem(0),
m_pStats(new StatsThread(2000)), // 2 second statistics intervals
m_pEventFn(NULL),
m_pEmptyDoneFn(pEmptyDoneFn),
m_pFillDoneFn(pFillDoneFn),
m_pAppData(pAppData),
m_bInUseBuffer(OMX_FALSE),
m_bOutUseBuffer(OMX_FALSE),
m_pInputBuffers(NULL),
m_pOutputBuffers(NULL),
m_hEncoder(NULL),
m_eState(OMX_StateLoaded),
m_nInputBuffers(0),
m_nOutputBuffers(0),
m_nInputBufferSize(0),
m_nOutputBufferSize(0),
m_eCodec(eCodec),
m_nInFrameIn(0),
m_nOutFrameIn(0),
m_nInFrameOut(0),
m_nOutFrameOut(0)
{
static OMX_CALLBACKTYPE callbacks = {EventCallback,
EmptyDoneCallback,
FillDoneCallback};
if (m_pEmptyDoneFn == NULL)
{
VENC_TEST_MSG_ERROR("Empty buffer fn is NULL");
}
if (m_pFillDoneFn == NULL)
{
VENC_TEST_MSG_ERROR("Fill buffer fn is NULL");
}
// MPEG4
if (eCodec == OMX_VIDEO_CodingMPEG4)
{
VENC_TEST_MSG_MEDIUM("Getting handle for mpeg4");
if (OMX_GetHandle(&m_hEncoder,
(OMX_STRING)"OMX.qcom.video.encoder.mpeg4",
this,
&callbacks) != OMX_ErrorNone)
{
VENC_TEST_MSG_ERROR("Error getting component handle");
}
}
// H263
else if (eCodec == OMX_VIDEO_CodingH263)
{
VENC_TEST_MSG_MEDIUM("Getting handle for h263");
if (OMX_GetHandle(&m_hEncoder,
(OMX_STRING)"OMX.qcom.video.encoder.h263",
this,
&callbacks) != OMX_ErrorNone)
{
VENC_TEST_MSG_ERROR("Error getting component handle");
}
}
// H264
else if (eCodec == OMX_VIDEO_CodingAVC)
{
VENC_TEST_MSG_MEDIUM("Getting handle for avc");
if (OMX_GetHandle(&m_hEncoder,
(OMX_STRING)"OMX.qcom.video.encoder.avc",
this,
&callbacks) != OMX_ErrorNone)
{
VENC_TEST_MSG_ERROR("Error getting component handle");
}
}
else
{
VENC_TEST_MSG_ERROR("Invalid codec selection");
}
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
Encoder::~Encoder()
{
OMX_FreeHandle(m_hEncoder);
if (m_pSignalQueue)
{
delete m_pSignalQueue;
}
if (m_pStats)
{
delete m_pStats;
}
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE Encoder::Configure(EncoderConfigType* pConfig)
{
OMX_ERRORTYPE result = OMX_ErrorNone;
if (pConfig == NULL)
{
result = OMX_ErrorBadParameter;
}
else
{
m_nInputBuffers = pConfig->nInBufferCount;
m_nOutputBuffers = pConfig->nOutBufferCount;
}
//////////////////////////////////////////
// port format (set the codec)
//////////////////////////////////////////
if (result == OMX_ErrorNone)
{
OMX_VIDEO_PARAM_PORTFORMATTYPE fmt;
OMX_INIT_STRUCT(&fmt, OMX_VIDEO_PARAM_PORTFORMATTYPE);
fmt.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
result = OMX_GetParameter(m_hEncoder,
OMX_IndexParamVideoPortFormat,
(OMX_PTR) &fmt);
if (result == OMX_ErrorNone)
{
fmt.eCompressionFormat = m_eCodec;
result = OMX_SetParameter(m_hEncoder,
OMX_IndexParamVideoPortFormat,
(OMX_PTR) &fmt);
}
}
//////////////////////////////////////////
// codec specific config
//////////////////////////////////////////
if (result == OMX_ErrorNone)
{
if (m_eCodec == OMX_VIDEO_CodingMPEG4)
{
OMX_VIDEO_PARAM_MPEG4TYPE mp4;
OMX_INIT_STRUCT(&mp4, OMX_VIDEO_PARAM_MPEG4TYPE);
mp4.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
result = OMX_GetParameter(m_hEncoder,
OMX_IndexParamVideoMpeg4,
(OMX_PTR) &mp4);
if (result == OMX_ErrorNone)
{
mp4.nTimeIncRes = pConfig->nTimeIncRes;
mp4.nPFrames = pConfig->nIntraPeriod - 1;
mp4.eProfile = OMX_VIDEO_MPEG4ProfileSimple;
mp4.eLevel = OMX_VIDEO_MPEG4Level5;
if (pConfig->nOutputFrameWidth > 176 &&
pConfig->nOutputFrameHeight > 144)
{
mp4.eLevel = OMX_VIDEO_MPEG4Level2;
}
else
{
mp4.eLevel = OMX_VIDEO_MPEG4Level0;
}
mp4.bACPred = OMX_TRUE;
mp4.bSVH = pConfig->bEnableShortHeader;
mp4.nHeaderExtension = pConfig->nHECInterval;
result = OMX_SetParameter(m_hEncoder,
OMX_IndexParamVideoMpeg4,
(OMX_PTR) &mp4);
}
}
else if (m_eCodec == OMX_VIDEO_CodingH263)
{
OMX_VIDEO_PARAM_H263TYPE h263;
OMX_INIT_STRUCT(&h263, OMX_VIDEO_PARAM_H263TYPE);
h263.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
result = OMX_GetParameter(m_hEncoder,
OMX_IndexParamVideoH263,
(OMX_PTR) &h263);
if (result == OMX_ErrorNone)
{
h263.nPFrames = pConfig->nIntraPeriod - 1;
h263.nBFrames = 0;
h263.eProfile = OMX_VIDEO_H263ProfileBaseline;
h263.eLevel = OMX_VIDEO_H263Level10;
h263.bPLUSPTYPEAllowed = OMX_FALSE;
h263.nAllowedPictureTypes = 2;
h263.bForceRoundingTypeToZero = OMX_TRUE;
h263.nPictureHeaderRepetition = 0;
if (pConfig->eResyncMarkerType == RESYNC_MARKER_GOB)
{
h263.nGOBHeaderInterval = pConfig->nResyncMarkerSpacing;
}
else if (pConfig->eResyncMarkerType == RESYNC_MARKER_MB)
{
OMX_VIDEO_PARAM_MPEG4TYPE mp4;
OMX_INIT_STRUCT(&mp4, OMX_VIDEO_PARAM_MPEG4TYPE);
mp4.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
result = OMX_GetParameter(m_hEncoder,
OMX_IndexParamVideoMpeg4,
(OMX_PTR) &mp4);
if (result == OMX_ErrorNone)
{
// annex k
mp4.nSliceHeaderSpacing = pConfig->nResyncMarkerSpacing;
result = OMX_SetParameter(m_hEncoder,
OMX_IndexParamVideoMpeg4,
(OMX_PTR) &mp4);
}
h263.nGOBHeaderInterval = 0;
}
else
{
h263.nGOBHeaderInterval = 0;
}
result = OMX_SetParameter(m_hEncoder,
OMX_IndexParamVideoH263,
(OMX_PTR) &h263);
}
}
else if (m_eCodec == OMX_VIDEO_CodingAVC)
{
OMX_VIDEO_PARAM_AVCTYPE avc;
OMX_INIT_STRUCT(&avc, OMX_VIDEO_PARAM_AVCTYPE);
avc.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
result = OMX_GetParameter(m_hEncoder,
OMX_IndexParamVideoAvc,
(OMX_PTR) &avc);
if (result == OMX_ErrorNone)
{
avc.nPFrames = pConfig->nIntraPeriod - 1;
avc.nBFrames = 0;
avc.eProfile = OMX_VIDEO_AVCProfileBaseline;
avc.eLevel = OMX_VIDEO_AVCLevel1;
if (pConfig->nOutputFrameWidth * pConfig->nOutputFrameHeight / 256 < 792)
{
avc.eLevel = OMX_VIDEO_AVCLevel21;
}
else if (pConfig->nOutputFrameWidth * pConfig->nOutputFrameHeight / 256 < 1620)
{
avc.eLevel = OMX_VIDEO_AVCLevel22;
}
if (pConfig->eResyncMarkerType == RESYNC_MARKER_MB)
{
avc.nSliceHeaderSpacing = pConfig->nResyncMarkerSpacing;
}
else
{
avc.nSliceHeaderSpacing = 0;
}
result = OMX_SetParameter(m_hEncoder,
OMX_IndexParamVideoAvc,
(OMX_PTR) &avc);
}
}
}
//////////////////////////////////////////
// error resilience
//////////////////////////////////////////
if (result == OMX_ErrorNone)
{
// see if we already configured error resilience (which is the case for h263)
if (m_eCodec == OMX_VIDEO_CodingMPEG4)
{
OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrection; //OMX_IndexParamVideoErrorCorrection
OMX_INIT_STRUCT(&errorCorrection, OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE);
errorCorrection.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
result = OMX_GetParameter(m_hEncoder,
OMX_IndexParamVideoErrorCorrection,
(OMX_PTR) &errorCorrection);
if (result == OMX_ErrorNone)
{
if (m_eCodec == OMX_VIDEO_CodingMPEG4)
{
errorCorrection.bEnableHEC = pConfig->nHECInterval == 0 ? OMX_FALSE : OMX_TRUE;
}
else
{
errorCorrection.bEnableHEC = OMX_FALSE;
}
if (pConfig->eResyncMarkerType == RESYNC_MARKER_BITS)
{
errorCorrection.bEnableResync = OMX_TRUE;
errorCorrection.nResynchMarkerSpacing = pConfig->nResyncMarkerSpacing;
}
else
{
errorCorrection.bEnableResync = OMX_FALSE;
errorCorrection.nResynchMarkerSpacing = 0;
}
errorCorrection.bEnableDataPartitioning = OMX_FALSE; // MP4 Resync
result = OMX_SetParameter(m_hEncoder,
OMX_IndexParamVideoErrorCorrection,
(OMX_PTR) &errorCorrection);
}
}
}
#ifdef QCOM_OMX_EXT
//////////////////////////////////////////
// qp
//////////////////////////////////////////
if (result == OMX_ErrorNone)
{
OMX_QCOM_VIDEO_CONFIG_QPRANGE qp; // OMX_QcomIndexConfigVideoQPRange
qp.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
result = OMX_GetConfig(m_hEncoder,
(OMX_INDEXTYPE) OMX_QcomIndexConfigVideoQPRange,
(OMX_PTR) &qp);
if (result == OMX_ErrorNone)
{
qp.nMinQP = (OMX_U32) pConfig->nMinQp;
qp.nMaxQP = (OMX_U32) pConfig->nMaxQp;
result = OMX_SetConfig(m_hEncoder,
(OMX_INDEXTYPE) OMX_QcomIndexConfigVideoQPRange,
(OMX_PTR) &qp);
}
}
#endif
//////////////////////////////////////////
// bitrate
//////////////////////////////////////////
if (result == OMX_ErrorNone)
{
OMX_VIDEO_PARAM_BITRATETYPE bitrate; // OMX_IndexParamVideoBitrate
OMX_INIT_STRUCT(&bitrate, OMX_VIDEO_PARAM_BITRATETYPE);
bitrate.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
result = OMX_GetParameter(m_hEncoder,
OMX_IndexParamVideoBitrate,
(OMX_PTR) &bitrate);
if (result == OMX_ErrorNone)
{
bitrate.eControlRate = pConfig->eControlRate;
bitrate.nTargetBitrate = pConfig->nBitrate;
result = OMX_SetParameter(m_hEncoder,
OMX_IndexParamVideoBitrate,
(OMX_PTR) &bitrate);
}
}
//////////////////////////////////////////
// quantization
//////////////////////////////////////////
if (result == OMX_ErrorNone)
{
if (pConfig->eControlRate == OMX_Video_ControlRateDisable)
{
///////////////////////////////////////////////////////////
// QP Config
///////////////////////////////////////////////////////////
OMX_VIDEO_PARAM_QUANTIZATIONTYPE qp; // OMX_IndexParamVideoQuantization
OMX_INIT_STRUCT(&qp, OMX_VIDEO_PARAM_QUANTIZATIONTYPE);
qp.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
result = OMX_GetParameter(m_hEncoder,
OMX_IndexParamVideoQuantization,
(OMX_PTR) &qp);
if (result == OMX_ErrorNone)
{
if (m_eCodec == OMX_VIDEO_CodingAVC)
{
qp.nQpI = 30;
qp.nQpP = 30;
}
else
{
qp.nQpI = 14;
qp.nQpP = 14;
}
result = OMX_SetParameter(m_hEncoder,
OMX_IndexParamVideoQuantization,
(OMX_PTR) &qp);
}
}
}
//////////////////////////////////////////
// frame rate
//////////////////////////////////////////
if (result == OMX_ErrorNone)
{
OMX_CONFIG_FRAMERATETYPE framerate; // OMX_IndexConfigVideoFramerate
framerate.nPortIndex = (OMX_U32) PORT_INDEX_IN; // input
result = OMX_GetConfig(m_hEncoder,
OMX_IndexConfigVideoFramerate,
(OMX_PTR) &framerate);
if (result == OMX_ErrorNone)
{
framerate.xEncodeFramerate = pConfig->nFramerate << 16;
result = OMX_SetConfig(m_hEncoder,
OMX_IndexConfigVideoFramerate,
(OMX_PTR) &framerate);
}
}
//////////////////////////////////////////
// rotation
//////////////////////////////////////////
if (result == OMX_ErrorNone)
{
OMX_CONFIG_ROTATIONTYPE framerotate; // OMX_IndexConfigCommonRotate
framerotate.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
result = OMX_GetConfig(m_hEncoder,
OMX_IndexConfigCommonRotate,
(OMX_PTR) &framerotate);
if (result == OMX_ErrorNone)
{
framerotate.nRotation = pConfig->nRotation;
result = OMX_SetConfig(m_hEncoder,
OMX_IndexConfigCommonRotate,
(OMX_PTR) &framerotate);
}
}
//////////////////////////////////////////
// intra refresh
//////////////////////////////////////////
if (result == OMX_ErrorNone)
{
OMX_VIDEO_PARAM_INTRAREFRESHTYPE ir; // OMX_IndexParamVideoIntraRefresh
OMX_INIT_STRUCT(&ir, OMX_VIDEO_PARAM_INTRAREFRESHTYPE);
ir.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
result = OMX_GetParameter(m_hEncoder,
OMX_IndexParamVideoIntraRefresh,
(OMX_PTR) &ir);
if (result == OMX_ErrorNone)
{
if (pConfig->bEnableIntraRefresh == OMX_TRUE)
{
/// @todo need an extension dynamic for intra refresh configuration
ir.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
ir.nCirMBs = 5;
result = OMX_SetParameter(m_hEncoder,
OMX_IndexParamVideoIntraRefresh,
(OMX_PTR) &ir);
}
}
}
//////////////////////////////////////////
// input buffer requirements
//////////////////////////////////////////
if (result == OMX_ErrorNone)
{
OMX_PARAM_PORTDEFINITIONTYPE inPortDef; // OMX_IndexParamPortDefinition
OMX_INIT_STRUCT(&inPortDef, OMX_PARAM_PORTDEFINITIONTYPE);
inPortDef.nPortIndex = (OMX_U32) PORT_INDEX_IN; // input
result = OMX_GetParameter(m_hEncoder,
OMX_IndexParamPortDefinition,
(OMX_PTR) &inPortDef);
if (result == OMX_ErrorNone)
{
inPortDef.nBufferCountActual = m_nInputBuffers;
inPortDef.format.video.nFrameWidth = pConfig->nFrameWidth;
inPortDef.format.video.nFrameHeight = pConfig->nFrameHeight;
result = OMX_SetParameter(m_hEncoder,
OMX_IndexParamPortDefinition,
(OMX_PTR) &inPortDef);
result = OMX_GetParameter(m_hEncoder,
OMX_IndexParamPortDefinition,
(OMX_PTR) &inPortDef);
if (m_nInputBuffers != (OMX_S32) inPortDef.nBufferCountActual)
{
VENC_TEST_MSG_ERROR("Buffer reqs dont match...");
}
}
m_nInputBufferSize = (OMX_S32) inPortDef.nBufferSize;
}
//////////////////////////////////////////
// output buffer requirements
//////////////////////////////////////////
if (result == OMX_ErrorNone)
{
OMX_PARAM_PORTDEFINITIONTYPE outPortDef; // OMX_IndexParamPortDefinition
OMX_INIT_STRUCT(&outPortDef, OMX_PARAM_PORTDEFINITIONTYPE);
outPortDef.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
result = OMX_GetParameter(m_hEncoder,
OMX_IndexParamPortDefinition,
(OMX_PTR) &outPortDef);
if (result == OMX_ErrorNone)
{
outPortDef.nBufferCountActual = m_nOutputBuffers;
outPortDef.format.video.nFrameWidth = pConfig->nOutputFrameWidth;
outPortDef.format.video.nFrameHeight = pConfig->nOutputFrameHeight;
result = OMX_SetParameter(m_hEncoder,
OMX_IndexParamPortDefinition,
(OMX_PTR) &outPortDef);
result = OMX_GetParameter(m_hEncoder,
OMX_IndexParamPortDefinition,
(OMX_PTR) &outPortDef);
if (m_nOutputBuffers != (OMX_S32) outPortDef.nBufferCountActual)
{
VENC_TEST_MSG_ERROR("Buffer reqs dont match...");
}
}
m_nOutputBufferSize = (OMX_S32) outPortDef.nBufferSize;
}
return result;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE Encoder::EnableUseBufferModel(OMX_BOOL bInUseBuffer, OMX_BOOL bOutUseBuffer)
{
OMX_ERRORTYPE result = OMX_ErrorNone;
m_bInUseBuffer = bInUseBuffer;
m_bOutUseBuffer = bOutUseBuffer;
return result;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE Encoder::GoToExecutingState()
{
OMX_ERRORTYPE result = OMX_ErrorNone;
if (m_eState == OMX_StateLoaded)
{
///////////////////////////////////////
// 1. send idle state command
// 2. allocate input buffers
// 3. allocate output buffers
// 4. wait for idle state complete
// 5. send executing state command and wait for complete
///////////////////////////////////////
m_nInFrameIn = 0;
m_nOutFrameIn = 0;
m_nInFrameOut = 0;
m_nOutFrameOut = 0;
// send idle state comand
VENC_TEST_MSG_MEDIUM("going to state OMX_StateIdle...");
result = SetState(OMX_StateIdle, OMX_FALSE);
if (result == OMX_ErrorNone)
{
result = AllocateBuffers();
}
// wait for idle state complete
if (result == OMX_ErrorNone)
{
result = WaitState(OMX_StateIdle);
}
// send executing state command and wait for complete
if (result == OMX_ErrorNone)
{
VENC_TEST_MSG_MEDIUM("going to state OMX_StateExecuting...");
result = SetState(OMX_StateExecuting, OMX_TRUE);
}
}
else
{
VENC_TEST_MSG_ERROR("invalid state");
result = OMX_ErrorIncorrectStateTransition;
}
return result;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE Encoder::GetOutOfBandSyntaxHeader(OMX_U8* pSyntaxHdr,
OMX_S32 nSyntaxHdrLen,
OMX_S32* pSyntaxHdrFilledLen)
{
OMX_ERRORTYPE result = OMX_ErrorNone;
#ifdef QCOM_OMX_EXT
if (pSyntaxHdr != NULL &&
nSyntaxHdrLen > 0 &&
pSyntaxHdrFilledLen != NULL)
{
OMX_QCOM_VIDEO_PARAM_SYNTAXHDRTYPE syntax;
OMX_INIT_STRUCT(&syntax, OMX_QCOM_VIDEO_PARAM_SYNTAXHDRTYPE);
syntax.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
syntax.pBuff = pSyntaxHdr;
syntax.nBuffLen = (OMX_U32) nSyntaxHdrLen;
result = OMX_GetParameter(m_hEncoder,
(OMX_INDEXTYPE) OMX_QcomIndexParamVideoSyntaxHdr,
(OMX_PTR) &syntax);
if (result == OMX_ErrorNone)
{
*pSyntaxHdrFilledLen = (OMX_S32) syntax.nFilledLen;
}
else
{
VENC_TEST_MSG_ERROR("failed to get syntax header");
}
}
else
{
VENC_TEST_MSG_ERROR("bad param(s)");
result = OMX_ErrorBadParameter;
}
#endif
return result;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE Encoder::GoToLoadedState()
{
OMX_ERRORTYPE result = OMX_ErrorNone;
///////////////////////////////////////
// 1. send idle state command and wait for complete
// 2. send loaded state command
// 3. free input buffers
// 4. free output buffers
// 5. wait for loaded state complete
///////////////////////////////////////
// send idle state comand and wait for complete
if (m_eState == OMX_StateExecuting ||
m_eState == OMX_StatePause)
{
VENC_TEST_MSG_MEDIUM("going to state OMX_StateIdle...");
result = SetState(OMX_StateIdle, OMX_TRUE);
}
// send loaded state command
VENC_TEST_MSG_MEDIUM("going to state OMX_StateLoaded...");
result = SetState(OMX_StateLoaded, OMX_FALSE);
if (result == OMX_ErrorNone)
{
result = FreeBuffers();
// wait for loaded state complete
result = WaitState(OMX_StateLoaded);
}
return result;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE Encoder::DeliverInput(OMX_BUFFERHEADERTYPE* pBuffer)
{
VENC_TEST_MSG_MEDIUM("deliver input frame %ld", m_nInFrameIn);
++m_nInFrameIn;
if (m_pStats != NULL)
{
(void) m_pStats->SetInputStats(pBuffer);
}
return OMX_EmptyThisBuffer(m_hEncoder, pBuffer);
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE Encoder::DeliverOutput(OMX_BUFFERHEADERTYPE* pBuffer)
{
VENC_TEST_MSG_MEDIUM("deliver output frame %ld", m_nOutFrameIn);
++m_nOutFrameIn;
pBuffer->nFlags = 0;
return OMX_FillThisBuffer(m_hEncoder, pBuffer);
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
OMX_BUFFERHEADERTYPE** Encoder::GetBuffers(OMX_BOOL bIsInput)
{
OMX_BUFFERHEADERTYPE** ppBuffers;
if (m_eState == OMX_StateExecuting)
{
ppBuffers = (bIsInput == OMX_TRUE) ? m_pInputBuffers : m_pOutputBuffers;
}
else
{
ppBuffers = NULL;
}
return ppBuffers;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE Encoder::RequestIntraVOP()
{
OMX_ERRORTYPE result = OMX_ErrorNone;
OMX_CONFIG_INTRAREFRESHVOPTYPE vop;
vop.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
result = OMX_GetConfig(m_hEncoder,
OMX_IndexConfigVideoIntraVOPRefresh,
(OMX_PTR) &vop);
if (result == OMX_ErrorNone)
{
vop.IntraRefreshVOP = OMX_TRUE;
result = OMX_SetConfig(m_hEncoder,
OMX_IndexConfigVideoIntraVOPRefresh,
(OMX_PTR) &vop);
}
else
{
VENC_TEST_MSG_ERROR("failed to get state");
}
return result;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE Encoder::SetIntraPeriod(OMX_S32 nIntraPeriod)
{
OMX_ERRORTYPE result = OMX_ErrorNone;
#ifdef QCOM_OMX_EXT
OMX_QCOM_VIDEO_CONFIG_INTRAPERIODTYPE intra;
intra.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
result = OMX_GetConfig(m_hEncoder,
(OMX_INDEXTYPE) OMX_QcomIndexConfigVideoIntraperiod,
(OMX_PTR) &intra);
if (result == OMX_ErrorNone)
{
intra.nPFrames = (OMX_U32) nIntraPeriod - 1;
result = OMX_SetConfig(m_hEncoder,
(OMX_INDEXTYPE) OMX_QcomIndexConfigVideoIntraperiod,
(OMX_PTR) &intra);
}
else
{
VENC_TEST_MSG_ERROR("failed to get state");
}
#endif
return result;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE Encoder::ChangeQuality(OMX_S32 nFramerate,
OMX_S32 nBitrate,
OMX_S32 nMinQp,
OMX_S32 nMaxQp)
{
OMX_ERRORTYPE result = OMX_ErrorNone;
(void) nMinQp;
(void) nMaxQp;
//////////////////////////////////////////
// frame rate
//////////////////////////////////////////
if (result == OMX_ErrorNone)
{
OMX_CONFIG_FRAMERATETYPE framerate; // OMX_IndexConfigVideoFramerate
framerate.nPortIndex = (OMX_U32) PORT_INDEX_IN; // input
result = OMX_GetConfig(m_hEncoder,
OMX_IndexConfigVideoFramerate,
(OMX_PTR) &framerate);
if (result == OMX_ErrorNone)
{
framerate.xEncodeFramerate = ((OMX_U32) nFramerate) << 16;
result = OMX_SetConfig(m_hEncoder,
OMX_IndexConfigVideoFramerate,
(OMX_PTR) &framerate);
}
}
//////////////////////////////////////////
// bitrate
//////////////////////////////////////////
if (result == OMX_ErrorNone)
{
OMX_VIDEO_CONFIG_BITRATETYPE bitrate; // OMX_IndexConfigVideoFramerate
bitrate.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
result = OMX_GetConfig(m_hEncoder,
OMX_IndexConfigVideoBitrate,
(OMX_PTR) &bitrate);
if (result == OMX_ErrorNone)
{
bitrate.nEncodeBitrate = (OMX_U32) nBitrate;
result = OMX_SetConfig(m_hEncoder,
OMX_IndexConfigVideoBitrate,
(OMX_PTR) &bitrate);
}
}
#ifdef QCOM_OMX_EXT
//////////////////////////////////////////
// qp
//////////////////////////////////////////
if (result == OMX_ErrorNone)
{
OMX_QCOM_VIDEO_CONFIG_QPRANGE qp; // OMX_QcomIndexConfigVideoQPRange
qp.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
result = OMX_GetConfig(m_hEncoder,
(OMX_INDEXTYPE) OMX_QcomIndexConfigVideoQPRange,
(OMX_PTR) &qp);
if (result == OMX_ErrorNone)
{
qp.nMinQP = (OMX_U32) nMinQp;
qp.nMaxQP = (OMX_U32) nMaxQp;
result = OMX_SetConfig(m_hEncoder,
(OMX_INDEXTYPE) OMX_QcomIndexConfigVideoQPRange,
(OMX_PTR) &qp);
}
}
#endif
if (result != OMX_ErrorNone)
{
VENC_TEST_MSG_ERROR("error changing quality");
}
return result;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE Encoder::AllocateBuffers()
{
int i;
OMX_U8 *pBuffer;
struct venc_pmem *pMem;
void *pVirt;
OMX_ERRORTYPE result = OMX_ErrorNone;
m_pInputBuffers = new OMX_BUFFERHEADERTYPE*[m_nInputBuffers];
m_pInBufPvtList = new OMX_QCOM_PLATFORM_PRIVATE_LIST[m_nInputBuffers];
m_pInBufPmemInfo = new OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO[m_nInputBuffers];
m_pInBufPvtEntry = new OMX_QCOM_PLATFORM_PRIVATE_ENTRY[m_nInputBuffers];
m_pOutputBuffers = new OMX_BUFFERHEADERTYPE*[m_nOutputBuffers];
m_pOutBufPvtList = new OMX_QCOM_PLATFORM_PRIVATE_LIST[m_nOutputBuffers];
m_pOutBufPmemInfo = new OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO[m_nOutputBuffers];
m_pOutBufPvtEntry = new OMX_QCOM_PLATFORM_PRIVATE_ENTRY[m_nOutputBuffers];
//////////////////////////////////////////
// USE BUFFER MODEL
//////////////////////////////////////////
if (m_bInUseBuffer == OMX_TRUE)
{
VENC_TEST_MSG_MEDIUM("USE BUFFER INPUT: allocating input buffer");
// allocate input buffers
m_pInMem = new Pmem(m_nInputBuffers);
for (i = 0; i < m_nInputBuffers; i++)
{
result = m_pInMem->Allocate(&pBuffer, m_nInputBufferSize, VENC_PMEM_SMI);
if (result != OMX_ErrorNone)
{
VENC_TEST_MSG_ERROR("error allocating input buffer");
break;
}
pMem = (venc_pmem*)pBuffer;
pVirt = pMem->virt;
/* VENC_TEST_MSG_MEDIUM("allocating input buffer fd:%d, offset:%d ", pBuffer->fd, pBuffer->offset); */
result = OMX_UseBuffer(m_hEncoder,
&m_pInputBuffers[i],
PORT_INDEX_IN, // port index
(OMX_PTR)pBuffer, // pAppPrivate
m_nInputBufferSize,
(OMX_U8 *)pVirt);
if (result != OMX_ErrorNone)
{
VENC_TEST_MSG_ERROR("error using input buffer");
break;
}
VENC_TEST_MSG_HIGH("Register pmem buffer: hdr=%p, fd%d, offset0x%x",
&m_pInputBuffers[i], pMem->fd, pMem->offset);
// Set the PMEM Info structure
m_pInBufPmemInfo[i].pmem_fd = pMem->fd;
m_pInBufPmemInfo[i].offset = pMem->offset;
//Link the entry structure pmem Info
m_pInBufPvtEntry[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
m_pInBufPvtEntry[i].entry = &m_pInBufPmemInfo[i];
// Initialize the List structure to have one entry
m_pInBufPvtList[i].nEntries = 1;
m_pInBufPvtList[i].entryList = &m_pInBufPvtEntry[i];
OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* private_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* )malloc(sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO));
private_info->pmem_fd = pMem->fd;
private_info->offset = pMem->offset;
m_pInputBuffers[i]->pPlatformPrivate = (OMX_PTR)private_info;
VENC_TEST_MSG_HIGH("Test App: entry = %p\n",m_pInBufPvtEntry[i].entry);
}
} else {
VENC_TEST_MSG_MEDIUM("ALLOCATE BUFFER INPUT: allocating input buffer");
for (i = 0; i < m_nInputBuffers; i++)
{
result = OMX_AllocateBuffer(m_hEncoder,
&m_pInputBuffers[i],
PORT_INDEX_IN, // port index
this, // pAppPrivate
m_nInputBufferSize);
if (result != OMX_ErrorNone)
{
VENC_TEST_MSG_ERROR("error allocating input buffer");
break;
}
}
}
if (m_bOutUseBuffer == OMX_TRUE) {
VENC_TEST_MSG_MEDIUM("USE BUFFER OUTPUT: allocating output");
// allocate output buffers
m_pOutMem = new Pmem(m_nOutputBuffers);
for (i = 0; i < m_nOutputBuffers; i++)
{
result = m_pOutMem->Allocate(&pBuffer, m_nOutputBufferSize, VENC_PMEM_SMI);
if (result != OMX_ErrorNone)
{
VENC_TEST_MSG_ERROR("error allocating output buffer");
break;
}
pMem = (venc_pmem*)pBuffer;
pVirt = pMem->virt;
result = OMX_UseBuffer(m_hEncoder,
&m_pOutputBuffers[i],
PORT_INDEX_OUT, // port index
(OMX_PTR)pBuffer, // pAppPrivate
m_nOutputBufferSize,
(OMX_U8 *)pVirt);
if (result != OMX_ErrorNone)
{
VENC_TEST_MSG_ERROR("error using output buffer");
break;
}
VENC_TEST_MSG_HIGH("Register pmem buffer: hdr=%p, fd%d, offset0x%x",
&m_pOutputBuffers[i], pMem->fd, pMem->offset);
// Set the PMEM Info structure
m_pOutBufPmemInfo[i].pmem_fd = pMem->fd;
m_pOutBufPmemInfo[i].offset = pMem->offset;
//Link the entry structure pmem Info
m_pOutBufPvtEntry[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
m_pOutBufPvtEntry[i].entry = &m_pOutBufPmemInfo[i];
// Initialize the List structure to have one entry
m_pOutBufPvtList[i].nEntries = 1;
m_pOutBufPvtList[i].entryList = &m_pOutBufPvtEntry[i];
OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* private_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* )malloc(sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO));
private_info->pmem_fd = pMem->fd;
private_info->offset = pMem->offset;
m_pOutputBuffers[i]->pPlatformPrivate = (OMX_PTR)private_info;
}
} else {
VENC_TEST_MSG_MEDIUM("ALLOCATE BUFFER OUTPUT: allocating output");
// allocate output buffers
for (i = 0; i < m_nOutputBuffers; i++)
{
result = OMX_AllocateBuffer(m_hEncoder,
&m_pOutputBuffers[i],
PORT_INDEX_OUT, // port index
this, // pAppPrivate
m_nOutputBufferSize);
if (result != OMX_ErrorNone)
{
VENC_TEST_MSG_ERROR("error allocating output buffer");
break;
}
}
}
return result;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE Encoder::FreeBuffers()
{
int i;
OMX_ERRORTYPE result = OMX_ErrorNone;
if (m_pInputBuffers)
{
for (i = 0; i < m_nInputBuffers; i++)
{
VENC_TEST_MSG_MEDIUM("freeing input buffer %d", i);
result = OMX_FreeBuffer(m_hEncoder,
PORT_INDEX_IN, // port index
m_pInputBuffers[i]);
if (result != OMX_ErrorNone)
{
VENC_TEST_MSG_ERROR("error freeing input buffer");
}
if (m_bInUseBuffer == OMX_TRUE)
{
result = m_pInMem->Free((OMX_U8 *)m_pInputBuffers[i]->pAppPrivate);
}
if (result != OMX_ErrorNone)
{
VENC_TEST_MSG_ERROR("error freeing input pmem");
}
}
delete [] m_pInputBuffers;
delete [] m_pInBufPvtList;
delete [] m_pInBufPmemInfo;
delete [] m_pInBufPvtEntry;
m_pInputBuffers = NULL;
m_pInBufPvtList = NULL;
m_pInBufPmemInfo = NULL;
m_pInBufPvtEntry = NULL;
}
// free output buffers
if (m_pOutputBuffers)
{
for (i = 0; i < m_nOutputBuffers; i++)
{
VENC_TEST_MSG_MEDIUM("freeing output buffer %d", i);
result = OMX_FreeBuffer(m_hEncoder,
PORT_INDEX_OUT, // port index
m_pOutputBuffers[i]);
if (result != OMX_ErrorNone)
{
VENC_TEST_MSG_ERROR("error freeing output buffer");
}
if (m_bOutUseBuffer == OMX_TRUE)
{
result = m_pOutMem->Free((OMX_U8*)m_pOutputBuffers[i]->pAppPrivate);
}
if (result != OMX_ErrorNone)
{
VENC_TEST_MSG_ERROR("error freeing output pmem");
}
}
delete [] m_pOutputBuffers;
m_pOutputBuffers = NULL;
delete [] m_pOutBufPvtList;
m_pOutBufPvtList = NULL;
delete [] m_pOutBufPmemInfo;
m_pOutBufPmemInfo = NULL;
delete [] m_pOutBufPvtEntry;
m_pOutBufPvtEntry = NULL;
}
if (m_pInMem)
delete m_pInMem;
m_pInMem = NULL;
if (m_pOutMem)
delete m_pOutMem;
m_pOutMem = NULL;
return result;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE Encoder::SetState(OMX_STATETYPE eState,
OMX_BOOL bSynchronous)
{
OMX_ERRORTYPE result = OMX_ErrorNone;
result = OMX_SendCommand(m_hEncoder,
OMX_CommandStateSet,
(OMX_U32) eState,
NULL);
if (result == OMX_ErrorNone)
{
if (result == OMX_ErrorNone)
{
if (bSynchronous == OMX_TRUE)
{
result = WaitState(eState);
if (result != OMX_ErrorNone)
{
VENC_TEST_MSG_ERROR("failed to wait state");
}
}
}
}
else
{
VENC_TEST_MSG_ERROR("failed to set state");
}
return result;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE Encoder::WaitState(OMX_STATETYPE eState)
{
OMX_ERRORTYPE result = OMX_ErrorNone;
CmdType cmd;
(void) m_pSignalQueue->Pop(&cmd, sizeof(cmd), 0); // infinite wait
result = cmd.eResult;
if (cmd.eEvent == OMX_EventCmdComplete)
{
if (cmd.eCmd == OMX_CommandStateSet)
{
if ((OMX_STATETYPE) cmd.sCmdData == eState)
{
m_eState = (OMX_STATETYPE) cmd.sCmdData;
}
else
{
VENC_TEST_MSG_ERROR("wrong state (%d)", (int) cmd.sCmdData);
result = OMX_ErrorUndefined;
}
}
else
{
VENC_TEST_MSG_ERROR("expecting state change");
result = OMX_ErrorUndefined;
}
}
else
{
VENC_TEST_MSG_ERROR("expecting cmd complete");
result = OMX_ErrorUndefined;
}
return result;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE Encoder::Flush()
{
OMX_ERRORTYPE result = OMX_ErrorNone;
result = OMX_SendCommand(m_hEncoder,
OMX_CommandFlush,
OMX_ALL,
NULL);
if (result == OMX_ErrorNone)
{
CmdType cmd;
if (m_pSignalQueue->Pop(&cmd, sizeof(cmd), 0) != OMX_ErrorNone)
{
VENC_TEST_MSG_ERROR("error popping signal");
}
result = cmd.eResult;
if (cmd.eEvent != OMX_EventCmdComplete || cmd.eCmd != OMX_CommandFlush)
{
VENC_TEST_MSG_ERROR("expecting flush");
result = OMX_ErrorUndefined;
}
if (result != OMX_ErrorNone)
{
VENC_TEST_MSG_ERROR("failed to wait for flush");
result = OMX_ErrorUndefined;
}
else
{
if (m_pSignalQueue->Pop(&cmd, sizeof(cmd), 0) != OMX_ErrorNone)
{
VENC_TEST_MSG_ERROR("error popping signal");
}
else
{
result = cmd.eResult;
if (cmd.eEvent != OMX_EventCmdComplete || cmd.eCmd != OMX_CommandFlush)
{
VENC_TEST_MSG_ERROR("expecting flush");
result = OMX_ErrorUndefined;
}
}
if (result != OMX_ErrorNone)
{
VENC_TEST_MSG_ERROR("failed to wait for flush");
result = OMX_ErrorUndefined;
}
}
}
else
{
VENC_TEST_MSG_ERROR("failed to set state");
}
return result;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE Encoder::EventCallback(OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_PTR pAppData,
OMX_IN OMX_EVENTTYPE eEvent,
OMX_IN OMX_U32 nData1,
OMX_IN OMX_U32 nData2,
OMX_IN OMX_PTR pEventData)
{
OMX_ERRORTYPE result = OMX_ErrorNone;
if (eEvent == OMX_EventCmdComplete)
{
if ((OMX_COMMANDTYPE) nData1 == OMX_CommandStateSet)
{
VENC_TEST_MSG_MEDIUM("Event callback with state change");
switch ((OMX_STATETYPE) nData2)
{
case OMX_StateLoaded:
VENC_TEST_MSG_HIGH("state status OMX_StateLoaded");
break;
case OMX_StateIdle:
VENC_TEST_MSG_HIGH("state status OMX_StateIdle");
break;
case OMX_StateExecuting:
VENC_TEST_MSG_HIGH("state status OMX_StateExecuting");
break;
case OMX_StatePause:
VENC_TEST_MSG_HIGH("state status OMX_StatePause");
break;
case OMX_StateInvalid:
VENC_TEST_MSG_HIGH("state status OMX_StateInvalid");
break;
case OMX_StateWaitForResources:
VENC_TEST_MSG_HIGH("state status OMX_StateWaitForResources");
break;
default:
VENC_TEST_MSG_HIGH("state status Invalid");
break;
}
CmdType cmd;
cmd.eEvent = OMX_EventCmdComplete;
cmd.eCmd = OMX_CommandStateSet;
cmd.sCmdData = nData2;
cmd.eResult = result;
if (((Encoder*) pAppData)->m_eState != OMX_StateExecuting &&
(OMX_STATETYPE) nData2 == OMX_StateExecuting)
{
// we are entering the execute state
((Encoder*) pAppData)->m_pStats->Start();
}
else if (((Encoder*) pAppData)->m_eState == OMX_StateExecuting &&
(OMX_STATETYPE) nData2 != OMX_StateExecuting)
{
// we are leaving the execute state
((Encoder*) pAppData)->m_pStats->Finish();
}
result = ((Encoder*) pAppData)->m_pSignalQueue->Push(&cmd, sizeof(cmd));
}
else if ((OMX_COMMANDTYPE) nData1 == OMX_CommandFlush)
{
VENC_TEST_MSG_MEDIUM("Event callback with flush status");
VENC_TEST_MSG_HIGH("flush status");
CmdType cmd;
cmd.eEvent = OMX_EventCmdComplete;
cmd.eCmd = OMX_CommandFlush;
cmd.sCmdData = 0;
cmd.eResult = result;
result = ((Encoder*) pAppData)->m_pSignalQueue->Push(&cmd, sizeof(cmd));
}
else
{
VENC_TEST_MSG_HIGH("error status");
VENC_TEST_MSG_ERROR("Unimplemented command");
}
}
else if (eEvent == OMX_EventError)
{
VENC_TEST_MSG_ERROR("async error");
CmdType cmd;
cmd.eEvent = OMX_EventError;
cmd.eCmd = OMX_CommandMax;
cmd.sCmdData = 0;
cmd.eResult = (OMX_ERRORTYPE) nData1;
result = ((Encoder*) pAppData)->m_pSignalQueue->Push(&cmd, sizeof(cmd));
}
else if (eEvent == OMX_EventBufferFlag)
{
VENC_TEST_MSG_MEDIUM("got buffer flag event");
}
else
{
VENC_TEST_MSG_ERROR("Unimplemented event");
}
return result;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE Encoder::EmptyDoneCallback(OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_PTR pAppData,
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
{
OMX_ERRORTYPE result = OMX_ErrorNone;
VENC_TEST_MSG_MEDIUM("releasing input frame %ld", ((Encoder*) pAppData)->m_nInFrameOut);
if (((Encoder*) pAppData)->m_pEmptyDoneFn)
{
((Encoder*) pAppData)->m_pEmptyDoneFn(hComponent,
((Encoder*) pAppData)->m_pAppData, // forward the client from constructor
pBuffer);
}
++((Encoder*) pAppData)->m_nInFrameOut;
return result;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE Encoder::FillDoneCallback(OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_PTR pAppData,
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
{
OMX_ERRORTYPE result = OMX_ErrorNone;
VENC_TEST_MSG_MEDIUM("releasing output frame %ld", ((Encoder*) pAppData)->m_nOutFrameOut);
if (((Encoder*) pAppData)->m_pStats != NULL)
{
(void) ((Encoder*) pAppData)->m_pStats->SetOutputStats(pBuffer);
}
if (((Encoder*) pAppData)->m_pFillDoneFn)
{
((Encoder*) pAppData)->m_pFillDoneFn(hComponent,
((Encoder*) pAppData)->m_pAppData, // forward the client from constructor
pBuffer);
}
++((Encoder*) pAppData)->m_nOutFrameOut;
return result;
}
} // namespace venctest