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

📄 dec_cabac.c

📁 T264是中国的视频编码自由组织合力开发的264编解码程序
💻 C
📖 第 1 页 / 共 3 页
字号:
			const int i8x8b = block_idx_xy[x][(y-1)&0x03]/4;
			if( ((cbp_yb >> i8x8b)&0x01) == 0 )
			{
				ctx += 2;
			}
		}
		sym = T264_cabac_decode_decision(&t->cabac, 73+ctx);
		cbp_y |= (sym<<i8x8);
	}
	t->mb.cbp_y = cbp_y;
}

static void T264_cabac_mb_cbp_chroma( T264_t *t )
{
	int cbp_a = -1;
	int cbp_b = -1;
	int ctx, sym;
	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;
	sym = T264_cabac_decode_decision(&t->cabac, 77+ctx);
	if(sym == 0)
	{
		t->mb.cbp_c = 0;
	}
	else
	{
		ctx = 4;
		if( cbp_a == 2 ) ctx++;
		if( cbp_b == 2 ) ctx += 2;
		sym = T264_cabac_decode_decision(&t->cabac, 77+ctx);
		t->mb.cbp_c = (sym==0)?1:2;
	}
}

/* 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;

	val = 0;
	while(T264_cabac_decode_decision(&t->cabac, 60+ctx) != 0)
	{
		val ++;
		if(ctx < 2)
			ctx = 2;
		else
			ctx = 3;
	}
	t->mb.mb_qp_delta = ((val&0x01)==0)?(-(val>>1)):((val+1)>>1);
}

int T264_cabac_dec_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 )
		b_skip = T264_cabac_decode_decision(&t->cabac, 11+ctx);
	else /* SLICE_TYPE_B */
		b_skip = T264_cabac_decode_decision(&t->cabac, 24+ctx);
	return b_skip;
}

static __inline  int T264_cabac_mb_sub_p_partition( T264_t *t)
{
	int i_sub, sym;
	sym = T264_cabac_decode_decision(&t->cabac, 21);
	if(sym == 1)
	{
		i_sub = MB_8x8;
	}
	else
	{
		sym = T264_cabac_decode_decision(&t->cabac, 22);
		if(sym == 0)
		{
			i_sub = MB_8x4;
		}
		else
		{
			sym = T264_cabac_decode_decision(&t->cabac, 23);
			i_sub = (sym==0)?MB_4x4:MB_4x8;
		}
	}
	return i_sub;
}

static __inline  int T264_cabac_mb_sub_b_partition( T264_t *t)
{
	int i_sub, sym, sym1;
	sym = T264_cabac_decode_decision(&t->cabac, 36);
	if(sym == 0)
	{
		i_sub = B_DIRECT_8x8;
	}
	else
	{
		sym = T264_cabac_decode_decision(&t->cabac, 37);
		if(sym == 0)
		{
			sym1 = T264_cabac_decode_decision(&t->cabac, 39);
			i_sub = (sym1==0)?B_L0_8x8:B_L1_8x8;
		}
		else
		{
			int idx;
			sym = T264_cabac_decode_decision(&t->cabac, 38);
			if(sym == 0)
			{
				static const int idx_2_sub0[] = {B_Bi_8x8, B_L0_8x4, B_L0_4x8, B_L1_8x4};
				sym1 = T264_cabac_decode_decision(&t->cabac, 39);
				idx = sym1<<1;
				idx |= T264_cabac_decode_decision(&t->cabac, 39);
				i_sub = idx_2_sub0[idx];
			}
			else
			{
				sym = T264_cabac_decode_decision(&t->cabac, 39);
				if(sym == 0)
				{
					static const int idx_2_sub1[] = {B_L1_4x8, B_Bi_8x4, B_Bi_4x8, B_L0_4x4};
					sym1 = T264_cabac_decode_decision(&t->cabac, 39);
					idx = sym1<<1;
					idx |= T264_cabac_decode_decision(&t->cabac, 39);
					i_sub = idx_2_sub1[idx];
				}
				else
				{
					sym1 = T264_cabac_decode_decision(&t->cabac, 39);
					i_sub = (sym1==0)?B_L1_4x4:B_Bi_4x4;
				}
			}
		}
	}
	return i_sub;
}


static __inline  void T264_cabac_mb_ref( T264_t *t, int i_list, int idx, int width, int height, int i_ref_max )
{
	int i8    = T264_scan8[idx];
	
	int i_ref, i, j;
	int luma_idx = luma_index[idx];
	if( i_ref_max <= 1 )
	{
		i_ref = 0;
	}
	else
	{
		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 a_direct, b_direct;
		int ctx  = 0;
		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;
		i_ref = 0;
		while(T264_cabac_decode_decision(&t->cabac, 54+ctx) != 0)
		{
			i_ref ++;
			if(ctx < 4)
				ctx = 4;
			else
				ctx = 5;
		}
	}
	/* save ref value */
	for(j=0; j<height; j++)
	{
		for(i=0; i<width; i++)
		{
			t->mb.vec_ref[i8+i].vec[i_list].refno = i_ref;
			t->mb.vec[i_list][luma_idx+i].refno = i_ref;
		}
		i8 += 8;
		luma_idx += 4;
	}
}


