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

📄 macroblock.c

📁 H.264编码器
💻 C
📖 第 1 页 / 共 5 页
字号:
        int k = 3;
        int i_suffix = i_abs - 9;

        while( i_suffix >= (1<<k) )
        {
            x264_cabac_encode_bypass( &h->cabac, 1 );
            i_suffix -= 1 << k;
            k++;
        }
        x264_cabac_encode_bypass( &h->cabac, 0 );
        while( k-- )
        {
            x264_cabac_encode_bypass( &h->cabac, (i_suffix >> k)&0x01 );
        }
    }

    /* sign */
    if( mvd > 0 )
    {
        x264_cabac_encode_bypass( &h->cabac, 0 );
    }
    else if( mvd < 0 )
    {
        x264_cabac_encode_bypass( &h->cabac, 1 );
    }
}

static void  x264_cabac_mb_mv( x264_t *h, x264_macroblock_t *mb, int i_list, int i_part, int i_sub )
{
    x264_macroblock_t *mbn;

    int mvd[2];
    int x, y, xn, yn;
    int i_ctxIdxInc;

    int i_absmv0 = 0;
    int i_absmv1 = 0;

    /* get and update mvd */
    x264_mb_partition_mvd( mb, i_list, i_part, i_sub, mvd );

    /* get context */
    x264_mb_partition_getxy( mb, i_part, i_sub, &x, &y );

    /* FIXME not complete for B frame (B_DIRECT and B_DIRECT 8x8 sub */
    /* Left  pixel (-1,0)*/
    xn = x - 1;
    mbn = mb;
    if( xn < 0 )
    {
        xn += 4;
        mbn = mb->context->mba;
    }
    if( mbn && !IS_INTRA( mbn->i_type ) && !IS_SKIP( mbn->i_type) )
    {
        i_absmv0 += abs( mbn->partition[xn][y].mvd[i_list][0] );
        i_absmv1 += abs( mbn->partition[xn][y].mvd[i_list][1] );
    }

    /* Up ( pixel(0,-1)*/
    yn = y - 1;
    mbn = mb;
    if( yn < 0 )
    {
        yn += 4;
        mbn = mb->context->mbb;
    }
    if( mbn && !IS_INTRA( mbn->i_type ) && !IS_SKIP( mbn->i_type) )
    {
        i_absmv0 += abs( mbn->partition[x][yn].mvd[i_list][0] );
        i_absmv1 += abs( mbn->partition[x][yn].mvd[i_list][1] );
    }

    /* x component */
    if( i_absmv0 < 3 )
    {
        i_ctxIdxInc = 0;
    }
    else if( i_absmv0 > 32 )
    {
        i_ctxIdxInc = 2;
    }
    else
    {
        i_ctxIdxInc = 1;
    }

    x264_cabac_mb_mvd( h, 40, i_ctxIdxInc, mvd[0] );

    /* y component */
    if( i_absmv1 < 3 )
    {
        i_ctxIdxInc = 0;
    }
    else if( i_absmv1 > 32 )
    {
        i_ctxIdxInc = 2;
    }
    else
    {
        i_ctxIdxInc = 1;
    }
    x264_cabac_mb_mvd( h, 47, i_ctxIdxInc, mvd[1] );
}
static void x264_cabac_mb_sub_partition( x264_t *h, int i_sub )
{
    switch( i_sub )
    {
        case D_L0_8x8:
            x264_cabac_encode_decision( &h->cabac, 21, 1 );
            break;
        case D_L0_8x4:
            x264_cabac_encode_decision( &h->cabac, 21, 0 );
            x264_cabac_encode_decision( &h->cabac, 22, 0 );
            break;
        case D_L0_4x8:
            x264_cabac_encode_decision( &h->cabac, 21, 0 );
            x264_cabac_encode_decision( &h->cabac, 22, 1 );
            x264_cabac_encode_decision( &h->cabac, 23, 1 );
            break;
        case D_L0_4x4:
            x264_cabac_encode_decision( &h->cabac, 21, 0 );
            x264_cabac_encode_decision( &h->cabac, 22, 1 );
            x264_cabac_encode_decision( &h->cabac, 23, 0 );
            break;
    }
}

