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

📄 cabac.c

📁 H.264编码器
💻 C
📖 第 1 页 / 共 3 页
字号:
    FIX8(3.7068), FIX8(3.7820), FIX8(3.8572), FIX8(3.9324),
    FIX8(4.0076), FIX8(4.0828), FIX8(4.1580), FIX8(4.2332),
    FIX8(4.3083), FIX8(4.3836), FIX8(4.4588), FIX8(4.5339),
    FIX8(4.6091), FIX8(4.6843), FIX8(4.7595), FIX8(4.8347),
    FIX8(4.9099), FIX8(4.9851), FIX8(5.0602), FIX8(5.1354),
    FIX8(5.2106), FIX8(5.2859), FIX8(5.3610), FIX8(5.4362),
    FIX8(5.5114), FIX8(5.5866), FIX8(5.6618), FIX8(5.7370)
};

#undef FIX8


/*****************************************************************************
 *
 *****************************************************************************/
void x264_cabac_context_init( x264_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_TYPE_I )
    {
        cabac_context_init = &x264_cabac_context_init_I;
    }
    else
    {
        cabac_context_init = &x264_cabac_context_init_PB[i_model];
    }

    for( i = 0; i < 399; i++ )
    {
        int i_pre_state;

        i_pre_state = x264_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 x264_cabac_decode_init( x264_cabac_t *cb, bs_t *s )
{
    cb->i_range = 0x01fe;
    cb->i_low   = bs_read( s, 9 );
    cb->s       = s;
}

static/* inline */ void x264_cabac_decode_renorm( x264_cabac_t *cb )
{
    while( cb->i_range < 0x0100 )
    {
        cb->i_range <<= 1;
        cb->i_low   = ( cb->i_low << 1 )|bs_read( cb->s, 1 );
    }
}

int  x264_cabac_decode_decision( x264_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 = x264_cabac_range_lps[i_state][(cb->i_range>>6)&0x03];

    int val;

    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 = x264_transition_lps[i_state];
    }
    else
    {
        val = i_mps;

        cb->ctxstate[i_ctx].i_state = x264_transition_mps[i_state];
    }

    x264_cabac_decode_renorm( cb );

    return val;
}
int  x264_cabac_decode_bypass( x264_cabac_t *cb )
{
    cb->i_low = (cb->i_low << 1)|bs_read( cb->s, 1 );

    if( cb->i_low >= cb->i_range )
    {
        cb->i_low -= cb->i_range;
        return 1;
    }
    return 0;
}
int  x264_cabac_decode_terminal( x264_cabac_t *cb )
{
    if( cb->i_low >= cb->i_range - 2 )
    {
        return 1;
    }

    cb->i_range -= 2;
    x264_cabac_decode_renorm( cb );
    return 0;
}


/*****************************************************************************
 *
 *****************************************************************************/
void x264_cabac_model_init( x264_cabac_t *cb )
{
    int i;

    for( i = 0; i < 3; i++ )
    {
        cb->slice[i].i_model = 0;
        cb->slice[i].i_cost  = -1;
    }
}

int  x264_cabac_model_get ( x264_cabac_t *cb, int i_slice_type )
{
    return cb->slice[i_slice_type].i_model;
}

void x264_cabac_model_update( x264_cabac_t *cb, int i_slice_type, int i_qp )
{
    int i;

    if( i_slice_type == SLICE_TYPE_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 = X264_MIN( (1<<8), (cb->ctxstate[i_ctx].i_count<<8) / 32 );
            i_model_state = x264_clip3( ((x264_cabac_context_init_PB[i][i_ctx][0] * i_qp)>>4) +
                                          x264_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 * (( x264_cabac_probability[      i_ctx_state] * x264_cabac_entropy[      i_model_state] +
                                     x264_cabac_probability[127 - i_ctx_state] * x264_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 x264_cabac_encode_init( x264_cabac_t *cb, bs_t *s )
{
    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 x264_cabac_putbit( x264_cabac_t *cb, int b )
{
    if( cb->b_first_bit )
    {
        cb->b_first_bit = 0;
    }
    else
    {
        bs_write1( cb->s, b );
    }

    while( cb->i_bits_outstanding > 0 )
    {
        bs_write1( cb->s, 1 - b );
        cb->i_bits_outstanding--;
    }
}

static/* inline */ void x264_cabac_encode_renorm( x264_cabac_t *cb )
{
    /* RenormE */
    while( cb->i_range < 0x0100 )
    {
        if( cb->i_low < 0x100 )
        {
            x264_cabac_putbit( cb, 0 );
        }
        else
        {
            if( cb->i_low >= 0x200 )
            {
                cb->i_low -= 0x200;
                x264_cabac_putbit( cb, 1 );
            }
            else
            {
                cb->i_low -= 0x100;
                cb->i_bits_outstanding++;
            }
        }

        cb->i_range <<= 1;
        cb->i_low   <<= 1;
    }
}

void x264_cabac_encode_decision( x264_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 = x264_cabac_range_lps[i_state][(cb->i_range>>6)&0x03];

#ifdef TRACE
    if( binCount >= 0 )
    {
        fprintf( stderr, "%d  ctx=%d b=%d\n", binCount, i_ctx, b );
    }
    fprintf( stderr, "%d  0x%04x  %d  %d\n", binCount++, cb->i_range, i_state, i_mps );
#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 = x264_transition_lps[i_state];
    }
    else
    {
        cb->ctxstate[i_ctx].i_state = x264_transition_mps[i_state];
    }
    cb->ctxstate[i_ctx].i_count++;

    x264_cabac_encode_renorm( cb );

    cb->i_sym_cnt++;
}

void x264_cabac_encode_bypass( x264_cabac_t *cb, int b )
{
#ifdef TRACE
    fprintf( stderr, "%d  0x%04x\n", binCount++, cb->i_range );
#endif

    cb->i_low <<= 1;
    if( b )
    {
        cb->i_low += cb->i_range;
    }

    if( cb->i_low >= 0x400 )
    {
        x264_cabac_putbit( cb, 1 );
        cb->i_low -= 0x400;
    }
    else
    {
        if( cb->i_low < 0x200 )
        {
            x264_cabac_putbit( cb, 0 );
        }
        else
        {
            cb->i_low -= 0x200;
            cb->i_bits_outstanding++;
        }
    }
    cb->i_sym_cnt++;
}

void x264_cabac_encode_terminal( x264_cabac_t *cb, int b )
{
#ifdef TRACE
    fprintf( stderr, "%d  0x%04x\n", binCount++, cb->i_range );
#endif

    cb->i_range -= 2;
    if( b )
    {
        cb->i_low += cb->i_range;
        cb->i_range = 2;
    }
    x264_cabac_encode_renorm( cb );

    cb->i_sym_cnt++;
}

void x264_cabac_encode_flush( x264_cabac_t *cb )
{
    x264_cabac_putbit( cb, (cb->i_low >> 9)&0x01 );
    bs_write1( cb->s, (cb->i_low >> 8)&0x01 );

    /* check that */
    bs_write1( cb->s, 0x01 );
    bs_align_0( cb->s );
}

⌨️ 快捷键说明

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