windows下的ffmpeg是采取mingw平台上编译,本人采用的是msys2,本人需要h264,于是先在msys2里面编译了x264静态库,注意这里是静态库,动态库经过了链接,不会出现下面的问题,然后在ffmpeg里面用下面配置命令生成Makefile。
./configure --toolchain=msvc --arch=x86_64 --disable-debug --enable-gpl --enable-libx264 --extra-cflags=-I/usr/local/x264/include --extra-ldflags=‘-LIBPATH:/usr/local/x264/lib’ --prefix=/home/ffmpeg_x264_static
注意,编译ffmpeg时,–toolchain=msvc表示用微软编译器编译。
结果configure报错,信息如下:
打开ffbuild/config.log,有下列报错
符号__mingw_vsprintf找不到,本人很好奇,在x264的代码里面搜索__mingw_vsprintf调用的地方,很明显没有直接搜找到,于是到msys2里面的stdio.h,搜寻此符号,还真找到了,如下图所示
其实像x264这种跨平台的开源代码,外层调用的是sprintf,然后sprintf由运行时库实现,不同的运行时库,里面的内部函数不一样,本人曾经用clang编译过webrtc,里面的运行时库前缀是另外一套,具体忘记了。
所以若想将ffmpeg configure通过,需要找到__mingw_vsprintf的实现库,读者也可以理解为需要找到mingw的运行时库,为此本人专门写了一个例子,在mingw里面写一个1.c。
gcc -c 1.c生成目标文件1.o。
然后用vs2017调用这个mysprintf函数,如下所示:
// mingwruntimetest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
extern "C" void mysprintf();
int main()
{
mysprintf();
std::cout << "Hello World!\n";
return 0;
}
由于需要符号mysprintf的定义地方,为此需要将在mingw编译的1.o链接进来,链接器配置如下:
编译,报如下错误:
此时跟在ffmpeg里面configure报错时的情况一样了,找到符号__mingw_vsprintf定义的文件libmingwex.a,拷贝到工程目录下,然后配置链接,如下所示:
编译,报如下错误:
符号___chkstk_ms未能找到,于是再次找到了此符号所在静态库文件libgcc.a,并拷贝到工程目录下,配置工程链接如下:
再次编译,编译通过。
读者可能有一些疑惑,如何得知__mingw_vsprintf符号在libmingwex.a里面定义,___chkstk_ms在libgcc.a里面定义,读者可以将__mingw_vsprintf在msys2的lib目录下搜索,包含此符号的文件会被搜索出来。
最后说明下:像ffmpeg这样的大型软件,依赖的插件特别多,若插件用静态库编译,则请保持这些静态库和最后的ffmpeg都用同一个编译器编译,免得最后需要各个编译器的运行时库都包含进来,给自己找罪受。
所以最后的解决方法是x264的静态库用vs2017编译,若x264是动态库,则可以直接用mingw编译,不过最终的成果物里面也会多一个x264.dll。
试想下,若ffmpeg本身,以及ffmpeg依赖的各种插件都用静态库编译,则在windows下面,编译其实是在很费劲的事情,本人曾见过一个博主专门写windows下的ffmpeg编译,意外发现ffmpeg编译之73,相当于ffmpeg的编译起码写了73篇博客。
linux下的ffmpeg编译相对而言,要简单太多