仅供学习参考用途
070702
主题:运动估计相关内容
摘要:本文先介绍运动矢量搜索类,解释类中关于运动矢量搜索的参数含义和用法;接着介绍运动估计
类,简要解释了其中的主要函数的作用;最后主要函数 MotionEstimation::estimateBlockWithStart 的流程
图,此函数包含了运动估计的整个流程。
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
};
Copyright © qtluck & Institute of Circuits and Systems, Ningbo University 1/8
仅供学习参考用途
运动估计类 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;
Copyright © qtluck & Institute of Circuits and Systems, Ningbo University 2/8
仅供学习参考用途
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,
Copyright © qtluck & Institute of Circuits and Systems, Ningbo University 3/8
仅供学习参考用途
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
UInt uiSearchRange = 0 ); //块搜索函数 Search Mode 0 调用此函数
Void
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
xPelBlockSearch ( IntYuvPicBuffer *pcPelData, Mv& rcMv, UInt& ruiSAD,
xPelSpiralSearch( IntYuvPicBuffer *pcPelData, Mv& rcMv, UInt& ruiSAD,
// ….该模式下搜索模式比较少
#endif
protected:
QuarterPelFilter* m_pcQuarterPelFilter;
Copyright © qtluck & Institute of Circuits and Systems, Ningbo University 4/8
仅供学习参考用途
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(rcRefFrame).getFullPelYuvBuffer();
pcRefPelData[1] = const_cast(rcRefFrame).getHalfPelYuvBuffer();
m_pcXDistortion->set4x4Block( cIdx );
pcRefPelData[0]->set4x4Block( cIdx );
pcRefPelData[1]->set4x4Block( cIdx );
if( bQPelRefinementOnly )rcMv = rcMvPred;
Copyright © qtluck & Institute of Circuits and Systems, Ningbo University 5/8
仅供学习参考用途
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:
Copyright © qtluck & Institute of Circuits and Systems, Ningbo University 6/8
仅供学习参考用途
{
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
Copyright © qtluck & Institute of Circuits and Systems, Ningbo University 7/8
仅供学习参考用途
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;
}
Copyright © qtluck & Institute of Circuits and Systems, Ningbo University 8/8