VVC代码阅读 xCompressCU(2) do while结构 最后面有两小段函数没看

编程入门 行业动态 更新时间:2024-10-12 22:28:20

VVC代码阅读 xCompressCU(2) do while结构 最后面有两<a href=https://www.elefans.com/category/jswz/34/1648558.html style=小段函数没看"/>

VVC代码阅读 xCompressCU(2) do while结构 最后面有两小段函数没看

H.266/VVC代码学习:xCompressCU函数_涵小呆的博客-CSDN博客

尝试当前编码器各种可用的模式:如skip,帧间,帧内,PCM等,进行预测及划分。

do
{
} while( m_modeCtrl->nextMode( *tempCS, partitioner ) );

for (int i = compBegin; i < (compBegin + numComp); i++){ComponentID comID = jointPLT ? (ComponentID)compBegin : ((i > 0) ? COMPONENT_Cb : COMPONENT_Y);tempCS->prevPLT.curPLTSize[comID] = curLastPLTSize[comID];memcpy(tempCS->prevPLT.curPLT[i], curLastPLT[i], curLastPLTSize[comID] * sizeof(Pel));}EncTestMode currTestMode = m_modeCtrl->currTestMode();currTestMode.maxCostAllowed = maxCostAllowed;

for循环:遍历分量,将 PLT 的相关变量填充。当前帧未使用PLT,先跳过

currTestMode:当前要测试的模式

maxCostAllowed:当前测试模式允许的最大cost

if (pps.getUseDQP() && partitioner.isSepTree(*tempCS) && isChroma( partitioner.chType )){const Position chromaCentral(tempCS->area.Cb().chromaPos().offset(tempCS->area.Cb().chromaSize().width >> 1, tempCS->area.Cb().chromaSize().height >> 1));const Position lumaRefPos(chromaCentral.x << getComponentScaleX(COMPONENT_Cb, tempCS->area.chromaFormat), chromaCentral.y << getComponentScaleY(COMPONENT_Cb, tempCS->area.chromaFormat));const CodingStructure* baseCS = bestCS->picture->cs;const CodingUnit* colLumaCu = baseCS->getCU(lumaRefPos, CHANNEL_TYPE_LUMA);if (colLumaCu){currTestMode.qp = colLumaCu->qp;}}

dqp:delta QP

【笔记】HEVC 编码标准(六)——量化_lock。的博客-CSDN博客_hevc 量化

这个函数放在后面去看

    if( currTestMode.type == ETM_INTER_ME ){if( ( currTestMode.opts & ETO_IMV ) != 0 ){const bool skipAltHpelIF = ( int( ( currTestMode.opts & ETO_IMV ) >> ETO_IMV_SHIFT ) == 4 ) && ( bestIntPelCost > 1.25 * bestCS->cost );if (!skipAltHpelIF){tempCS->bestCS = bestCS;xCheckRDCostInterIMV(tempCS, bestCS, partitioner, currTestMode, bestIntPelCost);tempCS->bestCS = nullptr;}}else{tempCS->bestCS = bestCS;xCheckRDCostInter( tempCS, bestCS, partitioner, currTestMode );tempCS->bestCS = nullptr;}}

当前测试模式为inter时启用

    // 若当前测试模式是 HASH INTER// 则检查 HashInter 的 RD cost 
else if (currTestMode.type == ETM_HASH_INTER){xCheckRDCostHashInter( tempCS, bestCS, partitioner, currTestMode );}// 若当前测试模式是 AFFINE// 则检查 Affine 的 RD costelse if( currTestMode.type == ETM_AFFINE ){xCheckRDCostAffineMerge2Nx2N( tempCS, bestCS, partitioner, currTestMode );}
#if REUSE_CU_RESULTS// 若当前测试模式是 RECO_CACHED// 则检查 Reuse Cached 的 RD costelse if( currTestMode.type == ETM_RECO_CACHED ){xReuseCachedResult( tempCS, bestCS, partitioner );}// 若当前测试模式是 MERGE_SKIP// 则检查 Merge 的 RD costelse if( currTestMode.type == ETM_MERGE_SKIP ){xCheckRDCostMerge2Nx2N( tempCS, bestCS, partitioner, currTestMode );CodingUnit* cu = bestCS->getCU(partitioner.chType);if (cu){cu->mmvdSkip = cu->skip == false ? false : cu->mmvdSkip;}}// 若当前测试模式是 MERGE_GEO// 则检查 Merge Geo 的 RD costelse if( currTestMode.type == ETM_MERGE_GEO ){xCheckRDCostMergeGeo2Nx2N( tempCS, bestCS, partitioner, currTestMode );}

