此系列是为了记录自己学习VTM10.0的过程,目前正在看编码端。主要的参考文档有JVET-S2001-vH和JVET-S2002-v1。由于本人水平有限,出现的错误恳请大家指正,欢迎与大家一起交流进步。
前两篇博文(VTM10.0代码学习14和VTM10.0代码学习15)讲述了如何抉择出亮度的最佳帧内模式,本篇博文就来看看色度部分的函数estIntraPredChromaQT(),会比亮度部分简单一些
1. estIntraPredChromaQT
const ChromaFormat format = cu.chromaFormat;
const uint32_t numberValidComponents = getNumberValidComponents(format);
CodingStructure &cs = *cu.cs;
const TempCtx ctxStart ( m_CtxCache, m_CABACEstimator->getCtx() );
cs.setDecomp( cs.area.Cb(), false );
double bestCostSoFar = maxCostAllowed;//色度目前最佳帧内模式的RDcost
bool lumaUsesISP = !cu.isSepTree() && cu.ispMode;//色度和亮度划分一致且当前CU开启ISP模式
PartSplit ispType = lumaUsesISP ? CU::getISPType( cu, COMPONENT_Y ) : TU_NO_ISP;//ISP划分类型
auto &pu = *cu.firstPU;
bestCostSoFar:色度目前最佳帧内模式的RDcost
lumaUsesISP:色度和亮度划分一致且当前CU开启ISP模式
ispType:ISP划分类型
uint32_t uiBestMode = 0;//色度最佳帧内模式
Distortion uiBestDist = 0;//当前CU最佳帧内模式下的失真(色度和亮度或单独色度)
double dBestCost = MAX_DOUBLE;//色度分量的最佳RDcost
uint32_t chromaCandModes[ NUM_CHROMA_MODE ];
PU::getIntraChromaCandModes( pu, chromaCandModes );//获得色度预测模式候选列表
uiBestMode:色度最佳帧内模式
uiBestDist:当前CU最佳帧内模式下的失真(色度和亮度或单独色度)
dBestCost:色度分量的最佳RDcost
chromaCandModes:色度预测模式候选列表
CodingStructure &saveCS = *m_pSaveCS[0];
saveCS.pcv = cs.pcv;
saveCS.picture = cs.picture;
saveCS.area.repositionTo( cs.area );
saveCS.clearTUs();
if( !cu.isSepTree() && cu.ispMode )
{
saveCS.clearCUs();
saveCS.clearPUs();
}
暂时的cs,用于存储最佳模式下的cs
if( cu.isSepTree() )
{
if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
{
partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
do
{
cs.addTU( CS::getArea( cs, partitioner.currArea(), partitioner.chType ), partitioner.chType ).depth = partitioner.currTrDepth;
} while( partitioner.nextPart( cs ) );
partitioner.exitCurrSplit();
}
else
cs.addTU( CS::getArea( cs, partitioner.currArea(), partitioner.chType ), partitioner.chType );
}
如果是dual tree或local dual tree,色度分量需要单独添加TU
std::vector<TransformUnit*> orgTUs;
if( lumaUsesISP )
{
CodingUnit& auxCU = saveCS.addCU( cu, partitioner.chType );
auxCU.ispMode = cu.ispMode;
saveCS.sps = cu.cs->sps;
saveCS.addPU( *cu.firstPU, partitioner.chType );
}
// create a store for the TUs
for( const auto &ptu : cs.tus )
{
// for split TUs in HEVC, add the TUs without Chroma parts for correct setting of Cbfs
if( lumaUsesISP || pu.contains( *ptu, CHANNEL_TYPE_CHROMA ) )
{
saveCS.addTU( *ptu, partitioner.chType );
orgTUs.push_back( ptu );
}
}
if( lumaUsesISP )
{
saveCS.clearCUs();
}
orgTUs:存放当前模式下的色度TU
这里主要是向saveCS添加TU和设置orgTUs
int satdModeList[NUM_CHROMA_MODE];//存储着模式候选列表的模式
int64_t satdSortedCost[NUM_CHROMA_MODE];//存储着模式候选列表的SAD和SATD的组合失真
for (int i = 0; i < NUM_CHROMA_MODE; i++)
{
satdSortedCost[i] = 0; // for the mode not pre-select by SATD, do RDO by default, so set the initial value 0.
satdModeList[i] = 0;
}
//表示对应模式是否可以进行RDcost计算
bool modeIsEnable[NUM_INTRA_MODE + 1]; // use intra mode idx to check whether enable
for (int i = 0; i < NUM_INTRA_MODE + 1; i++)
{
modeIsEnable[i] = 1;
}
DistParam distParamSad;
DistParam distParamSatd;
pu.intraDir[1] = MDLM_L_IDX; // temporary assigned, just to indicate this is a MDLM mode. for luma down-sampling operation.
//初始化帧内预测参数并获取参考像素,如果需要则对参考像素进行滤波
initIntraPatternChType(cu, pu.Cb());
initIntraPatternChType(cu, pu.Cr());
xGetLumaRecPixels(pu, pu.Cb());//获取亮度的重建值
satdModeList:存储着模式候选列表的模式
satdSortedCost:存储着模式候选列表的SAD和SATD的组合失真
modeIsEnable:表示对应模式是否可以进行RDcost计算
for (int idx = uiMinMode; idx <= uiMaxMode - 1; idx++)
{
int mode = chromaCandModes[idx];
satdModeList[idx] = mode;
if (PU::isLMCMode(mode) && !PU::isLMCModeEnabled(pu, mode))
{
continue;
}
if ((mode == LM_CHROMA_IDX) || (mode == PLANAR_IDX) || (mode == DM_CHROMA_IDX)) // only pre-check regular modes and MDLM modes, not including DM ,Planar, and LM
{
continue;
}
pu.intraDir[1] = mode; // temporary assigned, for SATD checking.
int64_t sad = 0;
int64_t sadCb = 0;
int64_t satdCb = 0;
int64_t sadCr = 0;
int64_t satdCr = 0;
CodingStructure& cs = *(pu.cs);
CompArea areaCb = pu.Cb();
PelBuf orgCb = cs.getOrgBuf(areaCb);
PelBuf predCb = cs.getPredBuf(areaCb);
m_pcRdCost->setDistParam(distParamSad, orgCb, predCb, pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), COMPONENT_Cb, false);
m_pcRdCost->setDistParam(distParamSatd, orgCb, predCb, pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), COMPONENT_Cb, true);
distParamSad.applyWeight = false;
distParamSatd.applyWeight = false;
if (PU::isLMCMode(mode))
{
predIntraChromaLM(COMPONENT_Cb, predCb, pu, areaCb, mode);
}
else
{
initPredIntraParams(pu, pu.Cb(), *pu.cs->sps);
predIntraAng(COMPONENT_Cb, predCb, pu);
}
sadCb = distParamSad.distFunc(distParamSad) * 2;
satdCb = distParamSatd.distFunc(distParamSatd);
sad += std::min(sadCb, satdCb);
CompArea areaCr = pu.Cr();
PelBuf orgCr = cs.getOrgBuf(areaCr);
PelBuf predCr = cs.getPredBuf(areaCr);
m_pcRdCost->setDistParam(distParamSad, orgCr, predCr, pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), COMPONENT_Cr, false)