/*
进行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()
最新推荐文章于 2021-04-21 21:01:59 发布