📄 macroblock.c
字号:
x264_mb_partition_get( mb, 0, i, 0, &i_ref, NULL, NULL ); for( i_sub = 0; i_sub < x264_mb_partition_count_table[mb->i_sub_partition[i]]; i_sub++ ) { int mv[2]; x264_mb_predict_mv( mb, 0, i, i_sub, mv ); mv[0] += bs_read_se( s ); mv[1] += bs_read_se( s ); x264_mb_partition_mv_set( mb, 0, i, i_sub, mv ); } } } else if( mb->i_type != B_DIRECT ) { /* FIXME will work only for P block */ /* FIXME using x264_mb_partition_set/x264_mb_partition_get here are too unoptimised * I should introduce ref and mv get/set */ /* Motion Vector */ int i_part = x264_mb_partition_count_table[mb->i_partition]; for( i = 0; i < i_part; i++ ) { int i_ref; i_ref = bs_read_te( s, h->sh.i_num_ref_idx_l0_active - 1 ); x264_mb_partition_ref_set( mb, 0, i, i_ref ); } for( i = 0; i < i_part; i++ ) { int mv[2]; x264_mb_predict_mv( mb, 0, i, 0, mv ); mv[0] += bs_read_se( s ); mv[1] += bs_read_se( s ); x264_mb_partition_mv_set( mb, 0, i, 0, mv ); } } if( mb->i_type != I_16x16 ) { int i_cbp; i_cbp = bs_read_ue( s ); if( i_cbp >= 48 ) { fprintf( stderr, "invalid cbp\n" ); return -1; } if( mb->i_type == I_4x4 ) { i_cbp = golomb_to_intra4x4_cbp[i_cbp]; } else { i_cbp = golomb_to_inter_cbp[i_cbp]; } mb->i_cbp_luma = i_cbp&0x0f; mb->i_cbp_chroma = i_cbp >> 4; } if( mb->i_cbp_luma > 0 || mb->i_cbp_chroma > 0 || mb->i_type == I_16x16 ) { mb->i_qp = bs_read_se( s ) + h->pps->i_pic_init_qp + h->sh.i_qp_delta; /* write residual */ if( mb->i_type == I_16x16 ) { /* DC Luma */ if( block_residual_read_cavlc( h, s, mb, BLOCK_INDEX_LUMA_DC , mb->luma16x16_dc, 16 ) < 0 ) { return -1; } if( mb->i_cbp_luma != 0 ) { /* AC Luma */ for( i = 0; i < 16; i++ ) { if( block_residual_read_cavlc( h, s, mb, i, mb->block[i].residual_ac, 15 ) < 0 ) { return -1; } } } else { for( i = 0; i < 16; i++ ) { mb->block[i].i_non_zero_count = 0; array_zero_set( mb->block[i].residual_ac, 15 ); } } } else { for( i = 0; i < 16; i++ ) { if( mb->i_cbp_luma & ( 1 << ( i / 4 ) ) ) { if( block_residual_read_cavlc( h, s, mb, i, mb->block[i].luma4x4, 16 ) < 0 ) { return -1; } } else { mb->block[i].i_non_zero_count = 0; array_zero_set( mb->block[i].luma4x4, 16 ); } } } if( mb->i_cbp_chroma &0x03 ) /* Chroma DC residual present */ { if( block_residual_read_cavlc( h, s, mb, BLOCK_INDEX_CHROMA_DC, mb->chroma_dc[0], 4 ) < 0 || block_residual_read_cavlc( h, s, mb, BLOCK_INDEX_CHROMA_DC, mb->chroma_dc[1], 4 ) < 0 ) { return -1; } } else { array_zero_set( mb->chroma_dc[0], 4 ); array_zero_set( mb->chroma_dc[1], 4 ); } if( mb->i_cbp_chroma&0x02 ) /* Chroma AC residual present */ { for( i = 0; i < 8; i++ ) { if( block_residual_read_cavlc( h, s, mb, 16 + i, mb->block[16+i].residual_ac, 15 ) < 0 ) { return -1; } } } else { for( i = 0; i < 8; i++ ) { mb->block[16+i].i_non_zero_count = 0; array_zero_set( mb->block[16+i].residual_ac, 15 ); } } } else { mb->i_qp = h->pps->i_pic_init_qp + h->sh.i_qp_delta; for( i = 0; i < 16; i++ ) { mb->block[i].i_non_zero_count = 0; array_zero_set( mb->block[i].luma4x4, 16 ); } array_zero_set( mb->chroma_dc[0], 4 ); array_zero_set( mb->chroma_dc[1], 4 ); for( i = 0; i < 8; i++ ) { array_zero_set( mb->block[16+i].residual_ac, 15 ); mb->block[16+i].i_non_zero_count = 0; } } //fprintf( stderr, "mb read type=%d\n", mb->i_type ); return 0;}static int x264_mb_pred_mode16x16_valid( x264_macroblock_t *mb, int i_mode ){ if( ( mb->i_neighbour & (MB_LEFT|MB_TOP) ) == (MB_LEFT|MB_TOP) ) { return i_mode; } else if( ( mb->i_neighbour & MB_LEFT ) ) { if( i_mode == I_PRED_16x16_DC ) { return I_PRED_16x16_DC_LEFT; } else if( i_mode == I_PRED_16x16_H ) { return I_PRED_16x16_H; } fprintf( stderr, "invalid 16x16 prediction\n" ); return I_PRED_16x16_DC_LEFT; } else if( ( mb->i_neighbour & MB_TOP ) ) { if( i_mode == I_PRED_16x16_DC ) { return I_PRED_16x16_DC_TOP; } else if( i_mode == I_PRED_16x16_V ) { return I_PRED_16x16_V; } fprintf( stderr, "invalid 16x16 prediction\n" ); return I_PRED_16x16_DC_TOP; } else { return I_PRED_16x16_DC_128; }}static int x264_mb_pred_mode8x8_valid( x264_macroblock_t *mb, int i_mode ){ if( ( mb->i_neighbour & (MB_LEFT|MB_TOP) ) == (MB_LEFT|MB_TOP) ) { return i_mode; } else if( ( mb->i_neighbour & MB_LEFT ) ) { if( i_mode == I_PRED_CHROMA_DC ) { return I_PRED_CHROMA_DC_LEFT; } else if( i_mode == I_PRED_CHROMA_H ) { return I_PRED_CHROMA_H; } fprintf( stderr, "invalid 8x8 prediction\n" ); return I_PRED_CHROMA_DC_LEFT; } else if( ( mb->i_neighbour & MB_TOP ) ) { if( i_mode == I_PRED_CHROMA_DC ) { return I_PRED_CHROMA_DC_TOP; } else if( i_mode == I_PRED_CHROMA_V ) { return I_PRED_CHROMA_V; } fprintf( stderr, "invalid 8x8 prediction\n" ); return I_PRED_CHROMA_DC_TOP; } else { return I_PRED_CHROMA_DC_128; }}static int x264_mb_pred_mode4x4_valid( x264_macroblock_t *mb, int idx, int i_mode, int *pb_emu ){ int b_a, b_b, b_c; static const int needmb[16] = { MB_LEFT|MB_TOP, MB_TOP, MB_LEFT, MB_PRIVATE, MB_TOP, MB_TOP|MB_TOPRIGHT, 0, MB_PRIVATE, MB_LEFT, 0, MB_LEFT, MB_PRIVATE, 0, MB_PRIVATE, 0, MB_PRIVATE }; int b_emu = 0; *pb_emu = 0; b_a = (needmb[idx]&mb->i_neighbour&MB_LEFT) == (needmb[idx]&MB_LEFT); b_b = (needmb[idx]&mb->i_neighbour&MB_TOP) == (needmb[idx]&MB_TOP); b_c = (needmb[idx]&mb->i_neighbour&(MB_TOPRIGHT|MB_PRIVATE)) == (needmb[idx]&(MB_TOPRIGHT|MB_PRIVATE)); if( b_c == 0 && b_b ) { b_emu = 1; b_c = 1; } /* handle I_PRED_4x4_DC */ if( i_mode == I_PRED_4x4_DC ) { if( b_a && b_b ) { return I_PRED_4x4_DC; } else if( b_a ) { return I_PRED_4x4_DC_LEFT; } else if( b_b ) { return I_PRED_4x4_DC_TOP; } return I_PRED_4x4_DC_128; } /* handle 1 dir needed only */ if( ( b_a && i_mode == I_PRED_4x4_H ) || ( b_b && i_mode == I_PRED_4x4_V ) ) { return i_mode; } /* handle b_c case (b_b always true) */ if( b_c && ( i_mode == I_PRED_4x4_DDL || i_mode == I_PRED_4x4_VL ) ) { *pb_emu = b_emu; return i_mode; } if( b_a && b_b ) { /* I_PRED_4x4_DDR, I_PRED_4x4_VR, I_PRED_4x4_HD, I_PRED_4x4_HU */ return i_mode; } fprintf( stderr, "invalid 4x4 predict mode(%d, mb:%x-%x idx:%d\n", i_mode, mb->i_mb_x, mb->i_mb_y, idx ); return I_PRED_CHROMA_DC_128; /* unefficient */}/**************************************************************************** * UnScan functions ****************************************************************************/static const int scan_zigzag_x[16]={0, 1, 0, 0, 1, 2, 3, 2, 1, 0, 1, 2, 3, 3, 2, 3};static const int scan_zigzag_y[16]={0, 0, 1, 2, 1, 0, 0, 1, 2, 3, 3, 2, 1, 2, 3, 3};static inline void unscan_zigzag_4x4full( int16_t dct[4][4], int level[16] ){ int i; for( i = 0; i < 16; i++ ) { dct[scan_zigzag_y[i]][scan_zigzag_x[i]] = level[i]; }}static inline void unscan_zigzag_4x4( int16_t dct[4][4], int level[15] ){ int i; for( i = 1; i < 16; i++ ) { dct[scan_zigzag_y[i]][scan_zigzag_x[i]] = level[i - 1]; }}static inline void unscan_zigzag_2x2_dc( int16_t dct[2][2], int level[4] ){ dct[0][0] = level[0]; dct[0][1] = level[1]; dct[1][0] = level[2]; dct[1][1] = level[3];}int x264_macroblock_decode( x264_t *h, x264_macroblock_t *mb ){ x264_mb_context_t *ctx = mb->context; int i_qscale; int ch; int i; if( !IS_INTRA(mb->i_type ) ) { /* Motion compensation */ x264_mb_mc( h, mb ); } /* luma */ i_qscale = mb->i_qp; if( mb->i_type == I_16x16 ) { int i_mode = x264_mb_pred_mode16x16_valid( mb, mb->i_intra16x16_pred_mode ); int16_t luma[16][4][4]; int16_t dct4x4[16+1][4][4]; /* do the right prediction */ h->predict_16x16[i_mode]( ctx->p_fdec[0], ctx->i_fdec[0] ); /* get dc coeffs */ unscan_zigzag_4x4full( dct4x4[0], mb->luma16x16_dc ); h->dctf.idct4x4dc( dct4x4[0], dct4x4[0] ); x264_mb_dequant_4x4_dc( dct4x4[0], i_qscale ); /* decode the 16x16 macroblock */ for( i = 0; i < 16; i++ ) { unscan_zigzag_4x4( dct4x4[1+i], mb->block[i].residual_ac ); x264_mb_dequant_4x4( dct4x4[1+i], i_qscale ); /* copy dc coeff */ dct4x4[1+i][0][0] = dct4x4[0][block_idx_y[i]][block_idx_x[i]]; h->dctf.idct4x4( luma[i], dct4x4[i+1] ); } /* put pixels to fdec */ h->pixf.add16x16( ctx->p_fdec[0], ctx->i_fdec[0], luma ); } else if( mb->i_type == I_4x4 ) { for( i = 0; i < 16; i++ ) { int16_t luma[4][4]; int16_t dct4x4[4][4]; uint8_t *p_dst_by; int i_mode; int b_emu; /* Do the right prediction */ p_dst_by = ctx->p_fdec[0] + 4 * block_idx_x[i] + 4 * block_idx_y[i] * ctx->i_fdec[0]; i_mode = x264_mb_pred_mode4x4_valid( mb, i, mb->block[i].i_intra4x4_pred_mode, &b_emu ); if( b_emu ) { fprintf( stderr, "mmmh b_emu\n" ); memset( &p_dst_by[4], p_dst_by[3], 4 ); } h->predict_4x4[i_mode]( p_dst_by, ctx->i_fdec[0] ); if( mb->block[i].i_non_zero_count > 0 ) { /* decode one 4x4 block */ unscan_zigzag_4x4full( dct4x4, mb->block[i].luma4x4 ); x264_mb_dequant_4x4( dct4x4, i_qscale ); h->dctf.idct4x4( luma, dct4x4 ); h->pixf.add4x4( p_dst_by, ctx->i_fdec[0], luma ); } } } else /* Inter mb */ { for( i = 0; i < 16; i++ ) { uint8_t *p_dst_by; int16_t luma[4][4]; int16_t dct4x4[4][4]; if( mb->block[i].i_non_zero_count > 0 ) { unscan_zigzag_4x4full( dct4x4, mb->block[i].luma4x4 ); x264_mb_dequant_4x4( dct4x4, i_qscale ); h->dctf.idct4x4( luma, dct4x4 ); p_dst_by = ctx->p_fdec[0] + 4 * block_idx_x[i] + 4 * block_idx_y[i] * ctx->i_fdec[0]; h->pixf.add4x4( p_dst_by, ctx->i_fdec[0], luma ); } } } /* chroma */ i_qscale = i_chroma_qp_table[x264_clip3( i_qscale + h->pps->i_chroma_qp_index_offset, 0, 51 )]; if( IS_INTRA( mb->i_type ) ) { int i_mode = x264_mb_pred_mode8x8_valid( mb, mb->i_chroma_pred_mode ); /* do the right prediction */ h->predict_8x8[i_mode]( ctx->p_fdec[1], ctx->i_fdec[1] ); h->predict_8x8[i_mode]( ctx->p_fdec[2], ctx->i_fdec[2] ); } if( mb->i_cbp_chroma != 0 ) { for( ch = 0; ch < 2; ch++ ) { int16_t chroma[4][4][4]; int16_t dct2x2[2][2]; int16_t dct4x4[4][4][4]; /* get dc chroma */ unscan_zigzag_2x2_dc( dct2x2, mb->chroma_dc[ch] ); h->dctf.idct2x2dc( dct2x2, dct2x2 ); x264_mb_dequant_2x2_dc( dct2x2, i_qscale ); for( i = 0; i < 4; i++ ) { unscan_zigzag_4x4( dct4x4[i], mb->block[16+i+ch*4].residual_ac ); x264_mb_dequant_4x4( dct4x4[i], i_qscale ); /* copy dc coeff */ dct4x4[i][0][0] = dct2x2[block_idx_y[i]][block_idx_x[i]]; h->dctf.idct4x4( chroma[i], dct4x4[i] ); } h->pixf.add8x8( ctx->p_fdec[1+ch], ctx->i_fdec[1+ch], chroma ); } } return 0;}void x264_macroblock_decode_skip( x264_t *h, x264_macroblock_t *mb ){ int i; int x, y; int mv[2]; /* decode it as a 16x16 with no luma/chroma */ mb->i_type = P_L0; mb->i_partition = D_16x16; mb->i_cbp_luma = 0; mb->i_cbp_chroma = 0; for( i = 0; i < 16 + 8; i++ ) { mb->block[i].i_non_zero_count = 0; } for( i = 0; i < 16; i++ ) { array_zero_set( mb->block[i].luma4x4, 16 ); } array_zero_set( mb->chroma_dc[0], 4 ); array_zero_set( mb->chroma_dc[1], 4 ); for( i = 0; i < 8; i++ ) { array_zero_set( mb->block[16+i].residual_ac, 15 ); } /* set ref0 */ for( x = 0; x < 4; x++ ) { for( y = 0; y < 4; y++ ) { mb->partition[x][y].i_ref[0] = 0; } } /* get mv */ x264_mb_predict_mv_pskip( mb, mv ); x264_mb_partition_mv_set( mb, 0, 0, 0, mv ); /* Motion compensation */ x264_mb_mc( h, mb ); mb->i_type = P_SKIP;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -