顺序是先把 x264、x265 编成库,再让 FFmpeg 去链它们。
MSVC 产物是 .lib 加 -60.dll,与 MinGW 的 .dll.a 不能互换。
1.2.5 装的是通用依赖,这一篇还要额外编两个编码器。 下一篇 1.2.7 是同一件事的 MinGW 版本,两篇对照着看最清楚。
一、为什么要先编 x264 与 x265
FFmpeg 自己不含 H.264 编码器,它只负责「调」外面的库。
所以 --enable-libx264 的意思不是「编译 x264」,而是「去链已经存在的 x264」。
先有库,才有得链。
顺序 编什么 产物 给谁用
1 x264 libx264.lib + .dll FFmpeg 的 H.264 编码 2 x265 libx265.lib + .dll FFmpeg 的 H.265 编码 3 FFmpeg avcodec.lib 等 + DLL 你的程序
顺序不能颠倒。 先编 FFmpeg 再补 x264, 只能把 FFmpeg 删了重编一遍——configure 的结果是写死在 config.h 里的,改不了。 x264 与 x265 自己也要用汇编器。 这就是 1.2.5 里 yasm 与 nasm 的用处; 没有它们,configure 会在汇编那一步失败。
二、configure 的四组参数
一条 configure 命令里,参数按用途分四组: 组 参数 作用
工具链 --toolchain=msvc 用 cl 编 产物 --enable-shared --disable-static 只出动态库 外部库 --enable-libx264 --enable-libx265 开两个编码器 许可 --enable-gpl x264 是 GPL,必须开
--enable-shared --disable-static 这一组,二次开发必须开。 静态库会把所有代码塞进你的 exe,
体积几十兆,改一次库就要重编整个工程;动态库只留导入库,链接快、换库方便。
--extra-cflags 与 --extra-ldflags 是给 x264 指路的。 FFmpeg 不知道 x264 装在哪,
得靠这两个参数把 include 与 lib 目录传进去。
少传一个会怎样: configure 报「找不到 libx264」,然后把 H.264 编码关掉,
整个编译照样成功。 这是最容易白编一次的地方。
三、产物清单:编完该看见什么
文件 是什么 二次开发要不要
avcodec.lib 导入库,链接时用 要 avcodec-60.dll 运行时库,发版要带 要 libavcodec/avcodec.h 头文件 要 libavcodec.dll.a MinGW 的导入库 不要 libavcodec.a 静态库 不要
三样配齐才叫「能开发」:头文件决定能不能编过,导入库决定能不能链上,
DLL 决定运行时能不能起来。少一样,错在不同的阶段。
make install 之后,这三样都在 --prefix 指定的目录下,分别是 include、lib、
bin 三个子目录。
四、.lib 与 .dll.a 为什么不能互换
两者都是「导入库」,但格式不同,一个是 COFF,一个是 ar 归档。 项 .lib(MSVC) .dll.a(MinGW)
格式 COFF 导入库 GNU ar 归档 符号名 __imp_av_xxx _av_xxx 或 av_xxx 给谁用 cl / link gcc / ld 混用报错 LNK2019 undefined reference
混链的报错特别能骗人:符号明明在库里,链接器说找不到。
原因是 MSVC 找的是 __imp_ 前缀的导入符号,而 GNU 格式的导入库里存的是另一套名字。
名字对不上,跟有没有这个函数无关。
所以第一件事永远是「统一工具链」:Qt 用哪套、VS 用哪套、Python 绑定用哪套,
FFmpeg 就跟着哪套编。
本机验不了这一步:cl.exe 不在 PATH,Visual Studio 目录也不在,
INCLUDE 与 LIB 两个环境变量都是空的。清单是真的,执行需要另一台机器。
五、动手 Demo:MSVC 工具链编 5.0+Libx264+Libx265——命令怎么拼
本机没有 cl,所以这一段做两件事:拼命令并逐项检查开关,再看产物名。 最后用 PyAV 证明「本机这版确实带了 x264 与 x265」。
line = ("./configure --toolchain=msvc --arch=x86_64 --enable-shared "
"--disable-static --enable-gpl --enable-libx264 --enable-libx265")
need = ["--toolchain=msvc", "--enable-shared", "--enable-gpl"]
for n in need:
print(n, n in line)
实跑输出:
--------------------------------------------------------------------
MSVC 工具链编 5.0+Libx264+Libx265——命令怎么拼
--------------------------------------------------------------------
**① configure 那一行,参数分四组**
组 参数 管什么
--------------------------------------------------------------------------------
工具链 --toolchain=msvc 叫 cl 来编
产物 --enable-shared 出 DLL,二次开发要它
外部库 --enable-libx264 --enable-libx265 开 H.264/H.265 编码
许可 --enable-gpl x264 是 GPL,不开就编不进去
**② 拼出来的完整命令行(本课按教材参数复原)**
`./configure --toolchain=msvc --arch=x86_64 --enable-shared --disable-static `
`--enable-gpl --enable-libx264 --enable-libx265 --extra-cflags=-I../x264/in`
`clude --extra-ldflags=-LIBPATH:../x264/lib`
**③ 参数齐不齐,用代码检查一遍**
开关 在不在
-------------------------------
--toolchain=msvc 在
--arch=x86_64 在
--enable-shared 在
--disable-static 在
--enable-gpl 在
--enable-libx264 在
--enable-libx265 在
七个开关一个不缺。
**④ MSVC 出来的是这几个文件**
文件 是什么 二次开发要不要
---------------------------------------------------------------
avcodec.lib 导入库,编译时要它 要
avcodec-60.dll 运行时库,发版要它 要
avcodec/avcodec.h 头文件 要
avcodec.dll.a MinGW 的导入库 不要,格式不同
**这里有一条硬规矩:`.lib` 与 `.dll.a` 不能互换。** 前者是 MSVC 的 COFF 导入库,
后者是 GNU 的 ar 归档;混着链,链接器会报「无法解析的外部符号」,而符号明明就在里面。
**⑤ 本机为什么验不了这一步**
`cl.exe` 不在 PATH(Demo 2 里查过),`INCLUDE` 与 `LIB` 两个环境变量都是 0 段。
MSVC 的编译能力绑在「开发者命令提示符」里那一套环境变量上,光装 VS 不进去点那一下,
命令行里永远找不到 cl。
**⑥ 本机能验的那一半:libx264 与 libx265 确实在**
`libx264`:在
`libx265`:在
`h264`:在
`hevc`:在
本机这版 FFmpeg(编解码器 557 个)是带 x264 与 x265 的。所以「有没有 x264」这一层能验;
「怎么把 x264 编进 FFmpeg」这一层验不到——那需要编译器。
七个开关一个不缺。 这类检查在真机上同样有用:长命令一行行看容易漏,交给代码数。
最后那几张表里,libx264 与 libx265 都「在」,说明本机这版带两个编码器。
30 秒实验
- 把本节的 configure 命令存成
build.sh,用bash -x跑一遍看每一步展开成什么。 cl找不到时,打开「x64 Native Tools Command Prompt」再敲一次,看有没有版本号。python -c "import av; print('libx264' in av.codec.codecs_available)"确认本机这版带不带 x264。
常见误区
- 先编 FFmpeg 再补 x264。 configure 的结果写死在 config.h 里,补完只能删掉重编。
- 忘了
--enable-gpl。 开了 libx264 却不开 gpl,configure 直接报错退出。 - 拿 MinGW 的 Qt 去链 MSVC 编的 FFmpeg。 报 LNK2019,这不是「部分能用」,是一个符号都链不上。
自测三问(点开对答案)
1. 为什么必须先编 x264 再编 FFmpeg? —— FFmpeg 不含 H.264 编码器,只负责调用外部库。configure 时要能找到并链上已有的 x264。 2. `--enable-shared --disable-static` 对二次开发意味着什么? —— 只产出动态库:导入库小、链接快、换库不用重编整个工程。静态库会把代码全塞进 exe。 3. 看见 LNK2019 无法解析 `__imp_avcodec_send_packet`,最可能的原因是什么? —— 拿 GNU 格式的 .dll.a 给 MSVC 链了。符号名格式不同,必须换成 .lib。- ☐ (本节完,下一节 1.2.7 使用 MinGW64 工具链来编译 FFmpeg 5.0+Libx264)