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

📄 cabac_engine.c

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