之后再细看

 else if( currTestMode.type == ETM_INTRA ){//若使用色彩变换且不为dual treeif (slice.getSPS()->getUseColorTrans() && !CS::isDualITree(*tempCS)){//不跳过第二色彩空间bool skipSecColorSpace = false;skipSecColorSpace = xCheckRDCostIntra(tempCS, bestCS, partitioner, currTestMode, (m_pcEncCfg->getRGBFormatFlag() ? true : false));if ((m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless()) && !m_pcEncCfg->getRGBFormatFlag()){skipSecColorSpace = true;}if (!skipSecColorSpace && !tempCS->firstColorSpaceTestOnly){xCheckRDCostIntra(tempCS, bestCS, partitioner, currTestMode, (m_pcEncCfg->getRGBFormatFlag() ? false : true));}if (!tempCS->firstColorSpaceTestOnly){if (tempCS->tmpColorSpaceIntraCost[0] != MAX_DOUBLE && tempCS->tmpColorSpaceIntraCost[1] != MAX_DOUBLE){double skipCostRatio = m_pcEncCfg->getRGBFormatFlag() ? 1.1 : 1.0;if (tempCS->tmpColorSpaceIntraCost[1] > (skipCostRatio*tempCS->tmpColorSpaceIntraCost[0])){tempCS->firstColorSpaceTestOnly = bestCS->firstColorSpaceTestOnly = true;}}}else{CHECK(tempCS->tmpColorSpaceIntraCost[1] != MAX_DOUBLE, "the RD test of the second color space should be skipped");}}else{xCheckRDCostIntra(tempCS, bestCS, partitioner, currTestMode, false);}}

当前测试模式是intra

    // 若当前测试模式是 PALETTE// 则检查 PLT 的 RD cost
else if (currTestMode.type == ETM_PALETTE){xCheckPLT( tempCS, bestCS, partitioner, currTestMode );}// 若当前测试模式是 IBC(Intra block copy)// 则检查 IBC 的 RD costelse if (currTestMode.type == ETM_IBC){xCheckRDCostIBCMode(tempCS, bestCS, partitioner, currTestMode);}// 若当前测试模式是 IBC_MERGE// 则检查 IBC_MERGE 的 RD costelse if (currTestMode.type == ETM_IBC_MERGE){xCheckRDCostIBCModeMerge2Nx2N(tempCS, bestCS, partitioner, currTestMode);}

之后再看

else if( isModeSplit( currTestMode ) ){if (bestCS->cus.size() != 0) //size()返回当前序列长度,不为0表示已划分过{splitmode = bestCS->cus[0]->splitSeries;}assert( partitioner.modeType == tempCS->modeType );int signalModeConsVal = tempCS->signalModeCons( getPartSplit( currTestMode ), partitioner, modeTypeParent );int numRoundRdo = signalModeConsVal == LDT_MODE_TYPE_SIGNAL ? 2 : 1;bool skipInterPass = false;// 遍历 RDO 轮次for( int i = 0; i < numRoundRdo; i++ ){//change cons modes// 若当前信号模式值为 LDT_MODE_TYPE_SIGNAL// 则当前测试模式类型在第一轮设置为 INTER,在第二轮设置为 INTRAif( signalModeConsVal == LDT_MODE_TYPE_SIGNAL ){CHECK( numRoundRdo != 2, "numRoundRdo shall be 2 - [LDT_MODE_TYPE_SIGNAL]" );tempCS->modeType = partitioner.modeType = (i == 0) ? MODE_TYPE_INTER : MODE_TYPE_INTRA;}// 若当前信号模式值为 LDT_MODE_TYPE_INFER// 则当前测试模式类型为 INTRAelse if( signalModeConsVal == LDT_MODE_TYPE_INFER ){CHECK( numRoundRdo != 1, "numRoundRdo shall be 1 - [LDT_MODE_TYPE_INFER]" );tempCS->modeType = partitioner.modeType = MODE_TYPE_INTRA;}// 若当前信号模式值为 LDT_MODE_TYPE_INHERIT// 则当前测试模式类型为父结点模式类型else if( signalModeConsVal == LDT_MODE_TYPE_INHERIT ){CHECK( numRoundRdo != 1, "numRoundRdo shall be 1 - [LDT_MODE_TYPE_INHERIT]" );tempCS->modeType = partitioner.modeType = modeTypeParent;}//for lite intra encoding fast algorithm, set the status to save inter coding info//帧间模式// 若父结点模式类型为 MODE_TYPE_ALL(可以尝试所有类型),且当前测试模式类型为 Inter// 则 SaveCuCostInSCIPU,且设置 NumCuInSCIPU 为0if( modeTypeParent == MODE_TYPE_ALL && tempCS->modeType == MODE_TYPE_INTER ){m_pcIntraSearch->setSaveCuCostInSCIPU( true );m_pcIntraSearch->setNumCuInSCIPU( 0 );}// 若父结点模式类型为 MODE_TYPE_ALL(可以尝试所有类型),且当前测试模式类型不为 Inter// 则 SaveCuCostInSCIPU 为 false,且当前测试模式 MODE_TYPE_ALL 时设置 NumCuInSCIPU 为0else if( modeTypeParent == MODE_TYPE_ALL && tempCS->modeType != MODE_TYPE_INTER ){m_pcIntraSearch->setSaveCuCostInSCIPU( false );if( tempCS->modeType == MODE_TYPE_ALL ){m_pcIntraSearch->setNumCuInSCIPU( 0 );}}xCheckModeSplit( tempCS, bestCS, partitioner, currTestMode, modeTypeParent, skipInterPass );//recover cons modestempCS->modeType = partitioner.modeType = modeTypeParent;tempCS->treeType = partitioner.treeType = treeTypeParent;partitioner.chType = chTypeParent;if( modeTypeParent == MODE_TYPE_ALL ){m_pcIntraSearch->setSaveCuCostInSCIPU( false );if( numRoundRdo == 2 && tempCS->modeType == MODE_TYPE_INTRA ){m_pcIntraSearch->initCuAreaCostInSCIPU();}}if( skipInterPass ){break;}}
#if GDR_ENABLEDif (bestCS->cus.size() > 0 && splitmode != bestCS->cus[0]->splitSeries)
#elseif (splitmode != bestCS->cus[0]->splitSeries)
#endif{splitmode = bestCS->cus[0]->splitSeries;const CodingUnit&     cu = *bestCS->cus.front();cu.cs->prevPLT = bestCS->prevPLT;for (int i = compBegin; i < (compBegin + numComp); i++){ComponentID comID = jointPLT ? (ComponentID)compBegin : ((i > 0) ? COMPONENT_Cb : COMPONENT_Y);bestLastPLTSize[comID] = bestCS->cus[0]->cs->prevPLT.curPLTSize[comID];memcpy(bestLastPLT[i], bestCS->cus[0]->cs->prevPLT.curPLT[i], bestCS->cus[0]->cs->prevPLT.curPLTSize[comID] * sizeof(Pel));}}}
else{THROW( "Don't know how to handle mode: type = " << currTestMode.type << ", options = " << currTestMode.opts );}} while( m_modeCtrl->nextMode( *tempCS, partitioner ) );

当前测试模式为划分

SplitSeries 类:对于每个cu尺寸的具体的划分顺序的一个参数

VVC学习之四:VTM中的数据结构——CodingUnit、PredictionUnit、TransformUnit_Aidoneus_y的博客-CSDN博客

bestCS->cus.size():若当前CU已划分,则当前BestCs的cu数目就不为零。此时设置splitmode,这个好像与在帧内预测中的一个叫getSplitSeries()函数有关,之后看到帧内时再写。推测表示划分时的顺序

assert:检验当前CS结构modeType是否和划分类中设定的modeType相同,如果不同,则终止程序

getPartSplit():从当前测试模式中得到当前CU的划分方式

signalModeConsVal():获得当前信号模式值,规定了子节点是否继承父节点的模式测试方法。0,1,2分别代表三个模式。如0代表LDT_MODE_TYPE_INHERIT

numRoundRdo:当前信号模式值为 LDT_MODE_TYPE_SIGNAL,则Rdo轮次为2

for循环:注释在代码里

xCheckModeSplit():划分模式,这里会递归调用xcompressCu

 //// Finishing CUif( tempCS->cost == MAX_DOUBLE && bestCS->cost == MAX_DOUBLE ){//although some coding modes were planned to be tried in RDO, no coding mode actually finished encoding due to early termination//thus tempCS->cost and bestCS->cost are both MAX_DOUBLE; in this case, skip the following process for normal casem_modeCtrl->finishCULevel( partitioner );return;}// set context statesm_CABACEstimator->getCtx() = m_CurrCtx->best;

如果tempCS和bestCS中的cost都等于double最大值,则finishCULevel()中实现

m_ComprCUCtxList.pop_back();

 在运行完以后,m_ComprCUCtxList的size减少了1.原本的那层出了intra没有其他模式,所以当前CU已经算测试完了,就把栈中这个CU的信息消去,返回上一层父CU

 

  // QP from last processed CU for further processing//copy the qp of the last non-chroma CUint numCUInThisNode = (int)bestCS->cus.size();if( numCUInThisNode > 1 && bestCS->cus.back()->chType == CHANNEL_TYPE_CHROMA && !CS::isDualITree( *bestCS ) ){CHECK( bestCS->cus[numCUInThisNode-2]->chType != CHANNEL_TYPE_LUMA, "wrong chType" );bestCS->prevQP[partitioner.chType] = bestCS->cus[numCUInThisNode-2]->qp;}else{bestCS->prevQP[partitioner.chType] = bestCS->cus.back()->qp;}if ((!slice.isIntra() || slice.getSPS()->getIBCFlag())&& partitioner.chType == CHANNEL_TYPE_LUMA&& bestCS->cus.size() == 1 && (bestCS->cus.back()->predMode == MODE_INTER || bestCS->cus.back()->predMode == MODE_IBC)&& bestCS->area.Y() == (*bestCS->cus.back()).Y()){const CodingUnit&     cu = *bestCS->cus.front();bool isIbcSmallBlk = CU::isIBC(cu) && (cu.lwidth() * cu.lheight() <= 16);CU::saveMotionInHMVP( cu, isIbcSmallBlk );}// 将预测像素和重建像素复制到bestCS->picture中bestCS->picture->getPredBuf(currCsArea).copyFrom(bestCS->getPredBuf(currCsArea));bestCS->picture->getRecoBuf( currCsArea ).copyFrom( bestCS->getRecoBuf( currCsArea ) );m_modeCtrl->finishCULevel( partitioner );if( m_pcIntraSearch->getSaveCuCostInSCIPU() && bestCS->cus.size() == 1 ){m_pcIntraSearch->saveCuAreaCostInSCIPU( Area( partitioner.currArea().lumaPos(), partitioner.currArea().lumaSize() ), bestCS->cost );}

这部分代码有预测和重建像素,要结合后面的预测函数来看

 if (bestCS->cus.size() == 1) // no partition{CHECK(bestCS->cus[0]->tileIdx != bestCS->pps->getTileIdx(bestCS->area.lumaPos()), "Wrong tile index!");if (bestCS->cus[0]->predMode == MODE_PLT){for (int i = compBegin; i < (compBegin + numComp); i++){ComponentID comID = jointPLT ? (ComponentID)compBegin : ((i > 0) ? COMPONENT_Cb : COMPONENT_Y);bestCS->prevPLT.curPLTSize[comID] = curLastPLTSize[comID];memcpy(bestCS->prevPLT.curPLT[i], curLastPLT[i], curLastPLTSize[comID] * sizeof(Pel));}bestCS->reorderPrevPLT(bestCS->prevPLT, bestCS->cus[0]->curPLTSize, bestCS->cus[0]->curPLT, bestCS->cus[0]->reuseflag, compBegin, numComp, jointPLT);}else{for (int i = compBegin; i<(compBegin + numComp); i++){ComponentID comID = jointPLT ? (ComponentID)compBegin : ((i > 0) ? COMPONENT_Cb : COMPONENT_Y);bestCS->prevPLT.curPLTSize[comID] = curLastPLTSize[comID];memcpy(bestCS->prevPLT.curPLT[i], curLastPLT[i], bestCS->prevPLT.curPLTSize[comID] * sizeof(Pel));}}}else{for (int i = compBegin; i<(compBegin + numComp); i++){ComponentID comID = jointPLT ? (ComponentID)compBegin : ((i > 0) ? COMPONENT_Cb : COMPONENT_Y);bestCS->prevPLT.curPLTSize[comID] = bestLastPLTSize[comID];memcpy(bestCS->prevPLT.curPLT[i], bestLastPLT[i], bestCS->prevPLT.curPLTSize[comID] * sizeof(Pel));}}const CodingUnit&     cu = *bestCS->cus.front();cu.cs->prevPLT = bestCS->prevPLT;// Assert if Best prediction mode is NONE// Selected mode's RD-cost must be not MAX_DOUBLE.CHECK( bestCS->cus.empty()                                   , "No possible encoding found" );CHECK( bestCS->cus[0]->predMode == NUMBER_OF_PREDICTION_MODES, "No possible encoding found" );CHECK( bestCS->cost             == MAX_DOUBLE                , "No possible encoding found" );
}

与PLT模式有关,之后再看

更多推荐

VVC代码阅读 xCompressCU(2) do while结构 最后面有两小段函数没看

本文发布于:2024-02-06 10:08:24,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1748019.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:小段   函数   结构   代码   VVC

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!