分享

x264中的CABAC编码

 X264 2011-09-16

x264中的CABAC编码  

很久没看264了,前几天突发奇想,想把264的熵编码方式改成全精细渐进模式。虽然我知道有分级编码中也有了精细分级方式,但是我还是想试试。

当年硕士的时候,我就剩下CABAC、码流格式没看懂,当时碰到那一堆函数就气馁。后来转到图像压缩,又不可避免的涉及到算术编码,后来花了大力气终于清楚了所以然。较常规的CABAC方式,精细分级方式肯定会出现一定的性能下降,所以需要先看看CABAC利用了残差数据的那些统计特性,也正好补一下以前的空缺。

打开x264,搜索x264_macroblock_write_cabac函数,进入残差编码block_residual_write_cabac函数,首先是

if( i_count != 64 )

    {

        x264_cabac_encode_decision( cb, 85 + x264_cabac_mb_cbf_ctxidxinc( h, i_ctxBlockCat, i_idx ), i_coeff != 0 );

        if( i_coeff == 0 )

            return;

    }

这是判断残差块是否全为0,如果全为0则返回。x264_cabac_encode_decision函数的第二个变量是算术编码的模板,第三个变量是所要算术编码的值。

for( i = 0; i < i_sigmap_size; i++ )

    {

        int i_sig_ctxIdxInc;

        int i_last_ctxIdxInc;

        if( i_ctxBlockCat == DCT_LUMA_8x8 )

        {

            i_sig_ctxIdxInc = significant_coeff_flag_offset_8x8[i];

            i_last_ctxIdxInc = last_coeff_flag_offset_8x8[i];

        }

        else

            i_sig_ctxIdxInc = i_last_ctxIdxInc = i;

        x264_cabac_encode_decision( cb, i_ctx_sig + i_sig_ctxIdxInc, l[i] != 0 );

        if( l[i] != 0 )

            x264_cabac_encode_decision( cb, i_ctx_last + i_last_ctxIdxInc, i == i_last );

    }

这是依次判断非零系数的位置,如果是非零系数,还要判断该数是否是最后一个非零系数。

for( i = i_coeff - 1; i >= 0; i-- )

    {   

        const int i_prefix = X264_MIN( i_coeff_abs_m1[i], 14 );

        const int i_ctxIdxInc = (i_abslevelgt1 ? 0 : X264_MIN( 4, i_abslevel1 + 1 )) + i_ctx_level;  // i_abslevel1是已编码的幅值为1的个数

        x264_cabac_encode_decision( cb, i_ctxIdxInc, i_prefix != 0 );  //是否正负1

        if( i_prefix != 0 )

        {

            const int i_ctxIdxInc = 5 + X264_MIN( 4, i_abslevelgt1 ) + i_ctx_level; // i_abslevelgt1是已编码的幅值大于1的个数

            int j;

            for( j = 0; j < i_prefix - 1; j++ )

                x264_cabac_encode_decision( cb, i_ctxIdxInc, 1 );

            if( i_prefix < 14 )

                x264_cabac_encode_decision( cb, i_ctxIdxInc, 0 );

            else 

                x264_cabac_encode_ue_bypass( cb, 0, i_coeff_abs_m1[i] - 14 );//哥伦布编码的算术形式

 

            i_abslevelgt1++;

        }

        else

            i_abslevel1++;   

        x264_cabac_encode_bypass( cb, i_coeff_sign[i] );  //编码非零系数的符号

    }

这里就是编码幅值和正负号了。倒序编码,幅值编码要复杂点,先编码是否是“1”,模板由已编码“1”的个数确定。如果大于1,就依次判断是否是“2”、是否是“3”.一直到“14”,模板由已编码大于1的个数确定。如果大于14,就用哥伦布编码剩下的差值。

总的来看,CABAC在非零系数的位置和符号编码上很简单,最复杂、压缩效率最高的就是幅值编码。一般而言,高频的幅值小于低频系数,幅值从高频到低频编码,根据高频的幅值大小,编码后续低频系数时选择不同的算术编码模板,从而达到高效的目的。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多