您的位置:首页 > 编程语言

FVC/JEM代码学习15:xCheckRDCostAffineMerge2Nx2N

2018-04-01 16:35 387 查看
Affine模式是JEM中新加的,属于帧间预测,与FRUC,merge,inter形成竞争关系。#if COM16_C1016_AFFINE

Void TEncCu::xCheckRDCostAffineMerge2Nx2N( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU )
{
assert( rpcTempCU->getSlice()->getSliceType() != I_SLICE );
if ( getFastDeltaQp() )
{
return;
}

TComMvField cAffineMvField[2][3];
UChar uhInterDirNeighbours[1] = {0};
Int numValidMergeCand = 0;
const Bool bTransquantBypassFlag = rpcTempCU->getCUTransquantBypass(0);

UChar uhDepth = rpcTempCU->getDepth( 0 );
#if JVET_C0024_QTBT
if (rpcBestCU->getWidth(0) * rpcBestCU->getHeight(0) < 64)//只对大于等于8*8的块执行affine merge;
{
return;
}
UInt uiWIdx = g_aucConvertToBit[rpcBestCU->getWidth(0)];
UInt uiHIdx = g_aucConvertToBit[rpcBestCU->getHeight(0)];
#else
rpcTempCU->setPartSizeSubParts( SIZE_2Nx2N, 0, uhDepth );
#endif
//得到仿射Merge候选;
rpcTempCU->getAffineMergeCandidates( 0, 0, cAffineMvField, uhInterDirNeighbours, numValidMergeCand );
if ( numValidMergeCand == -1 )//如果merge候选个数为-1,则退出,不执行Affine merge
{
return;
}
Int mergeCandBuffer[1] = {0};

UInt iteration;
if ( rpcTempCU->isLosslessCoded(0))//无损编码迭代次数为1,否则为2;
{
iteration = 1;
}
else
{
iteration = 2;
}
///////////////////至少迭代一次,如果没有残差,则不会进行第二次迭代//////////////////
for ( UInt uiNoResidual = 0; uiNoResidual < iteration; ++uiNoResidual )
{//遍历所有有效的Merge候选;
for ( UInt uiMergeCand = 0; uiMergeCand < numValidMergeCand; ++uiMergeCand )//numValidMergeCand=1;
{//第一次迭代uiNoResidual=0,if条件一定成立,会执行里面的内容;
//第二次迭代中,如果在第一次迭代时,没有残差,则mergeCandBuffer[uiMergeCand]=1 ,此时不满足if条件,不进入下面的步骤;
if ( !( uiNoResidual==1 && mergeCandBuffer[uiMergeCand]==1 ) )
{
// set MC parameters,设置运动补偿参数;
rpcTempCU->setPredModeSubParts( MODE_INTER, 0, uhDepth );//设置预测模式为帧间;
rpcTempCU->setCUTransquantBypassSubParts( bTransquantBypassFlag, 0, uhDepth );//设置TransquantBypassFlag;
rpcTempCU->setChromaQpAdjSubParts( bTransquantBypassFlag ? 0 : m_cuChromaQpOffsetIdxPlus1, 0, uhDepth );//设置色度QP调整
#if !JVET_C0024_QTBT
rpcTempCU->setPartSizeSubParts( SIZE_2Nx2N, 0, uhDepth );
#endif
rpcTempCU->setAffineFlagSubParts( true, 0, 0, uhDepth );//设置Affine flag为true;
rpcTempCU->setMergeFlagSubParts( true, 0, 0, uhDepth );//设置merge flag为true;
rpcTempCU->setMergeIndexSubParts( uiMergeCand, 0, 0, uhDepth );//设置mergeidx 设置为0;
rpcTempCU->setInterDirSubParts( uhInterDirNeighbours[uiMergeCand], 0, 0, uhDepth );//将帧间模式设置为uhInterDirNeighbours[uiMergeCand]
rpcTempCU->setAllAffineMvField( 0, 0, cAffineMvField[0 + 2*uiMergeCand], REF_PIC_LIST_0, 0 );//设置affine mvf;
rpcTempCU->setAllAffineMvField( 0, 0, cAffineMvField[1 + 2*uiMergeCand], REF_PIC_LIST_1, 0 );

#if COM16_C806_OBMC
rpcTempCU->setOBMCFlagSubParts( true, 0, uhDepth );//设置OBMC Flag为true
#endif

// do MC,做运动补偿
#if JVET_C0024_QTBT
m_pcPredSearch->motionCompensation ( rpcTempCU, m_pppcPredYuvTemp[uiWIdx][uiHIdx] );

#if COM16_C806_OBMC//进行重叠块运动补偿;
m_pcPredSearch->subBlockOBMC( rpcTempCU, 0, m_pppcPredYuvTemp[uiWIdx][uiHIdx], m_pppcTmpYuv1[uiWIdx][uiHIdx], m_pppcTmpYuv2[uiWIdx][uiHIdx] );
#endif
// estimate residual and encode everything,估计残差和编码所有数据
m_pcPredSearch->encodeResAndCalcRdInterCU( rpcTempCU,
m_pppcOrigYuv [uiWIdx][uiHIdx],
m_pppcPredYuvTemp[uiWIdx][uiHIdx],
m_pppcResiYuvTemp[uiWIdx][uiHIdx],
m_pppcResiYuvBest[uiWIdx][uiHIdx],
m_pppcRecoYuvTemp[uiWIdx][uiHIdx],
(uiNoResidual != 0)
#if COM16_C806_EM
4000
T
, rpcBestCU->getTotalCost()
#endif
);
#else
m_pcPredSearch->motionCompensation ( rpcTempCU, m_ppcPredYuvTemp[uhDepth] );

#if COM16_C806_OBMC
m_pcPredSearch->subBlockOBMC( rpcTempCU, 0, m_ppcPredYuvTemp[uhDepth], m_ppcTmpYuv1[uhDepth], m_ppcTmpYuv2[uhDepth] );
#endif
// estimate residual and encode everything
m_pcPredSearch->encodeResAndCalcRdInterCU( rpcTempCU,
m_ppcOrigYuv [uhDepth],
m_ppcPredYuvTemp[uhDepth],
m_ppcResiYuvTemp[uhDepth],
m_ppcResiYuvBest[uhDepth],
m_ppcRecoYuvTemp[uhDepth],
(uiNoResidual != 0)
#if COM16_C806_EMT
, rpcBestCU->getTotalCost()
#endif
);
#endif
if ( uiNoResidual == 0 && rpcTempCU->getQtRootCbf(0) == 0 )
{ //如果是第一次迭代,且cbf为0时(即无残差时),令mergeCandBuffer[uiMergeCnad]=1;
// If no residual when allowing for one, then set mark to not try case where residual is forced to 0
mergeCandBuffer[uiMergeCand] = 1;
}

rpcTempCU->setSkipFlagSubParts( rpcTempCU->getQtRootCbf(0) == 0, 0, uhDepth );//如果当前CU的cbf为0时,设置Skip Flag为true,否则为false
Int orgQP = rpcTempCU->getQP( 0 );
xCheckDQP( rpcTempCU );
xCheckBestMode(rpcBestCU, rpcTempCU, uhDepth);
rpcTempCU->initEstData( uhDepth, orgQP, bTransquantBypassFlag );//比较完TempCU和BestCU,就将TempCU重新初始化
}
}//////////////////////遍历merge候选结束/////////////////////////
}///////////////////////迭代结束///////////////////////////////////
}
#endif
//得到Affine的merge候选预测模式
Void TComDataCU::getAffineMergeCandidates( UInt uiAbsPartIdx, UInt uiPUIdx, TComMvField (*pcMvFieldNeighbours)[3], UChar* puhInterDirNeighbours, Int& numValidMergeCand, Int mrgCandIdx )
{
TComMvField affineMvField[2][3];//2是表示有两个双向预测,3是表示3种运动矢量场???
UInt uiAbsPartAddr = m_absZIdxInCtu + uiAbsPartIdx;

TComDataCU *pcTempCU = NULL;
Bool bAvailable = false;
UInt uiPartIdx = 0;
//初始化运动场
for ( Int mvNum = 0; mvNum < 3; mvNum++ )
{
pcMvFieldNeighbours[0][mvNum].setMvField( TComMv(0,0), -1 );
pcMvFieldNeighbours[1][mvNum].setMvField( TComMv(0,0), -1 );
}

// Get Part Index in LCU,得到CU在LCU的索引
UInt uiPartIdxLT, uiPartIdxRT, uiPartIdxLB;
deriveLeftRightTopIdxGeneral( uiAbsPartIdx, uiPUIdx, uiPartIdxLT, uiPartIdxRT );//推导左上part和右上part的索引
deriveLeftBottomIdxGeneral  ( uiAbsPartIdx, uiPUIdx, uiPartIdxLB );//推导左下part的索引
//当一个CU应用AF_MERGE模式时,从有效的相邻重建块中得到第一个用仿射模式的编码块。候选块的选择顺序是从左,上,右上,左下到左上
// left
pcTempCU = getPULeft( uiPartIdx, uiPartIdxLB );
bAvailable = pcTempCU && pcTempCU->isAffine( uiPartIdx );//左边CU是否是Affine模式

// above
if ( !bAvailable )//如果左边不是,则查看上边的CU
{
pcTempCU = getPUAbove( uiPartIdx, uiPartIdxRT );
bAvailable = pcTempCU && pcTempCU->isAffine( uiPartIdx );
}

// aboveRight
if ( !bAvailable )//上边不是,则查看右上CU
{
pcTempCU = getPUAboveRight( uiPartIdx, uiPartIdxRT );
bAvailable = pcTempCU && pcTempCU->isAffine( uiPartIdx );
}

// leftBottom
if ( !bAvailable )//右上不是,则查看左下CU
{
pcTempCU = getPUBelowLeft( uiPartIdx, uiPartIdxLB );
bAvailable = pcTempCU && pcTempCU->isAffine( uiPartIdx );
}

// aboveLeft
if ( !bAvailable )//左下不是,则查看左上CU
{
pcTempCU = getPUAboveLeft( uiPartIdx, uiAbsPartAddr );
bAvailable = pcTempCU && pcTempCU->isAffine( uiPartIdx );
}

if ( !bAvailable )//如果5个相邻块都不是仿射模式,则有效的merge候选个数为0,退出;
{
numValidMergeCand = -1;
return;
}
else//否则,有效的merge候选个数为1;
{
assert( pcTempCU );
numValidMergeCand = 1;
}

Int width = pcTempCU->getWidth(uiPartIdx);
Int height = pcTempCU->getHeight(uiPartIdx);
#if !JVET_C0024_QTBT
Int depth  = pcTempCU->getDepth(uiPartIdx);
Int numPart = pcTempCU->getPic()->getNumPartitionsInCtu() >> ( depth << 1 );
#endif
Int iPartW = width / getPic()->getMinCUWidth();
Int iPartH = height / getPic()->getMinCUHeight();

#if JVET_C0024_QTBT
Int iBlkY = g_auiZscanToRaster[uiPartIdx]/(getPic()->getNumPartInCtuWidth()*iPartH);
Int iBlkX = (g_auiZscanToRaster[uiPartIdx]%getPic()->getNumPartInCtuWidth())/iPartW;
Int aboveLeftIdx = g_auiRasterToZscan[iBlkY * getPic()->getNumPartInCtuWidth() * iPartH + iBlkX * iPartW];
#else
Int aboveLeftIdx = uiPartIdx - ( uiPartIdx % numPart );
#endif
Int aboveRightIdx = g_auiRasterToZscan[ g_auiZscanToRaster[aboveLeftIdx] + iPartW - 1 ];
Int bottomLeftIdx = g_auiRasterToZscan[ g_auiZscanToRaster[aboveLeftIdx] + ( iPartH - 1 ) * getPic()->getNumPartInCtuWidth() ];

// list0
affineMvField[0][0].setMvField( pcTempCU->getCUMvField(REF_PIC_LIST_0)->getMv( aboveLeftIdx ),  pcTempCU->getCUMvField(REF_PIC_LIST_0)->getRefIdx( aboveLeftIdx ) );
affineMvField[0][1].setMvField( pcTempCU->getCUMvField(REF_PIC_LIST_0)->getMv( aboveRightIdx ), pcTempCU->getCUMvField(REF_PIC_LIST_0)->getRefIdx( aboveRightIdx ) );
affineMvField[0][2].setMvField( pcTempCU->getCUMvField(REF_PIC_LIST_0)->getMv( bottomLeftIdx ), pcTempCU->getCUMvField(REF_PIC_LIST_0)->getRefIdx( bottomLeftIdx ) );

// list1
affineMvField[1][0].setMvField( pcTempCU->getCUMvField(REF_PIC_LIST_1)->getMv( aboveLeftIdx ),  pcTempCU->getCUMvField(REF_PIC_LIST_1)->getRefIdx( aboveLeftIdx ) );
affineMvField[1][1].setMvField( pcTempCU->getCUMvField(REF_PIC_LIST_1)->getMv( aboveRightIdx ), pcTempCU->getCUMvField(REF_PIC_LIST_1)->getRefIdx( aboveRightIdx ) );
affineMvField[1][2].setMvField( pcTempCU->getCUMvField(REF_PIC_LIST_1)->getMv( bottomLeftIdx ), pcTempCU->getCUMvField(REF_PIC_LIST_1)->getRefIdx( bottomLeftIdx ) );

Int pixelOrgX    = g_auiRasterToPelX[ g_auiZscanToRaster[ aboveLeftIdx ] ] + pcTempCU->getCUPelX();
Int pixelCurrX   = getCUPelX();
Int pixelOrgY    = g_auiRasterToPelY[ g_auiZscanToRaster[ aboveLeftIdx ] ] + pcTempCU->getCUPelY();
Int pixelCurrY   = getCUPelY();
//计算运动矢量场;
//vx0,vx1,vx2,vy0,vy1,vy2表示G1001里等式15???
Int vx0 = Int( affineMvField[0][0].getHor() + 1.0 * ( affineMvField[0][2].getHor() - affineMvField[0][0].getHor() ) * ( pixelCurrY - pixelOrgY ) / height
+ 1.0 * ( affineMvField[0][1].getHor() - affineMvField[0][0].getHor() ) * ( pixelCurrX - pixelOrgX ) / width );
Int vy0 = Int( affineMvField[0][0].getVer() + 1.0 * ( affineMvField[0][2].getVer() - affineMvField[0][0].getVer() ) * ( pixelCurrY - pixelOrgY ) / height
+ 1.0 * ( affineMvField[0][1].getVer() - affineMvField[0][0].getVer() ) * ( pixelCurrX - pixelOrgX ) / width );
pcMvFieldNeighbours[0][0].setMvField( TComMv(vx0, vy0), affineMvField[0][0].getRefIdx() );
if ( getSlice()->isInterB() )//如果是B_SLICE,则还要计算另一个方向的运动矢量场;
{
vx0 = Int( affineMvField[1][0].getHor() + 1.0 * ( affineMvField[1][2].getHor() - affineMvField[1][0].getHor() ) * ( pixelCurrY - pixelOrgY ) / height
+ 1.0 * ( affineMvField[1][1].getHor() - affineMvField[1][0].getHor() ) * ( pixelCurrX - pixelOrgX ) / width );
vy0 = Int( affineMvField[1][0].getVer() + 1.0 * ( affineMvField[1][2].getVer() - affineMvField[1][0].getVer() ) * ( pixelCurrY - pixelOrgY ) / height
+ 1.0 * ( affineMvField[1][1].getVer() - affineMvField[1][0].getVer() ) * ( pixelCurrX - pixelOrgX ) / width );
pcMvFieldNeighbours[1][0].setMvField( TComMv(vx0, vy0), affineMvField[1][0].getRefIdx() );
}

Int vx1 = Int( 1.0 * ( affineMvField[0][1].getHor() - affineMvField[0][0].getHor() ) * getWidth(0) / width + pcMvFieldNeighbours[0][0].getHor() );
Int vy1 = Int( 1.0 * ( affineMvField[0][1].getVer() - affineMvField[0][0].getVer() ) * getWidth(0) / width + pcMvFieldNeighbours[0][0].getVer() );
pcMvFieldNeighbours[0][1].setMvField( TComMv(vx1, vy1), affineMvField[0][0].getRefIdx() );
if ( getSlice()->isInterB() )//如果是B_SLICE,则还要计算另一个方向的运动矢量场;
{
vx1 = Int( 1.0 * ( affineMvField[1][1].getHor() - affineMvField[1][0].getHor() ) * getWidth(0) / width + pcMvFieldNeighbours[1][0].getHor() );
vy1 = Int( 1.0 * ( affineMvField[1][1].getVer() - affineMvField[1][0].getVer() ) * getWidth(0) / width + pcMvFieldNeighbours[1][0].getVer() );
pcMvFieldNeighbours[1][1].setMvField( TComMv(vx1, vy1), affineMvField[1][0].getRefIdx() );
}

Int vx2 = Int( 1.0 * ( affineMvField[0][2].getHor() - affineMvField[0][0].getHor() ) * getHeight(0) / height + pcMvFieldNeighbours[0][0].getHor() );
Int vy2 = Int( 1.0 * ( affineMvField[0][2].getVer() - affineMvField[0][0].getVer() ) * getHeight(0) / height + pcMvFieldNeighbours[0][0].getVer() );
pcMvFieldNeighbours[0][2].setMvField( TComMv(vx2, vy2), affineMvField[0][0].getRefIdx() );
if ( getSlice()->isInterB() )//如果是B_SLICE,则还要计算另一个方向的运动矢量场;
{
vx2 = Int( 1.0 * ( affineMvField[1][2].getHor() - affineMvField[1][0].getHor() ) * getHeight(0) / height + pcMvFieldNeighbours[1][0].getHor() );
vy2 = Int( 1.0 * ( affineMvField[1][2].getVer() - affineMvField[1][0].getVer() ) * getHeight(0) / height + pcMvFieldNeighbours[1][0].getVer() );
pcMvFieldNeighbours[1][2].setMvField( TComMv(vx2, vy2), affineMvField[1][0].getRefIdx() );
}

puhInterDirNeighbours[0] = pcTempCU->getInterDir( uiPartIdx );
return;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: