当前位置: 首页 > news >正文

ffprobe是如何处理命令行参数的.


author: hjjdebug
date: 2025年 04月 14日 星期一 13:04:30 CST
description: ffprobe是如何处理命令行参数的.


文章目录

    • 1.ffprobe, 功能:
    • 2.ffprobe 对命令行选项的处理,
    • 3.分析一个实例:
      • 3.1 命令行如下:$ffprobe audio.data -f s16le -ac 2 -ar 44100
      • 3.2 问1: -f s16le 最终被放到了哪里,怎样被使用的?
      • 3.3 问2: -ac 2, -ar 44100 这2个参数最终放到了哪里? 怎样被使用的?
      • 3.4 全局变量iformat 在哪里使用?
      • 3.5 全局变量 codec_opts 在哪里使用?
      • 3.6 AVOption 选项信息,最终去了哪里?
        • 3.6.1: iformat, 最终进入了s->iformat
        • 3.6.2: codec_opts字典,传送值到其ctx中对应的成员变量的位置

1.ffprobe, 功能:

1.解复用,解包等功能
2.极尽所能显示包信息,frame信息.
可以用命令行设置显示哪些条目. 想显示谁,不想显示谁.精准控制. 不是grep, 是control

2.ffprobe 对命令行选项的处理,

可以理解为,对每一个选项key,value对, 先从它定义的option表中找对应的option项,
根据option项的信息指引,或者直接存储到一个全局变量,或者进行一次函数调用,由函数调用再进一步处理这个key,value参数
总架构: parse_options -> parse_option -> write_option
集体->单个->写值

ffprobe 就没有使用OptionGroup, OptionGroupList, OptionParseContext 这些概念,
而是简化了命令行分析过程,因为它只针对一个文件

3.分析一个实例:

3.1 命令行如下:$ffprobe audio.data -f s16le -ac 2 -ar 44100

其中audio.data 是一个原始码流音频数据文件

3.2 问1: -f s16le 最终被放到了哪里,怎样被使用的?

答1: 因为其key 是 -f, write_option 时调用了 opt_format -> av_find_input_format()
iformat = av_find_input_format(arg); //对参数的进一步处理把arg转变成了iformat
其中 arg 就是 s16le,
其返回值存储到全局变量 iformat 中

3.3 问2: -ac 2, -ar 44100 这2个参数最终放到了哪里? 怎样被使用的?

答2: 因为其key 是 -ac, 在avprobe定义的option 表中找不到该选项,所以就让它指向一个项opt_default
write_options时,执行定义的opt_default 函数继续处理
-ac在avcodec_class 选项表中找到了它,所以把-ac 2放到 codec_opts 字典中, codec_opts是一个全局变量
av_dict_set(&codec_opts, opt, arg, 0); //codec_opts 是全局变量

同样,对于-ar 44100, 其处理过程相同. write_option->opt_default->av_dict_set
最终也放到了全局变量codec_opts 字典中储存.

由此可见, parse 的过程也是数据存储的过程, 是命令行参数向计算机内存传数的过程. 可以简单的理解为就是一个scan操作.
实际上是通过parse_options -> parse_option -> write_option 根据选项表来完成数据存储操作.
人机交互的接口除了命令行方式,其实也可以用文件, 例如json 格式的文件就很简洁清晰, 不过ffprobe 没有这么做.
这些存到内存的变量下一步如何使用,下次分解.

继续:

3.4 全局变量iformat 在哪里使用?

iformat 变量, 在打开文件时使用. 包括format_opts 选项表
if ((err = avformat_open_input(&fmt_ctx, filename, iformat, &format_opts)) < 0)

3.5 全局变量 codec_opts 在哪里使用?

codec_opts 选项字典, 在打开codec_ctx时使用
AVDictionary *opts = filter_codec_opts(codec_opts, stream->codecpar->codec_id, fmt_ctx, stream, codec);
if (avcodec_open2(ist->dec_ctx, codec, &opts) < 0)

3.6 AVOption 选项信息,最终去了哪里?

这些AVOpton 选项,会直接进一步通过接口调用保存到ctx 对应的成员变量中.
这部分具体的存储过程, 不在应用层,而有库函数来执行了, 不过ffmpeg 是开源的,我们还是可以看见它的存储过程.

3.6.1: iformat, 最终进入了s->iformat

iformat, input format是通过 format-name 查format 表对象查到的, 直接通过参数传给avformat_open_input
这样该函数就不用探测文件的 format了
avformat_open_input() 在 libavformat/utils.c 文件中,有如下语句:
if (fmt)
s->iformat = fmt;
如果fmt 为空的话,就需要读取一段文件数据,调用每一个format 对象,让它们检查这段数据是否是它们的格式,
觉得是,返回高分,觉得不是,返回低分,最后根据得分情况,把format 对象地址赋值给s->iformat
至于s->iformat 以后怎样用, 那就是调用它执行format 对象的函数了. 读header, 读包等等.

