FFplay是如何解析命令行参数的

文章介绍了FFmpeg中FFplay命令行参数解析的关键,主要围绕OptionDef数据结构展开,包括name、flags、u、help和argname字段的含义。flags字段的各个属性如HAS_ARG、OPT_BOOL等被详细解释,说明了如何处理不同类型的命令行参数。此外,文章提到了ffplay和ffmpeg在解析命令行参数时的差异,并指出parse_options()函数在解析过程中的作用。

FFmpeg 的社群来了,想加入微信社群的朋友请购买《FFmpeg原理》VIP版 电子书,里有更高级的内容与答疑服务。


为什么我会把命令行参数解析的文章放在后面,因为初学者使用 FFplay,通常不会去用太多的命令参数,通常初学者接触到的第一条 FFplay 命令是这样的。

ffplay -i juren.mp4

就是简简单单播放一个文件。


但是深入使用 FFplay 之后,必然会接触到各种各样的参数,你在工作中要验证一些问题的时候,也会用到各种各样的参数。因此理解 FFplay 命令行参数的解析逻辑是非常重要的。

命令行参数的解析逻辑,是通过一个 OptionDef 的数据结构定义的,如下:

ypedef struct OptionDef {
    const char *name;
    int flags;
    .....
    union {
        void *dst_ptr;
        int (*func_arg)(void *, const char *, const char *);
        size_t off;
    } u;
    const char *help;
    const char *argname;
} OptionDef;

OptionDef 其实是一个通用的数据结构,ffprobe.exe ,ffplay.exe 跟 ffprobe.exe 都是用的 OptionDef 数据结构来定义自己的命令行参数。

因此只要了解了 OptionDef 结构,基本上就成功了一半。

下面详细讲一下 OptionDef 里各个字段的含义。

1,const char *name,命令行参数名称,也就是 - 符号后面的字符串。

2,int flags,参数的属性,一共有 19 种属性,但是有些不是给 ffpaly.exe 用的,而是给 ffmpeg.exe 用的,等下会详细讲解各个值。

3,union {...} u,这是一个联合体,可以是参数的值,或者是处理参数的函数,又或者是 OptionsContext 结构体的偏移值(off),通过偏移值找到结构体中的某个字段。

在 FFplay 播放器里面,union {...} u 只会是 参数的值 或者 是处理参数的函数,不会用到偏移值(off),off 是给 ffmpeg.exe 用的。

4,const char *help,帮助信息。

5,const char *argname,参数的英文解释,用来拼接,输出帮助信息的。


现在来讲一下 flags 字段分别有哪些属性,这个 flags 字段是最重要的。

1,#define HAS_ARG 0x0001

代表命令行参数是否有值,例如 -x 400 指定播放宽度为 400 就是有值的,400 就是一个值。而 -an 代表不播放音频,-an 命令行参数是没有值的。


2,#define OPT_BOOL 0x0002

代表命令行参数是否是布尔值,布尔值后面都是没有 value 的,例如 -an 就是一个布尔值,如果想取反,需要在前面加上 no 前缀,例如 -noan

OPT_BOOL 跟 HAS_ARG 是相反的两个属性。

提醒:C99 标准是没有布尔值的,命令行的布尔参数最后会转成 0 跟 1 赋值给变量。

3,#define OPT_STRING 0x0008,代表命令行参数的值是一个字符串。

4,#define OPT_INT 0x0080,代表命令行参数的值是一个32位整数(int)。

5,#define OPT_INT64 0x0400,代表命令行参数的值是一个64位整数(int64)。

6,#define OPT_FLOAT 0x0100,代表命令行参数的值是一个单精度浮点数(float)。

7,#define OPT_DOUBLE 0x20000,代表命令行参数的值是双精度浮点数。

8,#define OPT_TIME 0x10000,代表命令行参数的值是时间字符串格式,如果格式不对会报错。


9,#define OPT_EXPERT 0x0004,只是一个标记,可以在 show_help() 输出帮助信息的时候指定 flags 为 OPT_EXPERT ,只显示这个标记相关的命令行参数。

10,#define OPT_VIDEO 0x0010,同 OPT_EXPERT,输出帮助信息用的。

11,#define OPT_AUDIO 0x0020,同 OPT_EXPERT,输出帮助信息用的。

12,#define OPT_SUBTITLE 0x0200,同 OPT_EXPERT,输出帮助信息用的。

13,#define OPT_DATA 0x1000,同 OPT_EXPERT,输出帮助信息用的。

14,#define OPT_EXIT 0x0800,这个属性代表处理完这个命令行参数的时候是否自动退出程序 , 这个也是给 show_help() 用的,因为输入帮助信息之后,是需要退出程序的。


15,#define OPT_PERFILE 0x2000,这个属性目前只有 ffmpeg.exe 在用,因为 ffmpeg.exe 支持多个输入文件跟多个输出文件,所以这个属性是标记命令行参数只作用于一个输入/输出文件的。OPT_PERFILE 是跟 OPT_OFFSET 或者 OPT_SPEC 一起使用的。

16,#define OPT_INPUT 0x40000,代表命令行参数是作用于输入文件的,如果你把它用在输出文件前面,就会报错。

17,#define OPT_OUTPUT0x80000,代表命令行参数是作用于输出文件的,如果你把它用在输入文件前面,就会报错。

