先看HM中定义tC、β这两个变量的表格,与draft中的Table 8-10相对应:
const UChar tctable_8x8[54] =
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,5,5,6,6,7,8,9,10,11,13,14,16,18,20,22,24
}; //!< draft Table 8-10
const UChar betatable_8x8[52] =
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64
}; //!< draft Table 8-10
下面一个函数用于判断最终使用强滤波还是弱滤波:
__inline Bool TComLoopFilter::xUseStrongFiltering( Int offset, Int d, Int beta, Int tc, Pel* piSrc) //!< 判断使用强滤波还是弱滤波
{ //!< draft 8.7.2.4.6
Pel m4 = piSrc[0]; //!< q0
Pel m3 = piSrc[-offset]; //!< p0
Pel m7 = piSrc[ offset*3]; //!< q3
Pel m0 = piSrc[-offset*4]; //!< p3
Int d_strong = abs(m0-m3) + abs(m7-m4); //!< abs(p3 - p0) + abs(q3 - q0)
return ( (d_strong < (beta>>3)) && (d<(beta>>2)) && ( abs(m3-m4) < ((tc*5+1)>>1)) ); //!< dSam
}
__inline Int TComLoopFilter::xCalcDP( Pel* piSrc, Int iOffset) //!< 计算dpi,i=0..3
{
return abs( piSrc[-iOffset*3] - 2*piSrc[-iOffset*2] + piSrc[-iOffset] ) ;
}
__inline Int TComLoopFilter::xCalcDQ( Pel* piSrc, Int iOffset) //!< 计算dqi,i=0..3
{
return abs( piSrc[0] - 2*piSrc[iOffset] + piSrc[iOffset*2] );
}
下面函数实现最终的去方块滤波:
__inline Void TComLoopFilter::xPelFilterLuma( Pel* piSrc, Int iOffset, Int d, Int beta, Int tc , Bool sw, Bool bPartPNoFilter, Bool bPartQNoFilter, Int iThrCut, Bool bFilterSecondP, Bool bFilterSecondQ)
{//!< 对应于draft 8.7.2.4.7
Int delta;
//! m0 m1 m2 m3 | m4 m5 m6 m7
Pel m4 = piSrc[0];
Pel m3 = piSrc[-iOffset];
Pel m5 = piSrc[ iOffset];
Pel m2 = piSrc[-iOffset*2];
Pel m6 = piSrc[ iOffset*2];
Pel m1 = piSrc[-iOffset*3];
Pel m7 = piSrc[ iOffset*3];
Pel m0 = piSrc[-iOffset*4];
if (sw) //!< 强滤波
{ //! draft (8-305) to (8-310)
piSrc[-iOffset] = Clip3(m3-2*tc, m3+2*tc, ((m1 + 2*m2 + 2*m3 + 2*m4 + m5 + 4) >> 3));
piSrc[0] = Clip3(m4-2*tc, m4+2*tc, ((m2 + 2*m3 + 2*m4 + 2*m5 + m6 + 4) >> 3));
piSrc[-iOffset*2] = Clip3(m2-2*tc, m2+2*tc, ((m1 + m2 + m3 + m4 + 2)>>2));
piSrc[ iOffset] = Clip3(m5-2*tc, m5+2*tc, ((m3 + m4 + m5 + m6 + 2)>>2));
piSrc[-iOffset*3] = Clip3(m1-2*tc, m1+2*tc, ((2*m0 + 3*m1 + m2 + m3 + m4 + 4 )>>3));
piSrc[ iOffset*2] = Clip3(m6-2*tc, m6+2*tc, ((m3 + m4 + m5 + 3*m6 + 2*m7 +4 )>>3));
}
else //!< 弱滤波
{
/* Weak filter */
delta = (9*(m4-m3) -3*(m5-m2) + 8)>>4 ; //!< draft (8-311)
if ( abs(delta) < iThrCut )
{ //! draft (8-312) to (8-318)
delta = Clip3(-tc, tc, delta);
piSrc[-iOffset] = ClipY((m3+delta));
piSrc[0] = ClipY((m4-delta));
Int tc2 = tc>>1;
if(bFilterSecondP)
{
Int delta1 = Clip3(-tc2, tc2, (( ((m1+m3+1)>>1)- m2+delta)>>1));
piSrc[-iOffset*2] = ClipY((m2+delta1));
}
if(bFilterSecondQ)
{
Int delta2 = Clip3(-tc2, tc2, (( ((m6+m4+1)>>1)- m5-delta)>>1));
piSrc[ iOffset] = ClipY((m5+delta2));
}
}
}
if(bPartPNoFilter) //!< Part P不滤波,保留原值
{
piSrc[-iOffset] = m3;
piSrc[-iOffset*2] = m2;
piSrc[-iOffset*3] = m1;
}
if(bPartQNoFilter) //!< Part Q不滤波,保留原值
{
piSrc[0] = m4;
piSrc[ iOffset] = m5;
piSrc[ iOffset*2] = m6;
}
}