织梦CMS - 轻松建站从此开始!

罗索

x264代码分析

落鹤生 发布于 2013-01-23 22:22 点击:次 
以x264的示例代码对x264代码进行分析及研究
TAG:

Main(int argc,char *argv[]);

为了方便起见,不妨改写为:

  1. Main(void){ 
  2. ...... 
  3.     int argc=5; 
  4.     char *argv[]={ 
  5.        "main","-o","test.264","foreman.yuv","352x288"    
  6.     };       
  7.      ...... 

====================================

1.x264_param_default( &param );

这部分设置编码参数的缺省值

附部分变量的意义:

  1. param->i_csp  = X264_CSP_I420; // 设置输入的视频采样的格式 
  2. param->vui.i_sar_width = 0;  //VUI:video usability information 
  3. param->i_fps_num   = 10; //帧率 
  4. param->i_fps_den   = 1;  //用两个整型的数的比值,来表示帧率 
  5.   
  6. /* Encoder parameters */ 
  7. param->i_frame_reference = 1; //参考帧的最大帧数。 
  8. param->i_bframe = 0;  //两个参考帧之间的B帧数目。 
  9. param->b_deblocking_filter = 1; //去块效应相关 
  10.   
  11. param->b_cabac = 0;//cabac的开关 
  12. param->i_cabac_init_idc = -1; 
  13.   
  14. param->rc.b_cbr = 1;   //constant bitrate 恒定码率控制模式 
  15. param->rc.i_bitrate = 0;   //默认的码率 
  16. param->rc.i_rc_buffer_size = 0;   //buffer的大小 
  17. param->rc.i_rc_init_buffer = 0;   // 
  18. param->rc.i_rc_sens = 100;   ///* rate control sensitivity 
  19.  
  20.  
  21. //码率控制,CQP(恒定质量)、//CRF(恒定码率)、ABR(平均码率) 
  22. param->rc.i_rc_method = X264_RC_NONE; 
  23. param->rc.i_qp_constant = 26; //qp的初始值,最大最小的qp值, 
  24. param->rc.i_qp_min = 10;   //最小的qp值 
  25. param->rc.i_qp_max = 51;  //最大的qp值 
  26. param->rc.i_qp_step = 4;   //qp[步长step。 
  27. param->rc.f_ip_factor = 1.4;  //ip--i帧p帧的qp的差值 
  28. param->rc.f_pb_factor = 1.3;  //pb--p帧b帧的qp的差值 
  29.  
  30. /* Log */ //整个param的一个log文件 
  31.  
  32. /*analyse */ 
  33. param->analyse.intra = X264_ANALYSE_I4x4 | X264_ANALYSE_I8x8; 
  34. //桢内分析 
  35. param->analyse.inter = X264_ANALYSE_I4x4 | X264_ANALYSE_I8x8
  36.  | X264_ANALYSE_PSUB16x16 | X264_ANALYSE_BSUB16x16; 
  37. //桢间分析 
  38. param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_SPATIAL; 
  39. //预测模式 
  40. param->analyse.i_me_method = X264_ME_HEX;  //运动估计模式 
  41. param->analyse.i_me_range = 16;  //运动估计范围 
  42. param->analyse.i_subpel_refine = 5; 
  43. param->analyse.b_chroma_me = 1; 
  44. param->analyse.i_mv_range_thread = -1; 
  45. param->analyse.i_mv_range = -1; // set from level_idc 
  46. param->analyse.i_direct_8x8_inference = -1; // set from level_idc 
  47. param->analyse.i_chroma_qp_offset = 0; 
  48. param->analyse.b_fast_pskip = 1; 
  49. param->analyse.b_dct_decimate = 1; 
  50. param->analyse.i_luma_deadzone[0] = 21; 
  51. param->analyse.i_luma_deadzone[1] = 11; 
  52. param->analyse.b_psnr = 1; 
  53. param->analyse.b_ssim = 1; 
  54.  
  55. param->i_cqm_preset = X264_CQM_FLAT;  //自定义量化矩阵(CQM),初始化量化模式为flat 

2.Parse( argc, argv, &param, &opt ) ;

   解析函数int c = getopt_long( argc, argv, "8A:B:b:f:hI:i:m:o:p:q:r:t:Vvw",

  1. long_options, &long_options_index); 
  2. // 得到入口地址的向量与方式的选择   
  3. _getopt_internal (argc, argv, optstring, longopts, longind, long_only);                   
  4. //解析入口地址向量 

3.Encode( &param, &opt ) ;

3.1.x264_encoder_open( param ){

  1. …… 
  2. x264_t *h = x264_malloc( sizeof( x264_t ) );    //为h分配空间 
  3. /* Create a copy of param */ 
  4. memcpy( &h->param, param, sizeof( x264_param_t ) ); 
  5. …… 

3.1.1.x264_validate_parameters( h );  //验证参数

  1. /* VUI */ 
  2. /* Init x264_t */ 
  3. h->sps = &h->sps_array[0]; 

3.1.2.x264_sps_init( h->sps, h->param.i_sps_id, &h->param );

typedef struct
{
int i_id;   //本序列参数集的id号
int i_profile_idc;   //指明所用的profile
int i_level_idc; //指明所用的level
int b_constraint_set0;   //其值等于时,表示必须遵从附录A.2.1所指明的所有约束条件
int b_constraint_set1;   //其值等于时,表示必须遵从附录A.2.2所指明的所有约束条件
int b_constraint_set2;   //其值等于时,表示必须遵从附录A.2.3所指明的所有约束条件
int i_log2_max_frame_num;   //这个句法元素只要是为读取frame_num服务的
int i_poc_type;   //指明poc的编码方法,poc标识图像的播放顺序
/* poc 0 */
int i_log2_max_poc_lsb;   //指明了变量i_poc_lsb的max值
/* poc 1 */
int b_delta_pic_order_always_zero;//其值为时,i_delta_poc[0]和i_delta_poc[1]不在片头出现,并且它们的默认值为;当本句法元素为时,上述两个句法元素将在片头出现
int i_offset_for_non_ref_pic; //用于计算非参考帧或场的poc
int i_offset_for_top_to_bottom_field; //用于计算帧的底场的poc
int i_num_ref_frames_in_poc_cycle;//被用来解码poc
int i_offset_for_ref_frame[256];  //当i_poc_type=时用于解码poc,本句法元素对循环i_num_ref_frames_in_poc_cycle中的每一个元素指定一个偏移
int i_num_ref_frames;   //指定参考帧队列可能达到的最大长度,解码器根据这个句法元素的值开辟存储区,这个存储区用于存放已解码的参考帧
int b_gaps_in_frame_num_value_allowed;   //这个句法元素等于时,表示允许句法元素frame_num可以不连续;当传输信道堵塞时,允许丢弃若干帧
int i_mb_width;   //图像的宽度,以宏块为单位
int i_mb_height;  //图像的高度,以宏块为单位
int b_frame_mbs_only; //本句法元素等于时,表示本序列中所有的图像编码模式都是帧,没有其他编码模式存在;当为时,表示本序列中图像的编码模式可能是帧,也可能是场或帧场自适应
int b_mb_adaptive_frame_field;   //指明本序列是否属于帧场自适应模式
int b_direct8x8_inference; //指明b片的直接和skip模式下运动矢量的预测方法
int b_crop;//指明解码器是否要将图像裁剪后输出,如果是的话,后面紧跟的四个句法元素分别指出左、右、上、下裁剪的宽度
struct
{
   int i_left;
   int i_right;
   int i_top;
   int i_bottom;
} crop;
int b_vui;   //指明vui子结构是否出现在码流中
struct
{
......//省略
   /* FIXME to complete */
} vui;
int b_qpprime_y_zero_transform_bypass;
} x264_sps_t;

3.1.3.x264_pps_init( h->pps, h->param.i_sps_id, &h->param, h->sps);

typedef struct
{
    int i_id;      //本参数集的序号,在片头被引用
    int i_sps_id;  //本图像参数集所引用的序列参数集的序号
    int b_cabac;   //0时使用cavlc,时使用cabac
    int b_pic_order;  //poc的三种计算方法在片层还各需要用一些句法元素作为参数;当等于时,表示在片头会有句句法元素指明这些参数;当为时,表示片头不会给出这些参数
    int i_num_slice_groups;   //图像中片组的个数
    int i_num_ref_idx_l0_active;    //指明目前参考帧队列的长度,即有多少各参考帧(短期和长期),用于list0
    int i_num_ref_idx_l1_active;    //指明目前参考帧队列的长度,即有多少各参考帧(短期和长期),用于list1
    int b_weighted_pred;        //指明是否允许p和sp片的加权预测
    int b_weighted_bipred;      //指明是否允许b片的加权预测
    int i_pic_init_qp;          //亮度分量的量化参数的初始值
    int i_pic_init_qs;          //亮度分量的量化参数的初始值,用于SP和SI
    int i_chroma_qp_index_offset;    //色度分量的量化参数是根据亮度分量的量化参数计算出来的,本句法元素用以指明计算时用到的参数
    int b_deblocking_filter_control;   //编码器可以通过句法元素显式地控制去块滤波的强度
    int b_constrained_intra_pred;      //在p和b片中,帧内编码的宏块的邻近宏块可能是采用的帧间编码
    int b_redundant_pic_cnt;
    int b_transform_8x8_mode;
    int i_cqm_preset;
    const uint8_t *scaling_list[6]; /* could be 8, but we don't allow separate Cb/Cr lists */
} x264_pps_t;

 

x264_validate_levels( h );  

//////3.1.4.x264_cqm_init( x264_t *h ){

  1. …… 
  2. h->quant4_mf[i] = x264_malloc(52*size*sizeof(uint16_t) ); 
  3. h->dequant4_mf[i] = x264_malloc( 6*size*sizeof(int) ); 
  4. h->unquant4_mf[i] = x264_malloc(52*size*sizeof(int) ); 
  5. …… 
  6. h->quant4_bias[i] = x264_malloc(52*size*sizeof(uint16_t) ); 
  7. …… 
  8. } 
  9. //3.1.4 end 

/* Init frames. */

/* init CPU functions */

 

h->thread[i] = x264_malloc( sizeof(x264_t) );

 

h->thread[i]->fdec = x264_frame_pop_unused( h );

h->thread[i]->out.p_bitstream = x264_malloc( h->out.i_bitstream );

//定义要做nal的那些码流的地方,i_bitstream是大小,p_bitstream是指针

3.1.5 x264_frame_pop_unused( h ){

    x264_frame_t *frame;

    if( h->frames.unused[0] )

        frame = x264_frame_pop( h->frames.unused );  //从unused队列中//取出最后位置的一个桢

    else

        frame = x264_frame_new( h );        //分配一帧所需要的空间

///////3.1.5.1 x264_frame_new( h ){

        ……

for( i = 0; i < 3; i++ )      //分配frame的yuv空间,带边框

{

int i_divh = 1;

int i_divw = 1;

if( i > 0 )

{

if( h->param.i_csp == X264_CSP_I420 )

i_divh = i_divw = 2;

else if( h->param.i_csp == X264_CSP_I422 )

i_divw = 2;

}

frame->i_stride[i] = i_stride / i_divw;

frame->i_lines[i] = i_lines / i_divh;

CHECKED_MALLOC( frame->buffer[i],

frame->i_stride[i] * ( frame->i_lines[i] + 2*i_padv / i_divh ) );

 

frame->plane[i] = ((uint8_t*)frame->buffer[i]) +

frame->i_stride[i] * i_padv / i_divh + PADH / i_divw;

//plane指向除去buffer中图像边框的yuv真实数据

……

        }

///////3.1.5.1 end

}

    assert( frame->i_reference_count == 0 );

    frame->i_reference_count = 1;

return frame;

 

if( x264_macroblock_cache_init( h->thread[i] ) < 0 ) return NULL;

3.1.6.x264_macroblock_cache_init( x264_t *h ){

//分配x264_t结构体下子结构体mb对应的qp、cbp、skipbp、mb_transform_size、intra4x4_pred_mode、non_zero_count等等在宏块编码时用于控制和传输等用到的表!

……

CHECKED_MALLOC( h->mb.qp, i_mb_count * sizeof(int8_t) );

    CHECKED_MALLOC( h->mb.cbp, i_mb_count * sizeof(int16_t) );

    CHECKED_MALLOC( h->mb.skipbp, i_mb_count * sizeof(int8_t) );

    CHECKED_MALLOC( h->mb.mb_transform_size, i_mb_count * sizeof(int8_t) );

    /* 0 -> 3 top(4), 4 -> 6 : left(3) */

    CHECKED_MALLOC( h->mb.intra4x4_pred_mode, i_mb_count * 7 * sizeof(int8_t) );

    /* all coeffs */

    CHECKED_MALLOC( h->mb.non_zero_count, i_mb_count * 24 * sizeof(uint8_t) );

    //以4*4块为单位,24=4*4+2*2+2*2(yuv)

    CHECKED_MALLOC( h->mb.nnz_backup, h->sps->i_mb_width * 4 * 16 * sizeof(uint8_t) );

 

    if( h->param.b_cabac )

    {

        CHECKED_MALLOC( h->mb.chroma_pred_mode, i_mb_count * sizeof(int8_t) );

        CHECKED_MALLOC( h->mb.mvd[0], 2*16 * i_mb_count * sizeof(int16_t) );

//mvd[0]指x方向,2*16中的2指前向和后向,16表示mv以4*4为单位

        CHECKED_MALLOC( h->mb.mvd[1], 2*16 * i_mb_count * sizeof(int16_t) );

    }

 

    for( i=0; i<2; i++ )

    {

        int i_refs = X264_MIN(16, (i ? 1 : h->param.i_frame_reference) + h->param.b_bframe_pyramid) << h->param.b_interlaced;

        for( j=0; j < i_refs; j++ )

            CHECKED_MALLOC( h->mb.mvr[i][j], 2 * i_mb_count * sizeof(int16_t) );

    }

 

    for( i=0; i<=h->param.b_interlaced; i++ )

        for( j=0; j<3; j++ )

        {

            CHECKED_MALLOC( h->mb.intra_border_backup[i][j], h->fdec->i_stride[j] );

            h->mb.intra_border_backup[i][j] += 8;

        }

……

///////3.1.6 end

 

3.1.7

if( x264_ratecontrol_new( h ) < 0 ) return NULL;

//码率控制初始化

 

……

return h;

 

(jia_xiaoxin)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201301/16477.html]
本文出处:CSDN博客 作者:jia_xiaoxin 原文
顶一下
(3)
100%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容