x264去方块滤波函数解析(一)
先介绍最终真正完成滤波工作的几个函数:
static inline void deblock_luma_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta, int8_t *tc0 ) //!< bS=1~3时的滤波{ int i, d; for( i = 0; i < 4; i++ ) //!< 宏块的一条边界分成4段(即4x4块的边界) { if( tc0[i] < 0 ) //!< 小于0时bS=0,即不滤波,故跳过 { pix += 4*ystride; continue; } for( d = 0; d < 4; d++ ) //!< 遍历边界像素点 { const int p2 = pix[-3*xstride]; const int p1 = pix[-2*xstride]; const int p0 = pix[-1*xstride]; const int q0 = pix[ 0*xstride]; const int q1 = pix[ 1*xstride]; const int q2 = pix[ 2*xstride]; if( abs( p0 - q0 ) < alpha && abs( p1 - p0 ) < beta && abs( q1 - q0 ) < beta ) //!< 只有三个条件同时满足,才会进行滤波 { int tc = tc0[i]; int delta; if( abs( p2 - p0 ) < beta ) { pix[-2*xstride] = p1 + x264_clip3( (( p2 + ((p0 + q0 + 1) >> 1)) >> 1) - p1, -tc0[i], tc0[i] ); //!< (8-478) tc++; } if( abs( q2 - q0 ) < beta ) { pix[ 1*xstride] = q1 + x264_clip3( (( q2 + ((p0 + q0 + 1) >> 1)) >> 1) - q1, -tc0[i], tc0[i] ); //!< (8-480) tc++; } delta = x264_clip3( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc ); //!< (8-475) pix[-1*xstride] = x264_clip_uint8( p0 + delta ); /* p0' */ //!< (8-476) pix[ 0*xstride] = x264_clip_uint8( q0 - delta ); /* q0' */ //!< (8-477) } pix += ystride; } //!< for( d = 0; d < 4; d++ ) //!< 遍历边界像素点 } //!< for( i = 0; i < 4; i++ ) //!< 宏块的一条边界分成4段(即4x4块的边界) }static void deblock_v_luma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 ) //!< 对水平边界进行垂直滤波(亮度分量){ deblock_luma_c( pix, stride, 1, alpha, beta, tc0 );}static void deblock_h_luma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 ) //!< 对垂直边界进行水平滤波(亮度分量){ deblock_luma_c( pix, 1, stride, alpha, beta, tc0 );}static inline void deblock_chroma_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta, int8_t *tc0 ){ int i, d; for( i = 0; i < 4; i++ ) //!< 色度块的一条边界分成4段(即2x2块的边界) { const int tc = tc0[i]; if( tc <= 0 ) //!< bS=0,即不滤波,故跳过 { pix += 2*ystride; continue; } for( d = 0; d < 2; d++ ) //!< 遍历边界像素点 { const int p1 = pix[-2*xstride]; const int p0 = pix[-1*xstride]; const int q0 = pix[ 0*xstride]; const int q1 = pix[ 1*xstride];//!< 对色度来说,只有p0和q0才会被修正 if( abs( p0 - q0 ) < alpha && abs( p1 - p0 ) < beta && abs( q1 - q0 ) < beta ) { int delta = x264_clip3( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc ); //!< (8-475) pix[-1*xstride] = x264_clip_uint8( p0 + delta ); /* p0' */ pix[ 0*xstride] = x264_clip_uint8( q0 - delta ); /* q0' */ } pix += ystride; } //!< for( d = 0; d < 2; d++ ) //!< 遍历边界像素点 } //!< //!< 色度块的一条边界分成4段(即2x2块的边界)}static void deblock_v_chroma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 ) //!< bS=1~3, 对水平边界进行垂直滤波(亮度分量){ deblock_chroma_c( pix, stride, 1, alpha, beta, tc0 );}static void deblock_h_chroma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 ) //!< bS=1~3, 对垂直边界进行水平滤波(亮度分量){ deblock_chroma_c( pix, 1, stride, alpha, beta, tc0 );}//! bS=4时的滤波static inline void deblock_luma_intra_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta ) //!< 亮度分量{ int d; for( d = 0; d < 16; d++ ) { const int p2 = pix[-3*xstride]; const int p1 = pix[-2*xstride]; const int p0 = pix[-1*xstride]; const int q0 = pix[ 0*xstride]; const int q1 = pix[ 1*xstride]; const int q2 = pix[ 2*xstride]; if( abs( p0 - q0 ) < alpha && abs( p1 - p0 ) < beta && abs( q1 - q0 ) < beta ) { if(abs( p0 - q0 ) < ((alpha >> 2) + 2) ) //!< (8-484) { if( abs( p2 - p0 ) < beta ) /* p0', p1', p2' */ { const int p3 = pix[-4*xstride]; pix[-1*xstride] = ( p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4 ) >> 3; //!< (8-485) pix[-2*xstride] = ( p2 + p1 + p0 + q0 + 2 ) >> 2; //!< (8-486) pix[-3*xstride] = ( 2*p3 + 3*p2 + p1 + p0 + q0 + 4 ) >> 3; //!< (8-487) } else /* p0' */ pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2; //!< (8-488) if( abs( q2 - q0 ) < beta ) /* q0', q1', q2' */ { const int q3 = pix[3*xstride]; pix[0*xstride] = ( p1 + 2*p0 + 2*q0 + 2*q1 + q2 + 4 ) >> 3; //!< (8-492) pix[1*xstride] = ( p0 + q0 + q1 + q2 + 2 ) >> 2; //!< (8-493) pix[2*xstride] = ( 2*q3 + 3*q2 + q1 + q0 + p0 + 4 ) >> 3; //!< (8-494) } else /* q0' */ pix[0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2; //!< (8-495) } else /* p0', q0' */ { pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2; //!< (8-488) pix[ 0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2; //!< (8-495) } } //!< if( abs( p0 - q0 ) < alpha && abs( p1 - p0 ) < beta && abs( q1 - q0 ) < beta ) pix += ystride; } //!< for( d = 0; d< 16; d++ ) }static void deblock_v_luma_intra_c( uint8_t *pix, int stride, int alpha, int beta ) //!< bS=1~3, 对水平边界进行垂直滤波(色度分量){ deblock_luma_intra_c( pix, stride, 1, alpha, beta );}static void deblock_h_luma_intra_c( uint8_t *pix, int stride, int alpha, int beta ) //!< bS=1~3, 对垂直边界进行水平滤波(色度分量){ deblock_luma_intra_c( pix, 1, stride, alpha, beta );}static inline void deblock_chroma_intra_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta ) //!< bS=4, 对色度分量的滤波{ int d; for( d = 0; d < 8; d++ ) //!< 遍历8x8色度块的某个边界 { const int p1 = pix[-2*xstride]; const int p0 = pix[-1*xstride]; const int q0 = pix[ 0*xstride]; const int q1 = pix[ 1*xstride]; if( abs( p0 - q0 ) < alpha && abs( p1 - p0 ) < beta && abs( q1 - q0 ) < beta ) { pix[-1*xstride] = (2*p1 + p0 + q1 + 2) >> 2; /* p0' */ //!< (8-488) pix[ 0*xstride] = (2*q1 + q0 + p1 + 2) >> 2; /* q0' */ //!< (8-495) } pix += ystride; }}static void deblock_v_chroma_intra_c( uint8_t *pix, int stride, int alpha, int beta ) //!< bS=4,对水平边界进行垂直滤波(色度分量){ deblock_chroma_intra_c( pix, stride, 1, alpha, beta );}static void deblock_h_chroma_intra_c( uint8_t *pix, int stride, int alpha, int beta ) //!< bS=4,对垂直边界进行水平滤波(色度分量){ deblock_chroma_intra_c( pix, 1, stride, alpha, beta );}