一、前期准备
在 Visual Studio 2019 中编译 x264、x265、fdk-aac、lame 和 FFmpeg 需要在 Windows 环境下搭建一个类 Linux 的编译环境,因为这些库主要在 Linux 下开发,源码与 MSVC++ 不完全兼容,基于 MSYS2 和 MinGW 的工具链,并结合 Visual Studio 2019 的编译器(cl.exe)。
1.1 VS2019安装
要安装的组件:
- 使用C++的桌面开发
- Visual Studio 扩展开发
- 英语 语言包
1.2 MSYS2安装
下载地址:msys2-installer
启动MSYS2:
# 进入 mingw32环境
msys2_shell.cmd -mingw32
# 进入 mingw64环境
msys2_shell.cmd -mingw64
更换国内源:
# 修改源文件
sed -i "s#mirror.msys2.org/#mirrors.ustc.edu.cn/msys2/#g" /etc/pacman.d/mirrorlist*
# 更新源
pacman -Sy
参考地址:https://mirrors.ustc.edu.cn/help/msys2.html
继承终端的环境变量
使用VS2019的终端启动MSYS2(继承VS2019的变量):
1.3 安装基本工具
pacman -S --needed base-devel mingw-w64-x86_64-toolchain
pacman -S mingw-w64-x86_64-nasm mingw-w64-x86_64-yasm
pacman -S git pkg-config
说明:
base-devel
:提供编译和开发软件所需的基础工具集,包含 常用的工具如 make, patch, autoconf, automake, libtool, gettext, texinfo 等mingw-w64-x86_64-toolchain
:MinGW-w64 的完整工具链,用于在 Windows 上编译 64 位应用程序,包含 编译器(如 gcc, g++)、链接器、调试器(gdb)以及相关的开发库和头文件。mingw-w64-x86_64-nasm
:NASM(Netwide Assembler)是一个开源的 x86 和 x86-64 汇编器。mingw-w64-x86_64-yasm
:YASM 是一个模块化的汇编器,支持 x86 和 x86-64 架构,兼容 NASM 语法。git
:用于从 Git 仓库下载源码(如git clone
)。pkg-config
:用于检索已安装库的编译和链接信息。
二、编译
所有源码下载:ffmpeg4.4.1源代码
将所有源码解压到msys2家目录下(避免盘符转义问题):
2.1 设置终端代理
临时设置
# 设置代理
export http_proxy="http://127.0.0.1:11819"
export https_proxy="http://127.0.0.1:11819"
# 取消代理
unset http_proxy
unset https_proxy
永久设置
# 修改~/.bashrc配置文件
vim ~/.bashrc
export http_proxy="http://127.0.0.1:11819"
export https_proxy="http://127.0.0.1:11819"
# 使环境变量生效
source ~/.bashrc
2.2 重命名cmake和link(避免与VS2019的冲突)
# 如果使用msys2的cmake,会生成不了NMAKE的构建系统
mv /usr/bin/cmake /usr/bin/cmake_bak
# 要使用VS2019的link,否则容易在编译阶段失败
mv /usr/bin/link.exe /usr/bin/link.exe_bak
2.3 编译x264
# 下载源码
git clone https://code.videolan.org/videolan/x264.git
# 配置(disable-cli是禁止生成命令行工具)
CC=cl ./configure \
--prefix=$(pwd)/../3rdparty_msvc \
--enable-static \
--disable-cli
# 编译安装
make -j$(nproc) && make install
x264.pc文件内容(位置3rdparty_msvc\lib\pkgconfig\x264.pc):
prefix=/home/wujh/3rdparty_msvc
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: x264
Description: H.264 (MPEG4 AVC) encoder library
Version: 0.165.3222
Libs: -L${exec_prefix}/lib -lx264
Libs.private:
Cflags: -I${prefix}/include
2.4 编译x265
# 下载源码
git clone https://bitbucket.org/multicoreware/x265_git.git
# 配置
mkdir tmp && cd tmp
cmake -G "NMake Makefiles" \
-DCMAKE_INSTALL_PREFIX=$(pwd)/../../3rdparty_msvc \
-DCMAKE_CXX_FLAGS="-DWIN32 -D_WINDOWS -W4 -GR -EHsc" \
-DCMAKE_C_FLAGS="-DWIN32 -D_WINDOWS -W4" \
-DENABLE_SHARED=OFF \
-DENABLE_CLI=OFF \
-DSTATIC_LINK_CRT=ON \
../source
# 编译安装
nmake && nmake install
说明:
- -DWIN32 -D_WINDOWS -W4 -GR -EHsc 以确保与 Windows 环境的兼容性和编译器警告级别。
- -DENABLE_SHARED=OFF 确保只生成静态库 x265-static.lib,避免生成动态库 libx265.lib 和 x265.dll。
- -DENABLE_CLI=OFF:禁用 x265 的命令行工具,减少依赖(如标准 I/O 函数可能引入的动态 CRT 符号)。
- -DSTATIC_LINK_CRT=ON 强化静态 CRT 的使用,确保 x265 的所有对象文件使用 libcmt.lib 而非 msvcrt.lib。
x265.pc文件内容(-lx265-static 强制链接静态库):
prefix=/home/wujh/3rdparty_msvc
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: x265
Description: H.265/HEVC video encoder
Version: 4.1
Libs: -L${libdir} -lx265-static
Libs.private:
Cflags: -I${includedir}
2.5 编译fdk-aac
注意:2.0.1版提供了Makefile.vc编译文件,2.0.2版本没有提供。
# 下载源码
wget https://github.com/mstorsjo/fdk-aac/archive/refs/tags/v2.0.1.tar.gz
# 编译
nmake -f Makefile.vc
# 安装
nmake -f Makefile.vc install prefix=$(pwd)/../3rdparty_msvc
# 清理
nmake -f Makefile.vc clean
fdk-aac.pc文件内容:
prefix=/home/wujh/3rdparty_msvc
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: Fraunhofer FDK AAC Codec Library
Description: AAC codec library
Version: 2.0.1
Libs: -L${libdir} -lfdk-aac
Cflags: -I${includedir}
2.6 编译lame
# 下载源码
wget https://sourceforge.net/projects/lame/files/lame/3.100/lame-3.100.tar.gz
# 编译64位的库 (默认时编译32位)
nmake -f Makefile.MSVC rebuild MSVCVER=Win64 MACHINE=/machine:x64 OFF=win64
# 清理
nmake -f Makefile.MSVC clean
说明:
-f Makefile.MSVC
指定makefile文件rebuild
包括clean allMSVCVER=Win64
表示使用 64 位的 MSVC 编译器进行构建MACHINE=/machine:x64
指示链接器和汇编器生成 64 位目标文件。OFF=win64
指定汇编器的输出格式。
copy_dll.sh文本内容:
#!/bin/sh
# Check if installation directory is provided
if [ -z "$1" ]; then
echo "Usage: $0 <install_dir>"
exit 1
fi
INSTALL_DIR="$1"
# Check if output directory exists
if [ ! -d "output" ]; then
echo "Error: output directory not found."
exit 1
fi
# Create destination directories
mkdir -p "$INSTALL_DIR/bin"
mkdir -p "$INSTALL_DIR/lib"
mkdir -p "$INSTALL_DIR/include/lame"
# Copy DLLs to bin
cp -v output/*.dll "$INSTALL_DIR/bin/" 2>/dev/null || echo "No DLL files to copy."
# Copy LIBs to lib, excluding libmp3lame-static.lib
cp -v output/*.lib "$INSTALL_DIR/lib/" 2>/dev/null || echo "No LIB files to copy."
# Copy header files to include/lame
cp -v include/* "$INSTALL_DIR/include/lame/" 2>/dev/null || echo "No lame include to copy."
拷贝依赖库到指定目录(因为makefile中没有install指令):
chmod +x copy.sh
./copy_dll.sh $(pwd)/../3rdparty_msvc
将libmp3lame-static.lib重命名为mp3lame.lib:
2.7 编译ffmpeg
# 下载源码
git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg-4.4.1
cd ffmpeg-4.4.1
git checkout n4.4.1
# 设置.pc文件搜索路径
export PKG_CONFIG_PATH=$(pwd)/../3rdparty_msvc/lib/pkgconfig:$PKG_CONFIG_PATH
# 配置(--enable-shared编译动态库,--enable-static编译静态库)
./configure \
--prefix=$(pwd)/../ffmpeg_build \
--toolchain=msvc \
--disable-everything \
--disable-doc \
--enable-shared \
--enable-muxer=mp4,flv,mp3,wav \
--enable-demuxer=mp4,mov,mp3,aac \
--enable-encoder=libx264,libx265,libfdk_aac,libmp3lame \
--enable-decoder=aac,h264,hevc,mp3 \
--enable-protocol=file,http \
--enable-filter=aresample \
--enable-bsf=aac_adtstoasc \
--enable-gpl \
--enable-nonfree \
--enable-libx264 \
--enable-libx265 \
--enable-libfdk-aac \
--enable-libmp3lame \
--extra-cflags="-I$(pwd)/../3rdparty_msvc/include" \
--extra-ldflags="-LIBPATH:$(pwd)/../3rdparty_msvc/lib"
# 编译安装
make -j$(nproc) && make install
三、vscode使用ffmpeg库
3.1 使用ffmpeg动态库
项目目录结构:
./
├── 3rdparty # 第三方依赖库
│ └── ffmpeg_4.4.1
│ ├── include # 头文件
│ ├── lib # 静态库库
│ └── share
├── build # 编译目录
├── CMakeLists.txt # cmake配置文件
└── src # 源码文件
└── main.c
CMakeLists.txt文件内容:
cmake_minimum_required(VERSION 3.10)
project(ffmpeg_test VERSION 1.0)
set(CXX_STANDARD 11)
set(CXX_STANDARD_REQUIRED True)
# 设置可执行文件输出目录为 bin
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin)
# 配置FFmpeg(avcodec.lib时动态库的导入库)
set(FFMPEG_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/ffmpeg-4.4.1)
include_directories(${FFMPEG_DIR}/include)
# 动态库
set(FFMPEG_LIBS
${FFMPEG_DIR}/bin/avcodec.lib
${FFMPEG_DIR}/bin/avdevice.lib
${FFMPEG_DIR}/bin/avfilter.lib
${FFMPEG_DIR}/bin/avformat.lib
${FFMPEG_DIR}/bin/avutil.lib
${FFMPEG_DIR}/bin/swresample.lib
${FFMPEG_DIR}/bin/swscale.lib
)
# 编译和链接依赖库
add_executable(${PROJECT_NAME} src/main.c)
# 动态库
target_link_libraries(${PROJECT_NAME} PRIVATE ${FFMPEG_LIBS} )
# 使用file(GLOB)获取所有DLL文件
file(GLOB FFMPEG_DLLS "${FFMPEG_DIR}/bin/*.dll")
# 添加自定义命令,在构建后复制DLL文件到输出目录
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${FFMPEG_DLLS}
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
)
main.c文件内容:
#include <stdio.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
int main() {
// 待检查的编解码器列表
const char *codecs[] = {
"libx264", // H.264 编码器
"libx265", // HEVC 编码器
"libfdk_aac", // AAC 编码器
"libmp3lame", // MP3 编码器
NULL // 结束标记
};
printf("FFmpeg 集成编解码器状态检查:\n");
printf("===========================\n");
// 遍历并检查每个编解码器
for (int i = 0; codecs[i] != NULL; i++) {
const AVCodec *codec = avcodec_find_encoder_by_name(codecs[i]);
if (!codec) {
// 若编码器未找到,尝试查找解码器
codec = avcodec_find_decoder_by_name(codecs[i]);
}
if (codec) {
printf("[✅] %-12s : 已启用 (类型: %s)\n",
codecs[i],
codec->type == AVMEDIA_TYPE_VIDEO ? "视频" : "音频");
} else {
printf("[❌] %-12s : 未启用或未编译\n", codecs[i]);
}
}
return 0;
}
生成构建系统的文件(相当于cmake ..
这里省略了一些参数):
编译:
cd build
cmake --build . --config Release
3.2 使用ffmpeg静态库
除了CMakeLists.txt文件内容不同,其他的和上面的动态库一样。
CMakeLists.txt文件内容:
cmake_minimum_required(VERSION 3.10)
project(ffmpeg_test VERSION 1.0)
set(CXX_STANDARD 11)
set(CXX_STANDARD_REQUIRED True)
# 设置可执行文件输出目录为 bin
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin)
# 配置FFmpeg
set(FFMPEG_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/ffmpeg-4.4.1)
include_directories(${FFMPEG_DIR}/include)
set(FFMPEG_LIBS
${FFMPEG_DIR}/lib/libavcodec.a
${FFMPEG_DIR}/lib/libavdevice.a
${FFMPEG_DIR}/lib/libavfilter.a
${FFMPEG_DIR}/lib/libavformat.a
${FFMPEG_DIR}/lib/libavutil.a
${FFMPEG_DIR}/lib/libswresample.a
${FFMPEG_DIR}/lib/libswscale.a
)
# 添加 MSVC 编码支持
if(MSVC)
add_compile_options("/utf-8")
endif()
# 编译和链接依赖库
add_executable(${PROJECT_NAME} src/main.c)
# 强制使用静态运行时库(ffmpeg静态库使用MT,这里强制使用MT)
target_link_options(${PROJECT_NAME} PRIVATE "/NODEFAULTLIB:LIBCMT")
target_link_libraries(${PROJECT_NAME} PRIVATE ${FFMPEG_LIBS} ws2_32 bcrypt)