【二十】 H.266/VVC | 仿射运动估计AMVP继承相邻块的运动信息函数 | addAffineMVPCandUnscaled函数
程序员文章站
2022-07-07 13:54:27
...
/*
函数的作用:检验当前PU的相邻PU的运动信息是否可以继承,可以的话保存并返回true,否则返回false
函数的返回值是一个bool类型
形参说明
1、const PredictionUnit &pu 当前编码单元PU
2、const RefPicList &refPicList 当前PU的参考列表
3、const int &refIdx 当前PU参考图像在参考列表中的索引
4、const Position &pos
5、const MvpDir &dir 相邻块的方向,函数中根据这个方向,可以获取到当前PU的相邻块的位置
6、AffineAMVPInfo &affiAMVPInfo 用于存放AMVP候选列表的结构体
*/
bool PU::addAffineMVPCandUnscaled( const PredictionUnit &pu, const RefPicList &refPicList, const int &refIdx, const Position &pos, const MvpDir &dir, AffineAMVPInfo &affiAMVPInfo )
{
CodingStructure &cs = *pu.cs; //定义了一个存放当前PU编码信息的cs变量
const PredictionUnit *neibPU = NULL; //定义了一个PU指针,用于指向当前PU的相邻PU
Position neibPos; //位置信息变量,用于存放相邻块的位置信息
//根据相邻块的方向参数dir,得到指定方向的相邻PU的位置信息
switch ( dir )
{
case MD_LEFT: //左边
neibPos = pos.offset( -1, 0 );
break;
case MD_ABOVE: //上方
neibPos = pos.offset( 0, -1 );
break;
case MD_ABOVE_RIGHT: //右上方
neibPos = pos.offset( 1, -1 );
break;
case MD_BELOW_LEFT: //左下方
neibPos = pos.offset( -1, 1 );
break;
case MD_ABOVE_LEFT: //左上方
neibPos = pos.offset( -1, -1 );
break;
default:
break;
}
/*
调用cs.getPURestricted( neibPos, pu, pu.chType )来获得具体的相邻PU
返回值用变量neibPU接收
函数形参说明:
1、neibPos 相邻块的位置
2、pu 当前PU
3、pu.chType 当前PU的类型,是属于亮度PU还是色度PU,0表示luma、1表示chroma
*/
neibPU = cs.getPURestricted( neibPos, pu, pu.chType );
/*
用一个if判断当前相邻块是否可用
判断条件满足一个,则表示当前相邻PU不可用,条件如下:
1、相邻PU不存在,即还未被编码
2、相邻PU已经被编码,但是使用的不是帧间预测
3、相邻PU已经被编码,但是使用的不是仿射模式
4、当前PU没有使用默认的Merge类型
*/
if (neibPU == NULL || !CU::isInter(*neibPU->cu) || !neibPU->cu->affine || neibPU->mergeType != MRG_TYPE_DEFAULT_N)
{
return false;
}
//定义运动矢量MV数组,用于存储AffineMv
Mv outputAffineMv[3];
//定义一个运动信息变量neibMi,用于存放当前相邻PU的运动信息
const MotionInfo& neibMi = neibPU->getMotionInfo( neibPos );
//定义一个整形变量currRefPOC ,用于存放当前编码PU的参考图像的POC,picture order count代表显示顺序
const int currRefPOC = cs.slice->getRefPic( refPicList, refIdx )->getPOC();
//定义一个参考列表变量refPicList2nd,如果当前参考列表为L0,那么refPicList2nd就为L1,反之则反
const RefPicList refPicList2nd = (refPicList == REF_PIC_LIST_0) ? REF_PIC_LIST_1 : REF_PIC_LIST_0;
/*检查指定的参考图片列表,如果该列表不可用,检查其他列表*/
for ( int predictorSource = 0; predictorSource < 2; predictorSource++ ) // examine the indicated reference picture list, then if not available, examine the other list.
{
//定义一个参考列表变量eRefPicListIndex,如果predictorSource为0,则eRefPicListIndex为当前PU的参考列表,否则为另一个参考列表
const RefPicList eRefPicListIndex = (predictorSource == 0) ? refPicList : refPicList2nd;
//定义了一个neibRefIdx,存放是当前相邻PU的参考图像在当前PU参考图像列表中的索引值或者另一个参考列表中的索引值
const int neibRefIdx = neibMi.refIdx[eRefPicListIndex];
/*
满足条件,跳过本次循环,进行下一次循环
1、((neibPU->interDir & (eRefPicListIndex + 1)) == 0) 没看懂
2、相邻PU的参考图像的POC与当前PU的POC不相同
两个条件够满足才可用获得相邻PU的运动信息
*/
if ( ((neibPU->interDir & (eRefPicListIndex + 1)) == 0) || pu.cu->slice->getRefPOC( eRefPicListIndex, neibRefIdx ) != currRefPOC )
{
continue;
}
/*
调用xInheritedAffineMv函数来继承当前PU相邻PU的运动信息
函数的参数说明:
1、pu 当前编码的PU
2、neibPU 相邻的PU
3、eRefPicListIndex 相邻PU的3参考列表
4、outputAffineMv 一个长度为3的MV数组,用于存放继承的相邻PU的运动信息
*/
xInheritedAffineMv( pu, neibPU, eRefPicListIndex, outputAffineMv );
//调整继承得到的运动矢量的分辨率为1/16像素精度,帧间获得的运动矢量的像素精度要求为1/16像素精度
outputAffineMv[0].roundAffinePrecInternal2Amvr(pu.cu->imv);
outputAffineMv[1].roundAffinePrecInternal2Amvr(pu.cu->imv);
//将调整后由继承得到的运动矢量放入AMVP候选列表中
affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand] = outputAffineMv[0];
affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand] = outputAffineMv[1];
//如果是六参数仿射模型,还需要多添加一个继承的运动矢量到AMVP候选列表当中
if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
{
outputAffineMv[2].roundAffinePrecInternal2Amvr(pu.cu->imv);
affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand] = outputAffineMv[2];
}
//将AMVP候选列表的数目自增1
affiAMVPInfo.numCand++;
//成功继承相邻PU的运动信息
return true;
}
return false;
}
更多关于视频编码知识和资源的分享,更精致的文章排版,欢迎关注博主微信公众号,一起交流、学习、进步!!!
上一篇: 如何用cmd安装web.py