栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

windows系统下mysys+VS2005编译FFmpeg库过程

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

windows系统下mysys+VS2005编译FFmpeg库过程

如果你准备使用VS编译FFmpeg,推荐使用vs2013并且参考其他文章,而不是按照以下过程使用vs2005去编译,因为本文只是记录在编译过程出现的问题和解决办法,因为使用vs2005编译ffmpeg实在是作死


安装依赖环境:

  • 安装MSYS-1.0.11
  • 安装pkg-config,将pkg-config.exe、libglib-2.0-0.dll拷贝到mysys的bin目录下
  • 由于vs2005不支持c99,需要安装C99-to-C89 Converter & Wrapper
    解压c99-to-c89-1.0.3.zip,将c99conv.exe、c99wrap.exe拷贝到mysys的bin目录下
  • 安装make-3.81.exe,将make.exe拷贝到mysys的bin目录下
  • 解压coreutils-5.97-MSYS-1.0.11-snapshot.tar.bz2,将其中的pr.exe拷贝到mysys的bin目录下
  • 安装diffutils-2.8.7-1.exe,将将安装目录bin内的cmp.exe等拷贝到mysys的bin目录下
  • 安装yasm,将yasm.exe拷贝到mysys的bin目录下

msinttypes-r26.zip包括c99的两个头文件inttypes.h,stdint.h,解压到目录"C:UsersmDownloadsmsinttypes-r26"
由于msvc不支持unix的unistd.h,所以需要自己手动编写一个unistd.h
编辑以下代码,保存为unistd.h,并且同样保存在"C:UsersmDownloadsmsinttypes-r26"

#ifndef _UNISTD_H
#define _UNISTD_H
#include 
#include 
#include 
#endif //_UNISTD_H

在configure中使用参数-I附加头文件目录"C:UsersmDownloadsmsinttypes-r26"

解压ffmpeg-2.4.tar.gz
到源码目录下,编辑configure文件

        if [ -z "$cl_major_ver" ] || [ $cl_major_ver -ge 18 ]; then
            cc_default="cl"
        else
            cc_default="c99wrap cl"

改为

        if [ -z "$cl_major_ver" ] || [ $cl_major_ver -ge 18 ]; then
            cc_default="c99wrap cl"
        else
            cc_default="c99wrap cl"

否则会有因为不支持c99语法而产生的报错

