inter_ME模式中,xMotionEstimation函数实现运动估计,利用得到的AMVP最优候选为起点,搜索范围内的最佳匹配块,从而确定mv。
IntTZSearchStruct结构体在ME过程中很重要,包含了搜索匹配过程的所有关键数据:
typedef struct
{
SearchRange searchRange; //搜素范围
const CPelBuf* pcPatternKey; //匹配模板像素,orig
const Pel* piRefY; //参考帧像素,即搜索区域的像素
Int iRefStride; //搜索区域像素的stride
Int iBestX;
Int iBestY; //搜索范围内的最佳匹配点
UInt uiBestRound;
UInt uiBestDistance; //搜索点距起点的距离
Distortion uiBestSad; //匹配失真
UChar ucPointNr; //搜索点相对于起始点的位置的标号
Int subShiftMode; //搜索模式
} IntTZSearchStruct;
入口参数rcMvPred是当前参考帧通过AMVP得到的最优的mvp,用于ME。
基于AMVP的mvp,ME最终得到精度为Qter像素的mv,即rcMv。
大致流程为:
构建IntTZSearchStruct,其中确定模板像素,搜索参考像素;
设置搜索范围和搜索起点,xSetSearchRange;
分搜索类型,调用不同的搜索匹配函数进行块的匹配和mv的搜索,确定整数mv;
亚像素和Qter像素的mv的搜索,通过插值,搜索匹配得到;
最终得到Qter像素精度mv。
Void InterSearch::xMotionEstimation(PredictionUnit& pu, PelUnitBuf& origBuf, RefPicList eRefPicList, Mv& rcMvPred, Int iRefIdxPred, Mv& rcMv, Int& riMVPIdx, UInt& ruiBits, Distortion& ruiCost, const AMVPInfo& amvpInfo, Bool bBi)
{
Mv cMvHalf, cMvQter; //1/2精度和1/4精度mv
CHECK(eRefPicList >= MAX_NUM_REF_LIST_ADAPT_SR || iRefIdxPred>=Int(MAX_IDX_ADAPT_SR), "Invalid reference picture list");
m_iSearchRange = m_aaiAdaptSR[eRefPicList][iRefIdxPred];
Int iSrchRng = (bBi ? m_bipredSearchRange : m_iSearchRange); //搜索范围
Double fWeight = 1.0;
PelUnitBuf origBufTmp = m_tmpStorageLCU.getBuf( UnitAreaRelative(*pu.cu, pu) );
PelUnitBuf* pBuf = &origBuf; //orig像素信息
if(bBi) // Bi-predictive ME 双向预测中的运动估计时
{
// NOTE: Other buf contains predicted signal from another direction //另外一个方向的orig像素
PelUnitBuf otherBuf = m_tmpPredStorage[1 - (Int)eRefPicList].getBuf( UnitAreaRelative(*pu.cu, pu ));
origBufTmp