⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dec_cabac.c

📁 T264是中国的视频编码自由组织合力开发的264编解码程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************
*
*  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 + -