/*
進行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);
}
}
}
Deblock::edgeFilterLuma()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.