今天来看运动补偿,推荐两篇博文:
http://blog.csdn.net/hevc_cjl/article/details/8457642
http://blog.csdn.net/nb_vol_1/article/details/55253979
1、运动补偿整体介绍
运动补偿的功能是根据之前的局部图像来预测补偿当前的局部图像。而实际代码来看,主要完成的是亚像素插值补偿的工作。在运动估计中,得到的MV是亚像素精度的,而参考图像是整像素的,亚像素位置上是没有值的。如果通过MV找到的参考块是非整像素位置的,那么在参考图像上是没有这个参考块的。这就需要对参考图像进行插值,构造亚像素参考块。得到的这个参考块将用于计算残差。
实际运动补偿中的函数调用关系如下:
2、运动补偿入口函数motionCompensation
下面来看代码(没有具体看加权预测部分),运动补偿的入口函数是motionCompensation,在确定了MV之后被调用,用来构造参考块。
//运动补偿
Void TComPrediction::motionCompensation ( TComDataCU* pcCU, TComYuv* pcYuvPred, RefPicList eRefPicList, Int iPartIdx )
{
Int iWidth;
Int iHeight;
UInt uiPartAddr;
//如果PU的索引是有效值,那么直接处理该PU,然后返回
if ( iPartIdx >= 0 )
{
pcCU->getPartIndexAndSize( iPartIdx, uiPartAddr, iWidth, iHeight ); //获取PU地址和大小
if ( eRefPicList != REF_PIC_LIST_X ) //指明了具体参考列表
{
if( pcCU->getSlice()->getPPS()->getUseWP()) //是否进行加权预测
{
xPredInterUni (pcCU, uiPartAddr, iWidth, iHeight, eRefPicList, pcYuvPred, true ); //最后的参数true标识双向
}
else
{
xPredInterUni (pcCU, uiPartAddr, iWidth, iHeight, eRefPicList, pcYuvPred );
}
if ( pcCU->getSlice()->getPPS()->getUseWP() )
{
xWeightedPredictionUni( pcCU, pcYuvPred, uiPartAddr, iWidth, iHeight, eRefPicList, pcYuvPred );
}
}
else //没有指明明确的参考列表,那么判断PU两个方向上的参考帧是否相同
{
if ( xCheckIdenticalMotion( pcCU, uiPartAddr ) ) //检测PU与预测的CU是否匹配,匹配则进行单向补偿,否则进行双向补偿
{
xPredInterUni (pcCU, uiPartAddr, iWidth, iHeight, REF_PIC_LIST_0, pcYuvPred );
}
else
{
xPredInterBi (pcCU, uiPartAddr, iWidth, iHeight, pcYuvPred );
}
}
return;
}
//PU索引无效则处理所有PU,处理同上。
for ( iPartIdx = 0; iPartIdx < pcCU->getNumPartitions(); iPartIdx++ )
{
pcCU->getPartIndexAndSize( iPartIdx, uiPartAddr, iWidth, iHeight );
if ( eRefPicList != REF_PIC_LIST_X )
{
if( pcCU->getSlice()->getPPS()->getUseWP())
{
xPredInterUni (pcCU, uiPartAddr, iWidth, iHeight, eRefPicList, pcYuvPred, true );
}
else
{
xPredInterUni (pcCU, uiPartAddr, iWidth, iHeight, eRefPicList, pcYuvPred );
}
if ( pcCU->getSlice()->getPPS