一、ffmpeg编译选项说明
ffmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。其实 ffmpeg 只是对该框架的通俗称呼,该框架本质上为 libav,ffmpeg 也只是基于 libav 开发的一套工具。libav 框架可以编译在其他平台进行使用,在下载的源码中,包含有 configure 程序来进行编译工作,但是单纯的运行该程序进行编译,编译生成的包体积是非常大的,所以需要进行一些配置来减小编译包的大小。
1、增加编译选项
首先可以增加一些常规编译选项来减小最终编译包的大小。可以使用 ./configure -h
命令来列出 configure 程序支持的编译选项,每一项编译选项后都有对应的解释,其中能够直接减小编译包大小的命令有如下几个:
--enable-small: 使用编译速度来换取编译包大小
--disable-runtime-cpudetect: 禁止运行时检测CPU性能,可以编出较小的包
--disable-doc: 禁止编译文档,可以避免将文档编译入包中
--disable-htmlpages: 禁止编译html文档,可以避免将文档编译入包中
--disable-manpages: 禁止编译man文档,可以避免将文档编译入包中
--disable-podpages: 禁止编译pod文档,可以避免将文档编译入包中
--disable-txtpages: 禁止编译txt文档,可以避免将文档编译入包中
2、减少不必要的工具
最开始介绍了 ffmpeg 是基于 libav 开发的一套工具,除了 ffmpeg 之外,基于 libav 开发的工具还有:ffplay、ffprobe以及ffserver。这些不必要的工具是可以禁止掉的,相关选项为:
--disable-programs: 禁止编译命令行工具
--disable-ffmpeg: 禁止编译ffmpeg工具
--disable-ffplay: 禁止编译ffplay工具
--disable-ffprobe: 禁止编译ffprobe工具
--disable-ffserver: 禁止编译ffserver工具
3、减少不必要的模块
libav 包含以下几个模块:(1)libavdevice,该模块主要负责与硬件设备的交互,若无需该模块,可使用 --disable-avdevice
禁止编译;(2)libavcodec,该模块主要负责解码与编码,若无需该模块,可使用 --disable-avcodec
禁止编译,不过该模块为 libav 核心模块,非特殊情况最好不要禁止;(3)libavformat,该模块主要负责解封装与封装,若无需该模块,可使用 --disable-avformat
禁止编译,不过该模块为 libav 核心模块,非特殊情况最好不要禁止;(4)libswresample,该模块主要负责对原始音频数据进行格式转换,若无需该模块,可使用 --disable-swresample
禁止编译;(5)libswscale,该模块主要负责对原始视频数据进行场景转换、色彩映射以及格式转换,若无需该模块,可使用 --disable-swscale
禁止编译;(6)libpostproc,该模块主要负责对音视频进行后期处理,若无需该模块,可使用 --disable-postproc
禁止编译;(7)libavfilter,该模块主要负责音视频的过滤,包括裁剪、位置、水印等,若无需该模块,可使用 --disable-avfilter
禁止编译;(8)libavresample,该模块主要负责音视频封装编解码格式预设,该模块默认不编译,若要进行编译,使用 --enable-avresample
。
4、减少不必要设备的编译
libav 可以从硬件设备中获取输入,同时也可以输出至硬件设备。可以指定支持的输入输出设备来避免不必要的编译:
--disable-devices: 禁止所有设备的编译
--disable-indevs: 禁止所有输入设备的编译
--disable-indev=NAME: 禁止特定输入设备的编译
--enable-indev=NAME: 允许特定输入设备的编译,搭配–disable-indevs可以实现单纯指定支持的输入设备
--disable-outdevs: 禁止所有输出设备的编译
--disable-outdev=NAME: 禁止特定输出设备的编译
--enable-outdev=NAME: 允许特定输出设备的编译,搭配–disable-outdevs可以实现单纯指定支持的输出设备
关于 libav 支持的输入输出设备名称,可以使用 ./configure --list-indevs
和 ./configure --list-outdevs
命令获取。
5、减少不必要解析器的编译
libav 可以对输入的数据进行格式检测,该功能由解析器(parser)负责。可以指定支持的解析器来避免不必要的编译:
--disable-parsers: 禁止所有解析器的编译
--disable-parser=NAME: 禁止特定解析器的编译
--enable-parser=NAME: 允许特定解析器的编译,搭配 --disable-parsers 可以实现单纯指定支持的解析器
关于 libav 支持的解析器名称,可以使用 ./configure --list-parsers
命令获取。
6、减少不必要的二进制流过滤器的编译
libav 可以将输入的数据转为二进制数据,同时可以对二进制数据进行特殊的处理,该功能由二进制流过滤器(bit stream filter)负责。可以指定支持的二进制流过滤器来避免不必要的编译:
--disable-bsfs: 禁止所有二进制流过滤器的编译
--disable-bsf=NAME: 禁止特定二进制流过滤器的编译
--enable-bsf=NAME: 允许特定二进制流过滤器的编译,搭配 –disable-bsfs 可以实现单纯指定支持的二进制流过滤器
关于 libav 支持二进制流过滤器名称,可以使用 ./configure --list-bsfs
命令获取。
7、减少不必要的协议编译
libav 对于如何读入数据及输出数据制定了一套协议,同时 libav 内置了一些满足协议的方式,这些方式可以通过 ./configure --list-protocols
列出。可以指定支持的输入输出方式来避免不必要的编译:
--disable-protocols: 禁止所有输入输出方式的编译
--disable-protocol=NAME: 禁止特定输入输出方式的编译
--enable-protocol=NAME: 允许特定输入输出方式的编译,搭配 –disable-protocols 可以实现单纯指定支持的输入输出方式
必须指定至少一种输入输出方式,通常通过使用 --disable-protocols
搭配 --enable-protocol=NAME
来完成。
8、减少不必要组件的编译
先简单介绍一下 libav 处理音视频的流程,以将 FLV 格式(H264视频+AAC音频) 转换为 AVI 格式(MPEG2视频+MP3音频) 为例,流程图如下:
在该过程中,负责解封装的是分离器(demuxer)、负责封装的是复用器(muxer)、负责音视频解码的为解码器(decoder)、负责编码的为编码器(encoder)。可以从libav所支持的四个组件的类型来减少不必要的编译。可以使用以下命令获取组件所支持的类型:
./configure --list-demuxers
./configure --list-muxers
./configure --list-decoders
./configure --list-encoders
(1)分离器:
--disable-demuxers: 禁止所有分离器的编译
--disable-demuxer=NAME: 禁止特定分离器的编译
--enable-demuxer=NAME: 允许特定分离器的编译,搭配–disable-demuxers
(2)复用器:
--disable-muxers: 禁止所有复用器的编译
--disable-muxer=NAME: 禁止特定复用器的编译
--enable-muxer=NAME: 允许特定复用器的编译,搭配 --disable-muxers
(3)解码器:
--disable-decoders: 禁止所有解码器的编译
--disable-decoder=NAME: 禁止特定解码器的编译
--enable-decoder=NAME: 允许特定解码器的编译,搭配 --disable-decoders
(4)编码器:
--disable-encoders: 禁止所有编码器的编译
--disable-encoder=NAME: 禁止特定编码器的编译
--enable-encoder=NAME: 允许特定编码器的编译,搭配–disable-encoders
至此,通过对项目的特殊定制,可以最大化的减小编译包的大小,避免编译包太大造成最终产品体积过大的问题。
二、编译和使用
ffmpeg 可以用 mingw 编译,但有时候将编出来的 ffmpeg 静态库文件给 vs 工程链接使用,会出现编译错误,因为 mingw 的库和 vs 的库冲突了,所以 ffmpeg 可以直接使用 vs 的 msvc 编译,不依赖 mingw 的库。下面提供两种编译 ffmpeg 的方式。
1、基于 mingw 的库编译
(1)32位电脑使用 MinGW32
首先将 /MinGW32/msys/1.0/etc 里面的 fstab.sample 复制一份且将其更名为 fstab,打开 fstab,将其中相应的内容改为 MinGW32 的安装目录,如 D:/MinGW32;然后在 /MinGW32/msys/1.0/msys.bat 文件开头加上:
call "D:\soft\work_soft\vs\VC\bin\vcvars32.bat" #vs2010或其他版本vs的安装目录
添加环境变量 path,如:D:\MinGW32\bin;双击打开 /MinGW32/msys/1.0/msys.bat,开始编译。编译过程报错可以在工程的configure日志查看相关报错信息。 默认编译命令:
./configure --enable-shared --enable-static --enable-memalign-hack --arch=x86_32 --host-os=win64 \
--disable-debug --disable-yasm --extra-cflags=-I/mingw/include --extra-ldflags=-L/mingw/lib \
--prefix=./output
如果要求编出来的库比较小,比如给我公司的OCX网页插件使用,可以裁剪编译 (支持 h264 mjpeg h265), 命令:
./configure --enable-static --disable-everything --disable-debug --extra-cflags="-I/mingw/include" \
--extra-ldflags=-L/mingw/lib --prefix=./output --disable-doc --disable-htmlpages --disable-manpages \
--disable-podpages --disable-txtpages --disable-programs --disable-ffmpeg --disable-ffplay \
--disable-ffprobe --disable-decoders --enable-decoder=h264 --enable-decoder=mjpeg \
--enable-decoder=hevc --disable-encoders --disable-avfilter --disable-avdevice --disable-swscale \
--disable-demuxers --enable-demuxer=h264 --enable-demuxer=hevc --enable-demuxer=mjpeg --disable-iconv \
--disable-filters --disable-bsfs --disable-muxers --enable-muxer=avi --disable-protocols \
--enable-protocol=file --disable-parsers --disable-devices --enable-asm --enable-inline-asm \
--enable-hardcoded-tables --enable-hwaccel=h264_dxva2 --disable-network --cpu=i686 --arch=x86_32 \
--enable-small
或者比如给我公司的另一个程序HsPlayer.exe使用,裁剪编译 (支持 h264 mjpeg h265 aac) 命令:
./configure --enable-static --disable-everything --disable-debug --extra-cflags="-I/mingw/include" \
--extra-ldflags=-L/mingw/lib --prefix=./output --disable-doc --disable-htmlpages --disable-manpages \
--disable-podpages --disable-txtpages --disable-programs --disable-ffmpeg --disable-ffplay \
--disable-ffprobe --disable-decoders --enable-decoder=h264 --enable-decoder=mjpeg \
--enable-decoder=hevc --enable-decoder=aac --disable-encoders --enable-encoder=aac --disable-avfilter \
--disable-avdevice --disable-swscale --disable-demuxers --enable-demuxer=h264 --enable-demuxer=hevc \
--enable-demuxer=mjpeg --enable-demuxer=aac --enable-demuxer=avi --enable-demuxer=mov \
--enable-demuxer=mpegps --disable-iconv --disable-filters --enable-bsfs --disable-muxers \
--enable-muxer=avi --enable-muxer=mp4 --enable-muxer=adts --disable-protocols --enable-protocol=file \
--disable-parsers --enable-parser=h264 --enable-parser=hevc --enable-parser=mjpeg --disable-devices \
--enable-asm --enable-inline-asm --enable-hardcoded-tables --enable-hwaccel=h264_dxva2 \
--enable-hwaccel=hevc_dxva2 --disable-network --cpu=i686 --arch=x86_32
(2)64位电脑使用 MinGW64
首先将 /MinGW64/msys/1.0/etc 里面的 fstab.sample 复制一份且将其更名为 fstab,打开 fstab,将其中相应的内容改为 MinGW64 的安装目录,如 D:/MinGW64;然后在 /MinGW64/msys/1.0/msys.bat 文件开头加上:
call "D:\soft\work_soft\vs2015\VC\bin\amd64\vcvars64.bat" #vs2015或其他版本vs的安装目录
添加环境变量 path,如:D:\MinGW64\bin;双击打开 /MinGW64/msys/1.0/msys.bat,开始编译。编译命令同32位基本一样,只需将 --arch=x86_32
改成 --arch=x86_64
。编译过程报错可以在工程的configure日志查看相关报错信息。
2、不依赖 mingw 的库
(1)32位电脑使用 MinGW32
首先将 /MinGW32/msys/1.0/etc 里面的 fstab.sample 复制一份且将其更名为 fstab,打开 fstab,将其中相应的内容改为 MinGW32 的安装目录,如 D:/MinGW32;然后在 /MinGW32/msys/1.0/msys.bat 文件开头加上:
call "D:\soft\work_soft\vs\VC\bin\vcvars32.bat" #vs2010或其他版本vs的安装目录
添加环境变量 path,如:D:\MinGW32\bin;重命名 D:/MinGW32/msys/1.0/bin/link.exe 为 D:/MinGW32/msys/1.0/bin/link.bak,避免和 MSVC 的 link.exe 抵触;去开始菜单找到 vs2015 的工具,即 “VS2015 x86 本机工具命令提示符”,打开之后运行:
D:\soft\work_soft\MinGW32\msys\1.0\msys.bat
在新弹出的窗口中输入命令,查看是否使用 vs2015 的库(下图实际上是编译64位时的截图):
运行 ./configure
,命令同上基本一样,加上 --toolchain=msvc --host-os=win64
,去掉 --extra-cflags="-I/mingw/include" --extra-ldflags=-L/mingw/lib
。修改 config.mak 文件,删除其中的
-Dsnprintf=_snprintf
-Dsnprintf=avpriv_snprintf
-D_snprintf=avpriv_snprintf
-Dvsnprintf=avpriv_vsnprintf
否则出现如下错误:
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
修改 ffmpeg 源码的 compat\msvcrt\snprintf.c,添加:
#include "snprintf.h"
否则出现如下错误:
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
修改 ffmpeg.c,文件中 #elif HAVE_KBHIT
改成 #elif 0 //HAVE_KBHIT
,有两处,都需要改。否则出现如下错误:
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”的声明
执行 make clean && make
(注意要先make clean,否则编译出来的库可能会有上次编译的残留)。编译过程会有很多警告,忽略即可,执行 make install
。注意:不要用 vs2008 以下编译,vs2010没试过。vs2008 标准是C98标准,好多语法不识别,vs2015用的C99标准,就可以了。编译出的库要在 vs2015 中使用,不要用其他版本的vs。
(2)64位电脑使用 MinGW64
使用MinGW64,步骤同32位基本一样,不同点:在 /MinGW64/msys/1.0/msys.bat 文件开头加上:
call "D:\soft\work_soft\vs2015\VC\bin\amd64\vcvars64.bat"
打开的是 “VS2015 x64 本机工具命令提示符”。--arch=x86_32
改成 --arch=x86_64
,加上 --toolchain=msvc --host-os=win64
,去掉 --extra-cflags="-I/mingw/include" --extra-ldflags=-L/mingw/lib
。
3、H265的支持
某些版本的 ffmpeg 不支持 h265 流封装成 avi 文件,需要修改 ffmpeg 源码,在源码中添加 h265 类型:
4、ffplay的支持
首先解压 SDL-devel-1.2.11-mingw32.rar,将lib、include复制到mingw32下;将 bin 下的 i386-mingw32msvc-sdl-config 复制到 mingw32/bin 下,重命名为sdl-config;将 bin 下的 SDL.dll 复制到 mingw32/bin 下;vim config.mak 确保 line 544为:CONFIG_FFPLAY=yes(ffplay4.0版本默认前面有!)。
5、常见错误
libavformat/os_support.c: In function 'ff_gai_strerror':
libavformat/os_support.c:194:10: error: 'ERROR_NOT_ENOUGH_MEMORY' undeclared (first use in this function)
解决:打开libavformat/os_support.h 文件,在其中增加 #include <winerror.h>
。
libavformat/rtsp.c: In function 'rtsp_send_cmd_with_content_async':
libavformat/rtsp.c:1322:16: error: 'ENOTCONN' undeclared (first use in this function) return ENOTCONN;
解决:将ENOTCONN修改成126。文章来源:https://www.toymoban.com/news/detail-403574.html
6、使用
基于mingw的库编译的ffmpeg使用时,要先链接 mingw 的 libgcc.a、libmingwex.a、libcoldname.a 等,没有基于 mingw的库编译的直接链接 ffmpeg 编出来的库即可。文章来源地址https://www.toymoban.com/news/detail-403574.html
#ifdef __cplusplus
extern "C" {
#endif
#include "libavutil/imgutils.h"
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/opt.h"
#ifdef __cplusplus
}
//#pragma comment(lib, "../ThirdParty/ffmpeg3.4.8_64/lib/libgcc.a")
//#pragma comment(lib, "../ThirdParty/ffmpeg3.4.8_64/lib/libmingwex.a")
//#pragma comment(lib, "../ThirdParty/ffmpeg3.4.8_64/lib/libcoldname.a")
#pragma comment(lib, "../ThirdParty/ffmpeg3.4.8_64/lib/all/libavcodec.a")
#pragma comment(lib, "../ThirdParty/ffmpeg3.4.8_64/lib/all/libavformat.a")
#pragma comment(lib, "../ThirdParty/ffmpeg3.4.8_64/lib/all/libavutil.a")
#pragma comment(lib, "../ThirdParty/ffmpeg3.4.8_64/lib/all/libswresample.a")
//#pragma comment(lib, "../ThirdParty/ffmpeg3.4.8_64/lib/libz.a")
到了这里,关于Windows编译和使用ffmpeg的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!