x264代码剖析(三):主函数main()、解析函数parse()与编码函数encode()
x264的入口函数为main()。main()函数首先调用parse()解析输入的参数,然后调用encode()编码YUV数据。parse()首先调用x264_param_default()为保存参数的x264_param_t结构体赋默认值;然后在一个大循环中通过getopt_long()解析通过命令行传递来的存储在argv[]中的参数,并作相应的设置工作;最后调用select_input()和select_output()完成输入文件格式(yuv,y4m等)和输出文件格式(裸流,mp4,mkv,FLV等)的设置。encode()首先调用x264_encoder_open()打开编码器;接着在一个循环中反复调用encode_frame()一帧一帧地进行编码;最后在编码完成后调用x264_encoder_close()关闭编码器。encode_frame()则调用x264_encoder_encode()将存储YUV数据的x264_picture_t编码为存储H.264数据的x264_nal_t。具体函数关系如下图所示:
下面对该函数关系图中的主函数main()、解析函数parse()与编码函数encode()做详细的分析。
1、主函数main()
主函数主要调用了两个函数:parse()和encode()。main()首先调用parse()解析输入的命令行参数,然后调用encode()进行编码。对应代码如下:
/******************************************************************/
/******************************************************************/
/*
======Analysed by RuiDong Fang
======Csdn Blog:http://blog.csdn.net/frd2009041510
======Date:2016.03.07
*/
/******************************************************************/
/******************************************************************/
/************====== 主函数 ======************/
/*
功能:主要调用了两个函数:parse()和encode()。
main()首先调用parse()解析输入的命令行参数,然后调用encode()进行编码。
*/
int main( int argc, char **argv )
{
x264_param_t param; //参数集
cli_opt_t opt = {0};
int ret = 0;
FAIL_IF_ERROR( x264_threading_init(), "unable to initialize threading\n" )
#ifdef _WIN32
FAIL_IF_ERROR( !get_argv_utf8( &argc, &argv ), "unable to convert command line to UTF-8\n" )
GetConsoleTitleW( org_console_title, CONSOLE_TITLE_SIZE );
_setmode( _fileno( stdin ), _O_BINARY );
_setmode( _fileno( stdout ), _O_BINARY );
_setmode( _fileno( stderr ), _O_BINARY );
#endif
/* Parse command line */
if( parse( argc, argv, ¶m, &opt ) < 0 ) ///解析命令行输入,调用parse()
ret = -1;
#ifdef _WIN32
/* Restore title; it can be changed by input modules */
SetConsoleTitleW( org_console_title );
#endif
/* Control-C handler */
signal( SIGINT, sigint_handler );
if( !ret )
ret = encode( ¶m, &opt ); ///编码,调用encode()
/* clean up handles */
if( filter.free )
filter.free( opt.hin );
else if( opt.hin )
cli_input.close_file( opt.hin );
if( opt.hout )
cli_output.close_file( opt.hout, 0, 0 );
if( opt.tcfile_out )
fclose( opt.tcfile_out );
if( opt.qpfile )
fclose( opt.qpfile );
#ifdef _WIN32
SetConsoleTitleW( org_console_title );
free( argv );
#endif
return ret;
}
2、解析函数parse()
解析函数parse()解析输入的命令行参数,存储于argv[]中,对应的代码如下:
/************====== 解析函数 ======************/