static void block_residual_write_cabac( x264_t *h, x264_macroblock_t *mb, int i_ctxBlockCat, int i_idx, int *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_abs_m1[16];
    int i_coeff_sign[16];
    int i_coeff = 0;
    int i_last  = 0;

    int i_abslevel1 = 0;
    int i_abslevelgt1 = 0;

    int i;

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

    //fprintf( stderr, "l[] = " );
    for( i = 0; i < i_count; i++ )
    {
        //fprintf( stderr, "%d ", l[i] );
        if( l[i] != 0 )
        {
            i_coeff_abs_m1[i_coeff] = abs( l[i] ) - 1;
            i_coeff_sign[i_coeff]   = ( l[i] < 0 ? 1 : 0);
            i_coeff++;

            i_last = i;
        }
    }
    //fprintf( stderr, "\n" );

    if( i_coeff == 0 )
    {
        /* codec block flag */
        x264_cabac_encode_decision( &h->cabac,  85 + x264_cabac_mb_cbf_ctxidxinc( mb, i_ctxBlockCat, i_idx ), 0 );
        return;
    }

    /* block coded */
    x264_cabac_encode_decision( &h->cabac,  85 + x264_cabac_mb_cbf_ctxidxinc( mb, i_ctxBlockCat, i_idx ), 1 );
    for( i = 0; i < i_count - 1; i++ )
    {
        int i_ctxIdxInc;

        i_ctxIdxInc = X264_MIN( i, i_count - 2 );

        if( l[i] != 0 )
        {
            x264_cabac_encode_decision( &h->cabac, 105 + significant_coeff_flag_offset[i_ctxBlockCat] + i_ctxIdxInc, 1 );
            x264_cabac_encode_decision( &h->cabac, 166 + last_significant_coeff_flag_offset[i_ctxBlockCat] + i_ctxIdxInc, i == i_last ? 1 : 0 );
        }
        else
        {
            x264_cabac_encode_decision( &h->cabac, 105 + significant_coeff_flag_offset[i_ctxBlockCat] + i_ctxIdxInc, 0 );
        }
        if( i == i_last )
        {
            break;
        }
    }

    for( i = i_coeff - 1; i >= 0; i-- )
    {
        int i_prefix;
        int i_ctxIdxInc;

        /* write coeff_abs - 1 */

        /* prefix */
        i_prefix = X264_MIN( i_coeff_abs_m1[i], 14 );

        i_ctxIdxInc = (i_abslevelgt1 != 0 ? 0 : X264_MIN( 4, i_abslevel1 + 1 )) + coeff_abs_level_m1_offset[i_ctxBlockCat];
        if( i_prefix == 0 )
        {
            x264_cabac_encode_decision( &h->cabac,  227 + i_ctxIdxInc, 0 );
        }
        else
        {
            int j;
            x264_cabac_encode_decision( &h->cabac,  227 + i_ctxIdxInc, 1 );
            i_ctxIdxInc = 5 + X264_MIN( 4, i_abslevelgt1 ) + coeff_abs_level_m1_offset[i_ctxBlockCat];
            for( j = 0; j < i_prefix - 1; j++ )
            {
                x264_cabac_encode_decision( &h->cabac,  227 + i_ctxIdxInc, 1 );
            }
            if( i_prefix < 14 )
            {
                x264_cabac_encode_decision( &h->cabac,  227 + i_ctxIdxInc, 0 );
            }
        }
        /* suffix */
        if( i_coeff_abs_m1[i] >= 14 )
        {
            int k = 0;
            int i_suffix = i_coeff_abs_m1[i] - 14;

            while( i_suffix >= (1<<k) )
            {
                x264_cabac_encode_bypass( &h->cabac, 1 );
                i_suffix -= 1 << k;
                k++;
            }
            x264_cabac_encode_bypass( &h->cabac, 0 );
            while( k-- )
            {
                x264_cabac_encode_bypass( &h->cabac, (i_suffix >> k)&0x01 );
            }
        }

        /* write sign */
        x264_cabac_encode_bypass( &h->cabac, i_coeff_sign[i] );


        if( i_coeff_abs_m1[i] == 0 )
        {
            i_abslevel1++;
        }
        else
        {
            i_abslevelgt1++;
        }
    }
}



