由于工作原因,需要在MINGW下编译出一个单独完整的FFMPEG 功能库(而不是avcodec/avformat等很多库)提供给WINDOWS UI使用。
折腾了好几天,下过msys2,ming64,都没有成功,貌似国外的网站访问这些资源速度很慢。
最后使用vs2015+mingw1.0来解决这个问题。
过程如下记录如下。
一、mingw下编译ffmpeg
考虑了如下几种方案:
1.修改ffmpeg的makefile,使它能生成一个单独的DLL。也许这种方法是最好的,但是本人对MAKEFILE不熟悉,望而却步。
2.编译成静态库,再创建一个VS(2010、2013)的DLL功能对起进行封装。 众所周知,MINGW编译出的静态库需要libgcc.a、libmingwex.a、libcoldname.a
而且需要注意链接顺序,网上多数开发者的经验是MINGW生成的静态库兼容性不好,经常出现程序崩溃,所以放弃这种方案。
3.使用vs工具链来进行编译。由于 vs2013之前的版本不支持c99语言,故需要配置
C99-to-C89 Converter & Wrapper (http://ffmpeg.org/platform.html#Microsoft-Visual-C_002b_002b-or-Intel-C_002b_002b-Compiler-for-Windows)。
本人按照步骤做的,但是编译时还是不认识c99语法。 只能下载最新的vs2015来进行编译。
mingw的配置在此不做描述,网络有很多的参考。这里主要记录在mingw下用vs2015编译时碰到的一些问题以及解决方法。
环境:mingw1.0/vs2015/ffmpeg2.3
1. ./configure --enable-static --toolchain=msvc
2. make
一开始就碰到了如下错误:
问题1
C:\Program Files (x86)\Windows Kits\10\include\10.0.10150.0\ucrt\stdio.h(1419):
note: 命令行参数: 参见前面的“vsnprintf”定义
C:\Program Files (x86)\Windows Kits\10\include\10.0.10150.0\ucrt\stdio.h(1421):
fatal error C1189: #error: Macro definition of vsnprintf conflicts with Standa
d Library function declaration
经查找,原来是生成的config.mak文件里CPPFLAGS= -D_ISOC99_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_WIN32_WINNT=0x0502 -Dstrtod=avpriv_strtod -Dsnprintf=avpriv_snprintf -D_snprintf=avpriv_snprintf -Dvsnprintf=avpriv_vsnprintf
有snprintf的定义。本人对linuix不熟悉,只能简单把
-Dsnprintf=_snprintf
-Dsnprintf=avpriv_snprintf -D_snprintf=avpriv_snprintf -Dvsnprintf=avpriv_vsnprintf
定义去掉,再make。也许有更好的解决方法。
问题2
compat\msvcrt\snprintf.c文件需要#include "snprintf.h",否则提示
avpriv_vsnprintf未定义
CC libavutil/../compat/msvcrt/snprintf.o
snprintf.c
libavutil/../compat/msvcrt/snprintf.c(41): error C4013: “avpriv_vsnprintf”未定
义;假设外部返回 int
make: *** [libavutil/../compat/msvcrt/snprintf.o] Error 2
问题3:
ffmpeg.c文件中#elif HAVE_KBHIT 改成#elif 0 //HAVE_KBHIT,否则提示
_cnt错误
ffmpeg.c(395): error C2039: “_cnt”: 不是“_iobuf”的成员
C:\Program Files (x86)\Windows Kits\10\include\10.0.10150.0\ucrt\corecrt_wstdio.
h(26): note: 参见“_iobuf”的声明
!还好,才3个问题, 编译完成了 。
3.make install
可以发现lib下已经有生成的libavcodec.a等文件了。
二、vs里使用上面生成的静态库
由于ffmpeg是在mingw 下用vs2015编译的,可以预想这个库在低版本的vs中会存在
某些问题,果然,在vs2010里使用后,报了如下错误:
local\flvEditor-2010\Debug\flvEditor.dll) 与 Linker 的 OutputFile 属性值(D:\MinGW\msys\1.0\local\flvEditor-2010\bin\flvEditor.dll)不匹配。这可能导致项目生成不正确。若要更正此问题,请确保 $(OutDir)、$(TargetName) 和 $(TargetExt) 属性值与 %(Link.OutputFile) 中指定的值匹配。
1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: _fprintf 已经在 libavformat.a(dump.o) 中定义
1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: _sscanf 已经在 libavcodec.a(diracdec.o) 中定义
1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: __vsnprintf 已经在 libavutil.a(snprintf.o) 中定义
1>LIBCMT.lib(open.obj) : error LNK2005: __sopen 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义
1>LIBCMT.lib(_file.obj) : error LNK2005: ___iob_func 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义
1>LIBCMT.lib(dosmap.obj) : error LNK2005: __errno 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义
1>LIBCMT.lib(osfinfo.obj) : error LNK2005: __get_osfhandle 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义
1>LIBCMT.lib(lseeki64.obj) : error LNK2005: __lseeki64 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义
1>LIBCMT.lib(tidtable.obj) : error LNK2005: __encoded_null 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义
1>LIBCMT.lib(getenv.obj) : error LNK2005: _getenv 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义
1>LIBCMT.lib(mlock.obj) : error LNK2005: __unlock 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义
1>LIBCMT.lib(mlock.obj) : error LNK2005: __lock 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义
1>LIBCMT.lib(crt0dat.obj) : error LNK2005: __initterm_e 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义
1>LIBCMT.lib(crt0dat.obj) : error LNK2005: __amsg_exit 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义
1>LIBCMT.lib(fflush.obj) : error LNK2005: _fflush 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义
1>LIBCMT.lib(winxfltr.obj) : error LNK2005: ___CppXcptFilter 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义
1>LIBCMT.lib(fclose.obj) : error LNK2005: _fclose 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义
1>LIBCMT.lib(winsig.obj) : error LNK2005: _signal 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义
1>LIBCMT.lib(crt0init.obj) : error LNK2005: ___xi_a 已经在 MSVCRTD.lib(cinitexe.obj) 中定义
1>LIBCMT.lib(crt0init.obj) : error LNK2005: ___xi_z 已经在 MSVCRTD.lib(cinitexe.obj) 中定义
1>LIBCMT.lib(crt0init.obj) : error LNK2005: ___xc_a 已经在 MSVCRTD.lib(cinitexe.obj) 中定义
1>LIBCMT.lib(crt0init.obj) : error LNK2005: ___xc_z 已经在 MSVCRTD.lib(cinitexe.obj) 中定义
1>LIBCMT.lib(atox.obj) : error LNK2005: _atoi 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义
1>LIBCMT.lib(strtol.obj) : error LNK2005: _strtol 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义
1>LIBCMT.lib(strtol.obj) : error LNK2005: _strtoul 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义
1>LIBCMT.lib(strtoq.obj) : error LNK2005: __strtoi64 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义
1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: __read 已经在 LIBCMT.lib(read.obj) 中定义
1> 正在创建库 D:\MinGW\msys\1.0\local\flvEditor-2010\Debug\flvEditor.lib 和对象 D:\MinGW\msys\1.0\local\flvEditor-2010\Debug\flvEditor.exp
1>LINK : warning LNK4098: 默认库“MSVCRTD”与其他库的使用冲突;请使用 /NODEFAULTLIB:library
1>LINK : warning LNK4098: 默认库“LIBCMT”与其他库的使用冲突;请使用 /NODEFAULTLIB:library
1>libavformat.a(apetag.o) : error LNK2001: 无法解析的外部符号 ___report_rangecheckfailure
1>libavformat.a(subtitles.o) : error LNK2001: 无法解析的外部符号 ___report_rangecheckfailure
1>libavformat.a(rtmppkt.o) : error LNK2001: 无法解析的外部符号 ___report_rangecheckfailure
1>libavutil.a(opt.o) : error LNK2019: 无法解析的外部符号 ___report_rangecheckfailure,该符号在函数 _opt_size 中被引用
1>libavformat.a(wavdec.o) : error LNK2001: 无法解析的外部符号 ___report_rangecheckfailure
1>libavformat.a(yuv4mpegdec.o) : error LNK2001: 无法解析的外部符号 ___report_rangecheckfailure
1>libavformat.a(http.o) : error LNK2001: 无法解析的外部符号 ___report_rangecheckfailure
1>libavfilter.a(avfiltergraph.o) : error LNK2001: 无法解析的外部符号 ___stdio_common_vsprintf
1>libavfilter.a(graphparser.o) : error LNK2001: 无法解析的外部符号 ___stdio_common_vsprintf
1>libavfilter.a(af_amix.o) : error LNK2001: 无法解析的外部符号 ___stdio_common_vsprintf
1>libavfilter.a(f_select.o) : error LNK2001: 无法解析的外部符号 ___stdio_common_vsprintf
1>libavutil.a(eval.o) : error LNK2001: 无法解析的外部符号 __libm_sse2_pow_precise
1>libswscale.a(utils.o) : error LNK2001: 无法解析的外部符号 __libm_sse2_pow_precise
1>libavfilter.a(af_afade.o) : error LNK2001: 无法解析的外部符号 __libm_sse2_pow_precise
1>libavcodec.a(aacsbr.o) : error LNK2001: 无法解析的外部符号 __libm_sse2_pow_precise
1>libavfilter.a(vf_psnr.o) : error LNK2001: 无法解析的外部符号 __ultod3
1>libavutil.a(eval.o) : error LNK2001: 无法解析的外部符号 __ultod3
1>libavfilter.a(aeval.o) : error LNK2001: 无法解析的外部符号 __ultod3
1>libavfilter.a(af_astats.o) : error LNK2001: 无法解析的外部符号 __ultod3
1>libavfilter.a(af_volumedetect.o) : error LNK2001: 无法解析的外部符号 __ultod3
1>libavformat.a(aiffdec.o) : error LNK2001: 无法解析的外部符号 __ultod3
等47个无法linker的错误。其中LIBCMT.lib的错误在
属性--->输入--->忽略特定默认库 输入LIBCMT.lib,即可解决。
其他的___report_rangecheckfailure等错误是检查堆栈缓存溢出的代码,
在msvcrt11.dll及以后版本中都会调用到,而我们用的是vs2010,所以找不到。
上面这个问题如果使用mingw编译出来的动态库则没这个问题。
也许在mingw编译时禁掉对应的选项即可或者导入2010后的对应库可以解决,但是具体不知道是什么选项,所以放弃。
面对这么多个linker错误, 本人只能使用vs2015来创建一个DLL供其他VS版本使用。
vs2015的DLL 功能很顺利,inline等都有,引入的库如下:
#pragma comment(lib,"libavcodec.a")
#pragma comment(lib,"libavformat.a")
#pragma comment(lib,"libavutil.a")
#pragma comment(lib,"libswscale.a")
#pragma comment(lib,"libswresample.a")
#pragma comment(lib,"libavfilter.a")
#pragma comment(lib,"libavdevice.a")
#pragma comment(lib,"wsock32.lib")
#pragma comment(lib,"ws2_32.lib")
至此,DLL生成了,写了简单的界面测试,也可以跑起来了。但是只是基本功能,X264等外部库还需要移植。
至于ffmpeg.c等文件在vs2015中的编译问题,本处就不多加描述了。