x264-060805-vc6 之 main ()函数完全解析

转自:http://bbs.chinavideo.org/forum.php?mod=viewthread&tid=12041&extra=page%3D3%26filter%3Dtypeid%26typeid%3D13%26typeid%3D13


原创:x264-060805-vc6 之 main ()函数完全解析 - 加菲 - 视频会议 - 加菲


补一下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[])这样的形式进行定义。argcargv可以换成你自己喜欢的名称,不一定要用argvargc。这些形式只是习惯而已,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是参数个数,argvchar*字符数组。我猜想,Parse肯定会把argv一个字符一个字符的进行取出,然后做一些小动作。

而Parse函数返回值和0比较,那估计Parse的类型应该是int一类的(还没去看具体的Parse定义,先猜吧),从上面这段代码可以看到,如果返回值为负值,就会退出程序了,这种情况应该是因为我们输入的命令行参数不合法吧。比如文件路径不对,或者提供了x264.exe不支持的文件类型。不知道我猜的对不对,大侠路过时捎带指点一下啊。

main函数的类型是
int ,所以必须有返回值,也就是得有个return 0或者return1之类的。

 
   return Encode( ¶m, &opt );


Encode的汉语翻译是编码,这个函数的返回类型肯定也是int,不然main函数的return就要生气了。
根据字面意思,实际的编码就是“Encode( &para;m, &opt )”这句进行的,我们提供的命令行参数只是个前提和准备。

而要用“Encode(& p a r a m, & o p t )”,我们得提前准备好两个参数“ &para;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好像就是空字符,


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值