FFmpeg的makefile逻辑分析

news2025/7/12 11:30:21

在开始分析之前,讲一个 makefile 的调试技巧,推荐阅读《如何调试MAKEFILE变量》

make -f Makefile -f vars.mk HOSTPROGS

这里我对 vars.mk 做了点修改,因为源 vars.mk 没处理特殊字符,直接 echo 会报错。ffmpeg 的 makefile 的变量有很多特殊字符。我用了 warning 来输出,就不会报错。vars.mk 下载地址:百度网盘,提取码:i59d


先来看 FFmpeg 根目录的 makefile 的代码,如下:

 上图中的 vpath 是定义搜索目录,因为你可以在其他目录执行 configure 文件,那样 SRC_PATH 变量就不是 ./ 当前目录了。

FFLIBS-$(CONFIG_AVRESAMPLE) += avresample

这些 CONFIG_AVRESAMPLE 之类额变量都是 yes 或者 no,他就是用 yes/no 来控制要不要某些库或者组件。而这些 yes/no 的变量 是 configure 脚本输出的。


下面的代码 是 检测 configure 有没执行,这个是这样的,configure会 生成 ffbuild/.config 文件,如果你改了 FFmpeg 里面的代码,代码文件就会比 .config 文件更新,如果你不执行 configure , 直接 make ,就会报错。

config.h: ffbuild/.config
ffbuild/.config: $(CONFIGURABLE_COMPONENTS)
    @-tput bold 2>/dev/null
    @-printf '\nWARNING: $(?) newer than config.h, rerun configure\n\n'
    @-tput sgr0 2>/dev/null

到这里,我决定不再一行一行代码解析 FFmpeg 项目的 makefile,因为 FFmpeg 的 makefile 代码比较多,而且初学者,通常你不需要看完全部的 makefile 才能改二次开发。

之前说过,8 千行 configure 最后也只是往编译器,链接器传递了一些参数,这些参数就被定义在 config.mak 文件里面,如下:


 FFmpeg 的 makefile 比较分散,根目录有一个 makefile,各个库目录也有一个 makefile。库目录的 makefile 是通过 DOSUBDIR 函数 包含进来的,如下:

上图代码中,定义了 DOSUBDIR 函数,然后遍历 FFLIBS 数组变量 来调用,FFLIBS 就是 FFmpeg 的那 8个库。


 因此,FFmpeg 项目根目录有一个主的 makefile (MAIN_MAKEFILE),然后各个子目录都有一个各自的 makefile,代码量有点多。但是我们比较常用的只有 4个 知识点。

提示:makefile 也只是一个构建工具,他最后也是调 gcc 来执行编译。


makefile 里面,我们比较常用的有 4个 知识点。

1,第一个 target 是什么,在哪里定义的?

makefile 的规则是,执行 make 命令的时候要指定一个 target,就是要编译哪个目标,如果不指定,就是编译 makefile 文件里面的第一个目标,第一个 target 也叫默认target。那 FFmpeg 的默认目标是什么?如下:

 从上图可以看出,默认 target 是 all,因此,我们在编译 FFmpeg 的之后,执行 make 还是 make all ,效果是一样的。


2, .c 文件 编译成 .o 文件的规则在哪里?

我们知道,在编译阶段,各个 .c 文件都是独立编译的。而 makefile 也是调 gcc 来编译,那是在哪里调的 gcc 呢?

这些规则在 common.mak 文件里面,如下:

COMPILE_C 是一个函数调用,如下:

 这里提醒一下,所有的子目录,所有的 .c 文件编译都是这个规则。这是通用的。也就是说,ffmpeg.cffplay.c 文件也是这一个规则。

我们现在来测试一下 是不是这一个规则,看下 ffplay.c 是不是在这里编译的。我们加个东西,如下:

我加了一个无意义的选项 -num666 在后面。然后用 make -n > t33.txt 来查看命令,-n 代表不执行编译只打印信息。如下:

 果然,因此所有 的 .c 文件都是在 common.mak 文件里面定义编译规则的。


3,生成 FFmpeg 8个 动态库的规则在哪里?FFmpeg 里面提供了 8 个库给开发者使用,这些库可以通过打包形成静态库,或者通过链接器来生成动态库。那这些生成静态库,动态库的规则在哪里呢?

