/*
在进行帧内预测前,对PU的边界参考像素进行填充及平滑滤波
过程:
1.得到tu的size即size*2
2.取reconYUV
3.对neighbor不可用参考像素进行填充
4.分别取topLeft、topLast、leftLast像素
5.进行平滑滤波
·若tusize为32x32,且允许强平滑滤波,则使用强平滑滤波
1.计算阈值,并分别取topMiddle和leftMiddle像素值
2.若若上边的 (最左边+最右边)-中间*2小于阈值,且左边的 (最上边+最下边)-中间*2 小于 阈值,则使用强双线性差值进行平滑滤波
·否则,进行常规平滑滤波
*/
void Predict::initAdiPattern(const CUData& cu, const CUGeom& cuGeom, uint32_t puAbsPartIdx, const IntraNeighbors& intraNeighbors, int dirMode)
{
//得到tu的像素size
int tuSize = 1 << intraNeighbors.log2TrSize;
//得到tu的像素的两倍
int tuSize2 = tuSize << 1;
//取reconPic
PicYuv* reconPic = cu.m_encData->m_reconPic;
pixel* adiOrigin = reconPic->getLumaAddr(cu.m_cuAddr, cuGeom.absPartIdx + puAbsPartIdx);
intptr_t picStride = reconPic->m_stride;
//进行neighbor不可用参考像素进行填充,输出到intraNeighbourBuf[0]中
fillReferenceSamples(adiOrigin, picStride, intraNeighbors, intraNeighbourBuf[0]);
pixel* refBuf = intraNeighbourBuf[0]; //unfiltered参考像素
pixel* fltBuf = intraNeighbourBuf[1]; //filtered参考像素
//取左上角像素、上边的最右边像素、左边的最下边像素
pixel topLeft = refBuf[0], topLast = refBuf[tuSize2], leftLast = refBuf[tuSize2 + tuSize2];
/* 若所有帧内预测方向都允许 && tuSize为8/16/32之间一种,
或当前tuSize的当前预测方向允许平滑滤波,
则进行平滑滤波 */
if (dirMode == ALL_IDX ? (8 | 16 | 32) & tuSize : g_intraFilterFlags[dirMode] & tuSize)
{
// generate filtered intra prediction samples
//使用强帧内预测平滑 && tusize为32x32pixel,则进行强平滑滤波
if (cu.m_slice->m_sps->bUseStrongIntraSmoothing && tuSize == 32)
{
//计算阈值
const int threshold = 1 << (X265_DEPTH - 5);
//取上边的中间像素,左边的中间像素
pixel topMiddle = refBuf[32], leftMiddle = refBuf[tuSize2 + 32];
/* 若上边的 (最左边+最右边)-中间*2 小于 阈值,
且左边的 (最上边+最下边)-中间*2 小于 阈值,
则使用强双线性差值进行平滑滤波 */
if (abs(topLeft + topLast - (topMiddle << 1)) < threshold &&
abs(topLeft + leftLast - (leftMiddle << 1)) < threshold)
{
// "strong" bilinear interpolation 使用强双线性插值
const int shift = 5 + 1;
int init = (topLeft << shift) + tuSize;
int deltaL, deltaR;
//Δleft = 左边最下边-左边最上边,Δtop = 上边最右边-上边最左边
deltaL = leftLast - topLeft; deltaR = topLast - topLeft;
//最左上角,即左边最上,上边最左,像素不进行平滑滤波,直接输出
fltBuf[0] = topLeft;
//遍历2倍size长度边界参考像素
for (int i = 1; i < tuSize2; i++)
{
//左边平滑滤波,输出到fltBuf中
fltBuf[i + tuSize2] = (pixel)((init + deltaL * i) >> shift); // Left Filtering
//上边平滑滤波,输出到fltBuf中
fltBuf[i] = (pixel)((init + deltaR * i) >> shift); // Above Filtering
}
//上边最下不进行平滑滤波
fltBuf[tuSize2] = topLast;
//左边最下不进行平滑滤波
fltBuf[tuSize2 + tuSize2] = leftLast;
return;
}
}
//对参考像素refBuf进行常规的平滑过滤,输出到fltBuf中
primitives.cu[intraNeighbors.log2TrSize - 2].intra_filter(refBuf, fltBuf);
}
}
Predict::initAdiPattern()
最新推荐文章于 2021-01-08 21:52:39 发布