当前位置:
文档之家› x264学习笔记(1)-函数调用流程
x264学习笔记(1)-函数调用流程
i_file = 0; b_ctrl_c == 0 &&
(i_frame < i_frame_total || i_frame_total ==
0); )
parse_qpfile() Encode_frame()
i_frame++;
分析量化表,如果有 编码一帧
打印输出信息
编码循环结束 Encode_frame( )
x264_reference_build_list( h, h->fdec->i_poc ) /* build ref list 0/1 */
x264_ratecontrol_start( h, h->fenc->i_qpplus1 );
i_file += Encode_frame( h, opt->hout, &pic );
i_frame++;
… } 这是一个按 frame 计算的循环,逐帧编码,直到编完所有的帧; p_read_frame( &pic, opt->hin, i_frame + opt->i_seek ):从源文件中读取一个要编码 的帧数据; Encode_frame( h, opt->hout, &pic ):进行一帧编码; 流程图如下:
return
2. 函数 x264_encoder_open( param ): 这个函数主要作用是: 1) 检查编码参数4) 初始化量化表; 5) 初始化 RDO; 6) 初始化部分编码中用到的函数(函数指针); 函数流程如下:
初始化编码过程 中所用到的函
数,初始化部分
参数
h->thread[i]->fdec = x264_frame_pop_unused( h ); h->thread[i]->out.p_bitstream = x264_malloc( h>out.i_bitstream ); x264_macroblock_cache_init( h->thread[i] )
x264_init_vlc_tables(); x264_pixel_init( h->param.cpu, &h->pixf ); x264_dct_init( h->param.cpu, &h->dctf ); x264_zigzag_init( h->param.cpu, &h->zigzagf, h>param.b_interlaced ); x264_mc_init( h->param.cpu, &h->mc ); x264_quant_init( h, h->param.cpu, &h->quantf ); x264_deblock_init( h->param.cpu, &h->loopf ); x264_dct_init_weights(); mbcmp_init( h );
/* 1: Copy the picture to a frame and move it to a buffer */
x264_stack_align( x264_slicetype_decide, h )
/* 2: Select frame types */
x264_frame_push()
/* 3: move some B-frames and 1 non-B to encode queue */
x264_encoder_open(x264_param_t *param)
x264_validate_parameters()
检查编码参数
x264_cqm_parse_file()
分析quant matrices, 如果有配置
x264_sps_init()
初始化SPS参数集
x264_pps_init() x264_validate_levels()
x264_ratecontrol_new() return
初始化ratecontrol
3. x264_encoder_encode( h, &nal, &i_nal, pic, &pic_out ) 函数 Encode_frame()中主要调用 x264_encoder_encode(),这是编码器的编码主流 程,这个函数的调用流程如下: 1) x264_reference_update( h ) 更新参考帧队列,碰到不用作参考的 B 帧的时候,不做更新; 2) 根据上面的结果,对帧 buffer 进行管理; 3) x264_stack_align( x264_slicetype_decide, h ) 决定当前编码的 slice 的类型; 4) x264_frame_shift( h->frames.current ) 获得要编码的当前帧,注意:前面 p_read_frame()函数是按照显示顺序逐帧将数 据从源文件中读取进来的,但是并不会立即编码,会预先存放在 buffer 中,有 B 帧 的时候,编码顺序和显示顺序是不一样的;这里才会按照编码顺序从 buffer 中 load 一个需要编码的帧数据; 5) x264_reference_build_list( h, h->fdec->i_poc ) 在一个 slice 编码前,需要初始化参考帧队列,ref_list0 和 ref_list1; 6) x264_ratecontrol_start( ) 和 i_global_qp = x264_ratecontrol_qp( h ) 码率控制,对编码流程无影响; 7) x264_macroblock_bipred_init( h ) 如果是 B slice 则调用此函数,主要根据 POC 值初始化双向参考帧队列,以及预测权 重系数; 8) x264_slice_init( h, i_nal_type, i_global_qp ) 建立一个 slice header; 9) x264_nal_start(),x264_sps_write(),x264_pps_write(),x264_nal_end(); 这个好理解,SPS, PPS; 10) x264_slices_write( h ) 这个是主要编码函数,才是重点,该函数开始进行一个 slice 的 bit stream 的真正编 码;后面介绍
X264 源代码版本:x264-snapshot-20090319-2245
1. 函数主流程 函数的入口在 x264.c 中 main(): 1) 进入 main()函数 后,首 先执行 2 个 函数:x264_param_default( ¶m ) 和 Parse( argc, argv, ¶m, &opt ); x264_param_default( ¶m ):设置参数集 param 的缺省值; Parse( argc, argv, ¶m, &opt ):这里主要分析命令行参数,打开输入输出文件, 同时根据环境设置初始化某些函数指针; 2)之后进入函数 Encode( x264_param_t *param, cli_opt_t *opt ); 3 ) 函 数 Encode( x264_param_t *param, cli_opt_t *opt ) 首 先 调 用 x264_encoder_open( param ):后面论述 4)x264_picture_alloc( &pic, X264_CSP_I420, param->i_width, param->i_height ): 这个函数主要 malloc 一个编码 buffer,分 3 个部分,分别存放 Y,U,V; 5)之后就进去编码的一个主循环,一个 for 循环 /* Encode frames */ for( i_frame = 0, i_file = 0; b_ctrl_c == 0 && (i_frame < i_frame_total || i_frame_total == 0); ) { if( p_read_frame( &pic, opt->hin, i_frame + opt->i_seek ) ) break;
x264_mdate()
malloc一个picture buffer (i_width*i_height*1.5), img.plane[0],[1],[2]分别指向 Y,U,V, 并初始化i_stride
p_read_frame()
读取一个编码帧的原始数据
for循环:逐帧编码 for( i_frame = 0,
x264_encoder_encode ()的流程如下:
x264_encoder_encode( x264_t *h, x264_nal_t **pp_nal, int *pi_nal, x264_picture_t *pic_in, x264_picture_t *pic_out )
x264_reference_update()
Encode()函 数,编码器
主循环
main() (x264.c)
x264_param_default()
Parse()
分析命令行参数,并 打开输入输出文件
Encode()
x264_encoder_open()
初始化编码器参数,以及 编码器用到的函数
p_set_outfile_param() x264_picture_alloc()
context
/* init CPU functions */ x264_predict_16x16_init( h->param.cpu, h->predict_16x16 ); x264_predict_8x8c_init( h->param.cpu, h->predict_8x8c ); x264_predict_8x8_init( h->param.cpu, h->predict_8x8, &h>predict_8x8_filter ); x264_predict_4x4_init( h->param.cpu, h->predict_4x4 ); if( !h->param.b_cabac );