xDeriveCUMV函数根据解码得到的预测参数数据,计算得到mv。
函数内根据解码得到的各个模式的数据,获取到MMVD、三角预测、AffineMerge、普通merge、AffineME、普通interME等模式的运动信息。
函数中没有涉及MHIntra模式,是因为:MHIntra中的intra_dir已经在coding_unit()时解码获得,MHIntra模式的inter信息,其实不需要特别的解码,它是直接用普通merge来解码得到的。
注:代码中的ATMVP是因为JEM那时候叫习惯了,其实应该为SbTMVP
void DecCu::xDeriveCUMV( CodingUnit &cu )
{
for( auto &pu : CU::traversePUs( cu ) ) //对cu的每个pu计算mv 而vtm中的cu是不会划分pu的,即只有一个pu
{
MergeCtx mrgCtx; //merge候选列表
if( pu.mergeFlag ) //Merge一类模式
{
#if JVET_L0054_MMVD
if (pu.mmvdMergeFlag || pu.cu->mmvdSkip) //MMVD模式
{
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
CHECK(pu.mhIntraFlag == true, "invalid MHIntra");
#endif
if (pu.cs->sps->getSpsNext().getUseSubPuMvp()) //UseSubPuMvp
{
Size bufSize = g_miScaling.scale(pu.lumaSize());
mrgCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize);
}
if (cu.cs->pps->getLog2ParallelMergeLevelMinus2() && cu.partSize != SIZE_2Nx2N && cu.lumaSize().width <= 8)
{
//这里一般为false
if (!mrgCtx.hasMergedCandList)
{
// temporarily set size to 2Nx2N
PartSize tmpPS = SIZE_2Nx2N;
PredictionUnit tmpPU = pu;
static_cast<UnitArea&> (tmpPU) = cu;
std::swap(tmpPS, cu.partSize);
#if JVET_L0054_MMVD
int fPosBaseIdx = pu.mmvdMergeIdx / MMVD_MAX_REFINE_NUM;
PU::getInterMergeCandidates(tmpPU, mrgCtx, 1, fPosBaseIdx + 1);
#else
PU::getInterMergeCandidates(tmpPU, mrgCtx, 255);
#endif
PU::restrictBiPredMergeCands(pu, mrgCtx);
PU::getInterMMVDMergeCandidates(tmpPU, mrgCtx,
pu.mmvdMergeIdx
);
std::swap(tmpPS, cu.partSize);
mrgCtx.hasMergedCandList = true;
}
}
else
{
#if JVET_L0054_MMVD
int fPosBaseIdx = pu.mmvdMergeIdx / MMVD_MAX_REFINE_NUM; //MMVD模式baseMV的idx
PU::getInterMergeCandidates(pu, mrgCtx, 1, fPosBaseIdx + 1); //获取merge列表
#else
PU::getInterMergeCandidates(pu, mrgCtx, 255);
#endif
PU: