主题:
JMVM2.1
运动估计相关内容
MotionVectorSearchParams类,解释该类中运动矢量搜索的参数含义
class
H264AVCENCODERLIB_API MotionVectorSearchParams

...
{
public:

MotionVectorSearchParams() : m_eSearchMode(FAST_SEARCH), m_eFullPelDFunc(DF_SAD), m_eSubPelDFunc(DF_SAD), m_uiSearchRange(64), m_uiDirectMode(0) ...{} //具体默认参数的构造函数
ErrVal check() const;

const SearchMode getSearchMode() const ...{ return m_eSearchMode; }
//确定搜索模式Search Mode 0==Block,1==Spiral,2==Log,3==Fast, 4==NewFast

const DFunc getFullPelDFunc() const ...{ return m_eFullPelDFunc; }
//整像素搜索时的函数 Search Func (Full Pel) 0==SAD,1==SSE,2==Hadamard,3==YUV-SAD"

const DFunc getSubPelDFunc() const ...{ return m_eSubPelDFunc; }
//半像素搜索时的函数 Search Func (Sub Pel) 0==SAD,1==SSE,2==Hadamard"

const UInt getSearchRange() const ...{ return m_uiSearchRange; } //确定搜索范围

UInt getNumMaxIter () const ...{ return m_uiNumMaxIter; }

UInt getIterSearchRange() const ...{ return m_uiIterSearchRange; }

const UInt getDirectMode() const ...{ return m_uiDirectMode; }
//Direct模式选择0==Temporal, 1==Spatial


Void setSearchMode( UInt uiSearchMode ) ...{ m_eSearchMode = SearchMode(uiSearchMode); }

Void setFullPelDFunc( UInt uiFullPelDFunc ) ...{ m_eFullPelDFunc = DFunc(uiFullPelDFunc); }

Void setSubPelDFunc( UInt uiSubPelDFunc ) ...{ m_eSubPelDFunc = DFunc(uiSubPelDFunc); }

Void setSearchRange ( UInt uiSearchRange) ...{ m_uiSearchRange = uiSearchRange; }

Void setNumMaxIter ( UInt uiNumMaxIter ) ...{ m_uiNumMaxIter = uiNumMaxIter; }

Void setIterSearchRange ( UInt uiIterSearchRange ) ...{ m_uiIterSearchRange = uiIterSearchRange; }

Void setDirectMode( UInt uiDirectMode) ...{ m_uiDirectMode = uiDirectMode; }
public:
SearchMode m_eSearchMode; // 配置文件读取,默认值0==Block
DFunc m_eFullPelDFunc; // 配置文件读取,默认值0==SAD
DFunc m_eSubPelDFunc; // 配置文件读取,默认值0==SAD
UInt m_uiSearchRange; // 配置文件读取,默认值96
UInt m_uiNumMaxIter; // 配置文件读取,默认值4
UInt m_uiIterSearchRange; // 配置文件读取,默认值8
UInt m_uiDirectMode; // 0 temporal, 1 spatial
}
;
运动估计类MotionEstimation
class
MotionEstimation :
public
MotionCompensation ,
public
MotionEstimationCost

...
{
public:
class MEBiSearchParameters //运动估计双向搜索参数

...{
public:
IntYuvMbBuffer* pcAltRefPelData; // the prediction signal for the opposite list (not weighted)
UInt uiL1Search; // 1 if current search is L1 search, else false
const IntFrame* pcAltRefFrame; // the reference frame of the opposite list
const PW* apcWeight[2]; // { list 0 prediction weight, list 1 prediction weight }
};
protected:
typedef struct

...{
Void init( Short sLimit, Mv& rcMvPel, Mv cMin, Mv cMax)

...{
cMin >>= 2;
cMax >>= 2;
Short sPosV = cMax.getVer() - rcMvPel.getVer();
Short sNegV = rcMvPel.getVer() - cMin.getVer();
iNegVerLimit = min( sLimit, sNegV) - rcMvPel.getVer();
iPosVerLimit = min( sLimit, sPosV) + rcMvPel.getVer();

Short sPosH = cMax.getHor() - rcMvPel.getHor();
Short sNegH = rcMvPel.getHor() - cMin.getHor();
iNegHorLimit = min( sLimit, sNegH) - rcMvPel.getHor();
iPosHorLimit = min( sLimit, sPosH) + rcMvPel.getHor();
}
Int iNegVerLimit;
Int iPosVerLimit;
Int iNegHorLimit;
Int iPosHorLimit;
}
SearchRect; //结构体SearchRect,用于根据搜索范围确定搜索矩阵

typedef struct

...{
XPel* pucYRef;
XPel* pucURef;
XPel* pucVRef;
Int iYStride;
Int iCStride;
Int iBestX;
Int iBestY;
UInt uiBestRound;
UInt uiBestDistance;
UInt uiBestSad;
UChar ucPointNr;

#if TMS_SE_MVC_IC
IcpInMs sBestIcpInMs;
#endif

}
IntTZSearchStrukt; //快速搜索TZ方法的一些参数

protected:
MotionEstimation(); //构造函数
virtual ~MotionEstimation(); //析构函数

public:
ErrVal destroy();
virtual ErrVal uninit();


SampleWeighting* getSW() ...{ return m_pcSampleWeighting; }

ErrVal initMb( UInt uiMbPosY, UInt uiMbPosX, MbDataAccess& rcMbDataAccess ); //宏块初始化

virtual ErrVal init( XDistortion* pcXDistortion,
CodingParameter* pcCodingParameter,
RateDistortionIf* pcRateDistortionIf,
QuarterPelFilter* pcQuarterPelFilter,
Transform* pcTransform,
SampleWeighting* pcSampleWeighting);

UInt getRateCost ( UInt uiBits, Bool bSad) ...{ xGetMotionCost( bSad, 0 ); return xGetCost( uiBits ); }
ErrVal estimateBlockWithStart( const MbDataAccess& rcMbDataAccess, // estimateBlockWithStart
const IntFrame& rcRefFrame,
Mv& rcMv, // <-- MVSTART / --> MV
Mv& rcMvPred,
UInt& ruiBits,
UInt& ruiCost,
UInt uiBlk,
UInt uiMode,
Bool bQPelRefinementOnly,
UInt uiSearchRange,
const PW* pcPW,
MEBiSearchParameters* pcBSP = 0 );
#if TMS_SE_MVC_IC
ErrVal estimateBlockWithStart( Icp& rcIcp,
// …. 此函数与上面estimateBlockWithStart功能相同。
#endif
virtual ErrVal compensateBlock( IntYuvMbBuffer *pcRecPelData, UInt uiBlk, UInt uiMode, IntYuvMbBuffer *pcRefPelData2 = NULL ) = 0;

DFunc getDistortionFunction() ...{ return m_cParams.getSubPelDFunc(); } //块补偿函数

//TMM_WP

Void setLstIdx( ListIdx eLstIdx) ...{m_eLstIdx = eLstIdx;}

ListIdx getLstIdx() ...{return m_eLstIdx;}
//TMM_WP

protected:
//TZ快速搜索系列函数
Void xTZSearch ( IntYuvPicBuffer *pcPelData, Mv& rcMv, UInt& ruiSAD, UInt uiSearchRange = 0 );
__inline Void xTZSearchHelp ( IntTZSearchStrukt& rcStrukt, const Int iSearchX, const Int iSearchY, const UChar ucPointNr, const UInt uiDistance );
__inline Void xTZ2PointSearch ( IntTZSearchStrukt& rcStrukt, SearchRect rcSearchRect );
__inline Void xTZ8PointSquareSearch ( IntTZSearchStrukt& rcStrukt, SearchRect rcSearchRect, const Int iStartX, const Int iStartY, const Int iDist );
__inline Void xTZ8PointDiamondSearch( IntTZSearchStrukt& rcStrukt, SearchRect rcSearchRect, const Int iStartX, const Int iStartY, const Int iDist );

Void xPelBlockSearch ( IntYuvPicBuffer *pcPelData, Mv& rcMv, UInt& ruiSAD, UInt uiSearchRange = 0 ); //块搜索函数Search Mode 0调用此函数
Void xPelSpiralSearch( IntYuvPicBuffer *pcPelData, Mv& rcMv, UInt& ruiSAD, UInt uiSearchRange = 0 ); //螺旋搜索函数Search Mode 1调用此函数
Void xPelLogSearch ( IntYuvPicBuffer *pcPelData, Mv& rcMv, UInt& ruiSAD, Bool bFme, UInt uiStep = 4, UInt uiSearchRange = 0 ); //对数搜索Search Mode 2调用此函数
virtual Void xSubPelSearch ( IntYuvPicBuffer *pcPelData, Mv& rcMv, UInt& ruiSAD, UInt uiBlk, UInt uiMode, Bool bQPelOnly ) = 0; //半像素搜索函数

//TMM_WP
Int getDistScaleFactor(Int iCurrPoc, Int iL0Poc, Int iL1Poc ) const;
//TMM_WP

#if TMS_SE_MVC_IC
// ….该模式下搜索模式比较少
#endif
protected:
QuarterPelFilter* m_pcQuarterPelFilter;
MotionVectorSearchParams m_cParams;
Int m_iMaxLogStep;
Mv *m_pcMvSpiralSearch;
UInt m_uiSpiralSearchEntries;
Mv m_cLastPelMv;
Mv m_acMvPredictors[3];

XDistortion* m_pcXDistortion;
XDistSearchStruct m_cXDSS;

//TMM_WP
ListIdx m_eLstIdx;
//TMM_WP
}
;

//
主要函数MotionEstimation::estimateBlockWithStart的流程图
ErrVal
MotionEstimation::estimateBlockWithStart(
const
MbDataAccess
&
rcMbDataAccess,
const
IntFrame
&
rcRefFrame,
//
参考帧
Mv
&
rcMv,
//
<-- MVSTART / --> MV
Mv
&
rcMvPred,
//
Pred Mv
UInt
&
ruiBits,
//
bits
UInt
&
ruiCost,
//
cost
UInt uiBlk,
UInt uiMode,
//
searchmode
Bool bQPelRefinementOnly,
UInt uiSearchRange,
//
searchrange
const
PW
*
pcPW,
MEBiSearchParameters
*
pcBSP )

...
{
const LumaIdx cIdx = B4x4Idx(uiBlk);
IntYuvMbBuffer* pcWeightedYuvBuffer = NULL;
IntYuvPicBuffer* pcRefPelData[2];
IntYuvMbBuffer cWeightedYuvBuffer;

pcRefPelData[0] = const_cast<IntFrame&>(rcRefFrame).getFullPelYuvBuffer();
pcRefPelData[1] = const_cast<IntFrame&>(rcRefFrame).getHalfPelYuvBuffer();

m_pcXDistortion->set4x4Block( cIdx );
pcRefPelData[0]->set4x4Block( cIdx );
pcRefPelData[1]->set4x4Block( cIdx );

if( bQPelRefinementOnly )rcMv = rcMvPred;

UInt uiMinSAD = MSYS_UINT_MAX;
Mv cMv = rcMv;
Double fWeight = 1.0;

Double afCW[2] = ...{ 1.0, 1.0 };

Bool bOriginalSearchModeIsYUVSAD = ( m_cParams.getFullPelDFunc() == DF_YUV_SAD );
const Int iXSize = m_pcXDistortion->getBlockWidth ( uiMode );
const Int iYSize = m_pcXDistortion->getBlockHeight ( uiMode );

if( pcBSP ) // bi prediction

...{
//…….双向预测
}
else // unidirectional prediction 单向预测

...{

}
//===== FULL-PEL ESTIMATION ======

if( bOriginalSearchModeIsYUVSAD && ( pcBSP /**//* bi-prediction */ || fWeight != afCW[0] || fWeight != afCW[1] /**//* different component weights */ ) )

...{
m_cParams.setFullPelDFunc( DF_SAD ); // set to normal SAD
}
// <<< heiko.schwarz@hhi.fhg.de (fix for uninitialized memory with YUV_SAD and bi-directional search)
xGetMotionCost( ( 1 != m_cParams.getFullPelDFunc() ), 0 );
m_pcXDistortion->getDistStruct( uiMode, m_cParams.getFullPelDFunc(), false, m_cXDSS );
m_cXDSS.pYOrg = pcWeightedYuvBuffer->getLumBlk();
m_cXDSS.pUOrg = pcWeightedYuvBuffer->getCbBlk ();
m_cXDSS.pVOrg = pcWeightedYuvBuffer->getCrBlk ();
xSetPredictor( rcMvPred );
xSetCostScale( 2 );

if( ! bQPelRefinementOnly ) //这个参数不清楚

...{
if( uiSearchRange )

...{
xPelBlockSearch ( pcRefPelData[0], cMv, uiMinSAD, uiSearchRange );
}
else

...{
switch( m_cParams.getSearchMode() )

...{
case 0:

...{
xPelBlockSearch ( pcRefPelData[0], cMv, uiMinSAD );
}
break;
case 1:

...{
xPelSpiralSearch( pcRefPelData[0], cMv, uiMinSAD );
}
break;
case 2:

...{ xPelLogSearch ( pcRefPelData[0], cMv, uiMinSAD, false, m_iMaxLogStep << ((NULL == pcBSP) ? 1 : 0) );
}
break;
case 3:

...{
rcMbDataAccess.getMvPredictors( m_acMvPredictors );
xPelLogSearch ( pcRefPelData[0], cMv, uiMinSAD, true, (NULL == pcBSP) ? 2 : 1 );
}
break;
case 4:

...{
rcMbDataAccess.getMvPredictors( m_acMvPredictors );
xTZSearch( pcRefPelData[0], cMv, uiMinSAD );
}
break;
default:
RERR();
break;
}
}
cMv <<= 2;
}
else

...{
Mv cMvBase = cMv;
cMv.limitComponents( m_cMin, m_cMax );
if( ! ( cMvBase == cMv ) )

...{
// don't refine in that case
rcMv = cMvBase;
ruiBits += 2;
ruiCost = MSYS_UINT_MAX / 2;
// >>>> bug fix by H.Schwarz 19/9/05
if( bOriginalSearchModeIsYUVSAD )

...{
m_cParams.setFullPelDFunc( DF_YUV_SAD );
}
// <<<< bug fix by H.Schwarz 19/9/05
return Err::m_nOK;
}
}

//===== SUB-PEL ESTIMATION =====
xGetMotionCost( 1 != ( 1 & m_cParams.getSubPelDFunc() ), 0 );
m_pcXDistortion->getDistStruct( uiMode, m_cParams.getSubPelDFunc(), false, m_cXDSS );
m_cXDSS.pYOrg = pcWeightedYuvBuffer->getLumBlk();
xSetCostScale( 0 );

xSubPelSearch( pcRefPelData[1], cMv, uiMinSAD, uiBlk, uiMode, bQPelRefinementOnly );

Short sHor = cMv.getHor();
Short sVer = cMv.getVer();
UInt uiMvBits = xGetBits( sHor, sVer );
ruiBits += uiMvBits;
ruiCost = (UInt)floor( fWeight * (Double)( uiMinSAD - xGetCost( uiMvBits ) ) ) + xGetCost( ruiBits );
rcMv = cMv;

return Err::m_nOK;
}
摘要:本文先介绍运动矢量搜索类,解释类中关于运动矢量搜索的参数含义和用法;接着介绍运动估计类,简要解释了其中的主要函数的作用;最后主要函数
MotionEstimation::estimateBlockWithStart
的流程,此函数包含了运动估计的整个流程。
提供全文PDF下载: http://download.youkuaiyun.com/source/302826








































































































































































































































































































































































