📄 macroblock.c
字号:
}
/* Write:
- type
- prediction
- mv */
if( mb->i_type == I_PCM )
{
/* Untested */
bs_write_ue( s, i_mb_i_offset + 25 );
bs_align_0( s );
/* Luma */
for( i = 0; i < 16*16; i++ )
{
bs_write( s, 8, h->picture->plane[0][mb->i_mb_y * 16 * h->picture->i_stride[0] + mb->i_mb_x * 16+i] );
}
/* Cb */
for( i = 0; i < 8*8; i++ )
{
bs_write( s, 8, h->picture->plane[1][mb->i_mb_y * 8 * h->picture->i_stride[1] + mb->i_mb_x * 8+i] );
}
/* Cr */
for( i = 0; i < 8*8; i++ )
{
bs_write( s, 8, h->picture->plane[2][mb->i_mb_y * 8 * h->picture->i_stride[2] + mb->i_mb_x * 8+i] );
}
for( i = 0; i < 16 + 8; i++ )
{
/* special case */
mb->block[i].i_non_zero_count = 16;
}
return;
}
else if( mb->i_type == I_4x4 )
{
bs_write_ue( s, i_mb_i_offset + 0 );
/* Prediction: Luma */
for( i = 0; i < 16; i++ )
{
int i_predicted_mode = x264_mb_predict_intra4x4_mode( h, mb, i );
int i_mode = mb->block[i].i_intra4x4_pred_mode;
if( i_predicted_mode == i_mode)
{
bs_write1( s, 1 ); /* b_prev_intra4x4_pred_mode */
}
else
{
bs_write1( s, 0 ); /* b_prev_intra4x4_pred_mode */
if( i_mode < i_predicted_mode )
{
bs_write( s, 3, i_mode );
}
else
{
bs_write( s, 3, i_mode - 1 );
}
}
}
/* Prediction: chroma */
bs_write_ue( s, mb->i_chroma_pred_mode );
}
else if( mb->i_type == I_16x16 )
{
bs_write_ue( s, i_mb_i_offset + 1 + mb->i_intra16x16_pred_mode +
mb->i_cbp_chroma * 4 +
( mb->i_cbp_luma == 0 ? 0 : 12 ) );
/* Prediction: chroma */
bs_write_ue( s, mb->i_chroma_pred_mode );
}
else if( mb->i_type == P_L0 )
{
int mvp[2];
if( mb->i_partition == D_16x16 )
{
bs_write_ue( s, 0 );
if( h->sh.i_num_ref_idx_l0_active > 1 )
{
bs_write_te( s, h->sh.i_num_ref_idx_l0_active - 1, mb->partition[0][0].i_ref[0] );
}
x264_mb_predict_mv( mb, 0, 0, 0, mvp );
bs_write_se( s, mb->partition[0][0].mv[0][0] - mvp[0] );
bs_write_se( s, mb->partition[0][0].mv[0][1] - mvp[1] );
}
else if( mb->i_partition == D_16x8 )
{
bs_write_ue( s, 1 );
if( h->sh.i_num_ref_idx_l0_active > 1 )
{
bs_write_te( s, h->sh.i_num_ref_idx_l0_active - 1, mb->partition[0][0].i_ref[0] );
bs_write_te( s, h->sh.i_num_ref_idx_l0_active - 1, mb->partition[0][2].i_ref[0] );
}
x264_mb_predict_mv( mb, 0, 0, 0, mvp );
bs_write_se( s, mb->partition[0][0].mv[0][0] - mvp[0] );
bs_write_se( s, mb->partition[0][0].mv[0][1] - mvp[1] );
x264_mb_predict_mv( mb, 0, 1, 0, mvp );
bs_write_se( s, mb->partition[0][2].mv[0][0] - mvp[0] );
bs_write_se( s, mb->partition[0][2].mv[0][1] - mvp[1] );
}
else if( mb->i_partition == D_8x16 )
{
bs_write_ue( s, 2 );
if( h->sh.i_num_ref_idx_l0_active > 1 )
{
bs_write_te( s, h->sh.i_num_ref_idx_l0_active - 1, mb->partition[0][0].i_ref[0] );
bs_write_te( s, h->sh.i_num_ref_idx_l0_active - 1, mb->partition[2][0].i_ref[0] );
}
x264_mb_predict_mv( mb, 0, 0, 0, mvp );
bs_write_se( s, mb->partition[0][0].mv[0][0] - mvp[0] );
bs_write_se( s, mb->partition[0][0].mv[0][1] - mvp[1] );
x264_mb_predict_mv( mb, 0, 1, 0, mvp );
bs_write_se( s, mb->partition[2][0].mv[0][0] - mvp[0] );
bs_write_se( s, mb->partition[2][0].mv[0][1] - mvp[1] );
}
}
else if( mb->i_type == P_8x8 )
{
int b_sub_ref0;
if( mb->partition[0][0].i_ref[0] == 0 &&
mb->partition[0][2].i_ref[0] == 0 &&
mb->partition[2][0].i_ref[0] == 0 &&
mb->partition[2][2].i_ref[0] == 0 )
{
bs_write_ue( s, 4 );
b_sub_ref0 = 0;
}
else
{
bs_write_ue( s, 3 );
b_sub_ref0 = 1;
}
/* sub mb type */
for( i = 0; i < 4; i++ )
{
switch( mb->i_sub_partition[i] )
{
case D_L0_8x8:
bs_write_ue( s, 0 );
break;
case D_L0_8x4:
bs_write_ue( s, 1 );
break;
case D_L0_4x8:
bs_write_ue( s, 2 );
break;
case D_L0_4x4:
bs_write_ue( s, 3 );
break;
}
}
/* ref0 */
if( h->sh.i_num_ref_idx_l0_active > 1 && b_sub_ref0 )
{
bs_write_te( s, h->sh.i_num_ref_idx_l0_active - 1, mb->partition[0][0].i_ref[0] );
bs_write_te( s, h->sh.i_num_ref_idx_l0_active - 1, mb->partition[2][0].i_ref[0] );
bs_write_te( s, h->sh.i_num_ref_idx_l0_active - 1, mb->partition[0][2].i_ref[0] );
bs_write_te( s, h->sh.i_num_ref_idx_l0_active - 1, mb->partition[2][2].i_ref[0] );
}
for( i = 0; i < 4; i++ )
{
int i_part;
for( i_part = 0; i_part < x264_mb_partition_count_table[mb->i_sub_partition[i]]; i_part++ )
{
int mvx, mvy;
int mvp[2];
x264_mb_partition_get( mb, 0, i, i_part, NULL, &mvx, &mvy );
x264_mb_predict_mv( mb, 0, i, i_part, mvp );
bs_write_se( s, mvx - mvp[0] );
bs_write_se( s, mvy - mvp[1]);
}
}
}
else if( mb->i_type == B_8x8 )
{
fprintf( stderr, "invalid/unhandled mb_type (B_8x8)\n" );
return;
}
else if( mb->i_type != B_DIRECT )
{
/* All B mode */
/* Motion Vector */
int i_part = x264_mb_partition_count_table[mb->i_partition];
int i_ref;
int mvx, mvy;
int mvp[2];
int b_list0[2];
int b_list1[2];
/* init ref list utilisations */
for( i = 0; i < 2; i++ )
{
b_list0[i] = x264_mb_type_list0_table[mb->i_type][i];
b_list1[i] = x264_mb_type_list1_table[mb->i_type][i];
}
if( mb->i_partition == D_16x16 )
{
if( b_list0[0] && b_list1[0] )
{
bs_write_ue( s, 3 );
}
else if( b_list1[0] )
{
bs_write_ue( s, 2 );
}
else
{
bs_write_ue( s, 1 );
}
}
else
{
if( mb->i_type == B_BI_BI )
{
bs_write_ue( s, 20 + (mb->i_partition == D_16x8 ? 0 : 1 ) );
}
else if( b_list0[0] && b_list1[0] )
{
/* B_BI_LX* */
bs_write_ue( s, 16 + (b_list0[1]?0:2) + (mb->i_partition == D_16x8?0:1) );
}
else if( b_list0[1] && b_list1[1] )
{
/* B_LX_BI */
bs_write_ue( s, 12 + (b_list0[1]?0:2) + (mb->i_partition == D_16x8?0:1) );
}
else if( b_list1[1] )
{
/* B_LX_L1 */
bs_write_ue( s, 6 + (b_list0[0]?2:0) + (mb->i_partition == D_16x8?0:1) );
}
else if( b_list0[1] )
{
/* B_LX_L0 */
bs_write_ue( s, 4 + (b_list0[0]?0:6) + (mb->i_partition == D_16x8?0:1) );
}
}
if( h->sh.i_num_ref_idx_l0_active > 1 )
{
for( i = 0; i < i_part; i++ )
{
if( b_list0[i] )
{
x264_mb_partition_get( mb, 0, i, 0, &i_ref, NULL, NULL );
bs_write_te( s, h->sh.i_num_ref_idx_l0_active - 1, i_ref );
}
}
}
if( h->sh.i_num_ref_idx_l1_active > 1 )
{
for( i = 0; i < i_part; i++ )
{
if( b_list1[i] )
{
x264_mb_partition_get( mb, 1, i, 0, &i_ref, NULL, NULL );
bs_write_te( s, h->sh.i_num_ref_idx_l1_active - 1, i_ref );
}
}
}
for( i = 0; i < i_part; i++ )
{
if( b_list0[i] )
{
x264_mb_partition_get( mb, 0, i, 0, NULL, &mvx, &mvy );
x264_mb_predict_mv( mb, 0, i, 0, mvp );
bs_write_se( s, mvx - mvp[0] );
bs_write_se( s, mvy - mvp[1] );
}
}
for( i = 0; i < i_part; i++ )
{
if( b_list1[i] )
{
x264_mb_partition_get( mb, 1, i, 0, NULL, &mvx, &mvy );
x264_mb_predict_mv( mb, 1, i, 0, mvp );
bs_write_se( s, mvx - mvp[0] );
bs_write_se( s, mvy - mvp[1] );
}
}
}
else if( mb->i_type == B_DIRECT )
{
bs_write_ue( s, 0 );
}
else
{
fprintf( stderr, "invalid/unhandled mb_type\n" );
return;
}
/* Coded block patern */
if( mb->i_type == I_4x4 )
{
bs_write_ue( s, intra4x4_cbp_to_golomb[( mb->i_cbp_chroma << 4 )|mb->i_cbp_luma] );
}
else if( mb->i_type != I_16x16 )
{
bs_write_ue( s, inter_cbp_to_golomb[( mb->i_cbp_chroma << 4 )|mb->i_cbp_luma] );
}
/* write residual */
if( mb->i_type == I_16x16 )
{
if( mb->i_mb_x > 0 || mb->i_mb_y > 0 )
bs_write_se( s, mb->i_qp - (mb-1)->i_qp);
else
bs_write_se( s, mb->i_qp - h->pps->i_pic_init_qp - h->sh.i_qp_delta );
/* DC Luma */
block_residual_write_cavlc( h, s, mb, BLOCK_INDEX_LUMA_DC , mb->luma16x16_dc, 16 );
if( mb->i_cbp_luma != 0 )
{
/* AC Luma */
for( i = 0; i < 16; i++ )
{
block_residual_write_cavlc( h, s, mb, i, mb->block[i].residual_ac, 15 );
}
}
}
else if( mb->i_cbp_luma != 0 || mb->i_cbp_chroma != 0 )
{
bs_write_se( s, mb->i_qp - h->pps->i_pic_init_qp - h->sh.i_qp_delta );
for( i = 0; i < 16; i++ )
{
if( mb->i_cbp_luma & ( 1 << ( i / 4 ) ) )
{
block_residual_write_cavlc( h, s, mb, i, mb->block[i].luma4x4, 16 );
}
}
}
if( mb->i_cbp_chroma != 0 )
{
/* Chroma DC residual present */
block_residual_write_cavlc( h, s, mb, BLOCK_INDEX_CHROMA_DC, mb->chroma_dc[0], 4 );
block_residual_write_cavlc( h, s, mb, BLOCK_INDEX_CHROMA_DC, mb->chroma_dc[1], 4 );
if( mb->i_cbp_chroma&0x02 ) /* Chroma AC residual present */
{
for( i = 0; i < 8; i++ )
{
block_residual_write_cavlc( h, s, mb, 16 + i, mb->block[16+i].residual_ac, 15 );
}
}
}
}
/*****************************************************************************
*
* Cabac stuff
*
*****************************************************************************/
static void x264_cabac_mb_type( x264_t *h, x264_macroblock_t *mb )
{
x264_macroblock_t *mba = mb->context->mba;
x264_macroblock_t *mbb = mb->context->mbb;
int i_ctxIdxInc = 0;
if( h->sh.i_type == SLICE_TYPE_I )
{
if( mba != NULL && mba->i_type != I_4x4 )
{
i_ctxIdxInc++;
}
if( mbb != NULL && mbb->i_type != I_4x4 )
{
i_ctxIdxInc++;
}
if( mb->i_type == I_4x4 )
{
x264_cabac_encode_decision( &h->cabac, 3 + i_ctxIdxInc, 0 );
}
else if( mb->i_type == I_PCM )
{
x264_cabac_encode_decision( &h->cabac, 3 + i_ctxIdxInc, 1 );
x264_cabac_encode_terminal( &h->cabac, 1 ); /*ctxIdx == 276 */
}
else /* I_16x16 */
{
x264_cabac_encode_decision( &h->cabac, 3 + i_ctxIdxInc, 1 );
x264_cabac_encode_terminal( &h->cabac, 0 ); /*ctxIdx == 276 */
x264_cabac_encode_decision( &h->cabac, 3 + 3, ( mb->i_cbp_luma == 0 ? 0 : 1 ));
if( mb->i_cbp_chroma == 0 )
{
x264_cabac_encode_decision( &h->cabac, 3 + 4, 0 );
}
else
{
x264_cabac_encode_decision( &h->cabac, 3 + 4, 1 );
x264_cabac_encode_decision( &h->cabac, 3 + 5, ( mb->i_cbp_chroma == 1 ? 0 : 1 ) );
}
x264_cabac_encode_decision( &h->cabac, 3 + 6, ( (mb->i_intra16x16_pred_mode / 2) ? 1 : 0 ));
x264_cabac_encode_decision( &h->cabac, 3 + 7, ( (mb->i_intra16x16_pred_mode % 2) ? 1 : 0 ));
}
}
else if( h->sh.i_type == SLICE_TYPE_P )
{
/* prefix: 14, suffix: 17 */
if( mb->i_type == P_L0 )
{
if( mb->i_partition == D_16x16 )
{
x264_cabac_encode_decision( &h->cabac, 14, 0 );
x264_cabac_encode_decision( &h->cabac, 15, 0 );
x264_cabac_encode_decision( &h->cabac, 16, 0 );
}
else if( mb->i_partition == D_16x8 )
{
x264_cabac_encode_decision( &h->cabac, 14, 0 );
x264_cabac_encode_decision( &h->cabac, 15, 1 );
x264_cabac_encode_decision( &h->cabac, 17, 1 );
}
else if( mb->i_partition == D_8x16 )
{
x264_cabac_encode_decision( &h->cabac, 14, 0 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -