本文主要讲解 FFmpeg 相关知识,以及在 Windows 下编译 FFmpeg 源码以及使用。
ffmpeg 是广泛使用的多媒体解决方案,既是一款音视频编解码工具,同时也是一组音视频编解码开发套件,作为编解码开发套件,它为开发者提供了丰富的音视频处理的调用接口。
其包括了目前领先的音/视频编码库 libavcodec。
ffmpeg 提供了多种媒体格式的封装和解封装,包括多种音视频编码,多种协议的流媒体,多种色彩格式转换,多种采样率转换,多种码率转换等。ffmpeg 发展至今,已经被许多开源项目使用。
ffmpeg 框架的基本组成包含 AVFormat,AVCodec,AVFilter,AVDevice,AVUtil 等。
AVFormat:文件格式和协议库,该模块是最重要的模块之一,封装了 Protocol 层和 Demuxer、Muxer 层,使得协议和格式对于开发者来说是透明的。
AVFormat 中实现了目前多媒体领域中绝大多数媒体封装格式,包括封装和解封装,如 MP4,FLV 等文件封装格式,RTMP,HLS 等网络协议封装格式。ffmpeg 是否支持某种封装格式,取决于编译时是否包含了该格式的封装库。
应用于各种音视频封装格式的生成和解析,包括获取解码所需信息以生成解码上下文结构和读取音视频帧等功能;音视频的格式解析协议,为 libavcodec 分析码流提供独立的音频或视频码流源。
编解码库,该模块也是最重要的模块之一,封装了 Codec 层。
AVCodec 中实现了目前多媒体领域绝大多数常用的编解码格式,既支持编码,也支持解码。AVCodec 除了支持自带的媒体解码格式之外,还支持第三方的编解码器,如 H.264 编码,需要使用 x264 编码器;MP3编码,需要使用libmp3lame 编码器。如果希望增加自己的编码格式,或者硬件编解码,则需要在 AVCodec 中增加相应的编解码模块。(有一些 Codec 是具备自己的 License 的,FFmpeg 是不会默认添加像 libx264、FDK-AAC、lame 等库的,但是 FFmpeg 就像一个平台 一样,可以将其他的第三方的 Codec 以插件的方式添加进来,然后为开发者提供统一的接口)
该库是音视频编解码的核心,avcodec 库被其他各大解码器 ffdshow,Mplayer 等所包含或应用。
AVFilter 提供了一个通用的音频,视频,字幕等滤镜处理框架。该模块提供了包括音频特效和视频特效的处理,在使用 FFmpeg 的 API 进行编解码的过程中,直接使用该模块为音视频数据做特效处理是非常方便同时也非常高效的一种方式。
swscale 模块提供了高级别的图像转换 API,例如它允许进行图像缩放和像素格式转换,视频场景比例缩放、色彩映射转换;图像颜色空间或格式转换,如 gb565、rgb888 与 yuv420 等之间转换。
swresample 模块提供了高级别的音频重采样API。可以对数字音频进行声道数、数据格式、采样率等多种基本信息的转换。例如,它允许操作音频采样,音频通道布局转换与布局调整。
该模块是最基础的模块之一,许多其他模块都会依赖该库做一些基本的音视频处理操作。
硬件采集,加速,显示。输入输出设备库,比如,需要编译出播放声音或者视频的工具 ffplay,就需要确保该模块是打开的,同时也需要 libSDL 的预先编译,因为该设备模块播放声音与播放视频使用的都是 libSDL 库。
ffmpeg 已经编译好了3个常用的工具集 ffmpeg.exe、ffprobe.exe、ffplay.exe. 通过这 3 个工具就可以使用命令去操作一个多媒体文件。
这里参考一下我前面写的博客:音视频开发常用工具
Windows11 64位
需要安装的软件和工具:
除了需要安装 VS 之外,还要安装 MSYS2,这是一款 Windows下模拟 Linux 的软件。FFmpeg 的编译就是在该软件中进行的,而编译时使用的编译器(cl.exe)和链接器(link.exe)则是由 Visual Studio 提供的。
MSYS2 可以到这里下载:
链接:https://pan.baidu.com/s/1fWcS_5Xlxv1Bja4354JnvA
提取码:worc
我这里将其安装到了 D:\msys64 目录下
编译环境准备好之后,接下来我们需要下载一份最新的 FFmpeg 源码,可以使用 Git 下载。先将Git命令安装好,然后执行下面的命令。
cd /d/Git-Space
git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
代码就被下载到 D:\Git-Space 盘的 ffmpeg 目录下了
ffmpeg 源码也可以到这里下载:
链接:https://pan.baidu.com/s/1gjsDtEn_E4yCwnbT3TVUWQ
提取码:dlvx
首先,进入 MSYS2 的安装目录,比如我这里将 MSYS2 安装到了 D:\msys64 目录下。在该目录下打开 msys2_shell.cmd 文件,将该文件第 17 行代码的注释打开,即去掉 rem 关键字,如下所示:
之所以要打开该注释,是为了让 MSYS2 可以继承 Windows 控制台的环境变量。
之后,找到 x64 Native Tools Command Prompt for VS 2022 命令窗口:
在该命令窗口中输入下面的命令启动 MSYS2 软件
# 进入到 MSYS2 目录下
cd D:\msys64
# 启动 MSYS2
msys2_shell.cmd
此时,会弹出 MSYS2 的命令窗口。接下来,在该窗口中输入下面命令,安装必要的编译工具:
pacman -S diffutils make pkg-config yasm
其中 pacman 是 MSYS2的 包安装工具;而 diffutils、make…都是编译 FFmpeg 时需要用的编译工具。
当编译工具安装好后,在 MSYS2 命令窗中执行下面命令,进入到 FFmpeg 源码目录下:
cd /d/Git-Space/ffmpeg
紧接着,运行 FFmpeg 源码目录中的 configure 脚本生成 Makefile 文件,命令如下:
./configure --prefix=/usr/local/ffmpeg --enable-gpl --enable-nonfree --enable-shared --disable-ffprobe --toolchain=msvc
上述命令的含义是使用 mscv 作为 FFmpeg 的编译工具链;编译出的 FFmpeg 库被放到 /usr/local/ffmpeg 目录下;编译的库是动态库,在 Windows 下就是 DLL 库;编译时不生成 ffprobe 程序。
上述脚本执行完成后,你可以在 FFmpeg 源码目录下发现多了一个 Makefile 文件。有了这个文件我们就可以编译FFmpeg了,编译命令如下:
make -j4 && make install
出现了很多报错:
fftools/opt_common.c(206): error C2065: “slib”: 未声明的标识符
fftools/opt_common.c(206): error C2296: “%”: 无效,因为左操作数的类型为“char [138]”
解决办法:
该问题是因为在 Windows下无法识别 CC_IDENT 导致的,只需将包括 CC_IDENT 关键字的那行代码注释掉即可。
继续编译
make -j4 && make install
此时编译通过了
当执行完这条命令后,在 D:\MSYS64\usr\local\ffmpeg 目录下就可以找到编译好的 FFmpeg 库和 FFmpeg 命令了。
编译好 FFmpeg 库后,下面我们就可以在 VS 中引用它了。
在 项目右键 -> 属性 -> C/C++ -> 常规 -> 附加包含目录
中添加 FFmpeg 头文件所在路径。
首先说明一点,我编译出来的库文件存在于 D:\msys64\usr\local\ffmpeg\bin 目录下
在 项目右键 -> 属性 -> 链接器 -> 常规 -> 附加库目录
中添加 FFmpeg 库所在路径。
在 项目右键 -> 属性 -> 链接器 -> 输入 -> 附加依赖项
中指定你所用到的 FFmpeg 库
指定以下所有库:
avcodec.lib
avdevice.lib
avfilter.lib
avformat.lib
avutil.lib
postproc.lib
swresample.lib
swscale.lib
当上面这此工作完成后,我们就可以在 main(…) 函数中调用 FFmpeg API 了,如调用 FFmpeg 库中的日志函数:
#include
extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
}
int main()
{
av_log_set_level(AV_LOG_DEBUG);
av_log(NULL, AV_LOG_INFO, "Hello World!\n");
return 0;
}
执行出现了这样的报错,其原因是在运行时无法找到需要的动态库。
解决方案一:
将 D:\msys64\usr\local\ffmpeg\bin 目录下的 avutil-58.dll 文件拷贝到 C:\Windows\System32 目录下
拷贝结果如下:
再次执行程序,可以看到如下的结果
解决方案二:
只需将我们之前编译好的 FFmpeg 库,即提示的无法找到的 .dll 库,拷贝到执行程序的同一目录下,这样执行程序就可以找到该库并正确执行了。
很多时候我们在编译 FFmpeg 库时还要增加一些其它库,如 SDL、x264 等,如果要将这些库添加到 FFmpeg 中,首先我们要编译出 Windows 下可用的对应库。
首先从 github 上获取 SDL 源码,命令如下:
git clone https://github.com/libsdl-org/SDL.git
git checkout release-2.26.x
需要注意的是,SDL现在已经发布了3.0版本,而ffmpeg目前只能用SDL2版本,所以在拉取代码后,需要切换到2.26这个版本
可以到这里自取 SDL-2.26.x
链接:https://pan.baidu.com/s/1n_wMhIsBb9yaDhAL8NHZ8Q
提取码:qqbh
下载好 SDL2 源码后,我们需要使用 CMake 为其生成 VS 工程,并将其安装到 Windows 系统上。
可以到这里自取 CMake 安装包
链接:https://pan.baidu.com/s/1pQ7hh3WA6ES8pdBTpds1_Q
提取码:et4t
关于安装 CMake 这里,针对所有用户把 CMake 目录安装到系统目录
并将其安装到 D:\CMake\ 目录下
之后打开 CMake-GUI,在 CMake-GUI 中指定 SDL 源码所在路径(D:/Git-Space/SDL)以及编译后的输出路径(D:/CMake/usr/local/)
随后执行
Configure -> Generate -> Open Project
生成 VS 工程。有了 VS 工程,我们就可以通过 VS2022 来编译 SDL 了。
分别在 Release 和 Debug 模式下,重新生成一下 All_BUILD 子项目。
没啥问题的话 SDL 就编译好了,你可以去 D:\Project\VS_Project\sdl_test\Debug 和 D:\Project\VS_Project\sdl_test\Release 目录下看看有没有对应的 lib 文件
D:\CMake\usr\local\sdl\Debug 目录如下:
D:\Project\VS_Project\sdl_test\Release 目录如下
为了满足要求,我们需要在指定输出目录下创建 lib 目录,并将 SDL2.lib 和 SDL2.dll 文件拷贝到 lib 目录下。同时在 lib 目录下创建 pkgconfig 目录,将 sdl2.pc 文件拷贝到该目录中。
最终完整的目录结构如下所示:
/usr/local/sdl2
|------------ lib
| |-- sdl2.lib
| |-- sdl2.dll
| |-- pkgconfig
| |----- sdl2.pc
|------------ include
此外,我们还要修改 sdl2.pc 中的内容,将其中的库路径修改为指定的输出路径
x264 库的编译还是比较简单的,与 SDL 一样我们也要先获取其源码,可以通过下面的命令获取 x264 源码:
git clone https://code.videolan.org/videolan/x264.git
可以到这里自取 x264 源码
链接:https://pan.baidu.com/s/17HyuJBrka04DXoS4WOa3tQ
提取码:oqrb
源码获取到后,可以直接在 MSYS2 环境下编译出 Windows 下可用的动态库,具体步骤如下:
# 通过VS X64 Native... 窗口打开MSYS2
cd D:\msys64
msys2_shell.cmd
cd /d/Git-Space/x264/ # 在MSYS2中进入x264源码目录
pacman -S automake autoconf libtool # 安装生成Makefile的工具
CC=cl ./configure --prefix=/usr/local/x264 --enable-shared --disable-asm
make -j 4 && make install
通过上面的命令就可以将 x264 编译出来了。x264 编译好后,其输出的目录结构与 ffmepg 是一样的,在 /usr/local/x264 中包括了 include、lib、bin 等目录。
要特别强调的一点是,我们需要将 lib 目录下的 libx264.dll.lib 文件名修改为 libx264.lib,否则 ffmpeg 编译时会报 “无法找到该库” 的错误。
fdk-aac 的编译与 SDL 类似,它同样要使用 CMake 生成 VS 工程文件,之后再通过 VS 编译该库。
首先,通下面的的命令获取 fdk-aac 源码:
git clone https://github.com/mstorsjo/fdk-aac.git
可以到这里自取 fdk-aac 源码:
链接:https://pan.baidu.com/s/1ViuYEtEFFh71w9ZRgLaesA
提取码:hwf5
之后打开 CMake-GUI,在 CMake-GUI 中指定 SDL 源码所在路径(D:/Git-Space/fdk-aac)以及编译后的输出路径(D:/CMake/usr/local/fdk-aac)
随后执行
Configure -> Generate -> Open Project
生成 VS 工程。有了 VS 工程,我们就可以通过 VS2022 来编译 FDK-AAC 了。
分别在 Release 和 Debug 模式下,重新生成一下 All_BUILD 子项目。
没啥问题的话 FDK-AAC 就编译好了,你可以去 D:\CMake\usr\local\fdk-aac\Debug 和 D:\CMake\usr\local\fdk-aac\Release 目录下看看有没有对应的 lib 文件
D:\CMake\usr\local\sdl\Debug 目录如下:
D:\CMake\usr\local\fdk-aac\Release 目录如下:
为了满足要求,我们需要在指定输出目录下创建 lib 目录,并将 fdk-aac.lib 和 fdk-aac.dll 文件拷贝到 lib 目录下。同时在 lib 目录下创建 pkgconfig 目录,将 fdk-aac.pc 文件拷贝到该目录中。
但是这里发现一个问题,就是目录下没有 include 目录
为了解决这个问题,我又用 MSYS2+mingw 的方式重新编译了一遍 fdk-aac,这种方式是可以生成 include 头文件的
①、打开 MSYS2 MINGW64
②、在 fdk-aac 目录下执行如下命令
pacman -S mingw-w64-x86_64-gcc
./autogen.sh
./configure --prefix=/usr/local/fdk-aac --enable-shared
make -j4
make install
然后将生成的头文件手动拷贝到了 /usr/local/fdk-aac 目录下即可。
最终完整的目录结构如下所示:
/usr/local/fdk-aac
|------------ lib
| |-- fdk-aac.lib
| |-- fdk-aac.dll
| |-- pkgconfig
| |----- fdk-aac.pc
|------------ include
此外,我们还要修改 fdk-aac.pc 中的内容,将其中的库路径修改为指定的输出路径
首先,我们要设置环境变量 PKG_CONFIG_PATH,通过它告诉 FFmpeg 上述几个库从哪儿可以找到,具体的设置方法如下:
在 MSYS2 窗口中打开 .bashrc
pacman -S vim
vim ~/.bashrc
在 ~/.bashrc 中设置环境变量
export PKG_CONFIG_PATH=/d/CMake/usr/local/sdl/lib/pkgconfig:/usr/local/x264/lib/pkgconfig:/d/CMake/usr/local/fdk-aac/lib/pkgconfig:$PKG_CONFIG_PATH
:wq #保存并退出vim
让环境变是生效
source ~/.bashrc
接下来,重新生成 FFmpeg 的 Makefile 文件,并重新编译
首先进入到 ffmpeg 源码目录,执行下列命令
./configure --prefix=/usr/local/ffmpeg --arch=x86_64 --enable-shared --disable-ffprobe --disable-doc --enable-x264 --enable-gpl --enable-fdk-aac --enable-nonfree --toolchain=msvc
make clean
make -j 4 && make install
最后,将 sdl 的 dll、x264 的 dll 以及 fdk-aac 的 dll 拷贝到 ffmpeg 的 bin 目录下,这样就可以正确的执行 ffmpeg.exe 或 ffplay.exe 命令了。
进入 ffmpeg/bin 目录下,执行以下命令,如果能够输出版本信息,则说明正常
./ffmpeg.exe -version
我的qq:2442391036,欢迎交流!