前言
本章节记录在Windows上编译ffmpeg的过程及编译过程的问题,并使用编译库编写测试程序验证是否可用。
在windows上编译主要使用MSYS2和vs 2019编译器编译ffmpeg,并且验证32位和64位的编译。
环境准备
-
ffmpeg源代码
官网:https://ffmpeg.org/
版本信息:
5.1.2 was released on 2022-09-25. It is the latest stable FFmpeg release from the 5.1 release branch, which was cut from master on 2022-07-13.
It includes the following library versions:
libavutil 57. 28.100 libavcodec 59. 37.100 libavformat 59. 27.100 libavdevice 59. 7.100 libavfilter 8. 44.100 libswscale 6. 7.100 libswresample 4. 7.100 libpostproc 56. 6.100
-
系统版本:Windows 10
-
编译器:Visual Studio 2019
-
MSYS2
MSYS2是Windows下的Linux模拟器,支持绝大多数的Linux命令,软件包管理器是pacman
官网:https://www.msys2.org/
-
x264源代码
x264是一个用于将视频流编码为H.264/MPEG-4 AVC压缩格式的免费软件库和应用程序。为了支持ffmpeg的H264编解码必须编译这个。
官网:https://www.videolan.org/developers/x264.html
版本:master分支(20221112)
编译
-
启动msys2
通过vs2019的命令行启动msys2,这样msys2可以获取到vs的环境变量。
编译32位和64位的动态库,只是启动的vs2019命令行不一样,其他执行操作都一样。下面以编译32位的动态库为例,启动msys2:
-
修改msys2的配置文件
修改msys2_shell.cmd文件,打开set MSYS2_PATH_TYPE=inherit的注释(使其能继承vs2019的命令行环境)
-
启动vs2019 x86(32位)命令行
如下可以看到32和64的命令行,这里我们启动x86 Native ToolsCommand Prompt for Vs2019
-
测试cl.exe的版本确实是x86(32)
-
启动msys2
启动mysy2(c:\msys64是msy2的安装目录),不管启动的vs2019命令行是32位还是64位的,执行下面操作都一致。
启动后的msys2:
-
-
安装依赖项
# 安装mingw工具链 pacman -S mingw-w64-x86_64-toolchain # 安装linux base-devel pacman -S base-devel # 安装汇编工具,gcc等 pacman -S yasm nasm gcc
-
源代码解压
将ffmpeg和x264源码解压放在如下对应目录:
-
编译
- 编译脚本整理如下,该编译文件放置在x264-master和ffmpeg-5.1.2的同级目录。切换到该脚本目录执行脚本。
# 当前脚本的目录 base_path=$(cd `dirname $0`;pwd) # 设置输出目录:64还是32位 archtarget="x64" isContrainX64=$(which cl) if [[ $isContrainX64 =~ $archtarget ]];then archtarget="x64" else archtarget="win32" fi echo $archtarget # x264的源文件目录和编译后的安装目录 x264_src_path=$base_path/x264-master x264_lib_path=$base_path/install/$archtarget/x264 # ffmpeg的源文件目录和编译后的安装目录 ffmpeg_src_path=$base_path/ffmpeg-5.1.2 ffmpeg_lib_path=$base_path/install/$archtarget/ffmpeg # -------------编译x264------------- echo "[info] begin compile x264" cd $x264_src_path CC=cl ./configure --prefix=$x264_lib_path --enable-static make clean make -j8 if [ $? -eq 0 ];then echo "[info] x264 build sucessed." else echo "[error] x264 build failed." exit 1 fi make install # -------------编译ffmpeg静态库------------- echo "[info] begin compile ffmpeg" export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$x264_lib_path/lib/pkgconfig cd $ffmpeg_src_path # --prefix:生成文件目录 # --enable-shared:构建shared库 # --arch:目标架构(常用有aarch64,arm,ia64,x86,x86_32,x86_64) # --enable-libx264:通过x264使用h.264编码 #类似 # --enable-libopenh264 # --extra-cflags:(c)编译参数 # --extra-cflags="-MDd" debug版本 # --extra-libs:链接参数 # --extra-ldflags="/NODEFAULTLIB:libcmt" # --enable-debug:debug版本 # --toolchain:使用编译器vs2019 CC=cl ./configure --prefix=$ffmpeg_lib_path --enable-shared --enable-libx264 --enable-gpl --arch=x86 --toolchain=msvc \ --extra-cflags=-l$x264_lib_path/include \ --extra-ldflags=-L$x264_lib_path/lib # 修改config.h的内容,防止中文字符引起不能编译 # #define CC_IDENT "用于 x64 的 Microsoft (R) C/C++ 优化编译器 19.29.30146 版" -> #define CC_IDENT "Microsoft (R) C/C++" sed -i "/#define CC_IDENT.*/c\#define CC_IDENT \"Microsoft (R) C/C++\"" config.h make clean make -j8 if [ $? -eq 0 ];then echo "[info] ffmpeg build sucessed." else echo "[error] ffmpeg build failed." exit 1 fi make install # 保存PDB mkdir $ffmpeg_lib_path/pdb find . -iname "*.pdb" -type f -exec cp {} $ffmpeg_lib_path/pdb \; exit 0
-
编译好的动态库已经打包好了,包含32位和64位的动态库,下载地址:ffmpeg在Windows上vs2019编译的动态库(32位和64位包含pdb)-编解码文档类资源-CSDN文库
测试
编写测试程序测试是否可用,测试获取视频文件的时长。
测试代码:
extern "C"
{
#include <libavformat/avformat.h>
}
#include <iostream>
bool getVedioDuration(const std::string &filePath)
{
AVFormatContext *fmtCtx = avformat_alloc_context();
if (nullptr == fmtCtx)
{
return false;
}
auto ret = avformat_open_input(&fmtCtx, filePath.c_str(), NULL, NULL);
if (ret < 0)
{
return false;
}
int videoIndex = -1;
int audio_index = -1;
int nbStreams = fmtCtx->nb_streams;
for (int i = 0; i < nbStreams; i++)
{
// fmtCtx->streams[i]->codec 新版ffmpeg已弃用
if (fmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoIndex = i;
}
else if (fmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
{
audio_index = i;
}
}
if (videoIndex != -1)
{
auto streamVedio = fmtCtx->streams[videoIndex];
std::cout << "vedio duration: " << (streamVedio->duration * streamVedio->time_base.num / streamVedio->time_base.den) << std::endl;
}
if (audio_index != -1)
{
auto streamAudio = fmtCtx->streams[audio_index];
std::cout << "audio duration: " << (streamAudio->duration * streamAudio->time_base.num / streamAudio->time_base.den) << std::endl;
}
if (videoIndex == -1 && audio_index == -1)
{
return false;
}
return true;
}
int main(int argc, char *argv[])
{
getVedioDuration("D:\\vedio\\aa.mp4");
return 0;
}
基于Qt的工程配置
# 项目根目录
ROOT_DIR = $$PWD/..
# 第三方库
3RDPART_DIR = $${ROOT_DIR}/3rdparty
# 可执行目录
CONFIG(debug, debug|release){
BIN_DIR = $${ROOT_DIR}/debug
} else {
BIN_DIR = $${ROOT_DIR}/release
}
win32 {
contains(QMAKE_TARGET.arch, x86_64) {
# x64
INCLUDEPATH += $${3RDPART_DIR}/ffmpeg/x64/include
CONFIG(debug, debug|release){
LIBS += -L$${3RDPART_DIR}/ffmpeg/x64/bin \
-lavformat
} else {
LIBS += -L$${3RDPART_DIR}/ffmpeg/x64/bin \
-lavformat
}
} else {
# x86
INCLUDEPATH += $${3RDPART_DIR}/ffmpeg/win32/include
CONFIG(debug, debug|release){
LIBS += -L$${3RDPART_DIR}/ffmpeg/win32/bin \
-lavformat
} else {
LIBS += -L$${3RDPART_DIR}/ffmpeg/win32/bin \
-lavformat
}
}
}
其他
-
编译过程中出现make install报错
问题现象:在编译x264的时候,make install报错,msys2 make: install: No such file or directory
解决:未找到正式原因,将msys2卸载后,重新安装,并安装依赖环境解决
-
编译ffmpeg出现CC_IDENT引起的编译错误
问题现象:译ffmpeg出现CC_IDENT引起的编译错误
原因:configure后,会根据cl的版本信息写入config.h的头文件中,因中文版本原因,CC_IDENT包含中文字符,编译时不识别报错
解决:编译脚本中已修改如下
sed -i “/#define CC_IDENT.*/c#define CC_IDENT “Microsoft ® C/C++”” config.h
-
编译ffmpeg 64位时卡住
现象:编译ffmpeg 64时在如下地方卡住:
LD libavcodec/avcodec-59.dll 正在创建库 libavcodec/avcodec.lib 和对象 libavcodec/avcodec.exp
解决:重新使用vs 2016 x86_64的命令行编译通过