18,#define OPT_OFFSET 0x4000,代表命令行参数的值会赋值给 OptionsContext 结构体的某个字段,这个字段的位置通过 偏移(u.off)找到。

19,#define OPT_SPEC 0x8000 ,代表命令行参数的值会赋值给 OptionsContext 结构体里面的 SpecifierOpt 数组。

上面的一级指针就是数组,然后下一个字段 nb_codec_tags 代表数组有多大。

因为 SpecifierOpt 是一个数组,所以有些命令行参数可以指定多个值,例如

ffmpeg.exe -c:v h264_cuvid -c:v h264_mf -i juren.mp4 juren.flv

这样会优先使用 h264_cuvid 硬件解码器解码,如果 ffmpeg.exe 没有编译硬件解码器,就会使用 h264_mf


在 ffplay.c 里面,是调 parse_options() 函数来解析命令行参数的,流程图如下:

其实命令行参数分为 2 种类型:

1,ffplay.c 里面定义的 OptionDef options[] = {...},这些参数是 ffplay 播放器独有的。

2,组件库里面的参数。组件库是指,编解码库,容器库,重采样库,滤镜库等等。这些库支持的参数都可以在命令行里指定。

无论是通用的,还是私有的参数,都可以通过命令行参数指定,如下:

ffplay -probesize 1024 -export_all 1 -x 400 -i juren.mp4

上面的 probesize 是容器层通用参数mp4 跟 flv 都有这个参数,但是 export_all 是 mp4 封装格式自己的私有参数


下面来看一下 parse_option() 函数里面的重点代码,如下:

可以看到,一开始就是从 ffplay.c 定义的 options 去找命令行参数是否存在,如果找不到,po->name 就是空。

如果命令行参数前面有 no ,那就把 no 去掉,再找一遍。

如果命令行参数是 布尔类型,那 arg 就会置为 1 或者 0。


当在 ffplay.c 的 options 找不到这个命令行参数的时候,就会找 default 的 option,在 ffplay.c 里面,default option 是一个函数调用。

opt_default() 函数,就是从各个组件库去找 参数的定义,如果也找不到,就会报错。


如果 从 ffplay.c 的 optiions 或者 组件库里面找到了命令行参数的定义,就会调 write_option() 来处理这个参数,重点如下:

write_option() 里面的比较复杂的地方就是 OPT_SPEC 的处理逻辑,但是幸运的是,ffplay 播放器不会用到这块逻辑,所以我们暂时不需要关注它。

OPT_SPEC 是给 ffmpeg.exe 用的。

在 ffplay 播放器里面,optctx 参数总是 NULL,所以 dst 指针全都是指向一个全局变量的,不会指向 OptionsContext 结构体的某个字段。

当不能直接赋值给 dst 指针的时候,就会调 u.func_arg 函数来处理命令行参数,这样设计让命令行解析更加灵活

最后,如果这个命令行参数的属性标记如果是 OPT_EXIT,那解析完这个参数之后,就会立即退出程序。OPT_EXIT 通常是给帮助参数用的,因为输出帮助信息到控制台之后,确实是需要立即退出程序了。


总结,ffplay.c 解析命令行参数,只有两种逻辑,一是直接赋值给全局变量,二是调 u.func_arg 函数来处理。

ffprobe.exe 跟 ffplay.exe 的命令行参数解析逻辑是一样的,都是用的 parse_options()

但是 ffmpeg.exe 不是,ffmpeg.exe 用的是 ffmpeg_parse_options() 函数,稍微更复杂一些。

但是 parse_options() 跟 ffmpeg_parse_options() 内部都用了 parse_option() 。

注意 parse_options() 跟 parse_option() ,一个有 s ,一个没 s。

ffplay.exe 是一个出自 FFmpeg 项目的、轻量级且功能强大的多媒体播放器,主要通过命令行操作。 核心功能 万能播放器:基于 FFmpeg 强大的解码能力,它能播放几乎所有格式的本地音视频文件,如 MP4、AVI、MKV、FLV 等。 流媒体播放:可以直接播放网络流媒体,支持 HTTP、HTTPS、RTSP、RTMP 等多种协议。 音视频分析工具:对于开发者,它能用于测试 FFmpeg 的解码和滤镜引擎,还可以可视化媒体参数,比如显示音频波形。 如何使用 你需要先下载 FFmpegffplay.exe 就在其中的 bin 文件夹里。推荐下载 Static 版本,它把需要的库都编译进 exe 文件了,用起来最方便。之后,打开命令行工具(cmd),输入命令即可。 基本播放:ffplay 视频文件路径 或 ffplay 网络流地址。 例如:ffplay C:\videos\my-video.mp4 或 ffplay http://example.com/stream.m3u8 常用参数:你还可以在命令中加入参数,实现更多控制。 参数 功能描述 使用示例 -x N -y N 设置播放窗口的宽度和高度(像素) ffplay -x 800 -y 600 video.mp4 -fs 全屏播放 ffplay -fs video.mp4 -ss 秒数 从指定时间(秒或时:分:秒)开始播放 ffplay -ss 00:01:30 video.mp4(从1分30秒开始) -t 秒数 播放多长时间 ffplay -t 10 video.mp4(只播放10秒) -loop 次数 循环播放次数(0 表示无限循环) ffplay -loop 3 video.mp4 -window_title 标题 设置播放器窗口的标题 ffplay -window_title
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Loken2020

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值