📄 macroblock.c
字号:
/***************************************************************************** * macroblock.c: h264 decoder library ***************************************************************************** * Copyright (C) 2003 Laurent Aimar * $Id: macroblock.c,v 1.1 2004/06/03 19:27:07 fenrir Exp $ * * Authors: Laurent Aimar <fenrir@via.ecp.fr> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************/#include <stdlib.h>#include <stdio.h>#include <string.h>#include <stdint.h>#include "common/common.h"#include "common/vlc.h"#include "vlc.h"#include "macroblock.h"static const uint8_t block_idx_x[16] ={ 0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3};static const uint8_t block_idx_y[16] ={ 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3};static const uint8_t block_idx_xy[4][4] ={ { 0, 2, 8, 10}, { 1, 3, 9, 11}, { 4, 6, 12, 14}, { 5, 7, 13, 15}};static const int golomb_to_intra4x4_cbp[48]={ 47, 31, 15, 0, 23, 27, 29, 30, 7, 11, 13, 14, 39, 43, 45, 46, 16, 3, 5, 10, 12, 19, 21, 26, 28, 35, 37, 42, 44, 1, 2, 4, 8, 17, 18, 20, 24, 6, 9, 22, 25, 32, 33, 34, 36, 40, 38, 41};static const int golomb_to_inter_cbp[48]={ 0, 16, 1, 2, 4, 8, 32, 3, 5, 10, 12, 15, 47, 7, 11, 13, 14, 6, 9, 31, 35, 37, 42, 44, 33, 34, 36, 40, 39, 43, 45, 46, 17, 18, 20, 24, 19, 21, 26, 28, 23, 27, 29, 30, 22, 25, 38, 41};static const int i_chroma_qp_table[52] ={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 34, 35, 35, 36, 36, 37, 37, 37, 38, 38, 38, 39, 39, 39, 39};void x264_mb_partition_ref_set( x264_macroblock_t *mb, int i_list, int i_part, int i_ref ){ int x, y; int w, h; int dx, dy; x264_mb_partition_getxy( mb, i_part, 0, &x, &y ); if( mb->i_partition == D_16x16 ) { w = 4; h = 4; } else if( mb->i_partition == D_16x8 ) { w = 4; h = 2; } else if( mb->i_partition == D_8x16 ) { w = 2; h = 4; } else { /* D_8x8 */ w = 2; h = 2; } for( dx = 0; dx < w; dx++ ) { for( dy = 0; dy < h; dy++ ) { mb->partition[x+dx][y+dy].i_ref[i_list] = i_ref; } }}void x264_mb_partition_mv_set( x264_macroblock_t *mb, int i_list, int i_part, int i_sub, int mv[2] ){ int x, y; int w, h; int dx, dy; x264_mb_partition_getxy( mb, i_part, i_sub, &x, &y ); x264_mb_partition_size ( mb, i_part, i_sub, &w, &h ); for( dx = 0; dx < w; dx++ ) { for( dy = 0; dy < h; dy++ ) { mb->partition[x+dx][y+dy].mv[i_list][0] = mv[0]; mb->partition[x+dx][y+dy].mv[i_list][1] = mv[1]; } }}int x264_macroblock_read_cabac( x264_t *h, bs_t *s, x264_macroblock_t *mb ){ return -1;}static int x264_macroblock_decode_ipcm( x264_t *h, bs_t *s, x264_macroblock_t *mb ){ /* TODO */ return -1;}#define BLOCK_INDEX_CHROMA_DC (-1)#define BLOCK_INDEX_LUMA_DC (-2)static int bs_read_vlc( bs_t *s, x264_vlc_table_t *table ){ int i_nb_bits; int i_value = 0; int i_bits; int i_index; int i_level = 0; i_index = bs_show( s, table->i_lookup_bits ); if( i_index >= table->i_lookup ) { return( -1 ); } i_value = table->lookup[i_index].i_value; i_bits = table->lookup[i_index].i_size; while( i_bits < 0 ) { i_level++; if( i_level > 5 ) { return( -1 ); // FIXME what to do ? } bs_skip( s, table->i_lookup_bits ); i_nb_bits = -i_bits; i_index = bs_show( s, i_nb_bits ) + i_value; if( i_index >= table->i_lookup ) { return( -1 ); } i_value = table->lookup[i_index].i_value; i_bits = table->lookup[i_index].i_size; } bs_skip( s, i_bits ); return( i_value );}static int block_residual_read_cavlc( x264_t *h, bs_t *s, x264_macroblock_t *mb, int i_idx, int *l, int i_count ){ int i; int level[16], run[16]; int i_coeff; int i_total, i_trailing; int i_suffix_length; int i_zero_left; for( i = 0; i < i_count; i++ ) { l[i] = 0; } /* total/trailing */ if( i_idx == BLOCK_INDEX_CHROMA_DC ) { int i_tt; if( ( i_tt = bs_read_vlc( s, h->x264_coeff_token_lookup[4] )) < 0 ) { return -1; } i_total = i_tt / 4; i_trailing = i_tt % 4; } else { /* x264_mb_predict_non_zero_code return 0 <-> (16+16+1)>>1 = 16 */ static const int ct_index[17] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,3 }; int nC; int i_tt; if( i_idx == BLOCK_INDEX_LUMA_DC ) { nC = x264_mb_predict_non_zero_code( h, mb, 0 ); } else { nC = x264_mb_predict_non_zero_code( h, mb, i_idx ); } if( ( i_tt = bs_read_vlc( s, h->x264_coeff_token_lookup[ct_index[nC]] ) ) < 0 ) { return -1; } i_total = i_tt / 4; i_trailing = i_tt % 4; } if( i_idx >= 0 ) { mb->block[i_idx].i_non_zero_count = i_total; } if( i_total <= 0 ) { return 0; } i_suffix_length = i_total > 10 && i_trailing < 3 ? 1 : 0; for( i = 0; i < i_trailing; i++ ) { level[i] = 1 - 2 * bs_read1( s ); } for( ; i < i_total; i++ ) { int i_prefix; int i_level_code; i_prefix = bs_read_vlc( s, h->x264_level_prefix_lookup ); if( i_prefix == -1 ) { return -1; } else if( i_prefix < 14 ) { if( i_suffix_length > 0 ) { i_level_code = (i_prefix << i_suffix_length) + bs_read( s, i_suffix_length ); } else { i_level_code = i_prefix; } } else if( i_prefix == 14 ) { if( i_suffix_length > 0 ) { i_level_code = (i_prefix << i_suffix_length) + bs_read( s, i_suffix_length ); } else { i_level_code = i_prefix + bs_read( s, 4 ); } } else /* if( i_prefix == 15 ) */ { i_level_code = (i_prefix << i_suffix_length) + bs_read( s, 12 ); if( i_suffix_length == 0 ) { i_level_code += 15; } } if( i == i_trailing && i_trailing < 3 ) { i_level_code += 2; } /* Optimise */ level[i] = i_level_code&0x01 ? -((i_level_code+1)/2) : (i_level_code+2)/2; if( i_suffix_length == 0 ) { i_suffix_length++; } if( abs( level[i] ) > ( 3 << ( i_suffix_length - 1 ) ) && i_suffix_length < 6 ) { i_suffix_length++; } } if( i_total < i_count ) { if( i_idx == BLOCK_INDEX_CHROMA_DC ) { i_zero_left = bs_read_vlc( s, h->x264_total_zeros_dc_lookup[i_total-1] ); } else { i_zero_left = bs_read_vlc( s, h->x264_total_zeros_lookup[i_total-1] ); } if( i_zero_left < 0 ) { return -1; } } else { i_zero_left = 0; } for( i = 0; i < i_total - 1; i++ ) { if( i_zero_left <= 0 ) { break; } run[i] = bs_read_vlc( s, h->x264_run_before_lookup[X264_MIN( i_zero_left - 1, 6 )] ); if( run[i] < 0 ) { return -1; } i_zero_left -= run[i]; } if( i_zero_left < 0 ) { return -1; } for( ; i < i_total - 1; i++ ) { run[i] = 0; } run[i_total-1] = i_zero_left; i_coeff = -1; for( i = i_total - 1; i >= 0; i-- ) { i_coeff += run[i] + 1; l[i_coeff] = level[i]; } return 0;}static inline void array_zero_set( int *l, int i_count ){ int i; for( i = 0; i < i_count; i++ ) { l[i] = 0; }}int x264_macroblock_read_cavlc( x264_t *h, bs_t *s, x264_macroblock_t *mb ){ int i_mb_i_offset; int i_mb_p_offset; int b_sub_ref0 = 0; int i_type; int i; /* read the mb type */ switch( h->sh.i_type ) { case SLICE_TYPE_I: i_mb_p_offset = 0; /* shut up gcc */ i_mb_i_offset = 0; break; case SLICE_TYPE_P: i_mb_p_offset = 0; i_mb_i_offset = 5; break; case SLICE_TYPE_B: i_mb_p_offset = 23; i_mb_i_offset = 23 + 5; break; default: fprintf( stderr, "internal error or slice unsupported\n" ); return -1; } i_type = bs_read_ue( s ); if( i_type < i_mb_i_offset ) { if( i_type < i_mb_p_offset ) { fprintf( stderr, "unsupported mb type(B*)\n" ); /* TODO for B frame */ return -1; } else { i_type -= i_mb_p_offset; if( i_type == 0 ) { mb->i_type = P_L0; mb->i_partition = D_16x16; } else if( i_type == 1 ) { mb->i_type = P_L0; mb->i_partition = D_16x8; } else if( i_type == 2 ) { mb->i_type = P_L0; mb->i_partition = D_8x16; } else if( i_type == 3 || i_type == 4 ) { mb->i_type = P_8x8; mb->i_partition = D_8x8; b_sub_ref0 = i_type == 4 ? 1 : 0; } else { fprintf( stderr, "invalid mb type\n" ); return -1; } } } else { i_type -= i_mb_i_offset; if( i_type == 0 ) { mb->i_type = I_4x4; } else if( i_type < 25 ) { mb->i_type = I_16x16; mb->i_intra16x16_pred_mode = (i_type - 1)%4; mb->i_cbp_chroma = ( (i_type-1) / 4 )%3; mb->i_cbp_luma = ((i_type-1) / 12) ? 0x0f : 0x00; } else if( i_type == 25 ) { mb->i_type = I_PCM; } else { fprintf( stderr, "invalid mb type (%d)\n", i_type ); return -1; } } if( mb->i_type == I_PCM ) { return x264_macroblock_decode_ipcm( h, s, mb ); } if( IS_INTRA( mb->i_type ) ) { if( mb->i_type == I_4x4 ) { for( i = 0; i < 16; i++ ) { int b_coded; b_coded = bs_read1( s ); if( b_coded ) { mb->block[i].i_intra4x4_pred_mode = x264_mb_predict_intra4x4_mode( h, mb, i ); } else { int i_predicted_mode = x264_mb_predict_intra4x4_mode( h, mb, i ); int i_mode = bs_read( s, 3 ); if( i_mode >= i_predicted_mode ) { mb->block[i].i_intra4x4_pred_mode = i_mode + 1; } else { mb->block[i].i_intra4x4_pred_mode = i_mode; } } } } mb->i_chroma_pred_mode = bs_read_ue( s ); } else if( mb->i_type == P_8x8 || mb->i_type == B_8x8) { /* FIXME won't work for B_8x8 */ for( i = 0; i < 4; i++ ) { int i_sub_partition; i_sub_partition = bs_read_ue( s ); switch( i_sub_partition ) { case 0: mb->i_sub_partition[i] = D_L0_8x8; break; case 1: mb->i_sub_partition[i] = D_L0_8x4; break; case 2: mb->i_sub_partition[i] = D_L0_4x8; break; case 3: mb->i_sub_partition[i] = D_L0_4x4; break; default: fprintf( stderr, "invalid i_sub_partition\n" ); return -1; } } for( i = 0; i < 4; i++ ) { int i_ref; i_ref = b_sub_ref0 ? 0 : 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 < 4; i++ ) { int i_sub; int i_ref;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -