x264中的熵编码 cavlc

cavlc是以字段为单位来写数据的。代码位于cavlc.c中

主要函数

x264_macroblock_write_cavlc

{

cavlc_mb_header_i//包含预测模式

cavlc_mb_header_p//包含MVD,

cavlc_mb_header_b//包含MVD

cavlc_qp_delta//qp值

x264_cavlc_block_residual //残差

}

cavlc_mb_header_i 写了哪些信息?I 块没有MVD,只有intra预测模式

static void cavlc_mb_header_i( x264_t *h, int i_mb_type, int i_mb_i_offset, int chroma )

{

   bs_t *s = &h->out.bs;

  if( i_mb_type == I_16x16 )

  {//cbp 标示子块中哪些子块有残差信息

      bs_write_ue( s, i_mb_i_offset + 1 + x264_mb_pred_mode16x16_fix[h->mb.i_intra16x16_pred_mode]  + h->mb.i_cbp_chroma * 4 + ( h->mb.i_cbp_luma == 0 ? 0 : 12 ) );//pred 模式,以及cbp

 }

else //if( i_mb_type == I_4x4 || i_mb_type == I_8x8 )

{

  int di = i_mb_type == I_8x8 ? 4 : 1;

  bs_write_ue( s, i_mb_i_offset + 0 );

  if( h->pps->b_transform_8x8_mode )

  bs_write1( s, h->mb.b_transform_8x8 );

 

/* Prediction: Luma */

for( int i = 0; i < 16; i += di )

{

int i_pred = x264_mb_predict_intra4x4_mode( h, i );// 存储预测模式

int i_mode = x264_mb_pred_mode4x4_fix( h->mb.cache.intra4x4_pred_mode[x264_scan8[i]] ); 

 

if( i_pred == i_mode )

bs_write1( s, 1 ); /* b_prev_intra4x4_pred_mode */

else

bs_write( s, 4, i_mode - (i_mode > i_pred) );

}

 

}

if( chroma )

    bs_write_ue( s, x264_mb_chroma_pred_mode_fix[h->mb.i_chroma_pred_mode] );

}

cavlc_mb_header_p//有哪些信息

cavlc_mvd( h, 0, 0, 4 );// 各种不同的模式都需要存储mvd

bs_write_ue 无符号指数哥伦布编码写参考帧

else //if( IS_INTRA( i_mb_type ) )

cavlc_mb_header_i( h, i_mb_type, 5, chroma ); //写颜色相关的信息

cavlc_mb_header_b// B帧

先写子块形状

bs_write_ue( s, subpartition_b_to_golomb[ h->mb.i_sub_partition[i] ] );

bs_write_te( s, h->mb.pic.i_fref[0] - 1, h->mb.cache.ref[0][x264_scan8[i*4]] ); //参考帧,向前参考

bs_write_te( s, h->mb.pic.i_fref[1] - 1, h->mb.cache.ref[1][x264_scan8[i*4]] );//向后参考

写qp值

static void cavlc_qp_delta( x264_t *h )

{

bs_t *s = &h->out.bs;

int i_dqp = h->mb.i_qp - h->mb.i_last_qp;//qp差值

 

/* Avoid writing a delta quant if we have an empty i16x16 block, e.g. in a completely

* flat background area. Don't do this if it would raise the quantizer, since that could

* cause unexpected deblocking artifacts. */

if( h->mb.i_type == I_16x16 && !(h->mb.i_cbp_luma | h->mb.i_cbp_chroma)

&& !h->mb.cache.non_zero_count[x264_scan8[LUMA_DC]]

&& !h->mb.cache.non_zero_count[x264_scan8[CHROMA_DC+0]]

&& !h->mb.cache.non_zero_count[x264_scan8[CHROMA_DC+1]]

&& h->mb.i_qp > h->mb.i_last_qp )

{

#if !RDO_SKIP_BS

h->mb.i_qp = h->mb.i_last_qp;

#endif

i_dqp = 0;//如果是skip块,i_dqp = 0;

}

 

if( i_dqp )

{

if( i_dqp < -(QP_MAX_SPEC+1)/2 )

i_dqp += QP_MAX_SPEC+1;

else if( i_dqp > QP_MAX_SPEC/2 )

i_dqp -= QP_MAX_SPEC+1;

}

bs_write_se( s, i_dqp ); //写qp值

}

static ALWAYS_INLINE void cavlc_macroblock_luma_residual( x264_t *h, int plane_count )

{

if( h->mb.b_transform_8x8 )

{

/* shuffle 8x8 dct coeffs into 4x4 lists */

for( int p = 0; p < plane_count; p++ )

for( int i8 = 0; i8 < 4; i8++ )

if( h->mb.cache.non_zero_count[x264_scan8[p*16+i8*4]] )

h->zigzagf.interleave_8x8_cavlc( h->dct.luma4x4[p*16+i8*4], h->dct.luma8x8[p*4+i8],

&h->mb.cache.non_zero_count[x264_scan8[p*16+i8*4]] );

}

 

for( int p = 0; p < plane_count; p++ )

FOREACH_BIT( i8, 0, h->mb.i_cbp_luma )// cpb 标示的有残差的块

for( int i4 = 0; i4 < 4; i4++ )

x264_cavlc_block_residual( h, DCT_LUMA_4x4, i4+i8*4+p*16, h->dct.luma4x4[i4+i8*4+p*16] );//按4x4的块写

}

 

 

 

 

 

 

上一篇:硬盘


下一篇:如何解决MB SD C4无法登录EWA Net的问题?