Windows平台编译FFmpeg动态库
一、概要:
FFmpeg官方网站针对windows平台,提供了两种编译源码的方式:
- msys2 + msvc
- msys2 + mingw (本文就使用这种方式)
msys2就是在windows平台提供一个Linux环境(会把所有linux的shell命令映射成windows平台的命令)
mingw主要是是把 GCC 编译器以及一些 配套的命令 objdump 跟 readelf 也移植到 Windows 平台
二、本文所用版本:
温馨提示:最好跟我用一样的版本,您想锻炼下自己填坑的能力另说
FFmpeg:
版本:ffmpeg-5.1.4
官网:https://ffmpeg.org/download.html#releases
msys2:
版本:msys2-x86_64-20240113.exe
三、环境搭建
3.1 安装msys2:
国际惯用搞法,next…下一步…next…下一步…完成,没啥好讲的
3.2 运行mingw64:
因为我们是64位系统,并且想使用mingw而不是msvc,所以双击下图的exe即可;
看到界面如下图,搞Linux的同学,有没有很熟悉?这就是我们的Shell终端啊。
四、开始编译:
4.1 安装必要的包
msys2使用pacman管理安装包,非常好用,常用三条命令需要掌握:
- 刷新安装包
pacman -Syu
- 搜索安装包(你不知道具体名字可以搜一下)
pacman -Ss xxx
# 比如,你搜索libx264,就可以:
pacman -Ss libx264
- 安装:
pacman -S mingw-w64-x86_64-toolchain git make automake autoconf perl libtool mingw-w64-x86_64-cmake pkg-config yasm diffutils nasm
安装过程中出现的确认信息,仔细读读(其实我一般都无脑Y+Enter的啦,一般人我不告诉他)
4.2 拷贝FFmpeg源代码到msys2环境下:
4.3 解压:
tar xvf ffmpeg-5.1.4.tar.xz
4.3 编写编译脚本
- 在ffmpeg源代码同级目录新建编译脚本:
vim build_ffmpeg5.sh
内容如下:
#!/bin/bash
export BUILD=$PWD/build/ffmpeg.build
export STAGING=$BUILD/staging
FFMPEG_SRC=$PWD/ffmpeg-5.1.4
ADDI_CFLAGS="-Os -fpic -I$STAGING/include"
ADDI_LDFLAGS="-L$STAGING/libs"
function build_ffmpeg {
mkdir $BUILD 2> /dev/null
pushd $BUILD
$FFMPEG_SRC/configure \
--prefix=$STAGING \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-symver \
--enable-gpl \
--enable-debug=3 \
--disable-optimizations \
--disable-asm \
--disable-stripping \
--enable-nonfree
make
make install
popd
}
build_ffmpeg
*养成良好的编程思维,即使是shell脚本也封装成函数,还有,
ADDI_CFLAGS=“-Os -fpic -I
S
T
A
G
I
N
G
/
i
n
c
l
u
d
e
"
A
D
D
I
L
D
F
L
A
G
S
=
"
−
L
STAGING/include" ADDI_LDFLAGS="-L
STAGING/include"ADDILDFLAGS="−LSTAGING/libs”
这两个是后续编译依赖库时候使用的,比如ffmpeg依赖fdk-aac或者libx264等库,待续…
*
4.4 开始编译
-
执行编译脚本:
-
查看编译结果:
当出现下图时候,就表示已经编译完成了:
查看安装目录:
五、拷贝到QT中进行集成:
切记使用CMake来组织工程,这样可移植性才高
5.1 QT环境搭建:
这不是本文重点,我只能说我使用的版本是QT5.15.2(编译时候建议换成清华或者中科大源)
5.2 新建QT工程:
- 项目名称和位置:
点Next - 编译系统:
都4202年了,肯定选CMake啊,因为CMake才能做到真正跨平台,你选了qmake就自己玩吧。 - QT的UI主界面:
点Next - details:
默认即可,继续Next - 选择编译工具链:
开头我都说了,我要使用mingw,不适用msvc; - Summary:
默认,继续Finish - 工程目录:
先不带ffmpeg跑一下,点击下面Run按钮(或者Ctrl+R)
结果如下:
接下来就是集成FFmpeg
5.3 QT集成FFmpeg库
- 新建目录,copy刚才msys2编译成功的库和头文件
share目录下主要是一些examples,教你怎么使用ffmpeg的API的,你可以参考来写自己代码,加不加的不影响工程。- 最终目录结构如下:
【说明】考虑到封装性,新建了一个目录MeidaPlayer来专门和FFmpeg交互,顶层MainWindow是主线程(也就是UI线程),只和用户交互,避免耗时操作; - MediaPlayer的CMakeLists.txt如下:
cmake_minimum_required(VERSION 3.5)
project(MediaPlayer)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 设置FFmpeg的相关路径
set(FFMPEG_DIR ${CMAKE_SOURCE_DIR}/third-party/ffmpeg)
add_library(media_player SHARED
MediaPlayer.cpp
)
message("##***###ricky:${FFMPEG_DIR}")
# 导入另外一个共享库
add_library(external_library STATIC IMPORTED)
# 设置导入的共享库的路径
set_target_properties(external_library PROPERTIES
IMPORTED_LOCATION ${FFMPEG_DIR}/lib/libavcodec.dll.a
IMPORTED_IMPLIB ${FFMPEG_DIR}/lib/libavcodec.dll.a
IMPORTED_LOCATION ${FFMPEG_DIR}/lib/libavdevice.dll.a
IMPORTED_IMPLIB ${FFMPEG_DIR}/lib/libavdevice.dll.a
IMPORTED_LOCATION ${FFMPEG_DIR}/lib/libavfilter.dll.a
IMPORTED_IMPLIB ${FFMPEG_DIR}/lib/libavfilter.dll.a
IMPORTED_LOCATION ${FFMPEG_DIR}/lib/libavformat.dll.a
IMPORTED_IMPLIB ${FFMPEG_DIR}/lib/libavformat.dll.a
IMPORTED_LOCATION ${FFMPEG_DIR}/lib/libavutil.dll.a
IMPORTED_IMPLIB ${FFMPEG_DIR}/lib/libavutil.dll.a
IMPORTED_LOCATION ${FFMPEG_DIR}/lib/libswresample.dll.a
IMPORTED_IMPLIB ${FFMPEG_DIR}/lib/libswresample.dll.a
IMPORTED_LOCATION ${FFMPEG_DIR}/lib/libswscale.dll.a
IMPORTED_IMPLIB ${FFMPEG_DIR}/lib/libswscale.dll.a
IMPORTED_LOCATION ${FFMPEG_DIR}/lib/libpostproc.dll.a
IMPORTED_IMPLIB ${FFMPEG_DIR}/lib/libpostproc.dll.a
)
# 链接FFmpeg库
target_link_libraries(external_library INTERFACE
avcodec
avdevice
avfilter
avformat
avutil
swresample
postproc
)
target_include_directories(external_library INTERFACE ${FFMPEG_DIR}/include)
# 指定包含目录(相当于-I)
target_include_directories(media_player
PUBLIC
${FFMPEG_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR})
# 指定链接目录(相当于-L)
target_link_directories(media_player
PUBLIC
${FFMPEG_DIR}/lib
${FFMPEG_DIR}/bin)
# 需要链接那些库(相当于-l)
target_link_libraries(media_player
PUBLIC
external_library
)
# 安装
install(TARGETS media_player
LIBRARY DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR} # 安装动态库
ARCHIVE DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR} # 安装静态库
RUNTIME DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR} # 将可执行文件安装到CMAKE_INSTALL_BINDIR指定的目录,通常是bin目录
)
set(FFMPEG_CONTROLLER_HEADS ${CMAKE_CURRENT_SOURCE_DIR}/PcmPlayer.h)
install(FILES ${FFMPEG_CONTROLLER_HEADS}
DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/include
)
- 顶层目录的CMakeLists.txt如下:
cmake_minimum_required(VERSION 3.5)
# 定义项目信息,包括项目名称、版本号以及使用的编程语言。项目名为FFmpegPlayer,版本号为0.1,使用的语言是C++
project(FFmpegPlayer VERSION 0.1 LANGUAGES CXX)
# CMake自动生成UI文件的开关,也就是项目中包含了.ui文件时候,CMake会自动识别并生成ui_*.h
set(CMAKE_AUTOUIC ON)
# CMake自动处理MOC,也就是一些信号和槽等QT的元特性
set(CMAKE_AUTOMOC ON)
# CMake自动处理资源文件的开关,处理.qrc文件
set(CMAKE_AUTORCC ON)
# C++使用的是C++17
set(CMAKE_CXX_STANDARD 17)
# 强制使用C++17来编译
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 添加子目录
add_subdirectory(MediaPlayer)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
set(PROJECT_SOURCES
main.cpp
mainwindow.cpp
mainwindow.h
mainwindow.ui
)
add_executable(FFmpegPlayer
${PROJECT_SOURCES}
)
# 指定包含目录(相当于-I)
target_include_directories(FFmpegPlayer PUBLIC MediaPlayer)
# 指定链接目录(相当于-L)
target_link_directories(FFmpegPlayer PUBLIC MediaPlayer)
# 需要链接的库(相当于-l)
target_link_libraries(FFmpegPlayer PRIVATE
Qt${QT_VERSION_MAJOR}::Widgets
media_player
)
# 设置了目标(target)FFmpegPlayer的一些属性
set_target_properties(FFmpegPlayer PROPERTIES
WIN32_EXECUTABLE TRUE # 表示在windows平台生成可执行文件exe
)
# 这个命令是引入CMake自带的GNUInstallDirs模块,该模块定义了一些标准的安装目录变量,比如CMAKE_INSTALL_LIBDIR、CMAKE_INSTALL_BINDIR等,方便我们在后面的安装规则中使用。
include(GNUInstallDirs)
install(TARGETS FFmpegPlayer
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # 安装动态库
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # 安装静态库
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # 这表示将可执行文件安装到CMAKE_INSTALL_BINDIR指定的目录,通常是bin目录
)
我已经写了很详细的注释了,看不懂的同学该先去学习下Cmake语法了,祝各位使用顺利!
接下来就是直接用了…后续写个播放器,敬请期待。。。