以 libavcodec 库为例,libavcodec 目录的 makefile 里面的代码主要有3个重要的变量,HEADERSOBJSOBJS-YES,如下:

 上面的 OBJ-YES 变量有 x264 的 .o 文件,x264 应该是以动态库或者静态库的方式引用的,这里为什么直接填 .o ,我也不太清楚,后面补充,暂时不管。

上面 allcodecs.o 等等 这些 .o 后缀的文件是目标文件,这些目标文件肯定要传递给 ar 命令打包成静态库,或者传递给 gcc链接器 生成动态库,那在哪里使用这个 OBJS 变量的呢?

在 library.mak 里面,如下:

 这里我必须说一下,library.mak 里面的变量 OBJS, SUBDIR 跟 NAME 等等变量是从其他文件引入的,而且每次循环引入的变量值都不一样,循环发生在 DOSUBDIR 函数里面,如下:

FFmpeg 的各个库里面的 makefile 文件定义了 OBJS 变量,然后 被 library.mak 使用。实际上我个人觉得 makefile 的语法变量有点乱,不太容易确定是局部变量还是全局,反正逻辑就是我上面说的那样。

现在我们已经找到了 在哪里生成动态库的了,就是 library.mak 文件 51 行的地方,我讲一下我怎么找到这个地方,我是直接搜 SHFLAGS 变量的,因为这是动态库的 flags

现在加一些调试代码,来确认是不是在这个 地方生成 libavcodec.so 文件的,添加的代码,加了个 -num77 如下:

提示:之前 configure 的时候要使用 --enable-shared,然后才会执行到这条 动态库的 makefile 规则。

执行命令 make -n > t5.txt ,可以看到选项 -num777 加上去了,如下:

可以看到生成 libavcodec.so 依赖的 .o 文件太多了,非常多。


现在来找一下,把 .o 文件打包成 静态库的规则在哪里,猜测静态库跟动态库的规则是同一个文件的。 所以直接 在 library.mak 里面搜索 AR ,因为 config.mak 就是用 AR 这个变量来打包的。

AR 变量 在 Windows 系统是 lib.exe ,在 Linux 系统是 ar 命令,

library.mak 里面生成静态库的代码如下:

上图中的 OBJS 变量是在 libavcodec/makefile 里面定义的。各个库的 makefile 都会定义自己的 OBJS 变量。然后在 DOSUBDIR 函数循环使用

还是惯例,加个 -num888 在后面,如下:

 

这时候,我们一定要 重新 configure ,不要加 --enable-shared,这样这条规则才会执行到。他是有其他地方控制 生成动态库还是静态库的,make 只会生成静态库或者动态库,只能二选一。不过层层的 target 依赖找起来太麻烦了,初学者也不需要知道这个。只要知道 静态库,动态库的 makefile 规则在哪里就行。

执行命令 make -n > t6.txt ,可以看到选项 -num88 加上去了,如下:


4,生成 ffmpeg.exe ,ffplay.exe 的规则在哪里?

ffmpeg.exe 实际上也是调 那 8 个库实现的,ffmpeg.exe 相关的代码在 fftools 目录里面,ffmpeg.exe 相关的代码只有几个文件,如下:

ffmpeg.cffmpeg_opt.c ,cmdutils.cffmpeg_filter.cffmpeg_hw.cffmpeg_qsv.c ,ffmpeg_videotoolbox.c

后面的 ffmpeg_qsv.c 跟ffmpeg_videotoolbox.c 文件不是必须的,是可选的。也就是 生成 ffmpeg.exe 只需要 5个 C 文件。这 5个文件加起来只有 1万多行代码。

看完 这 1万多行代码,就能学会使用 FFmpeg API 函数了,是不是很简单。

回到 原来的问题。生成 ffmpeg.exe 的 makefile 规则在哪里?这个问题实际上要分析 fftools 目录的 makefile 文件。如下:

 上面的代码有两个重点, AVPROGS 跟 OBJS-ffmpeg,生成 ffmpeg.exe 应该会用到这两个变量,只有搜索这两个变量应该就能找到。

我试了一下,根据 AVPROGS 跟 OBJS-ffmpeg找,有点麻烦,还是直接 搜 _g 就行 因为 FFmpeg 项目是生成 ffmpeg_g.exe,再生成 ffmpeg.exe 的,

生成 ffmpeg_g.exe 的规则 在根目录的 makefile 里面,如下:

上图用的是 % 模糊匹配所有的有 _g 的文件。 还是老套路,我们在 后面加个 -num999 ,执行 make -n 之后如下:

 从上图可以看出,有 3个 num999 。证明我们找的地方是对的。


还有一个问题,上面的第 123 行代码, %$(PROGSSUF)_g$(EXESUF): $(FF_DEP_LIBS) ,_g 的规则是一个 target,target 要执行,肯定要被依赖,我们再找一下 这个 _g 在哪里被依赖了。实际上依赖代码就在附近,如下:

上面的规则实际上就是 ffmpeg.exe 依赖 ffmpeg_g.exe ,所以依赖 _g 的地方找到了。我们看到这个地方干了什么,可以看到 用了 strip,再看回去上面的打印日志,有一个关键的地方,如下:

strip -o ffmpeg ffmpeg_g

原来 ffmpeg_g.exe 就是带调试信息的可执行文件,而 ffmpeg.exe 是经过 strip 去掉调试信息的可执行文件。

提示:我为什么加 exe,其实 Linux 环境是没有 exe 后缀,但是为了区分我是在说 ffmpeg 可执行文件,还是指 FFmpeg 整个项目,所以我加了 exe


至此,FFmpeg 项目里面比较常用的 makefile 知识,你已经掌握。后面就让我们二次开发 FFmpeg,加一个自己程序进去。FFmpeg 项目默认有 3 个程序 ffmpeg.exe ,ffplay.exe ,ffprobe.exe 。我们新加的程序就叫 loken.exe

欢迎看下一篇文章。


 推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:

Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/38480.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

改进粒子滤波的无人机三维航迹预测方法附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。 🍎个人主页:Matlab科研工作室 🍊个人信条:格物致知。 更多Matlab仿真内容点击👇 智能优化算法 …

某公司常见题刷题笔记

LeetCode搞起来,虽说和实际业务没啥联系,但现在就卷起来了,没办法被迫卷起来。 1,滑动平均值,官网 给定窗口大小size,然后每次增加一个值value放入窗口,求此窗口内的平均值 class MovingAver…

李宏毅:Life Long Learning

Life Long Learing 也是continual Learning,也是incremental learning 目录 Life-Long Learning vs Transfer Learning Evaluation Research Directions Selective Synaptic Plasticity——Regulization Based Additional Neural Resourcr Allocation Memo…

Python简介-Python3及环境配置

Python简介 Python是一种跨平台的计算机程序设计语言。 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越多被用于独立的、大型项目的开发。 Python语…

MFC的YUV播放器实现

MFC的YUV播放器实现 文章目录MFC的YUV播放器实现一、主要参考链接二、开发踩坑记录1、Gdiplus 绘图前置条件2、播放时点击滑竿能精准跳转3、鼠标悬停在滑竿上时显示预览小窗口本文记录使用MFC编写一个YUV播放器的过程,尽量实现播放器都有的常用功能。功能参考与网上…

四旋翼无人机学习第9节--OpenMV以及WIFI电路、供电电路再分析

文章目录0、参考与学习1、OpenMV插座电路2、OpenMV供电电路3、ESP8266电路分析3.0 绘制分享3.1 模块正面图3.2 模块背面图3.3 模块引脚介绍3.4 模块模式选择3.5 芯片手册参考电路4、供电电路分析4.1 电池接口与电源开关部分4.2 usb供电电路与电池电压降压电路4.3 5V降3.3V电路4…

[论文精度|博士论文]非结构环境下病虫害识别方法研究

