Deblock::edgeFilterLuma()

/*
	進行luma環路濾波
	進行濾波開關選擇 => 進行濾波強度決策 => 執行環路濾波

	過程:
		1.獲取重建幀像素點reconYUV
		2.遍歷每個
			1.進行濾波開關選擇
				1.若block strength = 0,則不進行濾波
				2.若邊界兩邊的block都是無損壓縮,則不進行濾波
				3.根據紋理度與閾值來判斷
					1.計算邊界兩邊block的qp的均值,並進一步根據位深來計算閾值beta
					2.計算邊界兩邊block的紋理dp0/dp3/dq0/dq3,並進一步得到紋理度d
					3.若紋理度d超過了閾值beta,則判斷當前邊界爲紋理,不進行濾波
			2.進行濾波開關強度決定
			3.進行濾波
*/
void Deblock::edgeFilterLuma(const CUData* cuQ, uint32_t absPartIdx, uint32_t depth, int32_t dir, int32_t edge, const uint8_t blockStrength[])
{
	// 取重建幀像素
    PicYuv* reconPic = cuQ->m_encData->m_reconPic;
    pixel* src = reconPic->getLumaAddr(cuQ->m_cuAddr, absPartIdx);
    intptr_t stride = reconPic->m_stride;
    const PPS* pps = cuQ->m_slice->m_pps;

    intptr_t offset, srcStep;

    int32_t maskP = -1;
    int32_t maskQ = -1;
    int32_t betaOffset = pps->deblockingFilterBetaOffsetDiv2 << 1;
    int32_t tcOffset = pps->deblockingFilterTcOffsetDiv2 << 1;
    bool bCheckNoFilter = pps->bTransquantBypassEnabled;

	// 根據濾波方向計算像素的offset和step
    if (dir == EDGE_VER)
    {
        offset = 1;
        srcStep = stride;
        src += (edge << LOG2_UNIT_SIZE);
    }
    else // (dir == EDGE_HOR)
    {
        offset = stride;
        srcStep = 1;
        src += (edge << LOG2_UNIT_SIZE) * stride;
    }

    uint32_t numUnits = cuQ->m_slice->m_sps->numPartInCUSize >> depth;
    for (uint32_t idx = 0; idx < numUnits; idx++)
    {
		/*
			濾波開關選擇
		*/
        uint32_t partQ = calcBsIdx(absPartIdx, dir, edge, idx);
        uint32_t bs = blockStrength[partQ];

		// 若blockStrength = 0,則不進行濾波
        if (!bs)
            continue;

        // Derive neighboring PU index
		// 得到相鄰PU數據cuP及其索引partP,若是ver則取左CU,若是hor則取上CU
        uint32_t partP;
        const CUData* cuP = (dir == EDGE_VER ? cuQ->getPULeft(partP, partQ) : cuQ->getPUAbove(partP, partQ));

		// 若兩個PU都是無損,則不進行濾波
        if (bCheckNoFilter)
        {
            // check if each of PUs is lossless coded
            maskP = cuP->m_tqBypass[partP] - 1;
            maskQ = cuQ->m_tqBypass[partQ] - 1;
            if (!(maskP | maskQ))
                continue;
        }

		// 得到兩個QP的均值
        int32_t qpQ = cuQ->m_qp[partQ];
        int32_t qpP = cuP->m_qp[partP];
        int32_t qp  = (qpP + qpQ + 1) >> 1;

		// 計算閾值beta,與qp和位深相關
        int32_t indexB = x265_clip3(0, QP_MAX_SPEC, qp + betaOffset);
        const int32_t bitdepthShift = X265_DEPTH - 8;
        int32_t beta = s_betaTable[indexB] << bitdepthShift;

		// 計算dp0,dp3,dq0,dq3,得到紋理度d
        intptr_t unitOffset = idx * srcStep << LOG2_UNIT_SIZE;
        int32_t dp0 = calcDP(src + unitOffset              , offset);
        int32_t dq0 = calcDQ(src + unitOffset              , offset);
        int32_t dp3 = calcDP(src + unitOffset + srcStep * 3, offset);
        int32_t dq3 = calcDQ(src + unitOffset + srcStep * 3, offset);
        int32_t d0 = dp0 + dq0;
        int32_t d3 = dp3 + dq3;
        int32_t d =  d0 + d3;

		// 若紋理度d超過閾值,則不進行濾波
        if (d >= beta)
            continue;

		/*
			濾波強弱判斷
		*/
        int32_t indexTC = x265_clip3(0, QP_MAX_SPEC + DEFAULT_INTRA_TC_OFFSET, int32_t(qp + DEFAULT_INTRA_TC_OFFSET * (bs - 1) + tcOffset));
        int32_t tc = s_tcTable[indexTC] << bitdepthShift;

		// 判斷是否使用強濾波
        bool sw = (2 * d0 < (beta >> 2) &&
                   2 * d3 < (beta >> 2) &&
                   useStrongFiltering(offset, beta, tc, src + unitOffset              ) &&
                   useStrongFiltering(offset, beta, tc, src + unitOffset + srcStep * 3));

		/*
			進行濾波
		*/
		// 使用強濾波
        if (sw)
        {
            int32_t tc2 = 2 * tc;
            int32_t tcP = (tc2 & maskP);
            int32_t tcQ = (tc2 & maskQ);
            primitives.pelFilterLumaStrong[dir](src + unitOffset, srcStep, offset, tcP, tcQ);
        }
		// 使用弱濾波
        else
        {
            int32_t sideThreshold = (beta + (beta >> 1)) >> 3;
            int32_t dp = dp0 + dp3;
            int32_t dq = dq0 + dq3;
            int32_t maskP1 = (dp < sideThreshold ? -1 : 0);
            int32_t maskQ1 = (dq < sideThreshold ? -1 : 0);
            pelFilterLuma(src + unitOffset, srcStep, offset, tc, maskP, maskQ, maskP1, maskQ1);
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章