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;
}