之前的文章都是通过 msys2+MinGW 的方式编译ffmpeg。今天就来讲解如何用 msys2 + msvc 的方式来编译ffmpeg。
ffmpeg 的源码是跨平台的,通过 configure(shell脚本) 实现不同平台的编译规则。在 configure 的时候指定 --toolchain=msvc 就可以 使用 msvc 来编译 ffmpeg。
window10 的CMD 无法运行 configure 脚本,所以需要装 msys2 ,装了 msys2 就能运行 configure 。
msys2 自行安装,msvc 是使用的vs2019 的,所以也请自行安装 vs2019,msvc 其实是一个统称,实际上 configure 里面用到的是 vs2019 里面的 cl.exe 跟 link.exe。 cl.exe 可以用来编译C代码,link.exe 用来链接的。
为了在 msys2 命令行使用 vs2019 的环境变量,需要做以下操作:
MSYS2 环境继承vs2019 的环境变量 操作教程:
1,修改 C:\msys64\msys2_shell.cmd
中的 rem set MSYS2_PATH_TYPE=inherit
,去掉rem,取消这⼀句的注释。使MSYS2的环境变量继承当前CMD的窗口的环境变量。
2,重命名 C:/msys64/usr/bin/link.exe
为 C:/msys64/usr/bin/link.bak
, 避免和MSVC 的link.exe抵触。这个是网上文章的做法,这个一步操作其实在新版的ffmpeg 里面是不需要的,因为在 configure里面编译的时候,调用的是 ./compat/window/mslink ,如下:
./compat/window/mslink 代码
#!/bin/sh
LINK_EXE_PATH=$(dirname "$(command -v cl)")/link
if [ -x "$LINK_EXE_PATH" ]; then
"$LINK_EXE_PATH" $@
else
link.exe $@
fi
exit $?
上面是 mslink 的代码,可以看到,他的逻辑就是优先 使用 跟 cl.exe 同目录下的 link.exe。cl.exe 只有在vs2019 那里才有,C:/msys64/usr/bin 目录下没有 cl.exe,所以会优选使用 vs2019 里面的link.exe,所以不重命名 C:/msys64/usr/bin/link.exe
也没关系。
3,上面的 C:\msys64\msys2_shell.cmd
文件已经修改好了,现在要找到 x64 Native Tools Command Prompt for VS 2019 这个命令工具。
点击 x64 Native Tools Command Prompt for VS 2019 打开命令行,一定要这样打开命令行,这样命令行才能有 vs2019 的环境变量,然后才能让 msys2 来继承,我之前说的 MSYS2_PATH_TYPE=inherit 继承的环境变量 是当前窗口的环境变量就是这个意思。
千万不要用下面这种 win+R 的方式打开命令行,这样子打开命令行是没有 vs2019 的环境变量的。
4,演示完错误的打开CMD的方式,我们继续操作,在 x64 Native Tools Command Prompt for VS 2019 命令窗口输入 cd c:\msys64\
先回到 msys64目录,然后再输入 .\msys2_shell.cmd -mingw64
,启动 msys2 命令行窗口,如图:
#回到 MSYS2 的安装目录
cd c:\msys64\
#启动 msys2 命令行
.\msys2_shell.cmd -mingw64
5,在 msys2 命令行窗口 输入 echo $LIB
,可以看到 msys2 命令行窗口 已经继承了 vs2019 的 lib 环境变量。
6,再输入一下 which cl.exe
,确认一下 cl.exe 是在vs2019的目录下,同时看下cl.exe的目录是否有link.exe。
MSYS2 + MSVC 环境已经准备好了,MSYS2 命令行已经继承了 vs2019 的环境变量,下面开始编译ffmpeg,本文要编译的ffmpeg版本为 n4.4.1。
网网上的一些教程 编译ffmpeg 的时候,会 下载编译 x264 , fdk-aac ,然后引入ffmpeg 里面。但是 n4.4.1版本的 ffmpeg 已经基于微软的 MediaFoundation 实现了 h264 ,aac 编解码器,分别是 h264_mf 跟 aac_mf ,mf 是 MediaFoundation 的缩写。所以不需要 再编译 x264 ,也不需要编译 fdk-aac ,比较方便。
早期ffmpeg版本,例如4.2版本是没有 264 编码器的,只是自带了一个264的解码器。因为 x264 , fdk-aac ,这些库的版权不是ffmpeg的,所以没有直接集成进ffmpeg。ffmpeg也在开发自己的编解码器,4.4版的时候终于开发出了 h264_mf 跟 aac_mf 。
编解码器都是按照标准实现的,例如用 h264_mf 编码的mp4文件,同样能用 x264 的库去解码,反之亦然。除非项目需要,一定要用 x264 , fdk-aac 来进行编解码,否则用 ffmpeg 4.4.1 版本自带的 h264 ,acc 编解码器即可。
mp3 的编解码器,ffmpeg 4.4 也自带了,叫 mp3_mf ,所以也不需要下载编译 lame 库。
vp8 ,v9 标准的解码器,ffmpeg 4.4 自带了,但是vp8 ,v9 标准的编码器ffmpeg 4.4 没有自带。本文暂时不讲解 msys2 + MSVC 环境中 如何引入 vp8 ,v9 编码器到 ffmpeg 4.4 里。
下面开始正式 编译 ffmpeg。、
开始操作:
1,下载 FFmpeg-n4.4.1.zip ,百度网盘,提取码:rpo3 ,下载好之后解压到 C:\msys64\home\loken\ffmpeg
,这个目录是我们之前文章经常用的目录。
2,安装所需软件,pacman -S diffutils make pkg-config yasm
3,进入 FFmpeg-n4.4.1 源码目录
cd /home/loken/ffmpeg/FFmpeg-n4.4.1
4,执行configure ,如下:
./configure \
--prefix=/home/loken/ffmpeg/build64/ffmepg-4.4-msvc \
--enable-gpl \
--enable-nonfree \
--enable-shared \
--toolchain=msvc
make -j8
make install
5,编译完成之后,build64/ffmepg-4.4-msvc 目录如下:
因为 configure的时候使用了 --enable-shared 开启了编译动态库,所以生成了 一堆的 lib 跟 dll 文件,avcodec-58 等等库是以动态库的方式给 ffmpeg.exe 调用的。如果使用 --disable-shared ,avcodec-58,avdevice-58 等库是直接以静态库的方式集成进去 ffmpeg.exe,ffmpeg.exe 文件会比较大。
--disable-shared 的编译方式,只会生成 ffmpeg.exe 跟 ffprobe.exe 两个文件,而且这两个exe文件的运行不需要依赖其他的dll。
configure --enable-shared 会在bin目录生成 一堆 lib 跟 dll,ffmpeg 的api函数可以以动态库的方式给其他项目使用。
configure --disable-shared 会在lib目录生成 一堆 .a 后缀的静态库,ffmpeg 的api函数可以以静态库的方式给其他项目使用。
纠正: configure 脚本并没有 --disable-shared 这个选项,实际上不指定 --enable-shared 就是编译静态库。ffmpeg 的静态库跟动态库是互斥的,只能编译出静态库,或者只编译出动态库。
可以看到,msys2 + msvc 编译出来的 ffmpeg.exe 非常精简,不像之前 msys2 + MinGW 编译出来的 ffmpeg.exe 运行需要拷贝 libwinpthread-1 等库过来。
6,查看 ffmpeg.exe 支持的编解码器,
cd /home/loken/ffmpeg/build64/ffmepg-4.4-msvc/bin
./ffmpeg.exe -codecs > support_codecs.txt
从 support_codecs.txt 里面可以看到 h264_mf ,aac_mf , mp3_mf 等编码器。
MSYS2 + MSVC 编译ffmpeg 讲解完毕,下面用qt creator来调试一下 ffmpeg 的dll库,相对于MInGW编译方式,MSVC 编译有个好处,可以直接debug进去 ffmpeg api函数的内部实现。
qt creator创建 ffmpeg 项目的步奏,在《window10_ffmpeg调试环境搭建-自己编译》 文中最后已经讲过,本文不再重复讲,直接给出qt项目的zip包。直接下载即可。
ffmpeg-verison-msvc.zip 百度网盘,提取码:6kc3
运行效果如下图:
我选择了两种编译方式,MinGW 64-bit 跟 MSVC2019 64bit,两种方式都能打印出 ffmpeg 版本号。但是只有 MSVC 的方式能够断点进去 av_version_info() 函数的内部实现。
这里注意,MSVC 能断点调试的前提是不能移动或者删除之前的编译目录,也就是不能移动 C:\msys64\home\loken\ffmpeg\FFmpeg-n4.4.1 ,因为 lib 文件里面的符号定位,是定位到这个目录的文件的。
补充,需要安装CDB编调试器,要不QT MSVC环境虽然能编译成功,但不能断点调试。
CDB编调试器安装:https://www.cnblogs.com/lixuejian/p/12915174.html ,注意安装过程需要翻墙。
版权所属:知识星球:弦外之音,QQ:2338195090。 由于笔者的水平有限, 加之编写的同时还要参与开发工作,文中难免会出现一些错误或者不准确的地方,恳请读者批评指正。如果读者有任何宝贵意见,可以加我微信 Loken1。