概述 提出一种基于级联卷积神经网络的植物病害识别方法提出一种融合农田多源环境信息的害虫监测方法提出一种新的目标检测损失函数解决特征冲突问题 本文研究的主要方面在于特征提取。(其他部分沿用目前最全面的公开数据和病虫害数据以及最先进的开源算法&#xf…

30岁之后身体还能像年轻的时候一样撸代码吗?

在IT圈流传着一句话,程序员吃的是青春饭。很多人认为,30岁是个阶段,在这个阶段后就需要往管理方向转型。因为在30岁之后身体再也不能像年轻的时候一样熬夜撸代码,而且继续从事一线开发的待遇也不如管理层优厚。至于转管理层失败的…

redis缓存一致性以及解决方案

一致性问题: 首先要到redis里面读取缓存,如果没有缓存,那么就到mysql里面去取数据,并且将其放置在缓存中 关于解决缓存一致性的问题,不难想到主要有两种解决方案,双更模式和删除模式 ** 双更模式&#xf…

【JVM】native关键字的使用

native关键字的使用一、JVM体系结构二、native是什么?三、native能干什么?四、native怎么使用?五、native总结在研读**《深入理解Java虚拟机》这本书时,看到 Java 虚拟机运行时数据区中有关本地方法栈**(Native Method…

鲜花在线销售平台的设计与实现/鲜花商城/网上花店管理系统

摘 要 为了解决客户便捷地在网上购物,本文设计和开发了一个鲜花在线销售平台。本系统是基于web架构设计,SSM框架,javascript技术的前台页面设计与实现,使用Mysql数据库管理,综合采用java模式来完成系统的相关功能。主…

【GlobalMapper精品教程】028:栅格计算器的使用方法总结

文章目录 一、栅格计算器简介二、栅格计算器应用举例1. 归一化植被指数NDVI2. 归一化水体指数NDWI3. 归一化建筑指数NDBI一、栅格计算器简介 GlobalMapper中也提供了栅格计算器工具,可以方便的进行栅格计算、波段计算、指数计算等,使用方法有点儿像Envi软件。 用户可以使用系…

世界杯来了,让 Towhee 带你多语言「以文搜球」!

四年一度的世界杯已正式拉开战幕,各小组比赛正如火如荼地进行中。在这样一场球迷的盛宴中,不如让 Towhee 带你「以文搜球」,一览绿茵场上足球战将们的风采吧~ 「以文搜球」是跨模态图文检索的一部分,如今最热门的跨模…

Leetcode刷题Day5休息 Day6----------哈希表

Leetcode刷题Day5休息 & Day6----------哈希表 1. 哈希表理论基础 数组、Set、Map 如果数据量小------------数组 如果数据量大------------Set 如果有Key、value------------Map 文章讲解:https://programmercarl.com/%E5%93%88%E5%B8%8C%E8%A1%A8%E7%90%86…

【雷达检测】基于复杂环境下的雷达目标检测技术(Matlab代码实现)

👨‍🎓个人主页:研学社的博客 💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜…

数据之道读书笔记-06面向“自助消费”的数据服务建设

数据之道读书笔记-06面向“自助消费”的数据服务建设 数据底座建设的目标是更好地支撑数据消费,在完成数据的汇聚、整合、联接之后,还需要在供应侧确保用户更便捷、更安全地获取数据。一方面业务人员希望尽可能快速地获取各种所需的数据,另一…

基于双目相机拍摄图像的深度信息提取和目标测距matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB程序 1.算法描述 双目相机一般由左眼和右眼两个水平放置的相机组成。当然也可以做成上下两个目,但我们见到的主流双目都是做成左右的。在左右双目的相机中,我们可以把两个相机都看作针…

大数据毕设选题 - 深度学习图像超分辨率重建(opencv python cnn)

文章目录0 前言1 什么是图像超分辨率重建2 应用场景3 实现方法4 SRResNet算法原理5 SRCNN设计思路6 代码实现6.1 代码结构组织6.2 train_srresnet6.3 训练效果7 最后0 前言 🔥 Hi,大家好,这里是丹成学长的毕设系列文章! &#x…

读写分离和主从复制

这是只有一个数据库的情形,此时增删改查都是针对这个数据库而言 存在两个问题:所有压力都是由一台数据库承担,数据库压力很大 而且,一旦这个数据库发生故障,数据丢失,拿数据就全都没了 现在有两个数据库&…

总结使人进步,4句真章的理解和实践

在“总结使人进步,遵循事物的客观发展规律;祸福相依,知行合一”这篇文章里,首次全面提出了4句真章。 这么多年,最有感触的4句话。 一、4句真章 1、总结使人进步 2、遵循事物的发展规律 3、祸福相依 4、知行合一 …