3.6.2: codec_opts字典,传送值到其ctx中对应的成员变量的位置

codec_opts 字典, 当然 format_opts 字典也是一样,反正就像fmt一样最终送到ctx对象的成员变量上.
avcodec_open2(avctx,codec,&codec_opts) 在 libavcodec/codec.c 中
codec_opts 字典用法还比较曲折,首先它copy到tmp字典,以后用tmp字典操作
if (options)
av_dict_copy(&tmp, *options, 0);

如果codec 有私有类,先让私有类消费. av_opt_set_dict, 就是从源tmp 向目的传送,并删除源项
if (codec->priv_class && (ret = av_opt_set_dict(avctx->priv_data, &tmp)) < 0)
然后向本对象传递字典
if ((ret = av_opt_set_dict(avctx, &tmp)) < 0)

然后把剩下字典项的传回,当然可能是空字典了,都消费完了.
*options = tmp;
av_dict_free(&tmp); //释放自己占用的内存,如果有的话

至于av_opt_set_dict()是怎样把字典项传递到目的,并删除源项,这个简单又最基础,可以把代码copy过来

    while ((t = av_dict_get(*options, "", t, AV_DICT_IGNORE_SUFFIX))) //从源字典表中循环读取每一项
    { //向目标设置,目标不是一般的地址,而是AVClass对象,它们是有AVOption 选项表的, 
	  //AVOption结构与命令行中的Option结构是类似的. 
	  //其中最重要的属性是说明该key对应的value,应该存储再obj中的什么位置(offset)
	  //有个这个AVOpton表,就直到该类是否包含该选项,如果包含,应该把数据存储到哪里.
        ret = av_opt_set(obj, t->key, t->value, search_flags);  
		// 设置不进去,就是选项表中找不到key,那说明这个key,value不属于本表,就放到tmp项保留.
        if (ret == AVERROR_OPTION_NOT_FOUND)
            ret = av_dict_set(&tmp, t->key, t->value, 0);  
    }
    av_dict_free(options); //把源项全部删除
    *options = tmp; //把填不进去的项赋值给源项,表示是剩余的项

好了,这样我们把ffprobe 的命令行选项数据的周游过程叙述了一遍.
ffmpeg的命令行选项的处理过程其下层与ffprobe是一样的.
其上层由于要分清楚选项属于哪一个文件, 所以添加了option_group 概念,在上层把选项划分为不同的文件来进行,
并且在上层 还引入了parse_context概念,option_context概念. 因为它要同时处理多个文件.
因为多个文件处理就等于多次处理一个文件.
它也离不了parse_options->parse_option->write_option, 再到库级别av_opt_set_dict设置成员变量.
ffmpeg的上层概念的具体流程,留待ffmpeg选项分析时再说明.
另补充一句ffplay 的命令行参数与ffprobe 完全一致,入口都是parse_options, 因为它们都是处理一个文件.

相关文章:

  • BFD:网络链路检测与联动配置全攻略
  • 易境通WMS系统代理仓解决方案:让代理仓管理无后顾之忧!
  • 07软件测试需求分析案例-修改用户信息
  • 手机端可部署的开源大模型; 通义千问2.5训练和推理需要的内存和外存
  • 【DDR 内存学习专栏 1.4 -- DDR 的 Bank Group】
  • 机器学习:让数据开口说话的科技魔法
  • 网络基础和socket
  • 面试宝典(C++基础)-01
  • AlexNet神经网络详解及VGGNet模型和
  • 深度学习中的数学基础:从向量到概率的全面解析
  • 测试第三课-------自动化测试相关
  • 第十九讲 XGBoost 二分类模型案例(遥感数据识别玉米与小麦地块)
  • HTML:网页的骨架 — 入门详解教程
  • Python heapq模块
  • 【Pandas】pandas DataFrame items
  • AIGC工具平台-建筑平面图3D渲染
  • Android studio Unknown Kotlin JVM target: 21
  • macOS 上使用 Homebrew 安装和配置 frp 客户端
  • 【C++】——lambda表达式
  • 数据资产保护与数据知识产权保护有何不同?
  • 920余名在缅甸当阳等地实施跨境电信网络诈骗的中国籍犯罪嫌疑人被移交我方
  • 印控克什米尔发生恐袭事件,外交部:中方反对一切形式的恐怖主义
  • 兰斯莫斯想在雅典卫城拍《拯救地球》,希腊官方:价值观不符
  • 新任乒协副主席马龙:感谢刘国梁,愿把经验传给年轻运动员
  • 宫崎骏电影《幽灵公主》4K修复版定档五一
  • 瞭望:高校大门要向公众打开,不能让“一关了之”成为常态