八个库是「一底七柱」:libavutil 打底,其余七个各管一段。 能数出条目的是 codec、format、filter 三个,其余四个靠规则干活。
第一章把库编出来了,从这一章开始认它们各自管什么。 这一篇先给全景,2.2 起一个一个拆。
一、八个库,一句话一个
教材叫「八大金刚」,指的是这八个。 库 一句话 本机版本
libavutil 底座:内存、字典、日志、枚举 60 libavcodec 编解码器,五百多个 62 libavformat 容器读写,四百多个格式 62 libavfilter 滤镜,四百多个 11 libavdevice 摄像头、声卡、屏幕 62 libswscale 缩放与像素格式 9 libswresample 音频重采样 6 libpostproc 画面后处理,本机没有 —
这八行按「离业务远近」排:越往上越是工具,越往下越是具体功能。 你自己写的第一行代码, 多半从中间的 libavformat 开始。
二、谁垫在谁身上
依赖关系是一棵树,根是 libavutil。 库 底下垫着谁
libavutil 没有 libavcodec libavutil libavformat libavutil、libavcodec libavfilter libavutil、libswscale、libswresample libavdevice libavformat、libavcodec libswscale libavutil libswresample libavutil
这张表能回答「为什么链接时要加那么多库」。 用 libavformat 读文件,它自己要 avcodec 解、
avutil 打底,三个库一行都少不了。
链接顺序也有讲究:被依赖的放后面,否则 GNU ld 会报未定义符号。
-lavformat -lavcodec -lavutil 这个顺序不是随便写的。
三、三个能数的,四个数不出的
能数出条目的是 codec、format、filter,它们有「注册表」。 库 数什么 本机数量
libavcodec codecs_available 557 libavformat formats_available 414 libavfilter filters_available 468
这三个数很像,但含义差得远。 557 是「能压/能解的东西」,414 是「能装/能拆的盒子」, 468 是「能对画面做的动作」。 三个数对不上别人的构建,就是装的不是同一版。 这是排「我这儿没有某某功能」时最快的判断方法。
四、一张图看懂数据怎么流
步 谁在干 手里拿的是什么
读 libavformat AVPacket(压缩包) 解 libavcodec AVFrame(原始帧) 改 libavfilter 还是 AVFrame 转 libswscale/swresample 换格式的帧 编 libavcodec 新 AVPacket 写 libavformat 进容器
这条流水线是全课的主干,后面每一章都在放大其中一段。 转封装只走「读 → 写」两步,转码才把中间四步全走一遍。 记住这张表,就看懂了「为什么转封装快、转码慢」。
五、动手 Demo:八个库的账本——每个库能数出多少条目
这一段把能数的三个数出来,再摆一遍依赖关系。 数不出来的一律标「—」,不编数字。
import av, av.filter
print(len(av.codec.codecs_available))
print(len(av.formats_available))
print(len(av.filter.filters_available))
print(len(av.video.format.names))
实跑输出:
--------------------------------------------------------------------
八个库的账本——每个库能数出多少条目
--------------------------------------------------------------------
**① 有的库能数,有的库数不出来**
库 能数出的东西 数量
---------------------------------------------------
libavcodec codecs_available 557
libavformat formats_available 414
libavfilter filters_available 468
libswscale 像素格式名 267
libavutil 工具函数,数不出 —
libavdevice 设备,靠格式名间接看 —
libswresample 采样格式,数不出 —
libpostproc 本机没编进来 0
**这四个数不是同一层的东西。** 前三个是「条目表」,
第四个是「枚举量」——像素格式在 libavutil 里定义,只是由 libswscale 负责转换。
**② 一层压一层,谁离不开谁**
库 底下垫着谁
----------------------------------------------------------
libavutil 没有,它是最底
libavcodec libavutil
libavformat libavutil、libavcodec
libavfilter libavutil、libswscale、libswresample
libavdevice libavformat、libavcodec
libswscale libavutil
libswresample libavutil
libpostproc libavutil
**这张表解释了一个常见困惑:只读一个文件,链接时要加三四个库。**
libavformat 自己要 avcodec 帮忙,avcodec 又要 avutil 打底。少加一个,链接器就报一堆未定义符号。
**③ 三个数的量级记住了有用**
编解码器 **557** 个、格式 **414** 个、滤镜 **468** 个。
看见某个格式报「不认识」,先数一遍这三个数——数出来跟别人的不一样,就是两人装的不是同一版构建,
不是代码写错了。
三个条目数加一个枚举量:557、414、468、267。 前三个是注册表,最后一个是枚举,量级不同但都能当「构建指纹」用。
30 秒实验
python -c "import av; print(len(av.codec.codecs_available))",跟本节表格对一下数。- 找一个网上的 FFmpeg 版本对照表,看 557 对应哪个大版本。
- 把八个库名按依赖顺序排一行,再从右往左删,看删到哪个链接会报错。
常见误区
- 以为八个库是八个独立的东西。 它们是一棵树,libavutil 必须在。
- 链接时不按依赖顺序写 -l。 GNU ld 从右往左解析,顺序错就报未定义符号。
- 拿三个条目的数量当版本号。 它们是构建指纹,不同构建可能同数量。
自测三问(点开对答案)
1. 八个库里哪一个不能省? —— libavutil。其余七个都直接或间接依赖它,没有它什么都链接不上。 2. 557、414、468 分别是什么? —— 编解码器、格式、滤镜的条目数。一个是压解能力,一个是容器,一个是对画面的动作。 3. 为什么转封装比转码快? —— 转封装只走「读包 → 写包」,不经过解码与编码;转码要把中间四步全走一遍。- ☐ (本节完,下一节 2.2 libavutil 库简介)