CABAC编码

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

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

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

if( i_count != 64 )

    {

        /* coded block flag */

        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-- )

    {

        /* write coeff_abs - 1 */

        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 /* suffix */

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

            i_abslevelgt1++;

        }

        else

            i_abslevel1++;

        /* write sign */

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

    }

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值