C:Program Files (x86)Microsoft Visual Studio 8VCINCLUDEio.h(224) : 参见“unlink”的声明
消息:“The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _unlink. See online help for details.”
libavformat/hdsenc.c(535) : error C2059: 语法错误 : “{”
libavformat/hdsenc.c(544) : error C2059: 语法错误 : “if”
libavformat/hdsenc.c(546) : error C2143: 语法错误 : 缺少“{”(在“->”的前面)
libavformat/hdsenc.c(546) : error C2059: 语法错误 : “->”
libavformat/hdsenc.c(548) : error C2143: 语法错误 : 缺少“{”(在“->”的前面)
libavformat/hdsenc.c(548) : error C2059: 语法错误 : “->”
libavformat/hdsenc.c(549) : error C2059: 语法错误 : “return”
libavformat/hdsenc.c(550) : error C2059: 语法错误 : “}”
libavformat/hdsenc.c(579) : error C2059: 语法错误 : “.”
libavformat/hdsenc.c(580) : error C2059: 语法错误 : “,”
libavformat/hdsenc.c(581) : error C2059: 语法错误 : “,”
libavformat/hdsenc.c(582) : error C2059: 语法错误 : “,”
libavformat/hdsenc.c(583) : error C2059: 语法错误 : “,”
libavformat/hdsenc.c(587) : error C2059: 语法错误 : “.”
libavformat/hdsenc.c(594) : error C2059: 语法错误 : “.”
make: *** [libavformat/hdsenc.o] Error 2

执行configure时不知道为什么没有检测到msvc,导致$libc_type没有正确赋值,导致编译链接报错,strtod.c、snprintf.c没有得到编译

error LINK2001:undefined reference to '_avpriv__strtod'
error LINK2001:undefined reference to '_avpriv__snprintf'

手动去设置,在configure文件的

case $libc_type in
    bionic)
        add_compat strtod.o strtod=avpriv_strtod
        ;;

之前加上

libc_type_fix(){
pfx=$1
 eval ${pfx}libc_type=msvcrt
        # The MSVC 2010 headers (Win 7.0 SDK) set _WIN32_WINNT to
        # 0x601 by default unless something else is set by the user.
        # This can easily lead to us detecting functions only present
        # in such new versions and producing binaries requiring windows 7.0.
        # Therefore explicitly set the default to XP unless the user has
        # set something else on the command line.
        check_${pfx}cpp_condition stdlib.h "defined(_WIN32_WINNT)" ||
            add_${pfx}cppflags -D_WIN32_WINNT=0x0502
}
libc_type_fix

在源码目录下libavformat/os_support.h中,将以下行注释,否则报lseek重定义错误

//#  define lseek(f,p,w) _lseeki64((f), (p), (w))

在compatmsvcrtsnprintf.c中,注释

//#if defined(__MINGW32__)
#define EOVERFLOW EFBIG
//#endif

否则提示

error C2065:"EOVERFLOW";未声明的标识符

compatwindowsmakedef文件编辑,将

sed -e '/public symbols/,$!d' -e '/^ {1,}Summary/,$d' -e "s/ {1,}${prefix}/ /" -e 's/ {1,}/ /g' |

改为

sed -e '/public symbols/,$!d' -e '/^ {1,}Summary/,$d' -e "s/ {1,}${prefix}/ /" -e 's/ {1,}/ /g' |

否则sed报错,并且生成的def文件不完整:

sed.exe -e expression #1,char 1:unknow command :`C'

编译时用到User32.lib、Gdi32.lib库,创建库文件夹C:UsersmDownloadslib,加入Gdi32.Lib,并且在configure指定库目录,但是在链接过程出现

LINK: warning LNK4044: 无法识别的选项“/LC:UsersmDownloadslib";已忽略

原因是configure中指定库目录使用-L,这是mingw的用法,而对于msvc,应该是-LIBPATH:
还需要在libavdevicegdigrab.c中加入以下语句来调用库

#pragma comment  (lib,"User32.lib")
#pragma comment  (lib,"Gdi32.lib")

否则出现以下报错

正在创建库 libavdevice/avdevice.lib 和对象 libavdevice/avdevice.exp
gdigrab.o : error LNK2019: 无法解析的外部符号 __imp__EndPaint@8,该符号在函数 _gdigrab_region_wnd_proc@16 中被引用

对于mysys的启动,需要让其继承msvc的环境变量,才能够使用msvc的link.exe,cl.exe等工具。
首先对于mysys安装目录下的msys.bat文件加入以下内容

call "C:Program Files (x86)Microsoft Visual Studio 8VCvcvarsall.bat"

寻找以下行,取消注释(去掉rem)

rem setMSYS2_PATH_TYPE=inherit

在开始菜单中,找到vs的目录,启动Visual Studio 2005命令提示,并且在其中运行msys.bat来启动mysys,启动后,在mysys中输入

export PATH=/C/Program Files (x86)/Microsoft Visual Studio 8/VC/bin:$PATH

确保vs环境在系统变量前,则优先使用vs的link.exe,而不是mysys的link.exe(与编译链接无关的一个程序)

在mysys中,切换目录

 cd /C/Users/m/Downloads/ffmpeg-2.4.tar/ffmpeg-2.4

执行configure

 ./configure --prefix=build_msvc --toolchain=msvc --enable-shared --disable-static --extra-cflags="-I/C/Users/m/Downloads/msinttypes-r26 -Dsnprintf=_snprintf" --extra-ldflags="-LIBPATH:/C/Users/m/Downloads/lib"

-Dsnprintf=_snprintf 定义宏snprintf=_snprintf,否则提示

error C4013:"snprintf"未定义,假设外部返回int

–enable-shared 是指定生成动态链接库,可以在编程中进行使用,否则编译出来只有单个的ffmpeg程序

若configure出现以下提示

c99wrap cl is unable to create an executable file.
If c99wrap cl is a cross-compiler, use the --enable-cross-compile option.
Only do this if you know what cross compiling means.
C compiler test failed.

检查c99conv.exe、c99wrap.exe是否安装正确

configure会生成config.mak、config.h文件,编辑config.h
做如下修改,将0改为1,

#define HAVE_IO_H 1
#define HAVE_UNISTD_H 1

否则源文件不能相应头文件,导致提示

error C4013:"read"未定义,假设外部返回int
error C4013:"write"未定义,假设外部返回int
error C4013:"_lseeki64"未定义,假设外部返回int
error C4013:"close"未定义,假设外部返回int

编译安装

make
make install

若出现以下错误

CC      libavdevice/alldevices.o
make: *** [libavdevice/alldevices.o] Error 1

检查configure配置附加头文件目录是否正确,inttypes.h,stdint.h头文件是否在相应目录中

使用mysys2编译时,出现下面两个问题,使用mysys1.0.11可以避免

awk: 命令行:1: /including/ { sub(/^.*file: */, ""); gsub(//, "/"); if (!match($0, / /)) print "libavdevice/alldevices.o:", $0}
awk: 命令行:1:                                                                                                           ^ 未结束的字符串

只能将condig.mak文件以下部分注释

#CCDEP=$(DEP$(1)) $(DEP$(1)FLAGS) $($(1)DEP_FLAGS) $< 2>&1 | awk '/including/ { sub(/^.*file: */, ""); gsub(/\/, "/"); if (!match($$0, / /)) print "$@:", $$0}' > $(@:.o=.d)

而编译执行./compat/windows/makedef时mysys2由于参数过长,竟然不能解析所有输入的参数
问题就出在这里

for object in "$@"; do
    if [ ! -f "$object" ]; then
        echo "Object does not exist: ${object}" >&2
        exit 1
    fi
done

提示

Object does not exist: liba

对于makedef的参数,包含几百上千个.o文件名字,但是到libavcodec/mpegutils.o之后就截止了,后面就因为参数过长直接被舍弃,导致出现错误。而使用mysys1.0.11却可以编译通过
编译后的文件在build_msvc的bin目录下


总结:

  • 极度不推荐使用vs2005编译ffmpeg,他不是干这个的。千万不要去尝试,由于不支持c99标准,编译时会出现各种奇怪的错误,就算编译出来,也不一定能用
    windows还是得mysys+mingw编译ffmpeg最简单,不用做任何代码和编译脚本的修改。一次编译通过。如果考虑使用msvc编译出来的库具有pdb文件,可以进行调试,也要用vs2013以上的版本,支持c99标准,不会出现这么多问题
  • 这篇文章的目的只是作为编译过程出现的问题的解决办法的参考
  • 对于大型项目的编译,一般就是三种问题,依赖环境和环境变量的问题,编译配置文件和编译参数的问题,源代码本身相对于编译器的问题
  • 对于vs2005,我不想用他再编译ffmpeg第二次。每次编译好不容易解决了一个问题,都以为终于要结束了。结果就是报出更多的问题,如果一开始就知道会出这么多问题,我是无论如何不会去这样做的

关于msvc编译ffmpeg,参考文章:
vs2013编译ffmpeg之一 概述
the official compilation guide on ffmpeg wiki
windows下用vs2010编译ffmpeg
vs2013编译ffmpeg之四十二 zvbi
Compiling FFmpeg with X264 on Windows 10 using MSVC

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/887349.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号