Main(int argc,char *argv[]);
为了方便起见,不妨改写为:
Main(void){
......
intargc=5;
char*argv[]={
"main","-o","test.264","foreman.yuv","352x288"
};
......
}
====================================
1.x264_param_default(¶m);
这部分设置编码参数的缺省值
附部分变量的意义:
param->i_csp =X264_CSP_I420; // 设置输入的视频采样的格式
param->vui.i_sar_width =0; //VUI:videousability information
param->i_fps_num =10; //帧率
param->i_fps_den =1; //用两个整型的数的比值,来表示帧率
param->i_frame_reference= 1; //参考帧的最大帧数。
param->i_bframe=0; //两个参考帧之间的B帧数目。
param->b_deblocking_filter = 1; //去块效应相关
param->b_cabac =0; //cabac的开关
param->i_cabac_init_idc = -1;
param->rc.b_cbr=1; //constantbitrate 恒定码率控制模式
param->rc.i_bitrate=0; //默认的码率
param->rc.i_rc_buffer_size=0; //buffer的大小
param->rc.i_rc_init_buffer=0; //
param->rc.i_rc_sens =100; ////整个param的一个log文件
param->analyse.intra = X264_ANALYSE_I4x4 | X264_ANALYSE_I8x8;
//桢内分析
param->analyse.inter = X264_ANALYSE_I4x4 | X264_ANALYSE_I8x8 |X264_ANALYSE_PSUB16x16 |X264_ANALYSE_BSUB16x16;
//桢间分析
param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_SPATIAL;
//预测模式
param->analyse.i_me_method = X264_ME_HEX; //运动估计模式
param->analyse.i_me_range =16; //运动估计范围
param->analyse.i_subpel_refine= 5;
param->analyse.b_chroma_me= 1;
param->analyse.i_mv_range_thread= -1;
param->analyse.i_mv_range= -1; // set fromlevel_idc
param->analyse.i_direct_8x8_inference= -1; // set fromlevel_idc
param->analyse.i_chroma_qp_offset= 0;
param->analyse.b_fast_pskip= 1;
param->analyse.b_dct_decimate= 1;
param->analyse.i_luma_deadzone[0]= 21;
param->analyse.i_luma_deadzone[1]= 11;
param->analyse.b_psnr= 1;
param->analyse.b_ssim= 1;
param->i_cqm_preset= X264_CQM_FLAT; //自定义量化矩阵(CQM),初始化量化模式为flat
2.Parse(argc, argv, ¶m, &opt ) ;
解析函数intc= getopt_long( argc, argv, "8A:B:b:f:hI:i:m:o:p:q:r:t:Vvw",
long_options, &long_options_index);
// 得到入口地址的向量与方式的选择
_getopt_internal (argc,argv, optstring, longopts, longind, long_only);
//解析入口地址向量
3.Encode(¶m,&opt );
3.1.x264_encoder_open(param ){
……
x264_t*h = x264_malloc( sizeof( x264_t )); //为h分配空间
memcpy( &h->param, param, sizeof( x264_param_t ) );
……
3.1.1.x264_validate_parameters(h ); //验证参数
h->sps= &h->sps_array[0];
3.1.2.x264_sps_init(h->sps, h->param.i_sps_id, &h->param );
typedef struct
{
inti_id; //本序列参数集的id号
inti_profile_idc; //指明所用的profile
inti_level_idc; //指明所用的level
intb_constraint_set0; //其值等于时,表示必须遵从附录A.2.1所指明的所有约束条件
intb_constraint_set1; //其值等于时,表示必须遵从附录A.2.2所指明的所有约束条件
intb_constraint_set2; //其值等于时,表示必须遵从附录A.2.3所指明的所有约束条件
inti_log2_max_frame_num; //这个句法元素只要是为读取frame_num服务的
inti_poc_type; //指明poc的编码方法,poc标识图像的播放顺序
inti_log2_max_poc_lsb; //指明了变量i_poc_lsb的max值
intb_delta_pic_order_always_zero; //其值为时,i_delta_poc[0]和i_delta_poc[1]不在片头出现,并且它们的默认值为;当本句法元素为时,上述两个句法元素将在片头出现
inti_offset_for_non_ref_pic; //用于计算非参考帧或场的poc
inti_offset_for_top_to_bottom_field;//用于计算帧的底场的poc
inti_num_ref_frames_in_poc_cycle; //被用来解码poc
inti_offset_for_ref_frame[256]; //当i_poc_type=时用于解码poc,本句法元素对循环i_num_ref_frames_in_poc_cycle中的每一个元素指定一个偏移
inti_num_ref_frames; //指定参考帧队列可能达到的最大长度,解码器根据这个句法元素的值开辟存储区,这个存储区用于存放已解码的参考帧
intb_gaps_in_frame_num_value_allowed; //这个句法元素等于时,表示允许句法元素frame_num可以不连续;当传输信道堵塞时,允许丢弃若干帧
inti_mb_width; //图像的宽度,以宏块为单位
inti_mb_height; //图像的高度,以宏块为单位
intb_frame_mbs_only; //本句法元素等于时,表示本序列中所有的图像编码模式都是帧,没有其他编码模式存在;当为时,表示本序列中图像的编码模式可能是帧,也可能是场或帧场自适应
intb_mb_adaptive_frame_field; //指明本序列是否属于帧场自适应模式
intb_direct8x8_inference; //指明b片的直接和skip模式下运动矢量的预测方法
intb_crop; //指明解码器是否要将图像裁剪后输出,如果是的话,后面紧跟的四个句法元素分别指出左、右、上、下裁剪的宽度
struct
{
inti_left;
inti_right;
inti_top;
inti_bottom;
}crop;
intb_vui; //指明vui子结构是否出现在码流中
struct
{
...... //省略
}vui;
intb_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
{
inti_id; //本参数集的序号,在片头被引用
inti_sps_id; //本图像参数集所引用的序列参数集的序号
intb_cabac; //0时使用cavlc,时使用cabac
intb_pic_order; //poc的三种计算方法在片层还各需要用一些句法元素作为参数;当等于时,表示在片头会有句句法元素指明这些参数;当为时,表示片头不会给出这些参数
inti_num_slice_groups; //图像中片组的个数
inti_num_ref_idx_l0_active; //指明目前参考帧队列的长度,即有多少各参考帧(短期和长期),用于list0
inti_num_ref_idx_l1_active; //指明目前参考帧队列的长度,即有多少各参考帧(短期和长期),用于list1
intb_weighted_pred; //指明是否允许p和sp片的加权预测
intb_weighted_bipred; //指明是否允许b片的加权预测
inti_pic_init_qp; //亮度分量的量化参数的初始值
inti_pic_init_qs; //亮度分量的量化参数的初始值,用于SP和SI
inti_chroma_qp_index_offset; //色度分量的量化参数是根据亮度分量的量化参数计算出来的,本句法元素用以指明计算时用到的参数
intb_deblocking_filter_control; //编码器可以通过句法元素显式地控制去块滤波的强度
intb_constrained_intra_pred; //在p和b片中,帧内编码的宏块的邻近宏块可能是采用的帧间编码
intb_redundant_pic_cnt;
intb_transform_8x8_mode;
inti_cqm_preset;
constuint8_t *scaling_list[6];
} x264_pps_t;
x264_validate_levels(h);
//////3.1.4.x264_cqm_init(x264_t *h ){
……
h->quant4_mf[i] = x264_malloc(52*size*sizeof(uint16_t) );
h->dequant4_mf[i]= x264_malloc( 6*size*sizeof(int));
h->unquant4_mf[i] = x264_malloc(52*size*sizeof(int));
……
h->quant4_bias[i] = x264_malloc(52*size*sizeof(uint16_t) );
……
}
//////3.1.4 end
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.1x264_frame_new( h ){
……
for( i = 0;i < 3;i++) //分配frame的yuv空间,带边框
{
inti_divh = 1;
inti_divw = 1;
if( i> 0 )
{
if( h->param.i_csp == X264_CSP_I420 )
i_divh= i_divw = 2;
elseif( 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;
returnframe;
}
if( x264_macroblock_cache_init( h->thread[i]) < 0 ) returnNULL;
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) );
CHECKED_MALLOC(h->mb.intra4x4_pred_mode, i_mb_count * 7 * sizeof(int8_t) );
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++ )
{
inti_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;
}