predInterSearch函数在xCheckRDCostInter中被调用,用来获取inter_ME以及Affine_ME模式下的最优inter运动信息。
首先对单向预测,分别对L0和L1的所有帧进行AMVP、ME,得到各个参考帧下的各种最优的运动信息;
再进行双向预测,双向预测用到了单向时得到的各帧的各种运动信息,通过4次迭代,找到最优的双向运动信息;
对比前向、后向和双向预测的cost,取最优的模式,将运动信息存入pu;
如果cu不是2Nx2N,则需要合并运动信息;
再进行4参数Affine_ME,以及6参数Affine_ME的计算;
统一进行一次MC,得到pred像素信息;
最后再设置加权预测的参数。
//! search of the best candidate for inter prediction
void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
{
CodingStructure& cs = *cu.cs;
AMVPInfo amvp[2]; //存储一帧经过ME后的最优amvp信息。AMVP选择的运动信息为ME起始点
Mv cMvSrchRngLT;
Mv cMvSrchRngRB;
Mv cMvZero;
Mv cMv[2]; //两个单向预测的最优mv
Mv cMvBi[2]; //双向预测的最优mv
Mv cMvTemp[2][33];
Mv cMvHevcTemp[2][33];
int iNumPredDir = cs.slice->isInterP() ? 1 : 2; //前向/后向预测
Mv cMvPred[2][33]; //存储AMVP得到的最优mvp
Mv cMvPredBi[2][33]; //双向预测时,ME的起点mv
int aaiMvpIdxBi[2][33];
int aaiMvpIdx[2][33]; //2表示前向后向预测,33表示L0、L1参考列表中最多33帧
int aaiMvpNum[2][33]; //AMVP后得到的最优MvpIdx和MvpNum
AMVPInfo aacAMVPInfo[2][33]; //存储每一帧的最优AMVP信息
int iRefIdx[2]={
0,0}; //If un-initialized, may cause SEGV in bi-directional prediction iterative stage. 最优mv的refIdx
int iRefIdxBi[2];
uint32_t uiMbBits[3] = {
1, 1, 0};
uint32_t uiLastMode = 0;
uint32_t uiLastModeTemp = 0;
int iRefStart, iRefEnd;
int bestBiPRefIdxL1 = 0;
int bestBiPMvpL1 = 0;
Distortion biPDistTemp = std::numeric_limits<Distortion>::max();
#if JVET_L0646_GBI
uint8_t gbiIdx = (cu.cs->slice->isInterB() ? cu.GBiIdx : GBI_DEFAULT);
bool enforceGBiPred = false;
#endif
MergeCtx mergeCtx;
// Loop over Prediction Units
CHECK(!cu.firstPU, "CU does not contain any PUs");
uint32_t puIdx = 0;
auto &pu = *cu.firstPU; //xCheckRDCostInter函数中添加的pu
{
// motion estimation only evaluates luma component
m_maxCompIDToPred = MAX_NUM_COMPONENT;
// m_maxCompIDToPred = COMPONENT_Y;
CHECK(pu.cu != &cu, "PU is contained in another CU");
if (cu.cs->sps->getSpsNext().getUseSubPuMvp())
{
Size bufSize = g_miScaling.scale(pu.lumaSize());
mergeCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize);
}
PU::spanMotionInfo( pu );
Distortion uiHevcCost = std::numeric_limits<Distortion>::max();
Distortion uiAffineCost = 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;
int refIdxValidList1 = 0;
uint32_t bitsValidList1 = MAX_UINT;
Distortion costValidList1 = std::numeric_limits<Distortion>::max();
PelUnitBuf origBuf = pu.cs->getOrgBuf( pu ); //orig像素信息
xGetBlkBits( cu.partSize, cs.slice->isInterP(), puIdx, uiLastMode, uiMbBits ); //统计bit数
m_pcRdCost->selectMotionLambda( cu.transQuantBypass );
unsigned imvShift = pu.cu->imv << 1;
// Uni-directional prediction //单向预测
for ( int iRefList = 0; iRefList < iNumPredDir; iRefList++ ) //L0、L1
{
RefPicList eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
#if JVET_L0293_CPR
int refPicNumber = cs.slice->getNumRefIdx(eRefPicList);
if (cs.slice->getSPS()->getSpsNext().getCPRMode() && eRefPicList == REF_PIC_LIST_0)
{
refPicNumber--;
}
for (int iRefIdxTemp = 0; iRefIdxTemp < refPicNumber; iRefIdxTemp++)
#else
for ( int iRefIdxTemp = 0; iRefIdxTemp < cs.slice->getNumRefIdx(eRefPicList); iRefIdxTemp++ ) //L0或L1中各参考帧
#endif
{
uiBitsTemp = uiMbBits[iRefList]; //统计bit信息
if ( cs.slice->getNumRefIdx(eRefPicList) > 1 )
{
uiBitsTemp += iRefIdxTemp+1;
if ( iRefIdxTemp == cs.slice->getNumRefIdx(eRefPicList)-1 )
{
uiBitsTemp--;
}
} //AMVP,获取当前pu周围的最优运动信息,作为ME起点
xEstimateMvPredAMVP( pu, origBuf, eRefPicList, iRefIdxTemp, cMvPred[iRefList][iRefIdxTemp], amvp[eRefPicList], false, &biPDistTemp);
aaiMvpIdx[iRefList][iRefIdxTemp] = pu.mvpIdx[eRefPicList]; //每一帧通过AMVP获取的最优mvp
aaiMvpNum[iRefList][iRefIdxTemp] = pu.mvpNum[eRefPicList];
if(cs.slice->getMvdL1ZeroFlag() && iRefList==1 && biPDistTemp < bestBiPDist) //广义B帧时,L1信息直接复制L0
{
bestBiPDist = biPDistTemp;
bestBiPMvpL1 = aaiMvpIdx[iRefList][iRefIdxTemp];
bestBiPRefIdxL1 = iRefIdxTemp;
}
uiBitsTemp += m_auiMVPIdxCost[aaiMvpIdx[iRefList][iRefIdxTemp]][AMVP_MAX_NUM_CANDS]; //统计bit信息
if ( m_pcEncCfg->getFastMEForGenBLowDelayEnabled() && iRefList == 1 ) // list 1
{
if ( cs.slice->getList1IdxToList0Idx( iRefIdxTemp ) >= 0 ) //如果使用广义B帧,则list1直接复制list0的信息
{
cMvTemp[1][iRefIdxTemp] = cMvTemp[0][cs.slice->getList1IdxToList0Idx( iRefIdxTemp )];
uiCostTemp = uiCostTempL0[cs.slice->getList1IdxToList0Idx( iRefIdxTemp )];
/*first subtract the bit-rate part of the cost of the other list*/
uiCostTemp -= m_pcRdCost->getCost( uiBitsTempL0[cs.slice->getList1IdxToList0Idx( iRefIdxTemp )] );
/*correct the bit-rate part of the current ref*/
m_pcRdCost->setPredictor ( cMvPred[iRefList][iRefIdxTemp] );
uiBitsTemp += m_pcRdCost->getBitsOfVectorWithPredictor( cMvTemp[1][iRefIdxTemp].getHor(), cMvTemp[1][iRefIdxTemp].getVer(), imvShift );
/*calculate the correct cost*/
uiCostTemp += m_pcRdCost->getCost( uiBitsTemp );
}
else
{
xMotionEstimation( pu, origBuf, eRefPicList, cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp]