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

📄 encoder.c

📁 H.264编码器
💻 C
📖 第 1 页 / 共 3 页
字号:

    /* build ref list 0/1 */
    h->i_ref0 = 0;
    h->i_ref1 = 0;
    for( i = 1; i < h->param.i_frame_reference+2; i++ )
    {
        if( h->freference[i]->i_poc >= 0 )
        {
            if( h->freference[i]->i_poc < h->fdec->i_poc )
            {
                h->fref0[h->i_ref0++] = h->freference[i];
            }
            else if( h->freference[i]->i_poc > h->fdec->i_poc )
            {
                h->fref1[h->i_ref1++] = h->freference[i];
            }
        }
    }
    /* Order ref0 from higher to lower poc */
    do
    {
        b_ok = 1;
        for( i = 0; i < h->i_ref0 - 1; i++ )
        {
            if( h->fref0[i]->i_poc < h->fref0[i+1]->i_poc )
            {
                x264_frame_t *tmp = h->fref0[i+1];

                h->fref0[i+1] = h->fref0[i];
                h->fref0[i] = tmp;
                b_ok = 0;
                break;
            }
        }
    } while( !b_ok );
    /* Order ref1 from lower to higher poc (bubble sort) for B-frame */

	
    do
    {
        b_ok = 1;
        for( i = 0; i < h->i_ref1 - 1; i++ )
        {
            if( h->fref1[i]->i_poc > h->fref1[i+1]->i_poc )
            {
                x264_frame_t *tmp = h->fref1[i+1];

                h->fref1[i+1] = h->fref1[i];
                h->fref1[i] = tmp;
                b_ok = 0;
                break;
            }
        }
    } while( !b_ok );
	

    if( h->i_ref0 > h->param.i_frame_reference )
    {
        h->i_ref0 = h->param.i_frame_reference;
    }
	
    if( h->i_ref1 > 1 )
    {
        h->i_ref1 = 1;
    }
	


    /* Init the rate control */
    x264_ratecontrol_start( h->rc, i_slice_type );

    /* ------------------------ Create slice header  ----------------------- */
    if( i_nal_type == NAL_SLICE_IDR )
    {
        x264_slice_header_init( &h->sh, &h->param, h->sps, h->pps, i_slice_type, h->i_idr_pic_id, h->i_frame_num - 1 );

        /* increment id */
        h->i_idr_pic_id = ( h->i_idr_pic_id + 1 ) % 65535;
    }
    else
    {
        x264_slice_header_init( &h->sh, &h->param, h->sps, h->pps, i_slice_type, -1, h->i_frame_num - 1 );

        /* always set the real higher num of ref frame used */
        h->sh.b_num_ref_idx_override = 1;
        h->sh.i_num_ref_idx_l0_active = h->i_ref0 <= 0 ? 1 : h->i_ref0;
        h->sh.i_num_ref_idx_l1_active = h->i_ref1 <= 0 ? 1 : h->i_ref1;
    }

    if( h->sps->i_poc_type == 0 )
    {
        h->sh.i_poc_lsb = h->fdec->i_poc & ( (1 << h->sps->i_log2_max_poc_lsb) - 1 );
        h->sh.i_delta_poc_bottom = 0;   /* XXX won't work for field */
    }
    else if( h->sps->i_poc_type == 1 )
    {
        /* FIXME TODO FIXME */
    }
    else
    {
        /* Nothing to do ? */
    }

    /* global qp */
    h->sh.i_qp_delta = x264_ratecontrol_qp( h->rc ) - h->pps->i_pic_init_qp;

    /* get adapative cabac model if needed */
    if( h->param.b_cabac )
    {
        if( h->param.i_cabac_init_idc == -1 )
        {
            h->sh.i_cabac_init_idc = x264_cabac_model_get( &h->cabac, i_slice_type );
        }
    }


    /* ---------------------- Write the bitstream -------------------------- */

    /* init bitstream context */
    h->i_nal = 0;
    bs_init( &h->bs, h->p_bitstream, h->i_bitstream );

    /* Put SPS and PPS */
    if( h->i_frame == 0 )
    {
        /* generate sequence parameters */
        x264_nal_start( h, NAL_SPS, NAL_PRIORITY_HIGHEST );
        x264_sps_write( &h->bs, h->sps );
        x264_nal_end( h );

        /* generate picture parameters */
        x264_nal_start( h, NAL_PPS, NAL_PRIORITY_HIGHEST );
        x264_pps_write( &h->bs, h->pps );
        x264_nal_end( h );
    }

    /* Reset stats */
    for( i = 0; i < 18; i++ ) h->stat.i_mb_count[i] = 0;

    /* Slice */
    x264_nal_start( h, i_nal_type, i_nal_ref_idc );

    /* Slice header */
    x264_slice_header_write( &h->bs, &h->sh, i_nal_ref_idc );
    if( h->param.b_cabac )
    {
        /* alignement needed */
        bs_align_1( &h->bs );

        /* init cabac */
        x264_cabac_context_init( &h->cabac, h->sh.i_type, h->sh.pps->i_pic_init_qp + h->sh.i_qp_delta, h->sh.i_cabac_init_idc );
        x264_cabac_encode_init ( &h->cabac, &h->bs );
    }

    for( mb_xy = 0, i_skip = 0; mb_xy < h->sps->i_mb_width * h->sps->i_mb_height; mb_xy++ )
    {
        x264_mb_context_t context;
        x264_macroblock_t *mb;

        mb = &h->mb[mb_xy];

        /* load neighbour */
        x264_macroblock_context_load( h, mb, &context );

        /* analyse parameters
         * Slice I: choose I_4x4 or I_16x16 mode
         * Slice P: choose between using P mode or intra (4x4 or 16x16)
         * */
        TIMER_START( i_mtime_analyse );
        x264_macroblock_analyse( h, &h->mb[mb_xy] );
        TIMER_STOP( i_mtime_analyse );

        /* encode this macrobock -> be carefull it can change the mb type to P_SKIP if needed */
        TIMER_START( i_mtime_encode );
        x264_macroblock_encode( h, mb );
        TIMER_STOP( i_mtime_encode );

        TIMER_START( i_mtime_write );
        if( IS_SKIP( mb->i_type ) )
        {
            if( h->param.b_cabac )
            {
                if( mb_xy > 0 )
                {
                    /* not end_of_slice_flag */
                    x264_cabac_encode_terminal( &h->cabac, 0 );
                }

                x264_cabac_mb_skip( h, mb, 1 );
            }
            else
            {
                i_skip++;
            }
        }
        else
        {
            if( h->param.b_cabac )
            {
                if( mb_xy > 0 )
                {
                    /* not end_of_slice_flag */
                    x264_cabac_encode_terminal( &h->cabac, 0 );
                }
                if( i_slice_type != SLICE_TYPE_I )
                {
                    x264_cabac_mb_skip( h, mb, 0 );
                }
                x264_macroblock_write_cabac( h, &h->bs, mb );
            }
            else
            {
                if( i_slice_type != SLICE_TYPE_I )
                {
                    bs_write_ue( &h->bs, i_skip );  /* skip run */
                    i_skip = 0;
                }
                x264_macroblock_write_cavlc( h, &h->bs, mb );
            }
        }
        TIMER_STOP( i_mtime_write );
        h->stat.i_mb_count[mb->i_type]++;
    }

    if( h->param.b_cabac )
    {
        /* end of slice */
        x264_cabac_encode_terminal( &h->cabac, 1 );
    }
    else if( i_skip > 0 )
    {
        bs_write_ue( &h->bs, i_skip );  /* last skip run */
    }

    if( h->param.b_cabac )
    {
        int i_cabac_word;
        x264_cabac_encode_flush( &h->cabac );
        /* TODO cabac stuffing things (p209) */
        i_cabac_word = (((3 * h->cabac.i_sym_cnt - 3 * 96 * h->sps->i_mb_width * h->sps->i_mb_height)/32) - bs_pos( &h->bs)/8)/3;

        while( i_cabac_word > 0 )
        {
            bs_write( &h->bs, 16, 0x0000 );
            i_cabac_word--;
        }
    }
    else
    {
        /* rbsp_slice_trailing_bits */
        bs_rbsp_trailing( &h->bs );
    }

    x264_nal_end( h );

    /* now set output*/
    *pi_nal = h->i_nal;
    *pp_nal = &h->nal[0];

    /* update cabac */
    if( h->param.b_cabac )
    {
        x264_cabac_model_update( &h->cabac, i_slice_type, h->sh.pps->i_pic_init_qp + h->sh.i_qp_delta );
    }
    /* update rc */
    x264_ratecontrol_end( h->rc, h->nal[h->i_nal-1].i_payload * 8 );

    /* ----------------------- handle frame reference ---------------------- */
    if( i_nal_ref_idc != NAL_PRIORITY_DISPOSABLE )
    {
        /* apply deblocking filter to the current decoded picture */
        if( h->param.b_deblocking_filter )
        {
            TIMER_START( i_mtime_filter );
            x264_frame_deblocking_filter( h, i_slice_type );
            TIMER_STOP( i_mtime_filter );
        }
        /* expand border */
        x264_frame_expand_border( h->fdec );


        /* move frame in the buffer */
        h->fdec = h->freference[h->param.i_frame_reference+1];
        for( i = h->param.i_frame_reference+1; i > 0; i-- )
        {
            h->freference[i] = h->freference[i-1];
        }
        h->freference[0] = h->fdec;
    }

    /* increase frame count */
    h->i_frame++;

    /* PSNR */
    psnr_y = x264_psnr( frame_psnr->plane[0], frame_psnr->i_stride[0], h->picture->plane[0], h->picture->i_stride[0], h->param.i_width, h->param.i_height );
    psnr_u = x264_psnr( frame_psnr->plane[1], frame_psnr->i_stride[1], h->picture->plane[1], h->picture->i_stride[1], h->param.i_width/2, h->param.i_height/2);
    psnr_v = x264_psnr( frame_psnr->plane[2], frame_psnr->i_stride[2], h->picture->plane[2], h->picture->i_stride[2], h->param.i_width/2, h->param.i_height/2);

    /* print stat */  
	
    fprintf( stderr, "frame=%4d NAL=%d Slice:%c Poc:%-3d I4x4:%-5d I16x16:%-5d P:%-5d SKIP:%-3d size=%d bytes PSNR Y:%2.2f U:%2.2f V:%2.2f\n",
             h->i_frame - 1,
             i_nal_ref_idc,
             i_slice_type == SLICE_TYPE_I ? 'I' : (i_slice_type == SLICE_TYPE_P ? 'P' : 'B' ),
             frame_psnr->i_poc,
             h->stat.i_mb_count[I_4x4],
             h->stat.i_mb_count[I_16x16],
             h->stat.i_mb_count[P_L0] + h->stat.i_mb_count[P_8x8],
             h->stat.i_mb_count[P_SKIP],
             h->nal[h->i_nal-1].i_payload,
             psnr_y, psnr_u, psnr_v );


	
#if 0
    /* Dump reconstructed frame */
    x264_frame_dump( h, frame_psnr, "fdec.yuv" );
#endif
#if 0
    if( h->i_ref0 > 0 )
    {
        x264_frame_dump( h, h->fref0[0], "ref0.yuv" );
    }
    if( h->i_ref1 > 0 )
    {
        x264_frame_dump( h, h->fref1[0], "ref1.yuv" );
    }
#endif
    return 0;
}

/****************************************************************************
 * x264_encoder_close:
 ****************************************************************************/
void    x264_encoder_close  ( x264_t *h )
{
    int64_t i_mtime_total = i_mtime_analyse + i_mtime_encode + i_mtime_write + i_mtime_filter + 1;
    int i;

    fprintf( stderr, "x264: analyse=%d(%lldms) encode=%d(%lldms) write=%d(%lldms) filter=%d(%lldms)",
             (int)(100*i_mtime_analyse/i_mtime_total), i_mtime_analyse/1000,
             (int)(100*i_mtime_encode/i_mtime_total), i_mtime_encode/1000,
             (int)(100*i_mtime_write/i_mtime_total), i_mtime_write/1000,
             (int)(100*i_mtime_filter/i_mtime_total), i_mtime_filter/1000 );

    /* ref frames */
    for( i = 0; i < h->param.i_frame_reference+2; i++ )
    {
        x264_frame_delete( h->freference[i] );
    }

    /* empty all allocated picture for bframes */
    for( i = 0; i < h->param.i_bframe; i++ )
    {
        if( h->frame_unused[i] )
        {
            x264_frame_delete( h->frame_unused[i] );
        }
        if( h->bframe_current[i] )
        {
            x264_frame_delete( h->bframe_current[i] );
        }
        if( h->frame_next[i] )
        {
            x264_frame_delete( h->frame_next[i] );
        }
    }

    /* rc */
    x264_ratecontrol_delete( h->rc );

    x264_free( h->mb );
    x264_free( h->p_bitstream );
    x264_free( h );
}

⌨️ 快捷键说明

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