实测成功环境: WIN7 + VS2013 + FFmpeg4.3 和 WIN10 + VS2019 + FFmpeg4.3(N-98819-ge2589ac)
源码下载
- FFmpeg源码
依赖工具
- MSYS2
- YASM
下载安装MSYS2; 下载YASM,将文件名改为yasm.exe,将它所在的目录加入到环境变量中。
配置头文件和库搜索路径
以下几种方法任选一种
1.使用vcvarsall.bat
- 打开cmd,执行vcvarsall.bat(一般在C:Program Files (x86)Microsoft Visual Studio 12.0VC目录下,vcvarsall.bat将会设置INCLUDE和LIB环境变量,以便cl能找到对应头文件和.lib文文件);
- 继续在cmd中执行msys2安装目录下的msys2_shell.cmd
vcvarsall.bat x86
msys2_shell.cmd -use-full-path
2.在VS中打开msys2
- 在VS中选择:Tools -> External tools... -> Add
- 在VS中启动msys2:Tools->msys2
确保msvc编译器cl和链接器link是否正常
我们使用的是微软的编译器cl.exe和链接器link.exe,然而msys2自带有link.exe,和msvc 的link.exe重名,且前者所在目录在环境变量中靠前,所以运行link命令时实际运行的是msys2的link.exe,这将造成链接出错
解决方法
- 将<msys2安装目录>usrbin下的link.exe重新命名为其它名称;
- 或者,想办法修改PATH的顺序
msys2 安装pkg-config,diffutils,make工具(msys2没带这些工具,手动安装)
pacman -S pkg-config
pacman -S diffutils
pacman -S make
2.构建
切换至FFmpeg源码目录,执行
./configure --toolchain=msvc
make
构建成功:
编译ffplay
虽然ffplay是默认enable的,但ffplay的编译依赖第三方库sdl2,所以上述步骤可能因为缺少sdl2依赖而无法编译出ffplay.exe。
下面是解决方法 sdl2下载 下载VC版本,解压。
1.配置sdl2对msvc可见
显然,sdl2头文件和库文件必须让编译器可以找到, 可以把头文件目录添加到INCLUDE环境变量,将库文件目录添加到LIB环境变量 在MSYS2控制台执行(注意目录得使用Windows格式 C://...而非 /c/...):
export INCLUDE=$INCLUDE";<sdl2头文件目录>"
export LIB=$LIB";<sdl2库文件目录>"
也可以在cmd执行vcvarsall.bat后使用set命令添加
2.配置sdl2对pkg-config可见
另外,sdl2除了得对msvc可见,还要对pkg-config可见,方法如下(实测可用,但不知道有没有更好的方法) - 新建sdl2.pc 文件,编辑如下
prefix=你的sdl2所在目录(目录格式/c/...而非C://...)
libdir=${prefix}/lib/x86
includedir=${prefix}/includeName: sdl2
Description: sdl2
Version: 2.0.12
Libs: -L${libdir} -lsdl2
prefix设置为的sdl2目录(目录格式/c/...而非C://...),Version设置为你的sdl2版本
- 查看PKG_CONFIG_PATH环境变量,将sdl2.pc拷贝到其中任一目录(如<msys2安装目录>/usr/lib/pkgconfig)
echo $PKG_CONFIG_PATH
3.启用sdl2,编译
最后,使用--enable-sdl2启用sdl2
./configure --enable-sdl2 --toolchain=msvc
make
其他库的使用方法应该类似
问题
1.源码字符集不匹配的问题
msvc2019
因为msvc2019默认以utf-8编码读取源码,而./configure生成的config.h包含gbk字符 解决方法: - 将config.h以gbk编码打开(notepad++或vscode),复制全部,再以utf-8打开粘贴覆盖; - 或者,干脆将utf-8下乱码的字符删除
msvc2013
msvc2013默认以gbk编码读取源码,所以方法同msvc2019,不过恰好相反,要确保不出现gbk编码无法识别的字符
2.编译出错,timespec未定义
timespec结构体是C11标准定义的,包含在time.h头文件中,msvc2013可能没有完全实现这个标准。 幸好ffmpeg只是借用了这个结构体,而没有用到相应的函数, 所以我们手动定义一下好了:
#ifndef _MY_TIMESPEC_
#define _MY_TIMESPEC_
struct timespec{time_t tv_sec; // Seconds - >= 0long tv_nsec; // Nanoseconds - [0, 999999999]};
#endif
将它拷贝到源码中,重新make