www.pudn.com > h264src.zip > cabac.c
/***************************************************************************** * * T264 AVC CODEC * * Copyright(C) 2004-2005 joylife* 2004-2005 tricro * * 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-1307 USA * ****************************************************************************/ /***************************************************************************** * cabac.c: h264 encoder library ***************************************************************************** * Copyright (C) 2003 Laurent Aimar * * Authors: Laurent Aimar * * 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. *****************************************************************************/ /*Note: the CABAC routine is currently referenced from x264 temporarily, with adaptation to *the data structure of T264. It should be modified further in the near future. *It's can support B slice, but only with MB mode P16x16, P16x8, P8x16, Direct16x16, B_SKIP *ie., B8x8 is not support now */ #include #include #include #include #include "T264.h" #include "cabac_engine.h" #include "inter.h" /* From ffmpeg */ #define T264_SCAN8_SIZE (6*8) #define T264_SCAN8_0 (4+1*8) static const int T264_scan8[16+2*4] = { /* Luma */ VEC_LUMA + 0, VEC_LUMA + 1, VEC_LUMA + 1*8 + 0, VEC_LUMA + 1*8 + 1, VEC_LUMA + 2, VEC_LUMA + 3, VEC_LUMA + 1*8 + 2, VEC_LUMA + 1*8 + 3, VEC_LUMA + 2*8 + 0, VEC_LUMA + 2*8 + 1, VEC_LUMA + 3*8 + 0, VEC_LUMA + 3*8 + 1, VEC_LUMA + 2*8 + 2, VEC_LUMA + 2*8 + 3, VEC_LUMA + 3*8 + 2, VEC_LUMA + 3*8 + 3, /* Cb */ NNZ_CHROMA0 + 0, NNZ_CHROMA0 + 1, NNZ_CHROMA0 + 1*8 + 0, NNZ_CHROMA0 + 1*8 + 1, /* Cr */ NNZ_CHROMA1 + 0, NNZ_CHROMA1 + 1, NNZ_CHROMA1 + 1*8 + 0, NNZ_CHROMA1 + 1*8 + 1, }; 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} }; #define IS_INTRA(mode) (mode == I_4x4 || mode == I_16x16) #define IS_SKIP(type) ( (type) == P_SKIP || (type) == B_SKIP ) enum { INTRA_4x4 = 0, INTRA_16x16 = 1, INTRA_PCM = 2, P_L0 = 3, P_8x81 = 4, P_SKIP1 = 5, B_DIRECT = 6, B_L0_L0 = 7, B_L0_L1 = 8, B_L0_BI = 9, B_L1_L0 = 10, B_L1_L1 = 11, B_L1_BI = 12, B_BI_L0 = 13, B_BI_L1 = 14, B_BI_BI = 15, B_8x81 = 16, B_SKIP1 = 17, }; static const int T264_mb_partition_listX_table[][2] = { {0, 0}, //B_DIRECT_8x8 = 100, {1, 0}, //B_L0_8x8, {0, 1}, //B_L1_8x8, {1, 1}, //B_Bi_8x8, {1, 0}, //B_L0_8x4, {1, 0}, //B_L0_4x8, {0, 1}, //B_L1_8x4, {0, 1}, //B_L1_4x8, {1, 1}, //B_Bi_8x4, {1, 1}, //B_Bi_4x8, {1, 0}, //B_L0_4x4, {0, 1}, //B_L1_4x4, {1, 1} //B_Bi_4x4 }; static const int T264_mb_type_list0_table[18][2] = { {0,0}, {0,0}, {0,0}, /* INTRA */ {1,1}, /* P_L0 */ {0,0}, /* P_8x8 */ {1,1}, /* P_SKIP */ {0,0}, /* B_DIRECT */ {1,1}, {1,0}, {1,1}, /* B_L0_* */ {0,1}, {0,0}, {0,1}, /* B_L1_* */ {1,1}, {1,0}, {1,1}, /* B_BI_* */ {0,0}, /* B_8x8 */ {0,0} /* B_SKIP */ }; static const int T264_mb_type_list1_table[18][2] = { {0,0}, {0,0}, {0,0}, /* INTRA */ {0,0}, /* P_L0 */ {0,0}, /* P_8x8 */ {0,0}, /* P_SKIP */ {0,0}, /* B_DIRECT */ {0,0}, {0,1}, {0,1}, /* B_L0_* */ {1,0}, {1,1}, {1,1}, /* B_L1_* */ {1,0}, {1,1}, {1,1}, /* B_BI_* */ {0,0}, /* B_8x8 */ {0,0} /* B_SKIP */ }; static void T264_cabac_mb_type( T264_t *t ) { T264_mb_context_t *mb_ctxs = &(t->rec->mb[0]); int32_t mb_mode = t->mb.mb_mode; if( t->slice_type == SLICE_I ) { int ctx = 0; if( t->mb.mb_x > 0 && mb_ctxs[t->mb.mb_xy-1].mb_mode != I_4x4 ) { ctx++; } if( t->mb.mb_y > 0 && mb_ctxs[t->mb.mb_xy - t->mb_stride].mb_mode != I_4x4 ) { ctx++; } if( mb_mode == I_4x4 ) { T264_cabac_encode_decision( &t->cabac, 3 + ctx, 0 ); } else if(mb_mode == I_16x16) /* I_16x16 */ { T264_cabac_encode_decision( &t->cabac, 3 + ctx, 1 ); T264_cabac_encode_terminal( &t->cabac, 0 ); T264_cabac_encode_decision( &t->cabac, 3 + 3, ( t->mb.cbp_y == 0 ? 0 : 1 )); if( t->mb.cbp_c == 0 ) { T264_cabac_encode_decision( &t->cabac, 3 + 4, 0 ); } else { T264_cabac_encode_decision( &t->cabac, 3 + 4, 1 ); T264_cabac_encode_decision( &t->cabac, 3 + 5, ( t->mb.cbp_c == 1 ? 0 : 1 ) ); } T264_cabac_encode_decision( &t->cabac, 3 + 6, ( (t->mb.mode_i16x16 / 2) ? 1 : 0 )); T264_cabac_encode_decision( &t->cabac, 3 + 7, ( (t->mb.mode_i16x16 % 2) ? 1 : 0 )); } else /* I_PCM */ { T264_cabac_encode_decision( &t->cabac, 3 + ctx, 1 ); T264_cabac_encode_terminal( &t->cabac, 1 ); } } else if( t->slice_type == SLICE_P ) { /* prefix: 14, suffix: 17 */ if( mb_mode == P_MODE ) { if( t->mb.mb_part == MB_16x16 ) { T264_cabac_encode_decision( &t->cabac, 14, 0 ); T264_cabac_encode_decision( &t->cabac, 15, 0 ); T264_cabac_encode_decision( &t->cabac, 16, 0 ); } else if( t->mb.mb_part == MB_16x8 ) { T264_cabac_encode_decision( &t->cabac, 14, 0 ); T264_cabac_encode_decision( &t->cabac, 15, 1 ); T264_cabac_encode_decision( &t->cabac, 17, 1 ); } else if( t->mb.mb_part == MB_8x16 ) { T264_cabac_encode_decision( &t->cabac, 14, 0 ); T264_cabac_encode_decision( &t->cabac, 15, 1 ); T264_cabac_encode_decision( &t->cabac, 17, 0 ); } else /* P8x8 mode */ { T264_cabac_encode_decision( &t->cabac, 14, 0 ); T264_cabac_encode_decision( &t->cabac, 15, 0 ); T264_cabac_encode_decision( &t->cabac, 16, 1 ); } } else if( mb_mode == I_4x4 ) { /* prefix */ T264_cabac_encode_decision( &t->cabac, 14, 1 ); T264_cabac_encode_decision( &t->cabac, 17, 0 ); } else if(mb_mode == I_16x16) /* intra 16x16 */ { /* prefix */ T264_cabac_encode_decision( &t->cabac, 14, 1 ); /* suffix */ T264_cabac_encode_decision( &t->cabac, 17, 1 ); T264_cabac_encode_terminal( &t->cabac, 0 ); /*ctxIdx == 276 */ T264_cabac_encode_decision( &t->cabac, 17+1, ( t->mb.cbp_y == 0 ? 0 : 1 )); if( t->mb.cbp_c == 0 ) { T264_cabac_encode_decision( &t->cabac, 17+2, 0 ); } else { T264_cabac_encode_decision( &t->cabac, 17+2, 1 ); T264_cabac_encode_decision( &t->cabac, 17+2, ( t->mb.cbp_c == 1 ? 0 : 1 ) ); } T264_cabac_encode_decision( &t->cabac, 17+3, ( (t->mb.mode_i16x16 / 2) ? 1 : 0 )); T264_cabac_encode_decision( &t->cabac, 17+3, ( (t->mb.mode_i16x16 % 2) ? 1 : 0 )); } else /* I_PCM */ { /* prefix */ T264_cabac_encode_decision( &t->cabac, 14, 1 ); T264_cabac_encode_decision( &t->cabac, 17, 1 ); T264_cabac_encode_terminal( &t->cabac, 1 ); /*ctxIdx == 276 */ } } else if( t->slice_type == SLICE_B ) { int ctx = 0; if( t->mb.mb_x > 0 && mb_ctxs[t->mb.mb_xy-1].mb_mode != B_SKIP && !mb_ctxs[t->mb.mb_xy-1].is_copy ) { ctx++; } if( t->mb.mb_y > 0 && mb_ctxs[t->mb.mb_xy - t->mb_stride].mb_mode != B_SKIP && ! mb_ctxs[t->mb.mb_xy - t->mb_stride].is_copy) { ctx++; } if( t->mb.is_copy) { T264_cabac_encode_decision( &t->cabac, 27+ctx, 0 ); } else if( t->mb.mb_part == MB_8x8 ) { T264_cabac_encode_decision( &t->cabac, 27+ctx, 1 ); T264_cabac_encode_decision( &t->cabac, 27+3, 1 ); T264_cabac_encode_decision( &t->cabac, 27+4, 1 ); T264_cabac_encode_decision( &t->cabac, 27+5, 1 ); T264_cabac_encode_decision( &t->cabac, 27+5, 1 ); T264_cabac_encode_decision( &t->cabac, 27+5, 1 ); } else if( IS_INTRA( mb_mode ) ) { /* prefix */ T264_cabac_encode_decision( &t->cabac, 27+ctx, 1 ); T264_cabac_encode_decision( &t->cabac, 27+3, 1 ); T264_cabac_encode_decision( &t->cabac, 27+4, 1 ); T264_cabac_encode_decision( &t->cabac, 27+5, 1 ); T264_cabac_encode_decision( &t->cabac, 27+5, 0 ); T264_cabac_encode_decision( &t->cabac, 27+5, 1 ); /* Suffix */ if( mb_mode == I_4x4 ) { T264_cabac_encode_decision( &t->cabac, 32, 0 ); } else if(mb_mode == I_16x16) { T264_cabac_encode_decision( &t->cabac, 32, 1 ); T264_cabac_encode_terminal( &t->cabac, 0 ); /* TODO */ T264_cabac_encode_decision( &t->cabac, 32+1, ( t->mb.cbp_y == 0 ? 0 : 1 )); if( t->mb.cbp_c == 0 ) { T264_cabac_encode_decision( &t->cabac, 32+2, 0 ); } else { T264_cabac_encode_decision( &t->cabac, 32+2, 1 ); T264_cabac_encode_decision( &t->cabac, 32+2, ( t->mb.cbp_c == 1 ? 0 : 1 ) ); } T264_cabac_encode_decision( &t->cabac, 32+3, ( (t->mb.mode_i16x16 / 2) ? 1 : 0 )); T264_cabac_encode_decision( &t->cabac, 32+3, ( (t->mb.mode_i16x16 % 2) ? 1 : 0 )); } else /* I_PCM */ { T264_cabac_encode_decision( &t->cabac, 32, 1 ); T264_cabac_encode_terminal( &t->cabac, 1 ); } } else { static const int i_mb_len[21] = { 3, 6, 6, /* L0 L0 */ 3, 6, 6, /* L1 L1 */ 6, 7, 7, /* BI BI */ 6, 6, /* L0 L1 */ 6, 6, /* L1 L0 */ 7, 7, /* L0 BI */ 7, 7, /* L1 BI */ 7, 7, /* BI L0 */ 7, 7, /* BI L1 */ }; static const int i_mb_bits[21][7] = { { 1, 0, 0, }, { 1, 1, 0, 0, 0, 1, }, { 1, 1, 0, 0, 1, 0, }, /* L0 L0 */ { 1, 0, 1, }, { 1, 1, 0, 0, 1, 1, }, { 1, 1, 0, 1, 0, 0, }, /* L1 L1 */ { 1, 1, 0, 0, 0, 0 ,}, { 1, 1, 1, 1, 0, 0 , 0 }, { 1, 1, 1, 1, 0, 0 , 1 },/* BI BI */ { 1, 1, 0, 1, 0, 1, }, { 1, 1, 0, 1, 1, 0, }, /* L0 L1 */ { 1, 1, 0, 1, 1, 1, }, { 1, 1, 1, 1, 1, 0, }, /* L1 L0 */ { 1, 1, 1, 0, 0, 0, 0 }, { 1, 1, 1, 0, 0, 0, 1 }, /* L0 BI */ { 1, 1, 1, 0, 0, 1, 0 }, { 1, 1, 1, 0, 0, 1, 1 }, /* L1 BI */ { 1, 1, 1, 0, 1, 0, 0 }, { 1, 1, 1, 0, 1, 0, 1 }, /* BI L0 */ { 1, 1, 1, 0, 1, 1, 0 }, { 1, 1, 1, 0, 1, 1, 1 } /* BI L1 */ }; const int i_partition = t->mb.mb_part; int idx = 0; int i, b_part_mode, part_mode0, part_mode1; static const int b_part_mode_map[3][3] = { { B_L0_L0, B_L0_L1, B_L0_BI }, { B_L1_L0, B_L1_L1, B_L1_BI }, { B_BI_L0, B_BI_L1, B_BI_BI } }; switch(t->mb.mb_part) { case MB_16x16: part_mode0 = t->mb.mb_part2[0] - B_L0_16x16; b_part_mode = b_part_mode_map[part_mode0][part_mode0]; break; case MB_16x8: part_mode0 = t->mb.mb_part2[0] - B_L0_16x8; part_mode1 = t->mb.mb_part2[1] - B_L0_16x8; b_part_mode = b_part_mode_map[part_mode0][part_mode1]; break; case MB_8x16: part_mode0 = t->mb.mb_part2[0] - B_L0_8x16; part_mode1 = t->mb.mb_part2[1] - B_L0_8x16; b_part_mode = b_part_mode_map[part_mode0][part_mode1]; break; } switch( b_part_mode ) { /* D_16x16, D_16x8, D_8x16 */ case B_BI_BI: idx += 3; case B_L1_L1: idx += 3; case B_L0_L0: if( i_partition == MB_16x8 ) idx += 1; else if( i_partition == MB_8x16 ) idx += 2; break; /* D_16x8, D_8x16 */ case B_BI_L1: idx += 2; case B_BI_L0: idx += 2; case B_L1_BI: idx += 2; case B_L0_BI: idx += 2; case B_L1_L0: idx += 2; case B_L0_L1: idx += 3*3; if( i_partition == MB_8x16 ) idx++; break; default: return; } T264_cabac_encode_decision( &t->cabac, 27+ctx, i_mb_bits[idx][0] ); T264_cabac_encode_decision( &t->cabac, 27+3, i_mb_bits[idx][1] ); T264_cabac_encode_decision( &t->cabac, 27+(i_mb_bits[idx][1] != 0 ? 4 : 5), i_mb_bits[idx][2] ); for( i = 3; i < i_mb_len[idx]; i++ ) { T264_cabac_encode_decision( &t->cabac, 27+5, i_mb_bits[idx][i] ); } } } else { //dummy here } } static void T264_cabac_mb_intra4x4_pred_mode( T264_t *t, int i_pred, int i_mode ) { if( i_pred == i_mode ) { /* b_prev_intra4x4_pred_mode */ T264_cabac_encode_decision( &t->cabac, 68, 1 ); } else { /* b_prev_intra4x4_pred_mode */ T264_cabac_encode_decision( &t->cabac, 68, 0 ); if( i_mode > i_pred ) { i_mode--; } T264_cabac_encode_decision( &t->cabac, 69, (i_mode )&0x01 ); T264_cabac_encode_decision( &t->cabac, 69, (i_mode >> 1)&0x01 ); T264_cabac_encode_decision( &t->cabac, 69, (i_mode >> 2)&0x01 ); } } static void T264_cabac_mb_intra8x8_pred_mode( T264_t *t ) { const int i_mode = t->mb.mb_mode_uv; T264_mb_context_t *mb_ctxs = &(t->rec->mb[0]); int ctx = 0; if( t->mb.mb_x > 0 && mb_ctxs[t->mb.mb_xy-1].mb_mode_uv != Intra_8x8_DC) { ctx++; } if( t->mb.mb_y > 0 && mb_ctxs[t->mb.mb_xy - t->mb_stride].mb_mode_uv != Intra_8x8_DC ) { ctx++; } if( i_mode == Intra_8x8_DC ) { T264_cabac_encode_decision( &t->cabac, 64 + ctx, Intra_8x8_DC ); } else { T264_cabac_encode_decision( &t->cabac, 64 + ctx, 1 ); T264_cabac_encode_decision( &t->cabac, 64 + 3, ( i_mode == 1 ? 0 : 1 ) ); if( i_mode > 1 ) { T264_cabac_encode_decision( &t->cabac, 64 + 3, ( i_mode == 2 ? 0 : 1 ) ); } } } static void T264_cabac_mb_cbp_luma( T264_t *t ) { /* TODO: clean up and optimize */ T264_mb_context_t *mb_ctxs = &(t->rec->mb[0]); int i8x8; for( i8x8 = 0; i8x8 < 4; i8x8++ ) { int i_mba_xy = -1; int i_mbb_xy = -1; int x = luma_inverse_x[4*i8x8]; int y = luma_inverse_y[4*i8x8]; int ctx = 0; if( x > 0 ) i_mba_xy = t->mb.mb_xy; else if( t->mb.mb_x > 0 ) i_mba_xy = t->mb.mb_xy - 1; if( y > 0 ) i_mbb_xy = t->mb.mb_xy; else if( t->mb.mb_y > 0 ) i_mbb_xy = t->mb.mb_xy - t->mb_stride; /* No need to test for PCM and SKIP */ if( i_mba_xy >= 0 ) { const int i8x8a = block_idx_xy[(x-1)&0x03][y]/4; if( ((mb_ctxs[i_mba_xy].cbp_y >> i8x8a)&0x01) == 0 ) { ctx++; } } if( i_mbb_xy >= 0 ) { const int i8x8b = block_idx_xy[x][(y-1)&0x03]/4; if( ((mb_ctxs[i_mbb_xy].cbp_y >> i8x8b)&0x01) == 0 ) { ctx += 2; } } T264_cabac_encode_decision( &t->cabac, 73 + ctx, (t->mb.cbp_y >> i8x8)&0x01 ); } } static void T264_cabac_mb_cbp_chroma( T264_t *t ) { int cbp_a = -1; int cbp_b = -1; int ctx; T264_mb_context_t *mb_ctxs = &(t->rec->mb[0]); /* No need to test for SKIP/PCM */ if( t->mb.mb_x > 0 ) { cbp_a = (mb_ctxs[t->mb.mb_xy - 1].cbp_c)&0x3; } if( t->mb.mb_y > 0 ) { cbp_b = (mb_ctxs[t->mb.mb_xy - t->mb_stride].cbp_c)&0x3; } ctx = 0; if( cbp_a > 0 ) ctx++; if( cbp_b > 0 ) ctx += 2; if( t->mb.cbp_c == 0 ) { T264_cabac_encode_decision( &t->cabac, 77 + ctx, 0 ); } else { T264_cabac_encode_decision( &t->cabac, 77 + ctx, 1 ); ctx = 4; if( cbp_a == 2 ) ctx++; if( cbp_b == 2 ) ctx += 2; T264_cabac_encode_decision( &t->cabac, 77 + ctx, t->mb.cbp_c > 1 ? 1 : 0 ); } } /* TODO check it with != qp per mb */ static void T264_cabac_mb_qp_delta( T264_t *t ) { int i_mbn_xy = t->mb.mb_xy - 1; int i_dqp = t->mb.mb_qp_delta; int val = i_dqp <= 0 ? (-2*i_dqp) : (2*i_dqp - 1); int ctx; T264_mb_context_t *mb_ctxs = &(t->rec->mb[0]); /* No need to test for PCM / SKIP */ if( i_mbn_xy >= 0 && mb_ctxs[i_mbn_xy].mb_qp_delta != 0 && ( mb_ctxs[i_mbn_xy].mb_mode == I_16x16 || mb_ctxs[i_mbn_xy].cbp_y || mb_ctxs[i_mbn_xy].cbp_c) ) ctx = 1; else ctx = 0; while( val > 0 ) { T264_cabac_encode_decision( &t->cabac, 60 + ctx, 1 ); if( ctx < 2 ) ctx = 2; else ctx = 3; val--; } T264_cabac_encode_decision( &t->cabac, 60 + ctx, 0 ); } void T264_cabac_mb_skip( T264_t *t, int b_skip ) { T264_mb_context_t *mb_ctxs = &(t->rec->mb[0]); int ctx = 0; if( t->mb.mb_x > 0 && !IS_SKIP( mb_ctxs[t->mb.mb_xy -1].mb_mode) ) { ctx++; } if( t->mb.mb_y > 0 && !IS_SKIP( mb_ctxs[t->mb.mb_xy - t->mb_stride].mb_mode) ) { ctx++; } if( t->slice_type == SLICE_P ) T264_cabac_encode_decision( &t->cabac, 11 + ctx, b_skip ? 1 : 0 ); else /* SLICE_TYPE_B */ T264_cabac_encode_decision( &t->cabac, 24 + ctx, b_skip ? 1 : 0 ); } static __inline void T264_cabac_mb_sub_p_partition( T264_t *t, int i_sub ) { if( i_sub == MB_8x8 ) { T264_cabac_encode_decision( &t->cabac, 21, 1 ); } else if( i_sub == MB_8x4 ) { T264_cabac_encode_decision( &t->cabac, 21, 0 ); T264_cabac_encode_decision( &t->cabac, 22, 0 ); } else if( i_sub == MB_4x8 ) { T264_cabac_encode_decision( &t->cabac, 21, 0 ); T264_cabac_encode_decision( &t->cabac, 22, 1 ); T264_cabac_encode_decision( &t->cabac, 23, 1 ); } else if( i_sub == MB_4x4 ) { T264_cabac_encode_decision( &t->cabac, 21, 0 ); T264_cabac_encode_decision( &t->cabac, 22, 1 ); T264_cabac_encode_decision( &t->cabac, 23, 0 ); } } static __inline void T264_cabac_mb_sub_b_partition( T264_t *t, int i_sub ) { if( i_sub == B_DIRECT_8x8 ) { T264_cabac_encode_decision( &t->cabac, 36, 0 ); } else if( i_sub == B_L0_8x8 ) { T264_cabac_encode_decision( &t->cabac, 36, 1 ); T264_cabac_encode_decision( &t->cabac, 37, 0 ); T264_cabac_encode_decision( &t->cabac, 39, 0 ); } else if( i_sub == B_L1_8x8 ) { T264_cabac_encode_decision( &t->cabac, 36, 1 ); T264_cabac_encode_decision( &t->cabac, 37, 0 ); T264_cabac_encode_decision( &t->cabac, 39, 1 ); } else if( i_sub == B_Bi_8x8 ) { T264_cabac_encode_decision( &t->cabac, 36, 1 ); T264_cabac_encode_decision( &t->cabac, 37, 1 ); T264_cabac_encode_decision( &t->cabac, 38, 0 ); T264_cabac_encode_decision( &t->cabac, 39, 0 ); T264_cabac_encode_decision( &t->cabac, 39, 0 ); } else if( i_sub == B_L0_8x4 ) { T264_cabac_encode_decision( &t->cabac, 36, 1 ); T264_cabac_encode_decision( &t->cabac, 37, 1 ); T264_cabac_encode_decision( &t->cabac, 38, 0 ); T264_cabac_encode_decision( &t->cabac, 39, 0 ); T264_cabac_encode_decision( &t->cabac, 39, 1 ); } else if( i_sub == B_L0_4x8 ) { T264_cabac_encode_decision( &t->cabac, 36, 1 ); T264_cabac_encode_decision( &t->cabac, 37, 1 ); T264_cabac_encode_decision( &t->cabac, 38, 0 ); T264_cabac_encode_decision( &t->cabac, 39, 1 ); T264_cabac_encode_decision( &t->cabac, 39, 0 ); } else if( i_sub == B_L1_8x4 ) { T264_cabac_encode_decision( &t->cabac, 36, 1 ); T264_cabac_encode_decision( &t->cabac, 37, 1 ); T264_cabac_encode_decision( &t->cabac, 38, 0 ); T264_cabac_encode_decision( &t->cabac, 39, 1 ); T264_cabac_encode_decision( &t->cabac, 39, 1 ); } else if( i_sub == B_L1_4x8 ) { T264_cabac_encode_decision( &t->cabac, 36, 1 ); T264_cabac_encode_decision( &t->cabac, 37, 1 ); T264_cabac_encode_decision( &t->cabac, 38, 1 ); T264_cabac_encode_decision( &t->cabac, 39, 0 ); T264_cabac_encode_decision( &t->cabac, 39, 0 ); T264_cabac_encode_decision( &t->cabac, 39, 0 ); } else if( i_sub == B_Bi_8x4 ) { T264_cabac_encode_decision( &t->cabac, 36, 1 ); T264_cabac_encode_decision( &t->cabac, 37, 1 ); T264_cabac_encode_decision( &t->cabac, 38, 1 ); T264_cabac_encode_decision( &t->cabac, 39, 0 ); T264_cabac_encode_decision( &t->cabac, 39, 0 ); T264_cabac_encode_decision( &t->cabac, 39, 1 ); } else if( i_sub == B_Bi_4x8 ) { T264_cabac_encode_decision( &t->cabac, 36, 1 ); T264_cabac_encode_decision( &t->cabac, 37, 1 ); T264_cabac_encode_decision( &t->cabac, 38, 1 ); T264_cabac_encode_decision( &t->cabac, 39, 0 ); T264_cabac_encode_decision( &t->cabac, 39, 1 ); T264_cabac_encode_decision( &t->cabac, 39, 0 ); } else if( i_sub == B_L0_4x4 ) { T264_cabac_encode_decision( &t->cabac, 36, 1 ); T264_cabac_encode_decision( &t->cabac, 37, 1 ); T264_cabac_encode_decision( &t->cabac, 38, 1 ); T264_cabac_encode_decision( &t->cabac, 39, 0 ); T264_cabac_encode_decision( &t->cabac, 39, 1 ); T264_cabac_encode_decision( &t->cabac, 39, 1 ); } else if( i_sub == B_L1_4x4 ) { T264_cabac_encode_decision( &t->cabac, 36, 1 ); T264_cabac_encode_decision( &t->cabac, 37, 1 ); T264_cabac_encode_decision( &t->cabac, 38, 1 ); T264_cabac_encode_decision( &t->cabac, 39, 1 ); T264_cabac_encode_decision( &t->cabac, 39, 0 ); } else if( i_sub == B_Bi_4x4 ) { T264_cabac_encode_decision( &t->cabac, 36, 1 ); T264_cabac_encode_decision( &t->cabac, 37, 1 ); T264_cabac_encode_decision( &t->cabac, 38, 1 ); T264_cabac_encode_decision( &t->cabac, 39, 1 ); T264_cabac_encode_decision( &t->cabac, 39, 1 ); } } static __inline void T264_cabac_mb_ref( T264_t *t, int i_list, int idx ) { const int i8 = T264_scan8[idx]; T264_mb_context_t *mb_ctxs = &(t->rec->mb[0]); const int i_refa = t->mb.vec_ref[i8 - 1].vec[i_list].refno; const int i_refb = t->mb.vec_ref[i8 - 8].vec[i_list].refno; int i_ref = t->mb.vec_ref[i8].vec[i_list].refno; int a_direct, b_direct; int ctx = 0; int luma_idx = luma_index[idx]; if( t->slice_type==SLICE_B && t->mb.mb_x > 0 && (mb_ctxs[t->mb.mb_xy-1].mb_mode == B_SKIP||mb_ctxs[t->mb.mb_xy-1].is_copy ) && (luma_idx&0x03)==0) { a_direct = 1; } else a_direct = 0; if( t->slice_type==SLICE_B && t->mb.mb_y > 0 && (mb_ctxs[t->mb.mb_xy - t->mb_stride].mb_mode == B_SKIP||mb_ctxs[t->mb.mb_xy - t->mb_stride].is_copy) && luma_idx<4) { b_direct = 1; } else b_direct = 0; if( i_refa>0 && !a_direct) ctx++; if( i_refb>0 && !b_direct) ctx += 2; while( i_ref > 0 ) { T264_cabac_encode_decision( &t->cabac, 54 + ctx, 1 ); if( ctx < 4 ) ctx = 4; else ctx = 5; i_ref--; } T264_cabac_encode_decision( &t->cabac, 54 + ctx, 0 ); } static __inline void T264_cabac_mb_mvd_cpn( T264_t *t, int i_list, int i8, int l, int mvd ) { const int amvd = abs( t->mb.mvd_ref[i_list][i8 - 1][l] ) + abs( t->mb.mvd_ref[i_list][i8 - 8][l] ); const int i_abs = abs( mvd ); const int i_prefix = T264_MIN( i_abs, 9 ); const int ctxbase = (l == 0 ? 40 : 47); int ctx; int i; if( amvd < 3 ) ctx = 0; else if( amvd > 32 ) ctx = 2; else ctx = 1; for( i = 0; i < i_prefix; i++ ) { T264_cabac_encode_decision( &t->cabac, ctxbase + ctx, 1 ); if( ctx < 3 ) ctx = 3; else if( ctx < 6 ) ctx++; } if( i_prefix < 9 ) { T264_cabac_encode_decision( &t->cabac, ctxbase + ctx, 0 ); } if( i_prefix >= 9 ) { int i_suffix = i_abs - 9; int k = 3; while( i_suffix >= (1< cabac, 1 ); i_suffix -= 1 << k; k++; } T264_cabac_encode_bypass( &t->cabac, 0 ); while( k-- ) { T264_cabac_encode_bypass( &t->cabac, (i_suffix >> k)&0x01 ); } } /* sign */ if( mvd > 0 ) T264_cabac_encode_bypass( &t->cabac, 0 ); else if( mvd < 0 ) T264_cabac_encode_bypass( &t->cabac, 1 ); } static __inline void T264_cabac_mb_mvd( T264_t *t, int i_list, int idx, int width, int height ) { T264_vector_t mvp; int mdx, mdy; int i, j; int i8 = T264_scan8[idx]; int luma_idx = luma_index[idx]; /* Calculate mvd */ mvp.refno = t->mb.vec_ref[i8].vec[i_list].refno; T264_predict_mv( t, i_list, luma_idx, width, &mvp ); mdx = t->mb.vec_ref[i8].vec[i_list].x - mvp.x; mdy = t->mb.vec_ref[i8].vec[i_list].y - mvp.y; /* encode */ T264_cabac_mb_mvd_cpn( t, i_list, i8, 0, mdx ); T264_cabac_mb_mvd_cpn( t, i_list, i8, 1, mdy ); /* save mvd value */ for(j=0; j mb.mvd_ref[i_list][i8+i][0] = mdx; t->mb.mvd_ref[i_list][i8+i][1] = mdy; t->mb.mvd[i_list][luma_idx+i][0] = mdx; t->mb.mvd[i_list][luma_idx+i][1] = mdy; } i8 += 8; luma_idx += 4; } } static __inline void T264_cabac_mb8x8_mvd( T264_t *t, int i_list ) { int i; int sub_part; for( i = 0; i < 4; i++ ) { sub_part = t->mb.submb_part[luma_index[i<<2]]; if( T264_mb_partition_listX_table[sub_part-B_DIRECT_8x8][i_list] == 0 ) { continue; } switch( sub_part ) { case B_DIRECT_8x8: assert(0); break; case B_L0_8x8: case B_L1_8x8: case B_Bi_8x8: T264_cabac_mb_mvd( t, i_list, 4*i, 2, 2 ); break; case B_L0_8x4: case B_L1_8x4: case B_Bi_8x4: T264_cabac_mb_mvd( t, i_list, 4*i+0, 2, 1 ); T264_cabac_mb_mvd( t, i_list, 4*i+2, 2, 1 ); break; case B_L0_4x8: case B_L1_4x8: case B_Bi_4x8: T264_cabac_mb_mvd( t, i_list, 4*i+0, 1, 2 ); T264_cabac_mb_mvd( t, i_list, 4*i+1, 1, 2 ); break; case B_L0_4x4: case B_L1_4x4: case B_Bi_4x4: T264_cabac_mb_mvd( t, i_list, 4*i+0, 1, 1 ); T264_cabac_mb_mvd( t, i_list, 4*i+1, 1, 1 ); T264_cabac_mb_mvd( t, i_list, 4*i+2, 1, 1 ); T264_cabac_mb_mvd( t, i_list, 4*i+3, 1, 1 ); break; } } } static int T264_cabac_mb_cbf_ctxidxinc( T264_t *t, int i_cat, int i_idx ) { /* TODO: clean up/optimize */ T264_mb_context_t *mb_ctxs = &(t->rec->mb[0]); T264_mb_context_t *mb_ctx; int i_mba_xy = -1; int i_mbb_xy = -1; int i_nza = -1; int i_nzb = -1; int ctx = 0; int cbp; if( i_cat == 0 ) { if( t->mb.mb_x > 0 ) { i_mba_xy = t->mb.mb_xy -1; mb_ctx = &(mb_ctxs[i_mba_xy]); if( mb_ctx->mb_mode == I_16x16 ) { i_nza = (mb_ctx->cbp & 0x100); } } if( t->mb.mb_y > 0 ) { i_mbb_xy = t->mb.mb_xy - t->mb_stride; mb_ctx = &(mb_ctxs[i_mbb_xy]); if( mb_ctx->mb_mode == I_16x16 ) { i_nzb = (mb_ctx->cbp & 0x100); } } } else if( i_cat == 1 || i_cat == 2 ) { int x = luma_inverse_x[i_idx]; int y = luma_inverse_y[i_idx]; int i8 = T264_scan8[i_idx]; if( x > 0 ) i_mba_xy = t->mb.mb_xy; else if( t->mb.mb_x > 0 ) i_mba_xy = t->mb.mb_xy -1; if( y > 0 ) i_mbb_xy = t->mb.mb_xy; else if( t->mb.mb_y > 0 ) i_mbb_xy = t->mb.mb_xy - t->mb_stride; /* no need to test for skip/pcm */ if( i_mba_xy >= 0 ) { const int i8x8a = block_idx_xy[(x-1)&0x03][y]/4; if( (mb_ctxs[i_mba_xy].cbp_y&0x0f)>> i8x8a ) { i_nza = t->mb.nnz_ref[i8-1]; } } if( i_mbb_xy >= 0 ) { const int i8x8b = block_idx_xy[x][(y-1)&0x03]/4; if( (mb_ctxs[i_mbb_xy].cbp_y&0x0f)>> i8x8b ) { i_nzb = t->mb.nnz_ref[i8 - 8]; } } } else if( i_cat == 3 ) { /* no need to test skip/pcm */ if( t->mb.mb_x > 0 ) { i_mba_xy = t->mb.mb_xy -1; cbp = mb_ctxs[i_mba_xy].cbp; if( cbp&0x30 ) { i_nza = cbp&( 0x02 << ( 8 + i_idx) ); } } if( t->mb.mb_y > 0 ) { i_mbb_xy = t->mb.mb_xy - t->mb_stride; cbp = mb_ctxs[i_mbb_xy].cbp; if( cbp&0x30 ) { i_nzb = cbp&( 0x02 << ( 8 + i_idx) ); } } } else if( i_cat == 4 ) { int idxc = i_idx% 4; if( idxc == 1 || idxc == 3 ) i_mba_xy = t->mb.mb_xy; else if( t->mb.mb_x > 0 ) i_mba_xy = t->mb.mb_xy - 1; if( idxc == 2 || idxc == 3 ) i_mbb_xy = t->mb.mb_xy; else if( t->mb.mb_y > 0 ) i_mbb_xy = t->mb.mb_xy - t->mb_stride; /* no need to test skip/pcm */ if( i_mba_xy >= 0 && (mb_ctxs[i_mba_xy].cbp&0x30) == 0x20 ) { i_nza = t->mb.nnz_ref[T264_scan8[16+i_idx] - 1]; } if( i_mbb_xy >= 0 && (mb_ctxs[i_mbb_xy].cbp&0x30) == 0x20 ) { i_nzb = t->mb.nnz_ref[T264_scan8[16+i_idx] - 8]; } } if( ( i_mba_xy < 0 && IS_INTRA( t->mb.mb_mode ) ) || i_nza > 0 ) { ctx++; } if( ( i_mbb_xy < 0 && IS_INTRA( t->mb.mb_mode ) ) || i_nzb > 0 ) { ctx += 2; } return 4 * i_cat + ctx; } static void block_residual_write_cabac( T264_t *t, int i_ctxBlockCat, int i_idx, int16_t *l, int i_count ) { static const int significant_coeff_flag_offset[5] = { 0, 15, 29, 44, 47 }; static const int last_significant_coeff_flag_offset[5] = { 0, 15, 29, 44, 47 }; static const int coeff_abs_level_m1_offset[5] = { 0, 10, 20, 30, 39 }; int i_coeff_abs_m1[16]; int i_coeff_sign[16]; int i_coeff = 0; int i_last = 0; int i_abslevel1 = 0; int i_abslevelgt1 = 0; int i; /* i_ctxBlockCat: 0-> DC 16x16 i_idx = 0 * 1-> AC 16x16 i_idx = luma4x4idx * 2-> Luma4x4 i_idx = luma4x4idx * 3-> DC Chroma i_idx = iCbCr * 4-> AC Chroma i_idx = 4 * iCbCr + chroma4x4idx */ //fprintf( stderr, "l[] = " ); for( i = 0; i < i_count; i++ ) { //fprintf( stderr, "%d ", l[i] ); if( l[i] != 0 ) { i_coeff_abs_m1[i_coeff] = abs( l[i] ) - 1; i_coeff_sign[i_coeff] = ( l[i] < 0 ? 1 : 0); i_coeff++; i_last = i; } } //fprintf( stderr, "\n" ); if( i_coeff == 0 ) { /* codec block flag */ T264_cabac_encode_decision( &t->cabac, 85 + T264_cabac_mb_cbf_ctxidxinc( t, i_ctxBlockCat, i_idx ), 0 ); return; } /* block coded */ T264_cabac_encode_decision( &t->cabac, 85 + T264_cabac_mb_cbf_ctxidxinc( t, i_ctxBlockCat, i_idx ), 1 ); for( i = 0; i < i_count - 1; i++ ) { int i_ctxIdxInc; i_ctxIdxInc = T264_MIN( i, i_count - 2 ); if( l[i] != 0 ) { T264_cabac_encode_decision( &t->cabac, 105 + significant_coeff_flag_offset[i_ctxBlockCat] + i_ctxIdxInc, 1 ); T264_cabac_encode_decision( &t->cabac, 166 + last_significant_coeff_flag_offset[i_ctxBlockCat] + i_ctxIdxInc, i == i_last ? 1 : 0 ); } else { T264_cabac_encode_decision( &t->cabac, 105 + significant_coeff_flag_offset[i_ctxBlockCat] + i_ctxIdxInc, 0 ); } if( i == i_last ) { break; } } for( i = i_coeff - 1; i >= 0; i-- ) { int i_prefix; int i_ctxIdxInc; /* write coeff_abs - 1 */ /* prefix */ i_prefix = T264_MIN( i_coeff_abs_m1[i], 14 ); i_ctxIdxInc = (i_abslevelgt1 != 0 ? 0 : T264_MIN( 4, i_abslevel1 + 1 )) + coeff_abs_level_m1_offset[i_ctxBlockCat]; if( i_prefix == 0 ) { T264_cabac_encode_decision( &t->cabac, 227 + i_ctxIdxInc, 0 ); } else { int j; T264_cabac_encode_decision( &t->cabac, 227 + i_ctxIdxInc, 1 ); i_ctxIdxInc = 5 + T264_MIN( 4, i_abslevelgt1 ) + coeff_abs_level_m1_offset[i_ctxBlockCat]; for( j = 0; j < i_prefix - 1; j++ ) { T264_cabac_encode_decision( &t->cabac, 227 + i_ctxIdxInc, 1 ); } if( i_prefix < 14 ) { T264_cabac_encode_decision( &t->cabac, 227 + i_ctxIdxInc, 0 ); } } /* suffix */ if( i_coeff_abs_m1[i] >= 14 ) { int k = 0; int i_suffix = i_coeff_abs_m1[i] - 14; while( i_suffix >= (1< cabac, 1 ); i_suffix -= 1 << k; k++; } T264_cabac_encode_bypass( &t->cabac, 0 ); while( k-- ) { T264_cabac_encode_bypass( &t->cabac, (i_suffix >> k)&0x01 ); } } /* write sign */ T264_cabac_encode_bypass( &t->cabac, i_coeff_sign[i] ); if( i_coeff_abs_m1[i] == 0 ) { i_abslevel1++; } else { i_abslevelgt1++; } } } static int8_t T264_mb_predict_intra4x4_mode(T264_t *t, int32_t idx) { int32_t x, y; int8_t nA, nB, pred_blk; x = luma_inverse_x[idx]; y = luma_inverse_y[idx]; nA = t->mb.i4x4_pred_mode_ref[IPM_LUMA + x + y * 8 - 1]; nB = t->mb.i4x4_pred_mode_ref[IPM_LUMA + x + y * 8 - 8]; pred_blk = T264_MIN(nA, nB); if( pred_blk < 0 ) return Intra_4x4_DC; return pred_blk; } void T264_macroblock_write_cabac( T264_t *t, bs_t *s ) { const int i_mb_type = t->mb.mb_mode; const int i_mb_pos_start = BitstreamPos( s ); int i_mb_pos_tex; int i; /* Write the MB type */ T264_cabac_mb_type( t ); /* PCM special block type UNTESTED */ /* no PCM here*/ if( IS_INTRA( i_mb_type ) ) { /* Prediction */ if( i_mb_type == I_4x4 ) { for( i = 0; i < 16; i++ ) { const int i_pred = T264_mb_predict_intra4x4_mode( t, i ); const int i_mode = t->mb.i4x4_pred_mode_ref[T264_scan8[i]]; T264_cabac_mb_intra4x4_pred_mode( t, i_pred, i_mode ); } } T264_cabac_mb_intra8x8_pred_mode( t ); } else if( i_mb_type == P_MODE ) { if( t->mb.mb_part == MB_16x16 ) { if( t->ps.num_ref_idx_l0_active_minus1 > 0 ) { T264_cabac_mb_ref( t, 0, 0 ); } T264_cabac_mb_mvd( t, 0, 0, 4, 4 ); } else if( t->mb.mb_part == MB_16x8 ) { if( t->ps.num_ref_idx_l0_active_minus1 > 0 ) { T264_cabac_mb_ref( t, 0, 0 ); T264_cabac_mb_ref( t, 0, 8 ); } T264_cabac_mb_mvd( t, 0, 0, 4, 2 ); T264_cabac_mb_mvd( t, 0, 8, 4, 2 ); } else if( t->mb.mb_part == MB_8x16 ) { if( t->ps.num_ref_idx_l0_active_minus1 > 0 ) { T264_cabac_mb_ref( t, 0, 0 ); T264_cabac_mb_ref( t, 0, 4 ); } T264_cabac_mb_mvd( t, 0, 0, 2, 4 ); T264_cabac_mb_mvd( t, 0, 4, 2, 4 ); } else /* 8x8 */ { /* sub mb type */ T264_cabac_mb_sub_p_partition( t, t->mb.submb_part[0] ); T264_cabac_mb_sub_p_partition( t, t->mb.submb_part[2] ); T264_cabac_mb_sub_p_partition( t, t->mb.submb_part[8] ); T264_cabac_mb_sub_p_partition( t, t->mb.submb_part[10] ); /* ref 0 */ if( t->ps.num_ref_idx_l0_active_minus1 > 0 ) { T264_cabac_mb_ref( t, 0, 0 ); T264_cabac_mb_ref( t, 0, 4 ); T264_cabac_mb_ref( t, 0, 8 ); T264_cabac_mb_ref( t, 0, 12 ); } for( i = 0; i < 4; i++ ) { switch( t->mb.submb_part[luma_index[i<<2]] ) { case MB_8x8: T264_cabac_mb_mvd( t, 0, 4*i, 2, 2 ); break; case MB_8x4: T264_cabac_mb_mvd( t, 0, 4*i+0, 2, 1 ); T264_cabac_mb_mvd( t, 0, 4*i+2, 2, 1 ); break; case MB_4x8: T264_cabac_mb_mvd( t, 0, 4*i+0, 1, 2 ); T264_cabac_mb_mvd( t, 0, 4*i+1, 1, 2 ); break; case MB_4x4: T264_cabac_mb_mvd( t, 0, 4*i+0, 1, 1 ); T264_cabac_mb_mvd( t, 0, 4*i+1, 1, 1 ); T264_cabac_mb_mvd( t, 0, 4*i+2, 1, 1 ); T264_cabac_mb_mvd( t, 0, 4*i+3, 1, 1 ); break; } } } } else if( i_mb_type == B_MODE ) { if((t->mb.mb_part==MB_16x16&&t->mb.is_copy!=1) || (t->mb.mb_part==MB_16x8) || (t->mb.mb_part==MB_8x16)) { /* to be changed here*/ /* All B mode */ int i_list; int b_list[2][2]; const int i_partition = t->mb.mb_part; int b_part_mode, part_mode0, part_mode1; static const int b_part_mode_map[3][3] = { { B_L0_L0, B_L0_L1, B_L0_BI }, { B_L1_L0, B_L1_L1, B_L1_BI }, { B_BI_L0, B_BI_L1, B_BI_BI } }; switch(t->mb.mb_part) { case MB_16x16: part_mode0 = t->mb.mb_part2[0] - B_L0_16x16; b_part_mode = b_part_mode_map[part_mode0][part_mode0]; break; case MB_16x8: part_mode0 = t->mb.mb_part2[0] - B_L0_16x8; part_mode1 = t->mb.mb_part2[1] - B_L0_16x8; b_part_mode = b_part_mode_map[part_mode0][part_mode1]; break; case MB_8x16: part_mode0 = t->mb.mb_part2[0] - B_L0_8x16; part_mode1 = t->mb.mb_part2[1] - B_L0_8x16; b_part_mode = b_part_mode_map[part_mode0][part_mode1]; break; } /* init ref list utilisations */ for( i = 0; i < 2; i++ ) { b_list[0][i] = T264_mb_type_list0_table[b_part_mode][i]; b_list[1][i] = T264_mb_type_list1_table[b_part_mode][i]; } for( i_list = 0; i_list < 2; i_list++ ) { const int i_ref_max = i_list == 0 ? t->ps.num_ref_idx_l0_active_minus1+1 : t->ps.num_ref_idx_l1_active_minus1+1; if( i_ref_max > 1 ) { if( t->mb.mb_part == MB_16x16 ) { if( b_list[i_list][0] ) T264_cabac_mb_ref( t, i_list, 0 ); } else if( t->mb.mb_part == MB_16x8 ) { if( b_list[i_list][0] ) T264_cabac_mb_ref( t, i_list, 0 ); if( b_list[i_list][1] ) T264_cabac_mb_ref( t, i_list, 8 ); } else if( t->mb.mb_part == MB_8x16 ) { if( b_list[i_list][0] ) T264_cabac_mb_ref( t, i_list, 0 ); if( b_list[i_list][1] ) T264_cabac_mb_ref( t, i_list, 4 ); } } } for( i_list = 0; i_list < 2; i_list++ ) { if( t->mb.mb_part == MB_16x16 ) { if( b_list[i_list][0] ) T264_cabac_mb_mvd( t, i_list, 0, 4, 4 ); } else if( t->mb.mb_part == MB_16x8 ) { if( b_list[i_list][0] ) T264_cabac_mb_mvd( t, i_list, 0, 4, 2 ); if( b_list[i_list][1] ) T264_cabac_mb_mvd( t, i_list, 8, 4, 2 ); } else if( t->mb.mb_part == MB_8x16 ) { if( b_list[i_list][0] ) T264_cabac_mb_mvd( t, i_list, 0, 2, 4 ); if( b_list[i_list][1] ) T264_cabac_mb_mvd( t, i_list, 4, 2, 4 ); } } } else if(t->mb.mb_part==MB_16x16 && t->mb.is_copy) { } else /* B8x8 */ { /* TODO */ int i_list; /* sub mb type */ T264_cabac_mb_sub_b_partition( t, t->mb.submb_part[0] ); T264_cabac_mb_sub_b_partition( t, t->mb.submb_part[2] ); T264_cabac_mb_sub_b_partition( t, t->mb.submb_part[8] ); T264_cabac_mb_sub_b_partition( t, t->mb.submb_part[10] ); /* ref */ for( i_list = 0; i_list < 2; i_list++ ) { if( ( i_list ? t->ps.num_ref_idx_l1_active_minus1 : t->ps.num_ref_idx_l0_active_minus1 ) == 0 ) continue; for( i = 0; i < 4; i++ ) { int sub_part = t->mb.submb_part[luma_index[i<<2]]-B_DIRECT_8x8; if( T264_mb_partition_listX_table[sub_part][i_list] == 1 ) { T264_cabac_mb_ref( t, i_list, 4*i ); } } } T264_cabac_mb8x8_mvd( t, 0 ); T264_cabac_mb8x8_mvd( t, 1 ); } } i_mb_pos_tex = BitstreamPos( s ); if( i_mb_type != I_16x16 ) { T264_cabac_mb_cbp_luma( t ); T264_cabac_mb_cbp_chroma( t ); } if( t->mb.cbp_y > 0 || t->mb.cbp_c > 0 || i_mb_type == I_16x16 ) { T264_cabac_mb_qp_delta( t ); /* write residual */ if( i_mb_type == I_16x16 ) { /* DC Luma */ block_residual_write_cabac( t, 0, 0, t->mb.dc4x4_z, 16 ); if( t->mb.cbp_y != 0 ) { /* AC Luma */ for( i = 0; i < 16; i++ ) { block_residual_write_cabac( t, 1, i, &(t->mb.dct_y_z[i][1]), 15 ); } } } else { if(t->frame_num == 1) t->frame_num = 1; for( i = 0; i < 16; i++ ) { if( t->mb.cbp_y & ( 1 << ( i / 4 ) ) ) { block_residual_write_cabac( t, 2, i, &(t->mb.dct_y_z[i][0]), 16 ); } } } if( t->mb.cbp_c&0x03 ) /* Chroma DC residual present */ { block_residual_write_cabac( t, 3, 0, &(t->mb.dc2x2_z[0][0]), 4 ); block_residual_write_cabac( t, 3, 1, &(t->mb.dc2x2_z[1][0]), 4 ); } if( t->mb.cbp_c&0x02 ) /* Chroma AC residual present */ { for( i = 0; i < 8; i++ ) { block_residual_write_cabac( t, 4, i, &(t->mb.dct_uv_z[i>>2][i&0x03][1]), 15); } } } /* if( IS_INTRA( i_mb_type ) ) t->stat.frame.i_itex_bits += bs_pos(s) - i_mb_pos_tex; else t->stat.frame.i_ptex_bits += bs_pos(s) - i_mb_pos_tex; */ }