getIntraMPMs在estIntraPredLumaQT函数中被调用,用来获取亮度帧内预测模式的MPM候选模式,MPM模式存储在mpm中。
流程大致为:获取左侧和上侧的pu帧内预测模式,然后按照left和above模式的情况,给mpm列表赋值:
int PU::getIntraMPMs( const PredictionUnit &pu, unsigned* mpm, const ChannelType &channelType /*= CHANNEL_TYPE_LUMA*/ )
{
const unsigned numMPMs = pu.cs->pcv->numMPMs; //mpm候选模式的数目
{
Int numCand = -1;
Int leftIntraDir = DC_IDX, aboveIntraDir = DC_IDX;
const CompArea& area = pu.block( getFirstComponentOfChannel( channelType ) );
const Position& pos = area.pos(); //当前亮度pu的位置
// Get intra direction of left PU 左侧pu
const PredictionUnit *puLeft = pu.cs->getPURestricted( pos.offset( -1, 0 ), pu, channelType );
if( puLeft && CU::isIntra( *puLeft->cu ) )
{
leftIntraDir = puLeft->intraDir[channelType]; //左侧pu的亮度帧内模式
if( isChroma( channelType ) && leftIntraDir == DM_CHROMA_IDX )
{
leftIntraDir = puLeft->intraDir[0];
}
}
// Get intra direction of above PU 上侧pu
const PredictionUnit* puAbove = pu.cs->getPURestricted( pos.offset( 0, -1 ), pu, channelType );
if( puAbove && CU::isIntra( *puAbove->cu ) && CU::isSameCtu( *pu.cu, *puAbove->cu ) ) //上侧pu必须与当前pu在同一个ctu之内
{
aboveIntraDir = puAbove->intraDir[channelType]; //上侧pu的亮度帧内模式
if( isChroma( channelType ) && aboveIntraDir == DM_CHROMA_IDX )
{
aboveIntraDir = puAbove->intraDir[0];
}
}
CHECK( 2 >= numMPMs, "Invalid number of most probable modes" );
const Int offset = 29;
const Int mod = offset + 3;
///然后根据左侧和上侧pu的亮度帧内模式,构建mpm列表
if( leftIntraDir == aboveIntraDir )
{ //左侧和上侧pu的模式相同
numCand = 1;
if( leftIntraDir > DC_IDX ) // angular modes //左侧和上侧pu的模式大于DC模式,即leftIntraDir为65种角度模式
{
mpm[0] = g_intraMode65to33AngMapping[leftIntraDir];
mpm[1] = ((g_intraMode65to33AngMapping[leftIntraDir] + offset) % mod) + 2;
mpm[2] = ((g_intraMode65to33AngMapping[leftIntraDir] - 1) % mod) + 2;
}
else //non-angular //如果left和above的模式为DC或planar
{
mpm[0] = g_intraMode65to33AngMapping[PLANAR_IDX];
mpm[1] = g_intraMode65to33AngMapping[DC_IDX];
mpm[2] = g_intraMode65to33AngMapping[VER_IDX];
}
}
else //左侧和上侧pu的模式不同
{
numCand = 2;
mpm[0] = g_intraMode65to33AngMapping[leftIntraDir];
mpm[1] = g_intraMode65to33AngMapping[aboveIntraDir];
if( leftIntraDir && aboveIntraDir ) //both modes are non-planar
{
mpm[2] = g_intraMode65to33AngMapping[PLANAR_IDX]; //均不为planar模式时,添加planar
}
else
{
mpm[2] = g_intraMode65to33AngMapping[(leftIntraDir + aboveIntraDir) < 2 ? VER_IDX : DC_IDX];
}
}
for( UInt i = 0; i < numMPMs; i++ )
{
mpm[i] = g_intraMode33to65AngMapping[mpm[i]];
CHECK( mpm[i] >= NUM_LUMA_MODE, "Invalid MPM" );
}
CHECK( numCand == 0, "No candidates found" );
return numCand; //返回mpm候选模式的数目
}
}