Windows编译和使用ffmpeg


一、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。

6、使用

基于mingw的库编译的ffmpeg使用时,要先链接 mingw 的 libgcc.a、libmingwex.a、libcoldname.a 等,没有基于 mingw的库编译的直接链接 ffmpeg 编出来的库即可。

#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")
  • 8
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Windows使用NDK编译FFmpeg,你需要按照以下步骤进行操作: 1. 首先,确保你已经安装了NDK和CMake。你可以从Android开发者网站下载并安装Android Studio,它会自动安装NDK和CMake。 2. 下载FFmpeg源代码。你可以从FFmpeg的官方网站或GitHub上获取最新的源代码。 3. 创建一个用于编译FFmpeg的CMakeLists.txt文件。这个文件描述了编译过程中所需的配置和依赖项。你可以使用以下示例作为起点: ```cmakecmake_minimum_required(VERSION3.4.1) # 设置FFmpeg源代码的路径set(FFMPEG_SOURCE_DIR /path/to/ffmpeg/source) # 设置编译输出的路径set(FFMPEG_OUTPUT_DIR /path/to/ffmpeg/output) # 添加FFmpeg源代码的子目录add_subdirectory(${FFMPEG_SOURCE_DIR} ${FFMPEG_OUTPUT_DIR}) # 添加FFmpeg库到你的项目中add_library(ffmpeg SHARED IMPORTED) set_target_properties(ffmpeg PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/libs/${ANDROID_ABI}/libffmpeg.so) # 链接FFmpeg库到你的项目中target_link_libraries(your_project ffmpeg) ``` 在上面的示例中,你需要将`/path/to/ffmpeg/source`替换为你下载的FFmpeg源代码的路径,将`/path/to/ffmpeg/output`替换为你想要生成输出文件的路径。 4. 打开命令提示符或终端,并导航到包含CMakeLists.txt文件的目录。 5. 运行以下命令来生成构建文件: ```shellcmake -DCMAKE_TOOLCHAIN_FILE=/path/to/your/ndk/build/cmake/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DANDROID_NATIVE_API_LEVEL=21 . ``` 在上面的命令中,将`/path/to/your/ndk/build/cmake/android.toolchain.cmake`替换为你的NDK安装目录中的相应路径。`ANDROID_ABI`和`ANDROID_NATIVE_API_LEVEL`参数可以根据你的需求进行调整。 6. 运行以下命令来编译FFmpeg: ```shellcmake --build . ``` 这将使用CMake生成的构建文件来编译FFmpeg。 请注意,编译FFmpeg可能需要一些时间,具体取决于你的系统配置和源代码的大小。完成后,你将在指定的输出路径中找到编译好的FFmpeg库文件。 这只是一个简单的指导,实际中可能会遇到其他问题。在遇到困难时,你可以参考FFmpeg官方文档或在相关的开发者社区中寻求帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值