void x264_macroblock_write_cabac( x264_t *h, bs_t *s, x264_macroblock_t *mb )
{
    int i;

    /* Write the MB type */
#if 0
    fprintf( stderr, "[%d,%d] type=%d cbp=%d predc=%d\n",
             mb->i_mb_x, mb->i_mb_y,
             1 + mb->i_intra16x16_pred_mode + mb->i_cbp_chroma * 4 + ( mb->i_cbp_luma == 0 ? 0 : 12 ),
             (mb->i_cbp_chroma << 4)|mb->i_cbp_luma,
             mb->i_chroma_pred_mode );
#endif
    x264_cabac_mb_type( h, mb );

    /* PCM special block type UNTESTED */
    if( mb->i_type == I_PCM )
    {
        bs_align_0( s );    /* not sure */
        /* Luma */
        for( i = 0; i < 16*16; i++ )
        {
            bs_write( s, 8, h->picture->plane[0][mb->i_mb_y * 16 * h->picture->i_stride[0] + mb->i_mb_x * 16+i] );
        }
        /* Cb */
        for( i = 0; i < 8*8; i++ )
        {
            bs_write( s, 8, h->picture->plane[1][mb->i_mb_y * 8 * h->picture->i_stride[1] + mb->i_mb_x * 8+i] );
        }
        /* Cr */
        for( i = 0; i < 8*8; i++ )
        {
            bs_write( s, 8, h->picture->plane[2][mb->i_mb_y * 8 * h->picture->i_stride[2] + mb->i_mb_x * 8+i] );
        }

        for( i = 0; i < 16 + 8; i++ )
        {
            /* special case */
            mb->block[i].i_non_zero_count = 16;
        }

        x264_cabac_encode_init( &h->cabac, s );
        return;
    }

    if( IS_INTRA( mb->i_type ) )
    {
        /* Prediction */
        if( mb->i_type == I_4x4 )
        {
            for( i = 0; i < 16; i++ )
            {
                x264_cabac_mb_intra4x4_pred_mode( h, mb,
                                                  x264_mb_predict_intra4x4_mode( h, mb, i ),
                                                  mb->block[i].i_intra4x4_pred_mode );
            }
        }
        x264_cabac_mb_intra8x8_pred_mode( h, mb );
    }
    else if( mb->i_type == P_8x8 )
    {
        /* sub mb type */
        for( i = 0; i < 4; i++ )
        {
            x264_cabac_mb_sub_partition( h, mb->i_sub_partition[i] );
        }
        /* ref 0 */
        if( h->sh.i_num_ref_idx_l0_active > 1 )
        {
            for( i = 0; i < 4; i++ )
            {
                x264_cabac_mb_ref( h, mb, 0, i );
            }
        }

        for( i = 0; i < 4; i++ )
        {
            int i_sub;
            for( i_sub = 0; i_sub < x264_mb_partition_count_table[mb->i_sub_partition[i]]; i_sub++ )
            {
                x264_cabac_mb_mv( h, mb, 0, i, i_sub );
            }
        }
    }
    else if( mb->i_type == B_8x8 )
    {
        /* TODO */
        fprintf( stderr, "Arggg B_8x8\n" );
    }
    else if( mb->i_type != B_DIRECT )
    {
        /* FIXME -> invalid for B frame */

        /* Motion Vector */
        int i_part = x264_mb_partition_count_table[mb->i_partition];

        if( h->sh.i_num_ref_idx_l0_active > 1 )
        {
            for( i = 0; i < i_part; i++ )
            {
                if( mb->i_type == P_L0 )
                {
                    x264_cabac_mb_ref( h, mb, 0, i );
                }
            }
        }

        for( i = 0; i < i_part; i++ )
        {
            if( mb->i_type == P_L0 )
            {
                x264_cabac_mb_mv( h, mb, 0, i, 0 );
            }
        }
    }

    if( mb->i_type != I_16x16 )
    {
        x264_cabac_mb_cbp_luma( h, mb );
        x264_cabac_mb_cbp_chroma( h, mb );
    }

    if( mb->i_cbp_luma > 0 || mb->i_cbp_chroma > 0 || mb->i_type == I_16x16 )
    {
        x264_cabac_mb_qp_delta( h, mb );

        /* write residual */
        if( mb->i_type == I_16x16 )
        {
            /* DC Luma */
            block_residual_write_cabac( h, mb, 0, 0, mb->luma16x16_dc, 16 );

            if( mb->i_cbp_luma != 0 )
            {
                /* AC Luma */
                for( i = 0; i < 16; i++ )
                {
                    block_residual_write_cabac( h, mb, 1, i, mb->block[i].residual_ac, 15 );
                }
            }
        }
        else
        {
            for( i = 0; i < 16; i++ )
            {
                if( mb->i_cbp_luma & ( 1 << ( i / 4 ) ) )
                {
                    block_residual_write_cabac( h, mb, 2, i, mb->block[i].luma4x4, 16 );
                }
            }
        }

        if( mb->i_cbp_chroma &0x03 )    /* Chroma DC residual present */
        {
            block_residual_write_cabac( h, mb, 3, 0, mb->chroma_dc[0], 4 );
            block_residual_write_cabac( h, mb, 3, 1, mb->chroma_dc[1], 4 );
        }
        if( mb->i_cbp_chroma&0x02 ) /* Chroma AC residual present */
        {
            for( i = 0; i < 8; i++ )
            {
                block_residual_write_cabac( h, mb, 4, i, mb->block[16+i].residual_ac, 15 );
            }
        }
    }
}

//core下的macroblock
/****************************************************************************
 * x264_macroblocks_new: allocate and init macroblock.
 ****************************************************************************/
x264_macroblock_t *x264_macroblocks_new( int i_mb_width, int i_mb_height )
{
    x264_macroblock_t *mb  = (x264_macroblock_t *)x264_malloc( i_mb_width * i_mb_height * sizeof( x264_macrob

⌨️ 快捷键说明

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