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

📄 t264enc.c

📁 h.264编码库 (T264)..........................
💻 C
📖 第 1 页 / 共 5 页
字号:
    T264_vector_t mvp;
    int mdx, mdy;
	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 );
	mdx = t->mb.vec_ref[i8].vec[i_list].x - mvp.x;
	mdy = t->mb.vec_ref[i8].vec[i_list].y - mvp.y;
    
    /* encode */
    T264_cabac_mb_mvd_cpn( t, i_list, i8, 0, mdx );
    T264_cabac_mb_mvd_cpn( t, i_list, i8, 1, mdy );
	/* save mvd value */
	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;
		}
		i8 += 8;
		luma_idx += 4;
	}
}

static __inline void T264_cabac_mb8x8_mvd( T264_t *t, int i_list )
{
	int i;
	int sub_part;
	for( i = 0; i < 4; i++ )
	{
		sub_part = t->mb.submb_part[luma_index[i<<2]];
		if( T264_mb_partition_listX_table[sub_part-B_DIRECT_8x8][i_list] == 0 )
		{
			continue;
		}

		switch( sub_part )
		{
		case B_DIRECT_8x8:
			assert(0);
			break;
		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];
        if( x > 0 )
            i_mba_xy = t->mb.mb_xy;
        else if( t->mb.mb_x > 0 )
            i_mba_xy = t->mb.mb_xy -1;

        if( y > 0 )
            i_mbb_xy = t->mb.mb_xy;
        else if( t->mb.mb_y > 0 )
            i_mbb_xy = t->mb.mb_xy - t->mb_stride;

        /* no need to test for skip/pcm */
        if( i_mba_xy >= 0 )
        {
            const int i8x8a = block_idx_xy[(x-1)&0x03][y]/4;
            if( (mb_ctxs[i_mba_xy].cbp_y&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( (mb_ctxs[i_mbb_xy].cbp_y&0x0f)>> i8x8b )
            {
                i_nzb = t->mb.nnz_ref[i8 - 8];
            }
        }
    }
    else if( i_cat == 3 )
    {
        /* no need to test skip/pcm */
        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 idxc = i_idx% 4;

        if( idxc == 1 || idxc == 3 )
            i_mba_xy = t->mb.mb_xy;
        else if( t->mb.mb_x > 0 )
            i_mba_xy = t->mb.mb_xy - 1;

        if( idxc == 2 || idxc == 3 )
            i_mbb_xy = t->mb.mb_xy;
        else if( t->mb.mb_y > 0 )
            i_mbb_xy = t->mb.mb_xy - t->mb_stride;

        /* no need to test skip/pcm */
        if( i_mba_xy >= 0 && (mb_ctxs[i_mba_xy].cbp&0x30) == 0x20 )
        {
            i_nza = t->mb.nnz_ref[T264_scan8[16+i_idx] - 1];
        }
        if( i_mbb_xy >= 0 && (mb_ctxs[i_mbb_xy].cbp&0x30) == 0x20 )
        {
            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_write_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_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 */
        T264_cabac_encode_decision( &t->cabac,  85 + T264_cabac_mb_cbf_ctxidxinc( t, i_ctxBlockCat, i_idx ), 0 );
        return;
    }

    /* block coded */
    T264_cabac_encode_decision( &t->cabac,  85 + T264_cabac_mb_cbf_ctxidxinc( t, i_ctxBlockCat, i_idx ), 1 );
    for( i = 0; i < i_count - 1; i++ )
    {
        int i_ctxIdxInc;

        i_ctxIdxInc = T264_MIN( i, i_count - 2 );

        if( l[i] != 0 )
        {
            T264_cabac_encode_decision( &t->cabac, 105 + significant_coeff_flag_offset[i_ctxBlockCat] + i_ctxIdxInc, 1 );
            T264_cabac_encode_decision( &t->cabac, 166 + last_significant_coeff_flag_offset[i_ctxBlockCat] + i_ctxIdxInc, i == i_last ? 1 : 0 );
        }
        else
        {
            T264_cabac_encode_decision( &t->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 = T264_MIN( i_coeff_abs_m1[i], 14 );

        i_ctxIdxInc = (i_abslevelgt1 != 0 ? 0 : T264_MIN( 4, i_abslevel1 + 1 )) + coeff_abs_level_m1_offset[i_ctxBlockCat];
        if( i_prefix == 0 )
        {
            T264_cabac_encode_decision( &t->cabac,  227 + i_ctxIdxInc, 0 );
        }
        else
        {
            int j;
            T264_cabac_encode_decision( &t->cabac,  227 + i_ctxIdxInc, 1 );
            i_ctxIdxInc = 5 + T264_MIN( 4, i_abslevelgt1 ) + coeff_abs_level_m1_offset[i_ctxBlockCat];
            for( j = 0; j < i_prefix - 1; j++ )
            {
                T264_cabac_encode_decision( &t->cabac,  227 + i_ctxIdxInc, 1 );
            }
            if( i_prefix < 14 )
            {
                T264_cabac_encode_decision( &t->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) )
            {
                T264_cabac_encode_bypass( &t->cabac, 1 );
                i_suffix -= 1 << k;
                k++;
            }
            T264_cabac_encode_bypass( &t->cabac, 0 );
            while( k-- )
            {
                T264_cabac_encode_bypass( &t->cabac, (i_suffix >> k)&0x01 );
            }
        }

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


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


static int8_t
T264_mb_predict_intra4x4_mode(T264_t *t, int32_t idx)
{
	int32_t x, y;
	int8_t nA, nB, pred_blk;

	x = luma_inverse_x[idx];
	y = luma_inverse_y[idx];

	nA = t->mb.i4x4_pred_mode_ref[IPM_LUMA + x + y * 8 - 1];
	nB = t->mb.i4x4_pred_mode_ref[IPM_LUMA + x + y * 8 - 8];

	pred_blk  = T264_MIN(nA, nB);

	if( pred_blk < 0 )
		return Intra_4x4_DC;

	return pred_blk;	
}

void T264_macroblock_write_cabac( T264_t *t, bs_t *s )
{
    const int i_mb_type = t->mb.mb_mode;
    const int i_mb_pos_start = BitstreamPos( s );
    int       i_mb_pos_tex;

    int i;

    /* Write the MB type */
    T264_cabac_mb_type( t );

    /* PCM special block type UNTESTED */
	/* no PCM here*/
	
    if( IS_INTRA( i_mb_type ) )
    {
        /* Prediction */
        if( i_mb_type == I_4x4 )
        {
            for( i = 0; i < 16; i++ )
            {
                const int i_pred = T264_mb_predict_intra4x4_mode( t, i );
                const int i_mode = t->mb.i4x4_pred_mode_ref[T264_scan8[i]];
                T264_cabac_mb_intra4x4_pred_mode( t, i_pred, i_mode );
            }
        }
        T264_cabac_mb_intra8x8_pred_mode( t );
    }
    else if( i_mb_type == P_MODE )
    {
        if( t->mb.mb_part == MB_16x16 )
        {
            if( t->ps.num_ref_idx_l0_active_minus1 > 0 )
            {
                T264_cabac_mb_ref( t, 0, 0 );
            }
            T264_cabac_mb_mvd( t, 0, 0, 4, 4 );
        }
        else if( t->mb.mb_part == MB_16x8 )
        {
            if( t->ps.num_ref_idx_l0_active_minus1 > 0 )
            {
                T264_cabac_mb_ref( t, 0, 0 );
                T264_cabac_mb_ref( t, 0, 8 );

⌨️ 快捷键说明

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