📄 cabac_engine.c
字号:
/*****************************************************************************
*
*****************************************************************************/
void T264_cabac_context_init( T264_cabac_t *cb, int i_slice_type, int i_qp, int i_model )
{
const int (*cabac_context_init)[399][2];
int i;
if( i_slice_type == SLICE_I )
{
cabac_context_init = &T264_cabac_context_init_I;
}
else
{
cabac_context_init = &T264_cabac_context_init_PB[i_model];
}
for( i = 0; i < 399; i++ )
{
int i_pre_state;
i_pre_state = T264_clip3( (((*cabac_context_init)[i][0] * i_qp) >> 4) + (*cabac_context_init)[i][1], 1, 126 );
if( i_pre_state <= 63 )
{
cb->ctxstate[i].i_state = 63 - i_pre_state;
cb->ctxstate[i].i_mps = 0;
}
else
{
cb->ctxstate[i].i_state = i_pre_state - 64;
cb->ctxstate[i].i_mps = 1;
}
cb->ctxstate[i].i_count = 0;
}
}
/*****************************************************************************
*
*****************************************************************************/
void T264_cabac_decode_init( T264_cabac_t *cb, bs_t *s )
{
#ifdef TRACE
if(fpCABACDec == NULL)
{
fpCABACDec = fopen("cabac_dec.dat", "w");
}
#endif
cb->i_range = 0x01fe;
cb->i_low = BitstreamGetBits( s, 9 );
cb->s = s;
}
static __inline void T264_cabac_decode_renorm( T264_cabac_t *cb )
{
while( cb->i_range < 0x0100 )
{
cb->i_range <<= 1;
cb->i_low = ( cb->i_low << 1 )| BitstreamGetBits( cb->s, 1 );
}
}
int T264_cabac_decode_decision( T264_cabac_t *cb, int i_ctx )
{
int i_state = cb->ctxstate[i_ctx].i_state;
int i_mps = cb->ctxstate[i_ctx].i_mps;
int i_range_lps = T264_cabac_range_lps[i_state][(cb->i_range>>6)&0x03];
int val;
#ifdef TRACE
if(binCount == 64518)
binCount = binCount;
#endif
cb->i_range -= i_range_lps;
if( cb->i_low >= cb->i_range )
{
val = 1 - i_mps;
cb->i_low -= cb->i_range;
cb->i_range= i_range_lps;
if( i_state == 0 )
{
cb->ctxstate[i_ctx].i_mps = 1 - i_mps;
}
cb->ctxstate[i_ctx].i_state = T264_transition_lps[i_state];
}
else
{
val = i_mps;
cb->ctxstate[i_ctx].i_state = T264_transition_mps[i_state];
}
T264_cabac_decode_renorm( cb );
#ifdef TRACE
if(fpCABACDec != NULL && slice_type_cabac == SLICE_B)// && frame_cabac==5)
{
fprintf(fpCABACDec, "%5d, 0x%04x %1d %3d %2d %1d (%2d %3d)\n",
binCount++, cb->i_range, val, i_ctx, cb->ctxstate[i_ctx].i_state, cb->ctxstate[i_ctx].i_mps, 0, mb_cabac);
}
fflush(fpCABACDec);
#endif
return val;
}
int T264_cabac_decode_bypass( T264_cabac_t *cb )
{
int val;
cb->i_low = (cb->i_low << 1)|BitstreamGetBits( cb->s, 1 );
if( cb->i_low >= cb->i_range )
{
cb->i_low -= cb->i_range;
val = 1;
}
else
val = 0;
#ifdef TRACE
if(fpCABACDec != NULL && slice_type_cabac==SLICE_B)// && frame_cabac==5)
{
fprintf(fpCABACDec, "%5d, 0x%04x %1d (%2d %3d)\n", binCount++, cb->i_range, val, 0, mb_cabac);
}
fflush(fpCABACDec);
#endif
return val;
}
int T264_cabac_decode_terminal( T264_cabac_t *cb )
{
if( cb->i_low >= cb->i_range - 2 )
{
return 1;
}
cb->i_range -= 2;
T264_cabac_decode_renorm( cb );
return 0;
}
/*****************************************************************************
*
*****************************************************************************/
void T264_cabac_model_init( T264_cabac_t *cb )
{
int i;
for( i = 0; i < 3; i++ )
{
cb->slice[i].i_model = 0;
cb->slice[i].i_cost = -1;
}
}
int T264_cabac_model_get ( T264_cabac_t *cb, int i_slice_type )
{
return cb->slice[i_slice_type].i_model;
}
void T264_cabac_model_update( T264_cabac_t *cb, int i_slice_type, int i_qp )
{
int i;
if( i_slice_type == SLICE_I )
{
return;
}
cb->slice[i_slice_type].i_cost = -1;
for( i = 0; i < 3; i++ )
{
int i_ctx;
int i_cost;
i_cost = 0; /* fix8 */
for( i_ctx = 0; i_ctx < 399; i_ctx++ )
{
int i_weight;
int i_model_state;
int i_ctx_state;
i_weight = T264_MIN( (1<<8), (cb->ctxstate[i_ctx].i_count<<8) / 32 );
i_model_state = T264_clip3( ((T264_cabac_context_init_PB[i][i_ctx][0] * i_qp)>>4) +
T264_cabac_context_init_PB[i][i_ctx][1], 0, 127 );
i_ctx_state = cb->ctxstate[i_ctx].i_mps ? 64 + cb->ctxstate[i_ctx].i_state : 63 - cb->ctxstate[i_ctx].i_state;
i_cost += (i_weight * (( T264_cabac_probability[ i_ctx_state] * T264_cabac_entropy[ i_model_state] +
T264_cabac_probability[127 - i_ctx_state] * T264_cabac_entropy[127 - i_model_state] ) >> 8))>>8;
}
if( cb->slice[i_slice_type].i_cost == -1 || cb->slice[i_slice_type].i_cost > i_cost )
{
cb->slice[i_slice_type].i_model= i;
cb->slice[i_slice_type].i_cost = i_cost;
}
}
}
void T264_cabac_encode_init( T264_cabac_t *cb, bs_t *s )
{
#ifdef TRACE
if(fpCABAC == NULL)
{
fpCABAC = fopen("cabac_enc.dat", "w");
}
#endif
cb->i_low = 0;
cb->i_range = 0x01FE;
cb->b_first_bit= 1;
cb->i_bits_outstanding = 0;
cb->i_sym_cnt = 0;
cb->s = s;
}
static __inline void T264_cabac_putbit( T264_cabac_t *cb, int b )
{
if( cb->b_first_bit )
{
cb->b_first_bit = 0;
}
else
{
BitstreamPutBit( cb->s, b );
}
while( cb->i_bits_outstanding > 0 )
{
BitstreamPutBit( cb->s, 1 - b );
cb->i_bits_outstanding--;
}
}
static __inline void T264_cabac_encode_renorm( T264_cabac_t *cb )
{
/* RenormE */
while( cb->i_range < 0x0100 )
{
if( cb->i_low < 0x100 )
{
T264_cabac_putbit( cb, 0 );
}
else
{
if( cb->i_low >= 0x200 )
{
cb->i_low -= 0x200;
T264_cabac_putbit( cb, 1 );
}
else
{
cb->i_low -= 0x100;
cb->i_bits_outstanding++;
}
}
cb->i_range <<= 1;
cb->i_low <<= 1;
}
}
void T264_cabac_encode_decision( T264_cabac_t *cb, int i_ctx, int b )
{
int i_state = cb->ctxstate[i_ctx].i_state;
int i_mps = cb->ctxstate[i_ctx].i_mps;
int i_range_lps = T264_cabac_range_lps[i_state][(cb->i_range>>6)&0x03];
#ifdef TRACE
if(binCount == 48227)
binCount = binCount;
#endif
cb->i_range -= i_range_lps;
if( b != i_mps )
{
cb->i_low += cb->i_range;
cb->i_range = i_range_lps;
if( i_state == 0 )
{
cb->ctxstate[i_ctx].i_mps = 1 - i_mps;
}
cb->ctxstate[i_ctx].i_state = T264_transition_lps[i_state];
}
else
{
cb->ctxstate[i_ctx].i_state = T264_transition_mps[i_state];
}
cb->ctxstate[i_ctx].i_count++;
T264_cabac_encode_renorm( cb );
cb->i_sym_cnt++;
#ifdef TRACE
if(fpCABAC != NULL && slice_type_cabac==SLICE_B)
{
fprintf(fpCABAC, "%5d, 0x%04x %1d %3d %2d %1d (%2d %3d)\n",
binCount++, cb->i_range, b, i_ctx, cb->ctxstate[i_ctx].i_state, cb->ctxstate[i_ctx].i_mps, 0, mb_cabac);
}
/*if(fpCABAC != NULL && slice_type_cabac==SLICE_B)
{
fprintf(fpCABAC, "%5d, 0x%04x %1d %2d %1d (%2d %3d)\n",
binCount++, cb->i_range, b, cb->ctxstate[i_ctx].i_state, cb->ctxstate[i_ctx].i_mps, 0, mb_cabac);
}
*/
#endif
}
void T264_cabac_encode_bypass( T264_cabac_t *cb, int b )
{
cb->i_low <<= 1;
if( b )
{
cb->i_low += cb->i_range;
}
if( cb->i_low >= 0x400 )
{
T264_cabac_putbit( cb, 1 );
cb->i_low -= 0x400;
}
else
{
if( cb->i_low < 0x200 )
{
T264_cabac_putbit( cb, 0 );
}
else
{
cb->i_low -= 0x200;
cb->i_bits_outstanding++;
}
}
cb->i_sym_cnt++;
#ifdef TRACE
if(fpCABAC != NULL && slice_type_cabac==SLICE_B)
{
fprintf(fpCABAC, "%5d, 0x%04x %1d (%2d %3d)\n", binCount++, cb->i_range, b, 0, mb_cabac);
}
#endif
}
void T264_cabac_encode_terminal( T264_cabac_t *cb, int b )
{
cb->i_range -= 2;
if( b )
{
cb->i_low += cb->i_range;
cb->i_range = 2;
}
T264_cabac_encode_renorm( cb );
cb->i_sym_cnt++;
}
void T264_cabac_encode_flush( T264_cabac_t *cb )
{
T264_cabac_putbit( cb, (cb->i_low >> 9)&0x01 );
BitstreamPutBit( cb->s, (cb->i_low >> 8)&0x01 );
/* check that */
BitstreamPutBit( cb->s, 0x01 );
BitstreamPadZero( cb->s );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -