(个人理解)
predIntraAng()主要完成65种角度模式(外加DC和planar模式)的预测,预测之前还要对参考像素进行相应的滤波操作。
Void TComPrediction::predIntraAng( const ComponentID compID, UInt uiDirMode, Pel* piOrg /* Will be null for decoding */, UInt uiOrgStride, Pel* piPred, UInt uiStride, TComTU &rTu, const Bool bUseFilteredPredSamples, const Bool bUseLosslessDPCM )
{
const ChannelType channelType = toChannelType(compID);
const TComRectangle &rect = rTu.getRect(isLuma(compID) ? COMPONENT_Y : COMPONENT_Cb);
const Int iWidth = rect.width;
const Int iHeight = rect.height;
#if JVET_C0024_QTBT
assert( g_aucConvertToBit[ iWidth ] >= -1 ); //2x2
assert( g_aucConvertToBit[ iWidth ] <= MAX_CU_DEPTH - MIN_CU_LOG2 );
Pel *pDst = piPred;
// get starting pixel in block
#if JVET_C0024_QTBT
const Int sw = (iHeight + iWidth + 1);
#else
const Int sw = (2 * iWidth + 1);
#endif
#if COM16_C1046_PDPC_INTRA
TComDataCU *const pcCU = rTu.getCU();
const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU();
#endif
if ( bUseLosslessDPCM )//使用无损DPCM,默认关闭;
{
const Pel *ptrSrc = getPredictorPtr( compID, false );
// Sample Adaptive intra-Prediction (SAP)
if (uiDirMode==HOR_IDX)//水平模式;
{
// left column filled with reference samples
// remaining columns filled with piOrg data (if available).
for(Int y=0; y<iHeight; y++)
{
piPred[y*uiStride+0] = ptrSrc[(y+1)*sw];//当前块第一列的预测值用参考采样进行填充;
}
if (piOrg!=0)
{
piPred+=1; // miss off first column
for(Int y=0; y<iHeight; y++, piPred+=uiStride, piOrg+=uiOrgStride)
{
memcpy(piPred, piOrg, (iWidth-1)*sizeof(Pel));//剩余列用piOrg指向的数据进行填充;
}
}
}
else // VER_IDX
{
// top row filled with reference samples
// remaining rows filled with piOrd data (if available)
for(Int x=0; x<iWidth; x++)
{
piPred[x] = ptrSrc[x+1];
}
if (piOrg!=0)
{
piPred+=uiStride; // miss off the first row
for(Int y=1; y<iHeight; y++, piPred+=uiStride, piOrg+=uiOrgStride)
{
memcpy(piPred, piOrg, iWidth*sizeof(Pel));
}
}
}
}
else
{
#if COM16_C1046_PDPC_INTRA
#if !COM16_C1046_PDPC_RSAF_HARMONIZATION
Pel *ptrSrc = getPredictorPtr(compID, false);//指向的是当前块的参考数据(左上角),即p[-1][-1];
#endif
#if JVET_G0104_PLANAR_PDPC
if( uiDirMode == PLANAR_IDX )//如果是planar模式;
#if COM16_C1046_PDPC_RSAF_HARMONIZATION
Pel *ptrSrc = getPredictorPtr(compID, false);
#endif
#if JVET_C0024_QTBT
const Int iSrcStride = iWidth + iHeight + 1;//129;
const Int iDoubleSize = iWidth + iHeight;//128;
#else
const Int iBlkSize = iWidth;
const Int iSrcStride = (iWidth<<1) + 1;
const Int iDoubleWidth = iWidth<<1;
#endif
#if JVET_G0104_PLANAR_PDPC
const Int blkSizeGroup[2] = { std::min( 4, 1 + (Int)g_aucConvertToBit[iWidth] ), std::min( 4, 1 + (Int)g_aucConvertToBit[iHeight] ) };
const Short *pdpcParam[2] = { g_pdpcParam[blkSizeGroup[0]], g_pdpcParam[blkSizeGroup[1]] };
const Short *pPdpcPar = pdpcParam[iWidth < iHeight];
#if JVET_C0024_QTBT
Int * piRefVector = piTempRef + iDoubleSize;
Int * piLowpRefer = piFiltRef + iDoubleSize;
#else
Int * piRefVector = piTempRef + iDoubleWidth;
Int * piLowpRefer = piFiltRef + iDoubleWidth;
#endif
//unfiltered reference
#if JVET_C0024_QTBT
for (Int j = 0; j <= iDoubleSize; j++)
piRefVector[j] = ptrSrc[j];
for (Int i = 1; i <= iDoubleSize; i++)
piRefVector[-i] = ptrSrc[i*iSrcStride];
#else
for (Int j = 0; j <= iDoubleWidth; j++)
piRefVector[j] = ptrSrc[j];
for (Int i = 1; i <= iDoubleWidth; i++)
piRefVector[-i] = ptrSrc[i*iSrcStride];
#endif
if (pPdpcPar[5] != 0)
{ // filter reference samples
#if JVET_C0024_QTBT
xReferenceFilter(iDoubleSize, pPdpcPar[4], pPdpcPar[5], piRefVector, piLowpRefer);
for (Int j = 0; j <= iDoubleSize; j++)
ptrSrc[j] = piLowpRefer[j];
for (Int i = 1; i <= iDoubleSize; i++)
ptrSrc[i*iSrcStride] = piLowpRefer[-i];
#else
xReferenceFilter(iBlkSize, pPdpcPar[4], pPdpcPar[5], piRefVector, piLowpRefer);
for (Int j = 0; j <= iDoubleWidth; j++)
ptrSrc[j] = piLowpRefer[j];
for (Int i = 1; i <= iDoubleWidth; i++)
ptrSrc[i*iSrcStride] = piLowpRefer[-i];
#endif
}
if (uiDirMode == PLANAR_IDX)//若是planar模式,利用对应的计算预测值的公式计算预测值;
xPredIntraPlanar(ptrSrc + sw + 1, sw, pDst, uiStride, iWidth, iHeight);//ptrSrc + sw + 1,指向当前CU首地址;
else//不是planar模式;
{
const Bool enableEdgeFilters = !(pcCU->isRDPCMEnabled(uiAbsPartIdx) && pcCU->getCUTransquantBypass(uiAbsPartIdx));
#if O0043_BEST_EFFORT_DECODING
const Int channelsBitDepthForPrediction = rTu.getCU()->getSlice()->getSPS()->getStreamBitDepth(channelType);
#else
const Int channelsBitDepthForPrediction = rTu.getCU()->getSlice()->getSPS()->getBitDepth(channelType);
#endif
#if VCEG_AZ07_INTRA_4TAP_FILTER
const Bool enable4TapFilter = pcCU->getSlice()->getSPS()->getUseIntra4TapFilter();
#endif
//对DC模式和所有角度模式进行预测;
xPredIntraAng(channelsBitDepthForPrediction, ptrSrc + sw + 1, sw, pDst, uiStride,
iWidth, iHeight,
#if JVET_D0033_ADAPTIVE_CLIPPING
compID,
#else
channelType,
#endif
uiDirMode, enableEdgeFilters
#if VCEG_AZ07_INTRA_4TAP_FILTER
, enable4TapFilter
#endif
);
}
//使用未参考采样用于加权预测,就是JEM里的PDPC;
//use unfiltered reference sample for weighted prediction
if (pPdpcPar[5] != 0)
{
#if JVET_C0024_QTBT
for (int j = 0; j <= iDoubleSize; j++)
ptrSrc[j] = piRefVector[j];
for (int i = 1; i <= iDoubleSize; i++)
ptrSrc[i*iSrcStride] = piRefVector[-i];
#else
for (int j = 0; j <= iDoubleWidth; j++)
ptrSrc[j] = piRefVector[j];
for (int i = 1; i <= iDoubleWidth; i++)
ptrSrc[i*iSrcStride] = piRefVector[-i];
#endif
}
#if JVET_C0024_QTBT
Int scale = g_aucConvertToBit[iWidth] + MIN_CU_LOG2 + g_aucConvertToBit[iHeight] + MIN_CU_LOG2 < 10 ? 0: 1;
#else
Int scale = (iBlkSize < 32 ? 0 : 1);
#endif
#if !JVET_D0033_ADAPTIVE_CLIPPING
Int bitDepth = rTu.getCU()->getSlice()->getSPS()->getBitDepth(channelType);
#endif
Int ParShift = 6; //normalization factor
Int ParScale = 1 << ParShift;//64;
Int ParOffset = 1 << (ParShift - 1);//32;
#if JVET_C0024_QTBT
for (Int row = 0; row < iHeight; row++)
#else
for (Int row = 0; row < iBlkSize; row++)
#endif
{
Int pos = row * uiStride;
Int shiftRow = row >> scale;
#if JVET_C0024_QTBT
Int Coeff_Top = pdpcParam[1][2] >> shiftRow;
Int Coeff_offset = pdpcParam[1][3] >> shiftRow;
#else
Int Coeff_Top = pPdpcPar[2] >> shiftRow;
Int Coeff_offset = pPdpcPar[3] >> shiftRow;
#endif
#if JVET_C0024_QTBT
for (Int col = 0; col < iWidth; col++, pos++)
#else
for (Int col = 0; col < iBlkSize; col++, pos++)
#endif
{
Int shiftCol = col >> scale;
#if JVET_C0024_QTBT
Int Coeff_Left = pdpcParam[0][0] >> shiftCol;
Int Coeff_TopLeft = (pdpcParam[0][1] >> shiftCol) + Coeff_offset;
#else
Int Coeff_Left = pPdpcPar[0] >> shiftCol;
Int Coeff_TopLeft = (pPdpcPar[1] >> shiftCol) + Coeff_offset;
#endif
Int Coeff_Cur = ParScale - Coeff_Left - Coeff_Top + Coeff_TopLeft;
Int sampleVal = (Coeff_Left* piRefVector[-row - 1] + Coeff_Top * piRefVector[col + 1] - Coeff_TopLeft * piRefVector[0] + Coeff_Cur * pDst[pos] + ParOffset) >> ParShift;
#if JVET_D0033_ADAPTIVE_CLIPPING
pDst[pos] = ClipA(sampleVal,compID);
#else
pDst[pos] = Clip3(0, ((1 << bitDepth) - 1), sampleVal);
#endif
}
}
return; //terminate the prediction process
}
#else
const Pel *ptrSrc = getPredictorPtr( compID, bUseFilteredPredSamples );
#endif
#if JVET_G0104_PLANAR_PDPC
if( isLuma( compID ) )
{
if( pcCU->getROTIdx( CHANNEL_TYPE_LUMA, uiAbsPartIdx ) )
{
ptrSrc = getPredictorPtr( compID, bUseFilteredPredSamples );
}
}
#elif COM16_C1046_PDPC_RSAF_HARMONIZATION
const Pel *ptrSrc = getPredictorPtr(compID, bUseFilteredPredSamples);
#endif
#if VCEG_AZ05_INTRA_MPI
TComDataCU *const pcCU = rTu.getCU();
const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU();
#endif
if ( uiDirMode == PLANAR_IDX )
{
xPredIntraPlanar( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight );
}
else
{
// Create the prediction
#if !VCEG_AZ05_INTRA_MPI && !COM16_C1046_PDPC_INTRA
TComDataCU *const pcCU = rTu.getCU();
const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU();
#endif//是否进行边缘滤波的标记;
const Bool enableEdgeFilters = !(pcCU->isRDPCMEnabled(uiAbsPartIdx) && pcCU->getCUTransquantBypass(uiAbsPartIdx));
#if O0043_BEST_EFFORT_DECODING
const Int channelsBitDepthForPrediction = rTu.getCU()->getSlice()->getSPS()->getStreamBitDepth(channelType);
#else
const Int channelsBitDepthForPrediction = rTu.getCU()->getSlice()->getSPS()->getBitDepth(channelType);
#endif
#if VCEG_AZ07_INTRA_4TAP_FILTER//JEM中新加的4抽头滤波;
const Bool enable4TapFilter = pcCU->getSlice()->getSPS()->getUseIntra4TapFilter();
#endif
#if VCEG_AZ07_INTRA_BOUNDARY_FILTER
#if COM16_C983_RSAF_PREVENT_OVERSMOOTHING
#if VCEG_AZ05_INTRA_MPI
const Bool enableBoundaryFilter = pcCU->getSlice()->getSPS()->getUseIntraBoundaryFilter() && (pcCU->getMPIIdx(uiAbsPartIdx) <= 1 || pcCU->getWidth(uiAbsPartIdx)>=16 || !pcCU->getSlice()->getSPS()->getUseRSAF() );
#else
#if COM16_C1046_PDPC_INTRA
const Bool enableBoundaryFilter = pcCU->getSlice()->getSPS()->getUseIntraBoundaryFilter() && (pcCU->getPDPCIdx(uiAbsPartIdx) <= 1 || pcCU->getWidth(uiAbsPartIdx) >= 16 || !pcCU->getSlice()->getSPS()->getUseRSAF());
#else
const Bool enableBoundaryFilter = pcCU->getSlice()->getSPS()->getUseIntraBoundaryFilter() && (pcCU->getWidth(uiAbsPartIdx) >= 16 || !pcCU->getSlice()->getSPS()->getUseRSAF());
#endif
#endif
#else//是否进行边界滤波的标记,这里的边界指的是当前块的边界,不是参考像素的边界;
const Bool enableBoundaryFilter = pcCU->getSlice()->getSPS()->getUseIntraBoundaryFilter();
#endif
#endif
xPredIntraAng( channelsBitDepthForPrediction, ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight,
#if JVET_D0033_ADAPTIVE_CLIPPING
compID,
#else
channelType,
#endif
uiDirMode, enableEdgeFilters
#if VCEG_AZ07_INTRA_4TAP_FILTER
, enable4TapFilter
#endif
#if COM16_C983_RSAF_PREVENT_OVERSMOOTHING
, pcCU->getSlice()->getSPS()->getUseRSAF()
#endif
);
#if VCEG_AZ05_INTRA_MPI
#if JVET_C0024_QTBT
if (!(pcCU->getMPIIdx(uiAbsPartIdx) && isLuma(compID)) && (uiDirMode == DC_IDX))
#else
if (!pcCU->getMPIIdx(uiAbsPartIdx) && (uiDirMode == DC_IDX))
#endif
#else
if ( uiDirMode == DC_IDX )//如果是DC模式.
#endif
{
xDCPredFiltering( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight, channelType );
}
#if VCEG_AZ07_INTRA_BOUNDARY_FILTER
#if JVET_C0024_QTBT
else if( enableBoundaryFilter && isLuma(compID) && iWidth>2 && iHeight>2)
#else
else if( enableBoundaryFilter && isLuma(compID) )
#endif
{
#if VCEG_AZ07_INTRA_65ANG_MODES
if( uiDirMode == VDIA_IDX )
#else
if( uiDirMode == 34 )
#endif
{//对模式34进行预测滤波;
xIntraPredFilteringMode34( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight);
}
else if( uiDirMode == 2 )
{//对模式02进行预测滤波;
xIntraPredFilteringMode02( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight);
}
#if VCEG_AZ07_INTRA_65ANG_MODES
else if( ( uiDirMode<=10 && uiDirMode>2 ) || ( uiDirMode>=(VDIA_IDX-8) && uiDirMode<VDIA_IDX ) )
#else
else if( ( uiDirMode<=6 && uiDirMode>2 ) || ( uiDirMode>=30 && uiDirMode<34 ) )
#endif
{//对2<mode<10和58<mode<66的模式进行滤波;
xIntraPredFilteringModeDGL( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight, uiDirMode );
}
}
#endif
}
}
}