📄 dec_cabac.c
字号:
/*****************************************************************************
*
* T264 AVC CODEC
*
* Copyright(C) 2004-2005 joylife <joylife_video@yahoo.com.cn>
* 2004-2005 tricro <tricro@hotmail.com>
*
* 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 <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.
*****************************************************************************/
/*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 now only the baseline options is tested
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "T264.h"
#include "cabac_engine.h"
#include "inter.h"
#include "utility.h"
#include "inter_b.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_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 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_map_btype_mbpart[] =
{
MB_8x8, //B_DIRECT_8x8 = 100,
MB_8x8, //B_L0_8x8,
MB_8x8, //B_L1_8x8,
MB_8x8, //B_Bi_8x8,
MB_8x4, //B_L0_8x4,
MB_4x8, //B_L0_4x8,
MB_8x4, //B_L1_8x4,
MB_4x8, //B_L1_4x8,
MB_8x4, //B_Bi_8x4,
MB_4x8, //B_Bi_4x8,
MB_4x4, //B_L0_4x4,
MB_4x4, //B_L1_4x4,
MB_4x4 //B_Bi_4x4
};
static void T264_cabac_mb_type( T264_t *t )
{
int act_sym, mode_sym, sym, sym1, sym2;
T264_mb_context_t *mb_ctxs = &(t->rec->mb[0]);
int32_t 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++;
}
act_sym = T264_cabac_decode_decision(&t->cabac, 3+ctx);
if(act_sym == 0)
{
mb_mode = I_4x4;
}
else
{
mode_sym = T264_cabac_decode_terminal(&t->cabac);
if(mode_sym == 0) /*I_16x16*/
{
mb_mode = I_16x16;
t->mb.cbp_y = T264_cabac_decode_decision(&t->cabac, 3+3);
sym = T264_cabac_decode_decision(&t->cabac, 3+4);
if(sym == 0)
{
t->mb.cbp_c = 0;
}
else
{
sym = T264_cabac_decode_decision(&t->cabac, 3+5);
t->mb.cbp_c = (sym==0)?1:2;
}
sym1 = T264_cabac_decode_decision(&t->cabac, 3+6);
sym2 = T264_cabac_decode_decision(&t->cabac, 3+7);
t->mb.mode_i16x16 = (sym1<<1)|sym2;
}
else
{
//I_PCM
}
}
}
else if( t->slice_type == SLICE_P )
{
/* prefix: 14, suffix: 17 */
int ctx = 0;
act_sym = T264_cabac_decode_decision(&t->cabac, 14);
if(act_sym == 0)
{
//P_MODE
static int mb_part_map[] = {MB_16x16, MB_8x8, MB_8x16, MB_16x8};
mb_mode = P_MODE;
sym1 = T264_cabac_decode_decision(&t->cabac, 15);
ctx = (sym1==0)?16:17;
sym2 = T264_cabac_decode_decision(&t->cabac, ctx);
sym = (sym1<<1)|sym2;
t->mb.mb_part = mb_part_map[sym];
}
else
{
mode_sym = T264_cabac_decode_decision(&t->cabac, 17);
if(mode_sym == 0)
{
mb_mode = I_4x4;
}
else
{
sym = T264_cabac_decode_terminal(&t->cabac);
if(sym == 0)
{
//I_16x16
mb_mode = I_16x16;
t->mb.cbp_y = T264_cabac_decode_decision(&t->cabac, 17+1);
sym1 = T264_cabac_decode_decision(&t->cabac, 17+2);
if(sym1 == 0)
{
t->mb.cbp_c = 0;
}
else
{
sym2 = T264_cabac_decode_decision(&t->cabac, 17+2);
t->mb.cbp_c = (sym2==0)?1:2;
}
sym1 = T264_cabac_decode_decision(&t->cabac, 17+3);
sym2 = T264_cabac_decode_decision(&t->cabac, 17+3);
t->mb.mode_i16x16 = (sym1<<1)|sym2;
}
else
{
//I_PCM
}
}
}
}
else if( t->slice_type == SLICE_B )
{
int ctx = 0;
int idx;
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++;
}
sym = T264_cabac_decode_decision(&t->cabac, 27+ctx);
if(sym == 0)
{
t->mb.is_copy = 1;
t->mb.mb_part = MB_16x16;
mb_mode = B_MODE;
}
else
{
t->mb.is_copy = 0;
sym1 = T264_cabac_decode_decision(&t->cabac, 27+3);
if(sym1 == 0)
{
sym2 = T264_cabac_decode_decision(&t->cabac, 27+5);
mb_mode = B_MODE;
t->mb.mb_part = MB_16x16;
t->mb.mb_part2[0] = (sym2==0)?B_L0_16x16:B_L1_16x16;
}
else
{
sym2 = T264_cabac_decode_decision(&t->cabac, 27+4);
if(sym2 == 0)
{
static const int mb_bits_2_part0[] = {
MB_16x16, MB_16x8, MB_8x16, MB_16x8, MB_8x16,
MB_16x8, MB_8x16, MB_16x8
};
static const int mb_bits_2_part20[][2] = {
{B_Bi_16x16, B_Bi_16x16},
{B_L0_16x8, B_L0_16x8}, {B_L0_8x16, B_L0_8x16},
{B_L1_16x8, B_L1_16x8}, {B_L1_8x16, B_L1_8x16},
{B_L0_16x8, B_L1_16x8}, {B_L0_8x16, B_L1_8x16},
{B_L1_16x8, B_L0_16x8}
};
sym = T264_cabac_decode_decision(&t->cabac, 27+5);
idx = sym<<2;
sym = T264_cabac_decode_decision(&t->cabac, 27+5);
idx |= sym<<1;
sym = T264_cabac_decode_decision(&t->cabac, 27+5);
idx |= sym;
mb_mode = B_MODE;
t->mb.mb_part = mb_bits_2_part0[idx];
t->mb.mb_part2[0] = mb_bits_2_part20[idx][0];
t->mb.mb_part2[1] = mb_bits_2_part20[idx][1];
}
else
{
sym = T264_cabac_decode_decision(&t->cabac, 27+5);
idx = sym<<2;
sym = T264_cabac_decode_decision(&t->cabac, 27+5);
idx |= sym<<1;
sym = T264_cabac_decode_decision(&t->cabac, 27+5);
idx |= sym;
if(idx == 0x07)
{
mb_mode = B_MODE;
t->mb.mb_part = MB_8x8;
}
else if(idx == 0x05)
{
sym = T264_cabac_decode_decision(&t->cabac, 32);
if(sym == 0)
{
//I_4x4
mb_mode = I_4x4;
}
else
{
sym = T264_cabac_decode_terminal(&t->cabac);
if(sym == 0)
{
//I_16x16
mb_mode = I_16x16;
t->mb.cbp_y = T264_cabac_decode_decision(&t->cabac, 32+1);
sym = T264_cabac_decode_decision(&t->cabac, 32+2);
if(sym == 0)
{
t->mb.cbp_c = 0;
}
else
{
sym = T264_cabac_decode_decision(&t->cabac, 32+2);
t->mb.cbp_c = (sym==0)?1:2;
}
sym1 = T264_cabac_decode_decision(&t->cabac, 32+3);
sym2 = T264_cabac_decode_decision(&t->cabac, 32+3);
t->mb.mode_i16x16 = (sym1<<1)|sym2;
}
else
{
//I_PCM
}
}
}
else if(idx == 0x06)
{
mb_mode = B_MODE;
t->mb.mb_part = MB_8x16;
t->mb.mb_part2[0] = B_L1_8x16;
t->mb.mb_part2[1] = B_L0_8x16;
}
else
{
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 */
};
static const int mb_bits_2_part1[] = {
MB_16x8, MB_8x16, MB_16x8, MB_8x16,
MB_16x8, MB_8x16, MB_16x8, MB_8x16,
MB_16x8, MB_8x16, MB_16x8, MB_8x16,
MB_16x8, MB_8x16, MB_16x8, MB_8x16
};
static const int mb_bits_2_part21[][2] = {
{B_L0_16x8, B_Bi_16x8}, {B_L0_8x16, B_Bi_8x16},
{B_L1_16x8, B_Bi_16x8}, {B_L1_8x16, B_Bi_8x16},
{B_Bi_16x8, B_L0_16x8}, {B_Bi_8x16, B_L0_8x16},
{B_Bi_16x8, B_L1_16x8}, {B_Bi_8x16, B_L1_8x16},
{B_Bi_16x8, B_Bi_16x8}, {B_Bi_8x16, B_Bi_8x16},
{B_L0_16x8, B_L0_16x8}, {B_L0_8x16, B_L0_8x16},
{B_L0_16x8, B_L0_16x8}, {B_L0_8x16, B_L0_8x16},
{B_L0_16x8, B_L0_16x8}, {B_L0_8x16, B_L0_8x16}
};
idx <<= 1;
sym = T264_cabac_decode_decision(&t->cabac, 27+5);
idx |= sym;
mb_mode = B_MODE;
t->mb.mb_part = mb_bits_2_part1[idx];
t->mb.mb_part2[0] = mb_bits_2_part21[idx][0];
t->mb.mb_part2[1] = mb_bits_2_part21[idx][1];
}
}
}
}
}
else
{
//dummy here
mb_mode = t->mb.mb_mode;
}
t->mb.mb_mode = mb_mode;
}
static int T264_cabac_mb_intra4x4_pred_mode( T264_t *t, int i_pred)
{
int i_mode, sym;
sym = T264_cabac_decode_decision(&t->cabac, 68);
if(sym == 1)
{
i_mode = i_pred;
}
else
{
i_mode = T264_cabac_decode_decision(&t->cabac, 69);
sym = T264_cabac_decode_decision(&t->cabac, 69);
i_mode |= (sym<<1);
sym = T264_cabac_decode_decision(&t->cabac, 69);
i_mode |= (sym<<2);
if(i_mode >= i_pred)
i_mode ++;
}
return i_mode;
}
static void T264_cabac_mb_intra8x8_pred_mode( T264_t *t )
{
int i_mode, sym;
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++;
}
sym = T264_cabac_decode_decision(&t->cabac, 64+ctx);
if(sym == 0)
{
i_mode = Intra_8x8_DC;
}
else
{
sym = T264_cabac_decode_decision(&t->cabac, 64+3);
if(sym == 0)
{
i_mode = 1;
}
else
{
sym = T264_cabac_decode_decision(&t->cabac, 64+3);
i_mode = (sym==0)?2:3;
}
}
t->mb.mb_mode_uv = i_mode;
}
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, sym, cbp_y, cbp_ya, cbp_yb;
cbp_y = 0;
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;
cbp_ya = cbp_y;
}
else if( t->mb.mb_x > 0 )
{
i_mba_xy = t->mb.mb_xy - 1;
cbp_ya = mb_ctxs[i_mba_xy].cbp_y;
}
if( y > 0 )
{
i_mbb_xy = t->mb.mb_xy;
cbp_yb = cbp_y;
}
else if( t->mb.mb_y > 0 )
{
i_mbb_xy = t->mb.mb_xy - t->mb_stride;
cbp_yb = mb_ctxs[i_mbb_xy].cbp_y;
}
/* 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( ((cbp_ya >> i8x8a)&0x01) == 0 )
{
ctx++;
}
}
if( i_mbb_xy >= 0 )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -