x264代码剖析(五):encode()函数之x264_encoder_open()函数

x264代码剖析(五):encode()函数之x264_encoder_open()函数

我们知道x264源码从主观上分为两大块,一是解析函数parse(),另一个是编码函数encode()。解析函数parse()较简单,并且不涉及H.264编码算法,故不是重点,所以我们要学习的重点自然而然地就是编码函数encode()了。

encode()函数是x264的主干函数,主要包括x264_encoder_open()函数、x264_encoder_headers()函数、x264_encoder_encode()函数与x264_encoder_close()函数四大部分,如下图所示,其中x264_encoder_encode()函数是其核心部分,具体的H.264视频编码算法均在此模块。

本文主要分析x264_encoder_open()函数,x264_encoder_open()用于打开编码器,其中初始化了libx264编码所需要的各种变量,如下图所示。它调用了下面的函数:

x264_validate_parameters():检查输入参数(例如输入图像的宽高是否为正数)。

x264_sps_init():初始化SPS

x264_pps_init():初始化PPS

x264_predict_16x16_init():初始化Intra16x16帧内预测汇编函数。

x264_predict_4x4_init():初始化Intra4x4帧内预测汇编函数。

x264_pixel_init():初始化像素值计算相关的汇编函数(包括SAD、SATD、SSD等)。

x264_dct_init():初始化DCT变换和DCT反变换相关的汇编函数。

x264_mc_init():初始化运动补偿相关的汇编函数。

x264_quant_init():初始化量化和反量化相关的汇编函数。

x264_deblock_init():初始化去块效应滤波器相关的汇编函数。

x264_lookahead_init():初始化Lookahead相关的变量。

x264_ratecontrol_new():初始化码率控制相关的变量。

对应的代码如下:

/******************************************************************/
/******************************************************************/
/*
======Analysed by RuiDong Fang
======Csdn Blog:http://blog.csdn.net/frd2009041510
======Date:2016.03.08
 */
/******************************************************************/
/******************************************************************/

/************====== x264_encoder_open()函数 ======************/
/*
功能:打开编码器
*/
/****************************************************************************
 * x264_encoder_open:
 ****************************************************************************/
x264_t *x264_encoder_open( x264_param_t *param )
{
    x264_t *h;
    char buf[1000], *p;
    int i_slicetype_length;

    CHECKED_MALLOCZERO( h, sizeof(x264_t) );

    /* Create a copy of param */
    memcpy( &h->param, param, sizeof(x264_param_t) );	//将参数拷贝进来

    if( param->param_free )
        param->param_free( param );

#if HAVE_INTEL_DISPATCHER
    x264_intel_dispatcher_override();
#endif

    if( x264_threading_init() )
    {
        x264_log( h, X264_LOG_ERROR, "unable to initialize threading\n" );
        goto fail;
    }

    if( x264_validate_parameters( h, 1 ) < 0 )	////////////////////////检查输入参数(例如输入图像的宽高是否为正数)
        goto fail;

    if( h->param.psz_cqm_file )
        if( x264_cqm_parse_file( h, h->param.psz_cqm_file ) < 0 )
            goto fail;

    if( h->param.rc.psz_stat_out )
        h->param.rc.psz_stat_out = strdup( h->param.rc.psz_stat_out );
    if( h->param.rc.psz_stat_in )
        h->param.rc.psz_stat_in = strdup( h->param.rc.psz_stat_in );

    x264_reduce_fraction( &h->param.i_fps_num, &h->param.i_fps_den );
    x264_reduce_fraction( &h->param.i_timebase_num, &h->param.i_timebase_den );

    /* Init x264_t */
    h->i_frame = -1;
    h->i_frame_num = 0;

    if( h->param.i_avcintra_class )
        h->i_idr_pic_id = 5;
    else
        h->i_idr_pic_id = 0;

    if( (uint64_t)h->param.i_timebase_den * 2 > UINT32_MAX )
    {
        x264_log( h, X264_LOG_ERROR, "Effective timebase denominator %u exceeds H.264 maximum\n", h->param.i_timebase_den );
        goto fail;
    }

    x264_set_aspect_ratio( h, &h->param, 1 );

	//x264_sps_init()根据输入参数生成H.264码流的SPS (Sequence Parameter Set,序列参数集)信息
    x264_sps_init( h->sps, h->param.i_sps_id, &h->param );	////////////////////////初始化SPS
	//x264_pps_init()根据输入参数生成H.264码流的PPS(Picture Parameter Set,图像参数集)信息
    x264_pps_init( h->pps, h->param.i_sps_id, &h->param, h->sps );	////////////////////////初始化PPS

    x264_validate_levels( h, 1 );	//检查级Level-通过宏块个数等等

    h->chroma_qp_table = i_chroma_qp_table + 12 + h->pps->i_chroma_qp_index_offset;

    if( x264_cqm_init( h ) < 0 )
        goto fail;

	//赋值
    h->mb.i_mb_width = h->sps->i_mb_width;
    h->mb.i_mb_height = h->sps->i_mb_height;
    h->mb.i_mb_count = h->mb.i_mb_width * h->mb.i_mb_height;

    h->mb.chroma_h_shift = CHROMA_FORMAT == CHROMA_420 || CHROMA_FORMAT == CHROMA_422;
    h->mb.chroma_v_shift = CHROMA_FORMAT == CHROMA_420;

    /* Adaptive MBAFF and subme 0 are not supported as we require halving motion
     * vectors during prediction, resulting in hpel mvs.
     * The chosen solution is to make MBAFF non-adaptive in this case. */
    h->mb.b_adaptive_mbaff = PARAM_INTERLACED && h->param.analyse.i_subpel_refine;

    /* Init frames. */
    if( h->param.i_bframe_adaptive == X264_B_ADAPT_TRELLIS && !h->param.rc.b_stat_read )
        h->frames.i_delay = X264_MAX(h->param.i_bframe,3)*4;
    else
        h->frames.i_delay = h->param.i_bframe;
    if( h->param.rc.b_mb_tree || h->param.rc.i_vbv_buffer_size )
        h->frames.i_delay = X264_MAX( h->frames.i_delay, h->param.rc.i_lookahead );
    i_slicetype_length = h->frames.i_delay;
    h->frames.i_delay += h->i_thread_frames - 1;
    h->frames.i_delay += h->param.i_sync_lookahead;
    h->frames.i_delay += h->param.b_vfr_input;
    h->frames.i_bframe_delay = h->param.i_bframe ? (h->param.i_bframe_pyramid ? 2 : 1) : 0;

    h->frames.i_max_ref0 = h->param.i_frame_reference;
    h->frames.i_max_ref1 = X264_MIN( h->sps->vui.i_num_reorder_frames, h->param.i_frame_reference );
    h->frames.i_max_dpb  = h->sps->vui.i_max_dec_frame_buffering;
    h->frames.b_have_lowres = !h->param.rc.b_stat_read
        && ( h->param.rc.i_rc_method == X264_RC_ABR
          || h->param.rc.i_rc_method == X264_RC_CRF
          || h->param.i_bframe_adaptive
          || h->param.i_scenecut_threshold
          || h->param.rc.b_mb_tree
          || h->param.analyse.i_weighted_pred );
    h->frames.b_have_lowres |= h->param.rc.b_stat_read && h->param.rc.i_vbv_buffer_size > 0;
    h->frames.b_have_sub8x8_esa = !!(h->param.analyse.inter & X264_ANALYSE_PSUB8x8);

    h->frames.i_last_idr =
    h->frames.i_last_keyframe = - h->param.i_keyint_max;
    h->frames.i_input    = 0;
    h->frames.i_largest_pts = h->frames.i_second_largest_pts = -1;
    h->frames.i_poc_last_open_gop = -1;

	//CHECKED_MALLOCZERO(var, size)
    //调用malloc()分配内存,然后调用memset()置零
    CHECKED_MALLOCZERO( h->frames.unused[0], (h->frames.i_delay + 3) * sizeof(x264_frame_t *) );
    /* Allocate room for max refs plus a few extra just in case. */
    CHECKED_MALLOCZERO( h->frames.unused[1], (h->i_thread_frames + X264_REF_MAX + 4) * sizeof(x264_frame_t *) );
    CHECKED_MALLOCZERO( h->frames.current, (h->param.i_sync_lookahead + h->param.i_bframe
                        + h->i_thread_frames + 3) * sizeof(x264_frame_t *) );
    if( h->param.analyse.i_weighted_pred > 0 )
        CHECKED_MALLOCZERO( h->frames.blank_unused, h->i_thread_frames * 4 * sizeof(x264_frame_t *) );
    h->i_ref[0] = h->i_ref[1] = 0;
    h->i_cpb_delay = h->i_coded_fields = h->i_disp_fields = 0;
    h->i_prev_duration = ((uint64_t)h->param.i_fps_den * h->sps->vui.i_time_scale) / ((uint64_t)h->param.i_fps_num * h->sps->vui.i_num_units_in_tick);
    h->i_disp_fields_last_frame = -1;
    x264_rdo_init();	///////////////////////////RDO初始化

    /* init CPU functions */
	//初始化包含汇编优化的函数
    //帧内预测
    x264_predict_16x16_init( h->param.cpu, h->predict_16x16 );	///////////////////////////初始化Intra16x16帧内预测汇编函数(该函数的定义位于x264\common\predict.c)
    x264_predict_8x8c_init( h->param.cpu, h->predict_8x8c );
    x264_predict_8x16c_init( h->param.cpu, h->predict_8x16c );
    x264_predict_8x8_init( h->param.cpu, h->predict_8x8, &h->predict_8x8_filter );
    x264_predict_4x4_init( h->param.cpu, h->predict_4x4 );	///////////////////////////初始化Intra4x4帧内预测汇编函数

	x264_pixel_init( h->param.cpu, &h->pixf );	///////////////////////////初始化像素值计算相关的汇编函数(包括SAD、SATD、SSD等)(该函数的定义位于common\pixel.c)
    x264_dct_init( h->param.cpu, &h->dctf );	///////////////////////////初始化DCT变换和DCT反变换相关的汇编函数(该函数的定义位于common\dct.c)
    x264_zigzag_init( h->param.cpu, &h->zigzagf_progressive, &h->zigzagf_interlaced );//“之”字扫描
    memcpy( &h->zigzagf, PARAM_INTERLACED ? &h->zigzagf_interlaced : &h->zigzagf_progressive, sizeof(h->zigzagf) );
    x264_mc_init( h->param.cpu, &h->mc, h->param.b_cpu_independent );	///////////////////////////初始化运动补偿相关的汇编函数(该函数的定义位于common\mc.c)
    x264_quant_init( h, h->param.cpu, &h->quantf );	///////////////////////////初始化量化和反量化相关的汇编函数(该函数的定义位于common\quant.c)
    x264_deblock_init( h->param.cpu, &h->loopf, PARAM_INTERLACED );	///////////////////////////初始化去块效应滤波器相关的汇编函数(该函数的定义位于common\deblock.c)
    x264_bitstream_init( h->param.cpu, &h->bsf );

	//初始化CABAC或者是CAVLC
    if( h->param.b_cabac )
        x264_cabac_init( h );
    else
        x264_stack_align( x264_cavlc_init, h );

	//决定了像素比较的时候用SAD还是SATD
    mbcmp_init( h );
    chroma_dsp_init( h );

	//CPU属性
    p = buf + sprintf( buf, "using cpu capabilities:" );
    for( int i = 0; x264_cpu_names[i].flags; i++ )
    {
        if( !strcmp(x264_cpu_names[i].name, "SSE")
            && h->param.cpu & (X264_CPU_SSE2) )
            continue;
        if( !strcmp(x264_cpu_names[i].name, "SSE2")
            && h->param.cpu & (X264_CPU_SSE2_IS_FAST|X264_CPU_SSE2_IS_SLOW) )
            continue;
        if( !strcmp(x264_cpu_names[i].name, "SSE3")
            && (h->param.cpu & X264_CPU_SSSE3 || !(h->param.cpu & X264_CPU_CACHELINE_64)) )
            continue;
        if( !strcmp(x264_cpu_names[i].name, "SSE4.1")
            && (h->param.cpu & X264_CPU_SSE42) )
            continue;
        if( !strcmp(x264_cpu_names[i].name, "BMI1")
            && (h->param.cpu & X264_CPU_BMI2) )
            continue;
        if( (h->param.cpu & x264_cpu_names[i].flags) == x264_cpu_names[i].flags
            && (!i || x264_cpu_names[i].flags != x264_cpu_names[i-1].flags) )
            p += sprintf( p, " %s", x264_cpu_names[i].name );
    }
    if( !h->param.cpu )
        p += sprintf( p, " none!" );
    x264_log( h, X264_LOG_INFO, "%s\n", buf );

    if( x264_analyse_init_costs( h ) )
        goto fail;

    static const uint16_t cost_mv_correct[7] = { 24, 47, 95, 189, 379, 757, 1515 };
    /* Checks for known miscompilation issues. */
    if( h->cost_mv[X264_LOOKAHEAD_QP][2013] != cost_mv_correct[BIT_DEPTH-8] )
    {
        x264_log( h, X264_LOG_ERROR, "MV cost test failed: x264 has been miscompiled!\n" );
        goto fail;
    }

    /* Must be volatile or else GCC will optimize it out. */
    volatile int temp = 392;
    if( x264_clz( temp ) != 23 )
    {
        x264_log( h, X264_LOG_ERROR, "CLZ test failed: x264 has been miscompiled!\n" );
#if ARCH_X86 || ARCH_X86_64
        x264_log( h, X264_LOG_ERROR, "Are you attempting to run an SSE4a/LZCNT-targeted build on a CPU that\n" );
        x264_log( h, X264_LOG_ERROR, "doesn't support it?\n" );
#endif
        goto fail;
    }

    h->out.i_nal = 0;
    h->out.i_bitstream = X264_MAX( 1000000, h->param.i_width * h->param.i_height * 4
        * ( h->param.rc.i_rc_method == X264_RC_ABR ? pow( 0.95, h->param.rc.i_qp_min )
          : pow( 0.95, h->param.rc.i_qp_constant ) * X264_MAX( 1, h->param.rc.f_ip_factor )));

    h->nal_buffer_size = h->out.i_bitstream * 3/2 + 4 + 64; /* +4 for startcode, +64 for nal_escape assembly padding */
    CHECKED_MALLOC( h->nal_buffer, h->nal_buffer_size );

    CHECKED_MALLOC( h->reconfig_h, sizeof(x264_t) );

    if( h->param.i_threads > 1 &&
        x264_threadpool_init( &h->threadpool, h->param.i_threads, (void*)x264_encoder_thread_init, h ) )
        goto fail;
    if( h->param.i_lookahead_threads > 1 &&
        x264_threadpool_init( &h->lookaheadpool, h->param.i_lookahead_threads, NULL, NULL ) )
        goto fail;

#if HAVE_OPENCL
    if( h->param.b_opencl )
    {
        h->opencl.ocl = x264_opencl_load_library();
        if( !h->opencl.ocl )
        {
            x264_log( h, X264_LOG_WARNING, "failed to load OpenCL\n" );
            h->param.b_opencl = 0;
        }
    }
#endif

    h->thread[0] = h;
    for( int i = 1; i < h->param.i_threads + !!h->param.i_sync_lookahead; i++ )
        CHECKED_MALLOC( h->thread[i], sizeof(x264_t) );
    if( h->param.i_lookahead_threads > 1 )
        for( int i = 0; i < h->param.i_lookahead_threads; i++ )
        {
            CHECKED_MALLOC( h->lookahead_thread[i], sizeof(x264_t) );
            *h->lookahead_thread[i] = *h;
        }
    *h->reconfig_h = *h;

    for( int i = 0; i < h->param.i_threads; i++ )
    {
        int init_nal_count = h->param.i_slice_count + 3;
        int allocate_threadlocal_data = !h->param.b_sliced_threads || !i;
        if( i > 0 )
            *h->thread[i] = *h;

        if( x264_pthread_mutex_init( &h->thread[i]->mutex, NULL ) )
            goto fail;
        if( x264_pthread_cond_init( &h->thread[i]->cv, NULL ) )
            goto fail;

        if( allocate_threadlocal_data )
        {
            h->thread[i]->fdec = x264_frame_pop_unused( h, 1 );
            if( !h->thread[i]->fdec )
                goto fail;
        }
        else
            h->thread[i]->fdec = h->thread[0]->fdec;

        CHECKED_MALLOC( h->thread[i]->out.p_bitstream, h->out.i_bitstream );
        /* Start each thread with room for init_nal_count NAL units; it'll realloc later if needed. */
        CHECKED_MALLOC( h->thread[i]->out.nal, init_nal_count*sizeof(x264_nal_t) );
        h->thread[i]->out.i_nals_allocated = init_nal_count;

        if( allocate_threadlocal_data && x264_macroblock_cache_allocate( h->thread[i] ) < 0 )
            goto fail;
    }

#if HAVE_OPENCL
    if( h->param.b_opencl && x264_opencl_lookahead_init( h ) < 0 )
        h->param.b_opencl = 0;
#endif

    if( x264_lookahead_init( h, i_slicetype_length ) )	///////////////////////////初始化lookahead
        goto fail;

    for( int i = 0; i < h->param.i_threads; i++ )
        if( x264_macroblock_thread_allocate( h->thread[i], 0 ) < 0 )
            goto fail;

    if( x264_ratecontrol_new( h ) < 0 )	///////////////////////////创建码率控制
        goto fail;

    if( h->param.i_nal_hrd )
    {
        x264_log( h, X264_LOG_DEBUG, "HRD bitrate: %i bits/sec\n", h->sps->vui.hrd.i_bit_rate_unscaled );
        x264_log( h, X264_LOG_DEBUG, "CPB size: %i bits\n", h->sps->vui.hrd.i_cpb_size_unscaled );
    }

    if( h->param.psz_dump_yuv )
    {
        /* create or truncate the reconstructed video file */
        FILE *f = x264_fopen( h->param.psz_dump_yuv, "w" );
        if( !f )
        {
            x264_log( h, X264_LOG_ERROR, "dump_yuv: can't write to %s\n", h->param.psz_dump_yuv );
            goto fail;
        }
        else if( !x264_is_regular_file( f ) )
        {
            x264_log( h, X264_LOG_ERROR, "dump_yuv: incompatible with non-regular file %s\n", h->param.psz_dump_yuv );
            fclose( f );
            goto fail;
        }
        fclose( f );
    }

    const char *profile = h->sps->i_profile_idc == PROFILE_BASELINE ? "Constrained Baseline" :
                          h->sps->i_profile_idc == PROFILE_MAIN ? "Main" :
                          h->sps->i_profile_idc == PROFILE_HIGH ? "High" :
                          h->sps->i_profile_idc == PROFILE_HIGH10 ? (h->sps->b_constraint_set3 == 1 ? "High 10 Intra" : "High 10") :
                          h->sps->i_profile_idc == PROFILE_HIGH422 ? (h->sps->b_constraint_set3 == 1 ? "High 4:2:2 Intra" : "High 4:2:2") :
                          h->sps->b_constraint_set3 == 1 ? "High 4:4:4 Intra" : "High 4:4:4 Predictive";
    char level[4];
    snprintf( level, sizeof(level), "%d.%d", h->sps->i_level_idc/10, h->sps->i_level_idc%10 );
    if( h->sps->i_level_idc == 9 || ( h->sps->i_level_idc == 11 && h->sps->b_constraint_set3 &&
        (h->sps->i_profile_idc == PROFILE_BASELINE || h->sps->i_profile_idc == PROFILE_MAIN) ) )
        strcpy( level, "1b" );

    if( h->sps->i_profile_idc < PROFILE_HIGH10 )	//输出型和级
    {
        x264_log( h, X264_LOG_INFO, "profile %s, level %s\n",
            profile, level );
    }
    else
    {
        static const char * const subsampling[4] = { "4:0:0", "4:2:0", "4:2:2", "4:4:4" };
        x264_log( h, X264_LOG_INFO, "profile %s, level %s, %s %d-bit\n",
            profile, level, subsampling[CHROMA_FORMAT], BIT_DEPTH );
    }

    return h;
fail:
    x264_free( h );	//释放
    return NULL;
}
时间: 2024-09-30 19:57:28

x264代码剖析(五):encode()函数之x264_encoder_open()函数的相关文章

x264代码剖析(三):主函数main()、解析函数parse()与编码函数encode()

x264代码剖析(三):主函数main().解析函数parse()与编码函数encode() x264的入口函数为main().main()函数首先调用parse()解析输入的参数,然后调用encode()编码YUV数据.parse()首先调用x264_param_default()为保存参数的x264_param_t结构体赋默认值:然后在一个大循环中通过getopt_long()解析通过命令行传递来的存储在argv[]中的参数,并作相应的设置工作:最后调用select_input()和sele

x264代码剖析(七):encode()函数之x264_encoder_encode()函数

x264代码剖析(七):encode()函数之x264_encoder_encode()函数 encode()函数是x264的主干函数,主要包括x264_encoder_open()函数.x264_encoder_headers()函数.x264_encoder_encode()函数与x264_encoder_close()函数四大部分,其中x264_encoder_encode()函数是其核心部分,具体的H.264视频编码算法均在此模块.上两篇博文主要分析了x264_encoder_open(

x264代码剖析笔记

x264代码剖析笔记 x264的基本框架仍是采用基于预测+变换的混合编码框架,如下图所示,主要包括:帧内预测.帧间预测.变换与量化.熵编码.滤波等. 下面列举了x264代码剖析的系列文章: <x264代码剖析(一):图文详解x264在Windows平台上的搭建> <x264代码剖析(二):如何编译运行x264以及x264代码基本框架> <x264代码剖析(三):主函数main().解析函数parse()与编码函数encode()> <x264代码剖析(四):vs2

x264代码剖析(十七):核心算法之熵编码(Entropy Encoding)

x264代码剖析(十七):核心算法之熵编码(Entropy Encoding) 熵编码是无损压缩编码方法,它生产的码流可以经解码无失真地恢复出原始数据.熵编码是建立在随机过程的统计特性基础上的.本文对熵编码中的CAVLC(基于上下文自适应的可变长编码)和CABAC(基于上下文的自适应二进制算术熵编码)进行简单介绍,并给出x264中熵编码对应的代码分析. 在H.264的CAVLC中,通过根据已编码句法元素的情况,动态调整编码中使用的码表,取得了极高的压缩比.CAVLC用于亮度和色度残差数据的编码,

x264代码剖析(八):encode()函数之x264_encoder_close()函数

x264代码剖析(八):encode()函数之x264_encoder_close()函数 encode()函数是x264的主干函数.主要包含x264_encoder_open()函数.x264_encoder_headers()函数.x264_encoder_encode()函数与x264_encoder_close()函数四大部分,当中x264_encoder_encode()函数是其核心部分,详细的H.264视频编码算法均在此模块. 上三篇博文主要分析了x264_encoder_open(

x264代码剖析(十五):核心算法之宏块编码中的变换编码

x264代码剖析(十五):核心算法之宏块编码中的变换编码 为了进一步节省图像的传输码率,需要对图像进行压缩,通常采用变换编码及量化来消除图像中的相关性以减少图像编码的动态范围.本文主要介绍变换编码的相关内容,并给出x264中变换编码的代码分析. 1.变换编码 变换编码将图像时域信号变换成频域信号,在频域中图像信号能量大部分集中在低频区域,相对时域信号,码率有较大的下降. H.264对图像或预测残差采用4×4整数离散余弦变换技术,避免了以往标准中使用的通用8×8离散余弦变换逆变换经常出现的失配问题

(转)x264源码分析(1):main、parse、encode、x264_encoder_open函数代码分析

转自:http://nkwavelet.blog.163.com/blog/static/2277560382013103010312144/ x264版本:   x264-snapshot-20140226-2245  1.     首先对主函数进行分析,main函数很简洁,主要有三个步骤,见下图: 2.   接下来分析一下Parse函数中的主要过程: static int parse( int argc, char **argv, x264_param_t *param, cli_opt_t

c++ primer(第五版)学习笔记及习题答案代码版(第六章)函数

笔记较为零散,都是自己不熟悉的知识点. 习题答案至于一个.cc 中,编译需要包含Chapter6.h头文件. 需要演示某一题直接修改 #define NUM***, 如运行6.23题为#define NUM623: chapter 6 1. 形参初始化的机理与变量初始化一样. 当形参是引用类型时,它对应的实参被引用传递或者函数被传引用调用. 2. const和实参 void fcn(const int i){ /*fcn能够读取i,但是不能向i写值*/} void fcn(int i){ /*.

如何阅读X264代码

http://www.cnblogs.com/xkfz007/articles/2616057.html 最近我也开始看 X264 的代码了,于是想到把我读代码的过程记录下来,因为总有很多新手问如何读代码,我这个帖子就是专为这些人写的.至于会读代码的人就完全没有必要看了.下面当然是以 X264 为例了.JM 以及其他代码的学习方法和技巧都是完全一样的.我所用的版本是在帖子 在VS2008下编译最新版的x264连接错误 里上传的版本.最新版本的代码基本结构应该变化不大. 首先肯定是要把 X264