补一下C++的命令行参数的知识:
很早以前的dos应用程序中,我们经常会用命令行参数执行应用程序例如:
copy c:\1.txt d:\
在c/c++中,命令行参数的传递是利用main进行形参传递实现的。
前面的教程中我们都进行了void main()或者是void main(void)的定义,void 表示main不返回任何类型,main() 和main(void)表示不带有任何参数,但在缺剩状态下mian()这种形式下,形式参数一直是存在于栈空间内的,只是隐藏了起来。
为了实现命令行参数,我们将使用main(int argc,char*argv[])这样的形式进行定义。argc和argv可以换成你自己喜欢的名称,不一定要用argv,argc。这些形式只是习惯而已,char* argv[]我们前面已经讲述过,这就是一个指向指针数组,argv就是一个指针数组名,argv不是常量指针,而是具备变量特性的变量指针,它是可以移动的,由此我们可以改写成char* *argv也是正确的,int argc这个定义返回的将是参数的个数所以标记为整形(int)。
char *,它在C/C++中有专门的语义,既不同于signed char *,也不同于unsigned char *,专门用于指以'\0'为结束的字符串。(我记的好多地方都叫它做C风格字符串)
查一下这里面貌似英文单词的,笨人的笨办法:
argc:命令行参数个数;
argv:命令行参数数组;
BINARY:二进制的;
Parse:语法分析,解析;
default:默认;系统设定值;预置值
signal:信号情报
Handler:handle 句柄...handler 处理器
Encode:把…编码
main函数是VC程序的入口点函数,程序从这里开始执行,在dos命令行输入命令后,就直接到这里开始执行,提供的参数,程序肯定是要接收它,并用它们去影响程序的行为,我是这么想的,那么这两个参数在main的函数体中,我们就要找到它并试着去理解去猜想它们。
/* Parse command line */
if( Parse( argc, argv, ¶m, &opt ) < 0 )
return -1;
Parse,我查英汉词典了,意思是解析,呵呵。它的前两个参数正好是main入口函数的两个参数,argc是参数个数,argv是char*字符数组。我猜想,Parse肯定会把argv一个字符一个字符的进行取出,然后做一些小动作。
而Parse函数返回值和0比较,那估计Parse的类型应该是int一类的(还没去看具体的Parse定义,先猜吧),从上面这段代码可以看到,如果返回值为负值,就会退出程序了,这种情况应该是因为我们输入的命令行参数不合法吧。比如文件路径不对,或者提供了x264.exe不支持的文件类型。不知道我猜的对不对,大侠路过时捎带指点一下啊。
main函数的类型是int ,所以必须有返回值,也就是得有个return 0或者return1之类的。
return Encode( ¶m, &opt );
Encode的汉语翻译是编码,这个函数的返回类型肯定也是int,不然main函数的return就要生气了。
根据字面意思,实际的编码就是“Encode( ¶m, &opt )”这句进行的,我们提供的命令行参数只是个前提和准备。
而要用“Encode(& p a r a m, & o p t )”,我们得提前准备好两个参数“ ¶m” 和“&opt” ,看到这个,自然而然的想起了C++里的按地址传递和按值传递。
这两个参数到底是吗意思呢?先找找在哪儿定义的吧
x264_param_t param;
cli_opt_t opt;
如上,是在一进入main函数体就定义了它们,C++中内置类型没见过它们,那一定是#define之类,要不就是结构体了,先停一下去源码里搜一下。
结果在x264.h头文件里找到了(在代码中x264_param_t上点右键,右键菜单中选“转到x264_param_t的定义”),出现在面前的是一个超级大的结构体:
typedef struct
{
/* CPU flags */
unsigned int cpu;
int i_threads; /* divide each frame into multiple slices, encode in parallel */
/* Video Properties */
int i_width;
int i_height;
int i_csp; /* CSP of encoded bitstream, only i420 supported */
int i_level_idc;
int i_frame_total; /* number of frames to encode if known, else 0 */
struct
{
/* they will be reduced to be 0 < x <= 65535 and prime */
int i_sar_height;
int i_sar_width;
int i_overscan; /* 0=undef, 1=no overscan, 2=overscan */
/* see h264 annex E for the values of the following */
int i_vidformat;
int b_fullrange;
int i_colorprim;
int i_transfer;
int i_colmatrix;
int i_chroma_loc; /* both top & bottom */
} vui;
int i_fps_num;
int i_fps_den;
/* Bitstream parameters */
int i_frame_reference; /* Maximum number of reference frames */
int i_keyint_max; /* Force an IDR keyframe at this interval */
int i_keyint_min; /* Scenecuts closer together than this are coded as I, not IDR. */
int i_scenecut_threshold; /* how aggressively to insert extra I frames */
int i_bframe; /* how many b-frame between 2 references pictures */
int b_bframe_adaptive;
int i_bframe_bias;
int b_bframe_pyramid; /* Keep some B-frames as references */
int b_deblocking_filter;
int i_deblocking_filter_alphac0; /* [-6, 6] -6 light filter, 6 strong */
int i_deblocking_filter_beta; /* [-6, 6] idem */
int b_cabac;
int i_cabac_init_idc;
int i_cqm_preset;
char *psz_cqm_file; /* JM format */
uint8_t cqm_4iy[16]; /* used only if i_cqm_preset == X264_CQM_CUSTOM */
uint8_t cqm_4ic[16];
uint8_t cqm_4py[16];
uint8_t cqm_4pc[16];
uint8_t cqm_8iy[64];
uint8_t cqm_8py[64];
/* Log */
void (*pf_log)( void *, int i_level, const char *psz, va_list );
void *p_log_private;
int i_log_level;
int b_visualize;
/* Encoder analyser parameters */
struct
{
unsigned int intra; /* intra partitions */
unsigned int inter; /* inter partitions */
int b_transform_8x8;
int b_weighted_bipred; /* implicit weighting for B-frames */
int i_direct_mv_pred; /* spatial vs temporal mv prediction */
int i_chroma_qp_offset;
int i_me_method; /* motion estimation algorithm to use (X264_ME_*) */
int i_me_range; /* integer pixel motion estimation search range (from predicted mv) */
int i_mv_range; /* maximum length of a mv (in pixels) */
int i_subpel_refine; /* subpixel motion estimation quality */
int b_bidir_me; /* jointly optimize both MVs in B-frames */
int b_chroma_me; /* chroma ME for subpel and mode decision in P-frames */
int b_bframe_rdo; /* RD based mode decision for B-frames */
int b_mixed_references; /* allow each mb partition in P-frames to have it's own reference number */
int i_trellis; /* trellis RD quantization */
int b_fast_pskip; /* early SKIP detection on P-frames */
int b_dct_decimate; /* transform coefficient thresholding on P-frames */
int i_noise_reduction; /* adaptive pseudo-deadzone */
int b_psnr; /* Do we compute PSNR stats (save a few % of cpu) */
} analyse;
/* Rate control parameters */
struct
{
int i_rc_method; /* X264_RC_* */
int i_qp_constant; /* 0-51 */
int i_qp_min; /* min allowed QP value */
int i_qp_max; /* max allowed QP value */
int i_qp_step; /* max QP step between frames */
int i_bitrate;
int i_rf_constant; /* 1pass VBR, nominal QP */
float f_rate_tolerance;
int i_vbv_max_bitrate;
int i_vbv_buffer_size;
float f_vbv_buffer_init;
float f_ip_factor;
float f_pb_factor;
/* 2pass */
int b_stat_write; /* Enable stat writing in psz_stat_out */
char *psz_stat_out;
int b_stat_read; /* Read stat from psz_stat_in and use it */
char *psz_stat_in;
/* 2pass params (same as ffmpeg ones) */
char *psz_rc_eq; /* 2 pass rate control equation */
float f_qcompress; /* 0.0 => cbr, 1.0 => constant qp */
float f_qblur; /* temporally blur quants */
float f_complexity_blur; /* temporally blur complexity */
x264_zone_t *zones; /* ratecontrol overrides */
int i_zones; /* sumber of zone_t's */
char *psz_zones; /* alternate method of specifying zones */
} rc;
/* Muxing parameters */
int b_aud; /* generate access unit delimiters */
int b_repeat_headers; /* put SPS/PPS before each keyframe */
int i_sps_id; /* SPS and PPS id number */
} x264_param_t;
网上能搜到好多进行了中文注释的,我转到了我的博客上,不然人家随时可能会删了,要看的话点这里,值得注意的是,这里面有好多是结构体的嵌套定义,专业的就是不一样,看代码写的整整齐齐的,真的很享受。
另一个结构体的定义就显得小儿科了:
typedef struct {
int b_progress;
int i_seek;
hnd_t hin;
hnd_t hout;
FILE *qpfile;
} cli_opt_t;
上次编译的时候,不知道还要编译生成x264.exe,先去论坛里找找命令行的用法。
xp->开始->运行,输入cmd,回车,出现黑底白字的窗口和几行字,其中有 “C:\Document and Settings\User\>”表示当前所在的目录,后面闪的光标代表等待输入内容。
假设x264.exe在E:\Encoder\文件夹,输入
>cd /D E:\Encoder
回车
改变当前目录到E:\Encoder了。接下来,输入
>x264
回车
接下来,不用截图说明会返回的信息了,而直接粘贴cmd里返回的字符。输入命令会以“>”提示,看到“>”就代表此行是输入命令并回车。
我们看到,如果只运行x264,什么都不提供给他,x264会返回一个错误。他告诉我们缺少输入文件,并提示我门输入“x264 --help”会列出选项。照他说的,加--help试试。
>x264 --help
返回
x264 core:104 r1688M 0b36c6d Syntax: x264[options] -o outfile infile Infile can be raw (in which case resolution isrequired), or YUV4MPEG (*.y4m), or Avisynth if compiled with support (no). orlibav* formats if compiled with lavf support (no) or ffms support (yes).Outfile type is selected by filename: .264 -> Raw bytestream .mkv ->Matroska .flv -> Flash Video .mp4 -> MP4 Output bit depth: 8 (configuredat compile time) Options: -h, --help List basic options --longhelp List moreoptions --fullhelp List all options Example usage: Constant quality mode: x264--crf 24 -o <output> <input> 中间略... Input/Output: -o, --output Specify output file --sarwidth:height Specify Sample Aspect Ratio --fps <float|rational> Specifyframerate --seek <integer> First frame to encode --frames <integer>Maximum number of frames to encode --level <string> Specify level (asdefined by Annex A) --quiet Quiet Mode Filtering: Filter options may bespecified in the name=value format --vf, --video-filter <filter0>/<filter1>/...Apply video filtering to the input file Available filters:crop:left,top,right,bottomresize:[width,height][,sar][,fittobox][,csp][,method]select_every:step,offset1[,...]
这下返回了不少字符。x264先告诉我们他的版本号,再告诉我们他的基本用法是“x264 [options] -o outfile infile”。还提示我们可以输入“--longhelp”或“--fullhelp”查看详细选项或所有的选项。
接着输入
>x264 --fullhelp
列出了所有选项。
x264.exe的用法是,在命令行里输入形如
>x264 [--参数名 参数值 ...] --output 输出文件 输入文件
其中方括号里是可输入可不输入的,“...”是可以输很多个的意思。观察这个形式,每个参数名之前要加“--”,空格后跟此参数名的参数值;一定要有“--output”并指定输出文件;一定要指定输入文件,但前面没有“--”之类的提示符号。
此外,还有短参数模式。这是为了简化某些常用参数名设计的。一个“-”加一个字母构成一个短参数名,和与之对应的普通参数名效果一样。注意此时这个字母区分大小写。在--fullhelp列表里,有短参数的参数的短参数都列在此参数的前面。
实际命令实例:
>x264 --crf 22 --profile main --tune animation--preset medium --b-pyramid none -o psp.mp4 ep01.avs
调用x264编码当前目录下的"ep01.avs"文件,输入"psp.264"。
>"D:\encoder tools\x264.exe" --crf 18--tune touhou --preset slower -I 24 -o "D:\touhou\out.mkv""D:\touhou\th9\rec.avi"
这个例子中,x264.exe、和输入文件都不在当前目录下,也不输出到当前路径,就要写完整的路径,如果有空格就需要在完整的路径左右加上引号。
在Windows XP和Windows 7中,把文件拖拽到cmd里,cmd会自动把文件的完整路径写在命令行上的。
x264的输入输出文件类型
在加入了ffms/lavf后,x264可以直接输入几乎所有类型的片子,而不是像原来一样必须借助于avs。下面所讲的是输入输出的片子类型,除此之外的输入输出还有多pass中的stats文件、qp file、量化矩阵和tc file。
输入:
x264支持输入的文件类型有raw yuv、y4m、avs和任何可以由ffms或lavf打开的文件。raw yuv会用在64位的x264里。有ffms/lavf打开的片子会自动正确的处理vfr问题。avs和ffms/lavf输入不需要指定片子的分辨率。
输出:
x264可以输出没有封装的H.264视频流,扩展名是.264;matroska视频,扩展名是.mkv;flash视频,扩展名是.flv;mp4视频,扩展名是.mp4。mkv、mp4和flv可以是vfr的。
x264通过输出文件的扩展名判断输出文件类型。
详细的说明请点这里
刚才下载了个x264.exe,试着转了两个视频,一个是avi,一个是rmvb,这个rmvb半天了还在转换中,我把转换操作录了个视频,放到论坛上了:用X264.exe转换一个AVI文件的屏幕录像
我转换时,在dos窗口中输入的命令为:
x264 --crf 22 --profile main --tune animation--preset medium --b-pyramid none -o test.mp4 oldFile.avi
x264 --crf 22 --profile main --tune animation--preset medium --b-pyramid none -o 功夫熊猫感恩节特辑.mp4 功夫熊猫感恩节特辑.rmvb
只知道最后的两个,一个是待转的源文件名,一个是转换的目标文件名,其它的就不知道了,也难怪,既没看程序的源代码,也没在网上搜索,现在还是到源代码里转转吧,继续享受专家漂亮的代码。
main函数中,Parse( argc, argv, & p aram, &opt )这句引起了我的兴趣,函数名的翻译为:Parse:语法分析,解析;
顾名思议,就是把我们输入的参数进行识别,并且把main函数开始定义的两个参数地址一并用上了。
我在VC6中,定位到Parse函数的定义:
。。。省略若干行代码
里面有个注释“/* Parsecommand line options */”,解析命令行参数,是不是和前面我们输入的命令行对应上了,呵呵。越来越有意思了。
static struct option long_options[] = ....
这个是C++的结构体数组的定义,数组元素是option类型,option也是一个结构体:
struct option
{
# if (defined __STDC__ && __STDC__) || defined __cplusplus
const char *name;
# else
char *name;
# endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
option 结构体有 4 个字段,这就是为什么 struct option long_options[] 内部有好多 { "help", no_argument, NULL, 'h' } 之类的花括号,每一对用花括号中的内容都是初始化数组元素的,对应的就是 option 的 4 个参数。
我是这样理解的,不知道对不对。
其中:
"help" -------- const char *name
no_argument -------- # defineno_argument 0 -------- int has_arg
NULL -------- #define NULL ((void*)0) -------- int *flag;
'h' -------- char -------- int val; (char在标准中是unsigned)
static char const *strtable_lookup( const char* const table[], int index )
{
int i = 0; while( table ) i++;
return ( ( index >= 0 && index < i ) ? table[ index] : "???" );
}
第一个参数为const char *const,找点这方面的资料看看:
深入理解constchar*p,char const*p,char *const p,const char **p,char const
看了半天,这个函数好像是提供一个char字符串和一个数字,从中取这个数字所对应位置的字符,不是有现成的函数么,搞什么鬼啊
静态函数:
在函数的返回类型前加上static关键字,函数即被定义为静态函数。静态函数与普通函数不同,它只能在声明它的文件当中可见,不能被其它文件使用。
定义静态函数的好处:
静态函数不能被其它文件所用;
其它文件中可以定义相同名字的函数,不会发生冲突;
( ( index >= 0 && index < i )? table[ index ] : "???" );
&&逻辑与
?问号操作符,表达式1为真,执行问号后的,否则,执行冒号后的
while( table [ i ] ) i++;
只要数组的第i个元素不为0,while就一直循环下去执行i++,那什么时候table[i ] 会为0呢,难道是字符串尾,遇上\0吗,估计是这意思,\0好像就是空字符,