美文网首页
ffmpeg 264 环路滤波

ffmpeg 264 环路滤波

作者: ai___believe | 来源:发表于2017-04-25 16:18 被阅读88次

    参考:http://blog.csdn.net/leixiaohua1020/article/details/45224579

    (1)普通滤波器。针对边界的Bs(边界强度)为1、2、3的滤波器。
    (2)强滤波器。针对边界的Bs(边界强度)为4的滤波器。

        if( bS[0] < 4 || !intra ) {
            int8_t tc[4];
            tc[0] = tc0_table[index_a][bS[0]];
            tc[1] = tc0_table[index_a][bS[1]];
            tc[2] = tc0_table[index_a][bS[2]];
            tc[3] = tc0_table[index_a][bS[3]];
            h->h264dsp.h264_h_loop_filter_luma(pix, stride, alpha, beta, tc);
        } else {
            h->h264dsp.h264_h_loop_filter_luma_intra(pix, stride, alpha, beta);
        }
    

    强滤波器最终滤波实现如下:

    static av_always_inline av_flatten void FUNCC(h264_loop_filter_luma_intra)(uint8_t *p_pix, int xstride, int ystride, int inner_iters, int alpha, int beta)
    {
        pixel *pix = (pixel*)p_pix;
        int d;
        xstride >>= sizeof(pixel)-1;
        ystride >>= sizeof(pixel)-1;
        alpha <<= BIT_DEPTH - 8;
        beta  <<= BIT_DEPTH - 8;
        for( d = 0; d < 4 * inner_iters; 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( FFABS( p0 - q0 ) < alpha &&
                FFABS( p1 - p0 ) < beta &&
                FFABS( q1 - q0 ) < beta ) {
    
                if(FFABS( p0 - q0 ) < (( alpha >> 2 ) + 2 )){
                    if( FFABS( p2 - p0 ) < beta)
                    {
                        const int p3 = pix[-4*xstride];
                        /* p0', p1', p2' */
                        pix[-1*xstride] = ( p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4 ) >> 3;
                        pix[-2*xstride] = ( p2 + p1 + p0 + q0 + 2 ) >> 2;
                        pix[-3*xstride] = ( 2*p3 + 3*p2 + p1 + p0 + q0 + 4 ) >> 3;
                    } else {
                        /* p0' */
                        pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
                    }
                    if( FFABS( q2 - q0 ) < beta)
                    {
                        const int q3 = pix[3*xstride];
                        /* q0', q1', q2' */
                        pix[0*xstride] = ( p1 + 2*p0 + 2*q0 + 2*q1 + q2 + 4 ) >> 3;
                        pix[1*xstride] = ( p0 + q0 + q1 + q2 + 2 ) >> 2;
                        pix[2*xstride] = ( 2*q3 + 3*q2 + q1 + q0 + p0 + 4 ) >> 3;
                    } else {
                        /* q0' */
                        pix[0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
                    }
                }else{
                    /* p0', q0' */
                    pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
                    pix[ 0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
                }
            }
            pix += ystride;
        }
    }
    
    滤波.png

    依次做q0垂直线上4个像素点,根据p2,p1,p0,q0,q1,q2这六个点决定对哪些点做滤波。

    弱滤波器最终实现如下:

    static av_always_inline av_flatten void FUNCC(h264_loop_filter_luma)(uint8_t *p_pix, int xstride, int ystride, int inner_iters, int alpha, int beta, int8_t *tc0)
    {
        pixel *pix = (pixel*)p_pix;
        int i, d;
        xstride >>= sizeof(pixel)-1;
        ystride >>= sizeof(pixel)-1;
        alpha <<= BIT_DEPTH - 8;
        beta  <<= BIT_DEPTH - 8;
        for( i = 0; i < 4; i++ ) {
            const int tc_orig = tc0[i] << (BIT_DEPTH - 8);
            if( tc_orig < 0 ) {
                pix += inner_iters*ystride;
                continue;
            }
            for( d = 0; d < inner_iters; d++ ) {
                const int p0 = pix[-1*xstride];
                const int p1 = pix[-2*xstride];
                const int p2 = pix[-3*xstride];
                const int q0 = pix[0];
                const int q1 = pix[1*xstride];
                const int q2 = pix[2*xstride];
    
                if( FFABS( p0 - q0 ) < alpha &&
                    FFABS( p1 - p0 ) < beta &&
                    FFABS( q1 - q0 ) < beta ) {
    
                    int tc = tc_orig;
                    int i_delta;
    
                    if( FFABS( p2 - p0 ) < beta ) {
                        if(tc_orig)
                        pix[-2*xstride] = p1 + av_clip( (( p2 + ( ( p0 + q0 + 1 ) >> 1 ) ) >> 1) - p1, -tc_orig, tc_orig );
                        tc++;
                    }
                    if( FFABS( q2 - q0 ) < beta ) {
                        if(tc_orig)
                        pix[   xstride] = q1 + av_clip( (( q2 + ( ( p0 + q0 + 1 ) >> 1 ) ) >> 1) - q1, -tc_orig, tc_orig );
                        tc++;
                    }
    
                    i_delta = av_clip( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
                    pix[-xstride] = av_clip_pixel( p0 + i_delta );    /* p0' */
                    pix[0]        = av_clip_pixel( q0 - i_delta );    /* q0' */
                }
                pix += ystride;
            }
        }
    }
    

    其中上文中提到的边界强度Bs的判定方式如下。

    BS.png

    总体说来,与帧内预测相关的图像块(帧内预测块)的边界强度比较大,取值为3或者4;与运动补偿相关的图像块(帧间预测块)的边界强度比较小,取值为1。

    相关文章

      网友评论

          本文标题:ffmpeg 264 环路滤波

          本文链接:https://www.haomeiwen.com/subject/sxivzttx.html