xPredAffineInterSearch函数在predInterSearch函数中被调用,用来计算Affine_ME模式,进行4参数和6参数Affine_ME模式的计算。
函数流程和普通的interME的函数流程很像,即和predInterSearch函数流程很相似:初始化、单向、双向、数据存储。
函数中调用xEstimateAffineAMVP函数,得到AffineME模式的各控制点的CPMVP。
函数中调用xAffineMotionEstimation函数,由xEstimateAffineAMVP得到的CPMVP,进行Affine_ME,得到AffineME模式的MV。
xEstimateAffineAMVP函数、xAffineMotionEstimation函数,这两个函数以后要细看
void InterSearch::xPredAffineInterSearch( PredictionUnit& pu,
PelUnitBuf& origBuf,
int puIdx,
uint32_t& lastMode,
Distortion& affineCost,
Mv hevcMv[2][33]
, Mv mvAffine4Para[2][33][3]
, int refIdx4Para[2]
#if JVET_L0646_GBI
, uint8_t gbiIdx
, bool enforceGBiPred
, uint32_t gbiIdxBits
#endif
)
{
const Slice &slice = *pu.cu->slice;
affineCost = std::numeric_limits<Distortion>::max();
Mv cMvZero;
Mv aacMv[2][3];
Mv cMvBi[2][3];
Mv cMvTemp[2][33][3];
int iNumPredDir = slice.isInterP() ? 1 : 2;
int mvNum = 2;
mvNum = pu.cu->affineType ? 3 : 2; //3控制点、2控制点
// Mvp
Mv cMvPred[2][33][3];
Mv cMvPredBi[2][33][3];
int aaiMvpIdxBi[2][33];
int aaiMvpIdx[2][33];
int aaiMvpNum[2][33];
AffineAMVPInfo aacAffineAMVPInfo[2][33];
AffineAMVPInfo affiAMVPInfoTemp[2];
int iRefIdx[2]={
0,0}; // If un-initialized, may cause SEGV in bi-directional prediction iterative stage.
int iRefIdxBi[2];
uint32_t uiMbBits[3] = {
1, 1, 0};
int iRefStart, iRefEnd;
PartSize ePartSize = pu.cu->partSize;
int bestBiPRefIdxL1 = 0;
int bestBiPMvpL1 = 0;
Distortion biPDistTemp = std::numeric_limits<Distortion>::max();
Distortion uiCost[2] = {
std::numeric_limits<Distortion>::max(), std::numeric_limits<Distortion>::max() };
Distortion uiCostBi = std::numeric_limits<Distortion>::max();
Distortion uiCostTemp;
uint32_t uiBits[3];
uint32_t uiBitsTemp;
Distortion bestBiPDist = std::numeric_limits<Distortion>::max();
Distortion uiCostTempL0[MAX_NUM_REF];
for (int iNumRef=0; iNumRef < MAX_NUM_REF; iNumRef++)
{
uiCostTempL0[iNumRef] = std::numeric_limits<Distortion>::max();
}
uint32_t uiBitsTempL0[MAX_NUM_REF];
Mv mvValidList1[4];
int refIdxValidList1 = 0;
uint32_t bitsValidList1 = MAX_UINT;
Distortion costValidList1 = std::numeric_limits<Distortion>::max();
Mv mvHevc[3];
xGetBlkBits( ePartSize, slice.isInterP(), puIdx, lastMode, uiMbBits);
pu.cu->affine = true;
pu.mergeFlag = false;
#if JVET_L0646_GBI
if( gbiIdx != GBI_DEFAULT )
{
pu.cu->GBiIdx = gbiIdx;
}
#endif
// Uni-directional prediction //单向预测
for ( int iRefList = 0; iRefList < iNumPredDir; iRefList++ )
{
RefPicList eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
#if JVET_L0293_CPR
int refPicNumber = slice.getNumRefIdx(eRefPicList);
if (slice.getSPS()->getSpsNext().getCPRMode() && eRefPicList == REF_PIC_LIST_0)
{
refPicNumber--;
}
for (int iRefIdxTemp = 0; iRefIdxTemp < refPicNumber; iRefIdxTemp++) //对L0、L1中的所有参考帧loop
#else
for ( int iRefIdxTemp = 0; iRefIdxTemp < slice.getNumRefIdx(eRefPicList); iRefIdxTemp++ )
#endif
{
// Get RefIdx bits
uiBitsTemp = uiMbBits[iRefList];
if ( slice.getNumRefIdx(eRefPicList) > 1 )
{
uiBitsTemp += iRefIdxTemp+1;
if ( iRefIdxTemp == slice.getNumRefIdx(eRefPicList)-1 )
{
uiBitsTemp--;
}
}
// Do Affine AMVP //xEstimateAffineAMVP 得到CPMVP
xEstimateAffineAMVP( pu, affiAMVPInfoTemp[eRefPicList], origBuf, eRefPicList, iRefIdxTemp, cMvPred[iRefList][iRefIdxTemp], &biPDistTemp );
aaiMvpIdx[iRefList][iRefIdxTemp] = pu.mvpIdx[eRefPicList];
aaiMvpNum[iRefList][iRefIdxTemp] = pu.mvpNum[eRefPicList];;
if ( pu.cu->affineType == AFFINEMODEL_6PARAM && refIdx4Para[iRefList] != iRefIdxTemp )
{
xCopyAffineAMVPInfo( affiAMVPInfoTemp[eRefPicList], aacAffineAMVPInfo[iRefList][iRefIdxTemp] );
continue;
}
// set hevc ME result as start search position when it is best than mvp
for ( int i=0; i<3; i++ )
{
mvHevc[i] = hevcMv[iRefList][iRefIdxTemp]; //这里先计算一下以hevcMv为3个控制点mv得到的cost。类似L1002中所说的平移mv
}
PelUnitBuf predBuf = m_tmpStorageLCU.getBuf( UnitAreaRelative(*pu.cu, pu) );
// xGetAffineTemplateCost 得到AffineAMVP的失真,mvHevc的失真
Distortion uiCandCost = xGetAffineTemplateCost(pu, origBuf, predBuf, mvHevc, aaiMvpIdx[iRefList][iRefIdxTemp],
AMVP_MAX_NUM_CANDS, eRefPicList, iRefIdxTemp);
#if JVET_L0260_AFFINE_ME
if (pu.cu->affineType == AFFINEMODEL_4PARAM && m_affMVListSize
#if JVET_L0646_GBI
&& (!pu.cu->cs->sps->getSpsNext().getUseGBi() || gbiIdx == GBI_DEFAULT)
#endif
) //4参数模型
{
int shift = MAX_CU_DEPTH;
for (int i = 0; i < m_affMVListSize; i++) //这里需要看看m_affMVList的构成过程
{
AffineMVInfo *mvInfo = m_affMVList + ((m_affMVListIdx - i - 1 + m_affMVListMaxSize) % (m_affMVListMaxSize));
//check;
int j = 0;
for (; j < i; j++)
{
AffineMVInfo *prevMvInfo = m_affMVList + ((m_affMVListIdx - j - 1 + m_affMVListMaxSize) % (m_affMVListMaxSize));
if ((mvInfo->affMVs[iRefList][iRefIdxTemp][0] == prevMvInfo->affMVs[iRefList][iRefIdxTemp][0]) &&
(mvInfo->affMVs[iRefList][iRefIdxTemp][1] == prevMvInfo->affMVs[iRefList][iRefIdxTemp][1])
&& (mvInfo->x == prevMvInfo->x) && (mvInfo->y == prevMvInfo->y)
&& (mvInfo->w == prevMvInfo->w)
)
{
break;
}
}
if (j < i)
continue;
Mv mvTmp[3], *nbMv = mvInfo->affMVs[iRefList][iRefIdxTemp]; //以下的处理得到一组CPMVP,即mvTmp[3]
int vx, vy;
int dMvHorX, dMvHorY, dMvVerX, dMvVerY;
int mvScaleHor = nbMv[0].getHor() << shift;
int mvScaleVer = nbMv[0].getVer() << shift;
Mv dMv = nbMv[1] - nbMv[0];
#if REMOVE_MV_ADAPT_PREC
mvScaleHor <<= VCEG_AZ07_MV_ADD_PRECISION_BIT_FO