static __inline  int  T264_cabac_mb_mvd_cpn( T264_t *t, int i_list, int i8, int l)
{
	int i_abs, i_prefix, i_suffix;
	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 ctxbase = (l == 0 ? 40 : 47);
	
	int ctx;

	if( amvd < 3 )
		ctx = 0;
	else if( amvd > 32 )
		ctx = 2;
	else
		ctx = 1;

	i_prefix = 0;
	while(i_prefix<9 && T264_cabac_decode_decision(&t->cabac, ctxbase+ctx)!=0)
	{
		i_prefix ++;
		if(ctx < 3)
			ctx = 3;
		else if(ctx < 6)
			ctx ++;
	}
	if(i_prefix >= 9)
	{
		int k = 3;
		i_suffix = 0;
		while(T264_cabac_decode_bypass(&t->cabac) != 0)
		{
			i_suffix += 1<<k;
			k++;
		}
		while(k--)
		{
			i_suffix += T264_cabac_decode_bypass(&t->cabac)<<k;
		}
		i_abs = 9 + i_suffix; 
	}
	else
		i_abs = i_prefix;
	
	/* sign */
	if(i_abs != 0)
	{
		if(T264_cabac_decode_bypass(&t->cabac) != 0)
			i_abs = -i_abs;
	}
	return i_abs;
}

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, mvx, mvy;
	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 );
	/* decode */
	mdx = T264_cabac_mb_mvd_cpn( t, i_list, i8, 0);
	mdy = T264_cabac_mb_mvd_cpn( t, i_list, i8, 1);
	/* save mvd value */
	mvx = mdx + mvp.x;
	mvy = mdy + mvp.y;
	for(j=0; j<height; j++)
	{
		for(i=0; i<width; i++)
		{
			t->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;
			t->mb.vec_ref[i8+i].vec[i_list].x = mvx;
			t->mb.vec_ref[i8+i].vec[i_list].y = mvy;
			t->mb.vec[i_list][luma_idx+i].x = mvx;
			t->mb.vec[i_list][luma_idx+i].y = mvy;			
		}
		i8 += 8;
		luma_idx += 4;
	}
}
static __inline void T264_cabac_mb8x8_mvd( T264_t *t, int i_list )
{
	int i;
	int sub_part, luma_idx;
	for( i = 0; i < 4; i++ )
	{
		luma_idx = luma_index[i<<2];
		sub_part = t->mb.submb_part[luma_idx];
		if( T264_mb_partition_listX_table[sub_part-B_DIRECT_8x8][i_list] == 0 )
		{
			continue;
		}

		switch( sub_part )
		{
		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];
		int cbp_ya, cbp_yb;
		if( x > 0 )
		{
			i_mba_xy = t->mb.mb_xy;
			cbp_ya = t->mb.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 = t->mb.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 skip/pcm */
		if( i_mba_xy >= 0 )
		{
			const int i8x8a = block_idx_xy[(x-1)&0x03][y]/4;
			if( (cbp_ya&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( (cbp_yb&0x0f)>> i8x8b )
			{
				i_nzb = t->mb.nnz_ref[i8 - 8];
			}
		}
	}
	else if( i_cat == 3 )
	{
		/* no need to test skip/pcm */
		//only test other MB's cbp, so we do not care about it
		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 cbp_ca, cbp_cb;
		int idxc = i_idx% 4;

		if( idxc == 1 || idxc == 3 )
		{
			cbp_ca = t->mb.cbp_c;
			i_mba_xy = t->mb.mb_xy;
		}
		else if( t->mb.mb_x > 0 )
		{
			i_mba_xy = t->mb.mb_xy - 1;
			cbp_ca = mb_ctxs[i_mba_xy].cbp_c;
		}

		if( idxc == 2 || idxc == 3 )
		{
			i_mbb_xy = t->mb.mb_xy;
			cbp_cb = t->mb.cbp_c;
		}
		else if( t->mb.mb_y > 0 )
		{
			i_mbb_xy = t->mb.mb_xy - t->mb_stride;
			cbp_cb = mb_ctxs[i_mbb_xy].cbp_c;
		}
		/* no need to test skip/pcm */
		if( i_mba_xy >= 0 && (cbp_ca&0x03) == 0x02 )
		{
			i_nza = t->mb.nnz_ref[T264_scan8[16+i_idx] - 1];
		}
		if( i_mbb_xy >= 0 && (cbp_cb&0x03) == 0x02 )
		{
			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_read_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_sig_map[16];
	int i_coeff = 0;
	int i_last  = 0;

	int i_abslevel1 = 0;
	int i_abslevelgt1 = 0;

	int i, i1, sym, i_abs, x, y;

	/* 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
	*/

	memset(l, 0, sizeof(int16_t)*i_count);
	sym = T264_cabac_decode_decision(&t->cabac, 85 + T264_cabac_mb_cbf_ctxidxinc( t, i_ctxBlockCat, i_idx ));
	if(sym == 0)
	{
		//the block is not coded
		return;
	}
	for(i=0; i<i_count-1; i++)
	{
		int i_ctxIdxInc;
		i_ctxIdxInc = T264_MIN(i, i_count-2);
		sym = T264_cabac_decode_decision(&t->cabac, 105+significant_coeff_flag_offset[i_ctxBlockCat] + i_ctxIdxInc);
		if(sym != 0)
		{
			i_coeff_sig_map[i] = 1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -