📄 dec_cabac.c
字号:
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 + -