编码帧内预测模式
大量增加可选择的预测模式可以提供更高的编码效率,同时要求编码预测模式有更加高效的方法降低更多模式带来的负担。与H.264采用一个最可能模式不同的是,对于亮度分量,三个最可能模式用于预测实际的帧内预测模式。同时,也考虑了三个最可能模式中的冗余信息,重复的模式会使用其他模式进行替换。对于亮度分量,HEVC采用了同亮度分量相同的预测模式。在编码亮度和色度帧内预测模式时,各个语法元素的设计也体现了亮度分量更多的最可能候选模式以及亮度分量的统计特性。
(1)亮度帧内预测模式的预测
HEVC对每种PU大小共支持总计33种角度模式,外加上DC和平面模式。由于支持的模式更多,类似于H.264的单一最可能模式在HEVC中效率不高。HEVC针对每种PU大小定义了三个最可能模式,其选择依赖于相邻PU所选的模式。同时,由于最可能模式之外的模式概率分布接近平均,这样也可以由一个不经过CABAC的定长编码表示的结构来从剩余32个模式中指定一个模式。
最可能模式的选择根据左侧和上方的相邻块的模式确定。如果某一个相邻块不是帧内编码或者编码模式为PCM模式,或左边PU处于当前CTU之外,那么该块的模式在这个过程中等同于DC模式。设左侧和上方PU的模式分别为A和B,如果A≠B,那么这两个模式分别设为MPM[0]和MPM[1]。对于MPM[2]的确定需要遵循以下原则:①如果A或B都不是平面模式,那么MPM[2]设为平面模式;②否则,若A或B都不是DC模式,那么MPM[2]设为DC模式;③否则(即AB中有一个平面一个DC模式),MPM[2]设为模式26,即垂直模式。如果A=B,那么确定MPM的方法如下:①如果A和B都不是角度预测模式,那么MPM分别设定为平面、DC和垂直模式;②否则,MPM[0]设为A/B,MPM[1]和MPM[2]选择A的相邻模式,公式如下:
三个最可能模式确定后,会按照模式序号进行排序。如果当前预测模式等同于三个最可能模式之一,那么只有该模式在MPM的索引值会传递给解码器,否则将会传递一个5位且不经过CABAC的语法元素表示在MPM之外所选择的帧内预测模式。
该部分的实现如下:
/** Get most probable intra modes
*\param uiAbsPartIdx
*\param uiIntraDirPred pointer to the array for MPM storage
*\param piMode it is set with MPM mode in case both MPM are equal. It is used to restrict RD search at encode side.
*\returns Number of MPM
*/
Int TComDataCU::getIntraDirLumaPredictor( UInt uiAbsPartIdx, Int* uiIntraDirPred, Int* piMode )
{
TComDataCU* pcTempCU;
UInt uiTempPartIdx;
Int iLeftIntraDir, iAboveIntraDir;
Int uiPredNum = 0;
// Get intra direction of left PU
pcTempCU = getPULeft( uiTempPartIdx, m_uiAbsIdxInLCU + uiAbsPartIdx );//获取左方PU
iLeftIntraDir = pcTempCU ? ( pcTempCU->isIntra( uiTempPartIdx ) ? pcTempCU->getLumaIntraDir( uiTempPartIdx ) : DC_IDX ) : DC_IDX;//左方PU为空或非Intra,左方的PU模式则设置为DC,否则设置为左方PU的模式
// Get intra direction of above PU
pcTempCU = getPUAbove( uiTempPartIdx, m_uiAbsIdxInLCU + uiAbsPartIdx, true, true );//获取上方PU
iAboveIntraDir = pcTempCU ? ( pcTempCU->isIntra( uiTempPartIdx ) ? pcTempCU->getLumaIntraDir( uiTempPartIdx ) : DC_IDX ) : DC_IDX;//上方PU为空或非Intra,上方的PU模式则设置为DC,否则设置为上方PU的模式
uiPredNum = 3;
if(iLeftIntraDir == iAboveIntraDir)
{
//模式A和模式B相等的情况
if( piMode )
{
*piMode = 1;
}
if (iLeftIntraDir > 1) // angular modes
{
//如果二者都是角度预测,那么MPM[0]设置为该角度模式,MPM[1]和MPM[2]设置为该模式的相邻模式
uiIntraDirPred[0] = iLeftIntraDir;
uiIntraDirPred[1] = ((iLeftIntraDir + 29) % 32) + 2;
uiIntraDirPred[2] = ((iLeftIntraDir - 1 ) % 32) + 2;
}
else //non-angular
{
//如果二者都不是角度预测,那么三种模式分别设置为平面、DC和垂直模式
uiIntraDirPred[0] = PLANAR_IDX;
uiIntraDirPred[1] = DC_IDX;
uiIntraDirPred[2] = VER_IDX;
}
}
else
{
//模式A与模式B不等
if( piMode )
{
*piMode = 2;
}
uiIntraDirPred[0] = iLeftIntraDir;//MPM[0]和MPM[1]分别设置为这两种模式
uiIntraDirPred[1] = iAboveIntraDir;
if (iLeftIntraDir && iAboveIntraDir ) //both modes are non-planar
{
//当两个模式都不是平面模式时,MPM[2]设置为平面模式
uiIntraDirPred[2] = PLANAR_IDX;
}
else
{
//至少有一个是平面模式时,如果另一个是DC模式,那么MPM[2]设置为垂直模式;如果另一个不是DC模式,那么MPM[2]设置为DC模式
uiIntraDirPred[2] = (iLeftIntraDir+iAboveIntraDir)<2? VER_IDX : DC_IDX;
}
}
return uiPredNum;
}