Windows + MSVC环境编译ffmpeg

实测成功环境: WIN7 + VS2013 + FFmpeg4.3 和 WIN10 + VS2019 + FFmpeg4.3(N-98819-ge2589ac)

源码下载

依赖工具

下载安装MSYS2; 下载YASM,将文件名改为yasm.exe,将它所在的目录加入到环境变量中。

配置头文件和库搜索路径

以下几种方法任选一种

1.使用vcvarsall.bat

  • 打开cmd,执行vcvarsall.bat(一般在C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC目录下,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安装目录>\usr\bin下的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}/include

Name: 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 - >= 0
        long   tv_nsec; // Nanoseconds - [0, 999999999]
    };
#endif

将它拷贝到源码中,重新make

发布于 2020-08-29 13:53