I帧亮度和色度独立划分的原因:亮度分量和色度分量是两种具有不同特性的分量,亮度分量拥有大量的细节信息,而色度分量携带的信息比较少,比较平滑,如果把他们放在一起划分,划分的太细则会导致色度分量浪费比特,划分太粗则会导致亮度分量性能下降,所以将亮度分量和色度分量分开划分,则亮度分量可以划分的细一点,色度分量可以划分的粗一点,在保持编码性能的同时还能够减少编码比特。而在B和P帧中,大部分的块的都采用帧间预测,亮度块和色度块是对应的,所以就不必要分开划分了。
在H.266中,对于I slice,支持亮度和色度采用不同的QTBT结构,对于B 和P slice,亮度和色度才采取相同的QTBT结构,具体体现在代码中为(删除了无关代码):
Void TEncCu::compressCtu( TComDataCU* pCtu )
{
//函数刚开始就将分量类型设定为亮度分量,这样在第一次调用xCompressCU里的xCheckRDCostIntra时,如果是I slice只执行里面的estIntraPredLumaQT()函数,即只进行亮度块的划分;
pCtu->getSlice()->setTextType(CHANNEL_TYPE_LUMA);
xCompressCU();
if (pCtu->getSlice()->isIntra()) //如果是I_SLICE;
{//将分量固定为色度分量,所以第二次调用xCompressCU里的xCheckRDCostIntra时,如果是I slice时,只执行里面的estIntraPreChromaQT(),即进行色度块的划分;
pCtu->getSlice()->setTextType(CHANNEL_TYPE_CHROMA);
xCompressCU();
}
}
//再来看看下面这个函数,对于estIntraPredLumaQT()函数,不管I ,B还是P,都会调用,而对于estIntraPredChromaQT函数,只有当是色度分量或者是B和P slice的时候会调用,总的来说就是如果是B和P帧的话,在一个xCompressCU里就实现了亮度和色度的划分;
xCheckRDCostIntra()
{
if (isLuma(rpcBestCU->getTextType()))
{
m_pcPredSearch->estIntraPredLumaQT();
}
if (rpcBestCU->getPic()->getChromaFormat()!=CHROMA_400
&& (isChroma(rpcBestCU->getTextType()) || !rpcBestCU->getSlice()->isIntra()))
{
m_pcPredSearch->estIntraPredChromaQT();
}
}
综上,就实现了I SLICE的亮度和色度QTBT结构的分离,同时B和P帧的亮度和色度共享同一个QTBT结构;