Predict::initAdiPattern()

/*
	在進行幀內預測前,對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);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章