predIntraAng函数进行帧内角度预测,根据给定的帧内预测模式,求得该模式下的预测像素piPred:
void IntraPrediction::predIntraAng( const ComponentID compId, PelBuf &piPred, const PredictionUnit &pu, const bool useFilteredPredSamples )
{
const ComponentID compID = MAP_CHROMA( compId );
const ChannelType channelType = toChannelType( compID );
const Int iWidth = piPred.width;
const Int iHeight = piPred.height;
const UInt uiDirMode = PU::getFinalIntraMode( pu, channelType ); //当前测试的帧内模式
CHECK( g_aucLog2[iWidth] < 2 && pu.cs->pcv->noChroma2x2, "Size not allowed" );
CHECK( g_aucLog2[iWidth] > 7, "Size not allowed" );
CHECK( iWidth != iHeight && !pu.cs->pcv->rectCUs, "Rectangular block are only allowed with QTBT" );
const Int srcStride = ( iWidth + iHeight + 1 ); //参考像素的stride
//initIntraPatternChType函数中得到的当前pu的参考像素
Pel *ptrSrc = getPredictorPtr( compID, useFilteredPredSamples );
{
switch( uiDirMode )
{
case( DC_IDX ): xPredIntraDc ( CPelBuf( ptrSrc, srcStride, srcStride ), piPred, channelType ); break; // including DCPredFiltering
case( PLANAR_IDX ): xPredIntraPlanar( CPelBuf( ptrSrc, srcStride, srcStride ), piPred, *pu.cs->sps ); break;
default: xPredIntraAng ( CPelBuf( ptrSrc, srcStride, srcStride ), piPred, channelType, uiDirMode,
pu.cs->slice->clpRng( compID ), *pu.cs->sps ); break; //67种帧内角度模式
}
}
}
//DC模式
Void IntraPrediction::xPredIntraDc( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const bool enableBoundaryFilter )
{
const Pel dcval = xGetPredValDc( pSrc, pDst ); //将参考像素的左下、左、左上、上和右上区域的参考像素,取平均
pDst.fill( dcval ); //参考像素的平均值,作为DC模式的整个预测像素
}
//Planar模式
Void IntraPrediction::xPredIntraPlanar( const CPelBuf &pSrc, PelBuf &pDst, const SPS& sps )
{
const UInt width = pDst.width;
const UInt height = pDst.height;
const UInt log2W = g_aucLog2[ width ];
const UInt log2H = g_aucLog2[ height ];
Int leftColumn[MAX_CU_SIZE + 1], topRow[MAX_CU_SIZE + 1], bottomRow[MAX_CU_SIZE], rightColumn[MAX_CU_SIZE];
const UInt offset = width * height;
// Get left and above reference column and row
for( Int k = 0; k < width + 1; k++ )
{
topRow[k] = pSrc.at( k + 1, 0 ); //上区域的参考像素
}
for( Int k = 0; k < height + 1; k++ )
{
leftColumn[k] = pSrc.at( 0, k + 1 ); //左区域的参考像素
}
// Prepare intermediate variables used in interpolation
Int bottomLeft = leftColumn[height]; //左区域参考像素在pu最后一行位置的像素值
Int topRight = topRow[width]; //上区域参考像素在pu最后一列位置的像素值
for( Int k = 0; k < width; k++ )
{
bottomRow[k] = bottomLeft - topRow[k]; //构建底边的参考像素
topRow[k] = topRow[k] << log2H;
}
for( Int k = 0; k < height; k++ )
{
rightColumn[k] = topRight - leftColumn[k]; //构架右边的参考像素
leftColumn[k] = leftColumn[k] << log2W;
}
const UInt finalShift = 1 + log2W + log2H;
const UInt stride = pDst.stride;
Pel* pred = pDst.buf;
for( Int y = 0; y < height; y++, pred += stride )
{
Int horPred = leftColumn[y];
for( Int x = 0; x < width; x++ ) //最终利用上下左右4边的参考像素,求得pu内每个像素点的预测值
{
horPred += rightColumn[y];
topRow[x] += bottomRow[x];
Int vertPred = topRow[x];
pred[x] = ( ( horPred << log2H ) + ( vertPred << log2W ) + offset ) >> finalShift;
}
}
}