块是编码的最小处理单位,16×16 是经典宏块;块越小越贴合细节、但描述开销越大,所以现代标准把块大小做成可变的。
8.3.5 讲了帧内编码的流程,这一节把流程里的处理单位——块与宏块——单独说清楚。
一、为什么必须切块
编码器不逐像素处理,而是成块处理,原因有三个: 预测需要邻域——一块的邻居比一个像素的邻居更稳定,预测更准; 变换需要矩阵——DCT 本身就是二维块变换,块是它的天然输入; 并行与硬件——规则的小块便于流水线与 SIMD 加速。 所以【块】不是一个约定,而是由变换与预测的数学性质决定的。
二、16×16 这个经典尺寸
宏块(Macroblock)是 H.261 到 H.264 一路沿用下来的基本单位: 尺寸 16×16,一帧按行列整齐排布; 1080p 按 1920×1088 算,一帧 120×68 = 8160 个宏块; 宏块内部还可以再切:16×16、16×8、8×16、8×8,8×8 还能再分成 8×4、4×8、4×4。 宏块是【地址单位】,块是【处理单位】——两者不是一回事。
三、块越小的两面
块大小的取舍是一道很直白的题: 块越小——越能贴合细节与边缘,残差更小、压得更准; 但块数成倍增长,每块都要写模式、矢量、系数,描述开销也跟着涨; 数字很直观:同样的画面,4×4 的块数是 16×16 的 16 倍。 所以最优解不是【越细越好】,而是逐块试出最合适的尺寸。
四、可变块大小:现代标准的做法
既然一刀切都不对,现代标准就把它做成可选的: 平坦区域用大块——天空、墙面、失焦背景,大块最省; 纹理与边缘处用小块——细节多,小块才贴得住; 编码器逐块比较代价,选总代价最小的那种切法; H.265 更进一步,把固定 16×16 换成最大 64×64 的编码树单元(CTU)(第 7.4.3 节)。 代价也很直接:候选切法一多,搜索空间爆炸,编码就慢下来了。
五、块与它的邻居
最后记住一条和流程相关的要点——块的预测依赖邻居: 帧内预测要用左边和上边已经重建的像素; 所以块的处理顺序必须是从左到右、从上到下,不能打乱,否则邻居还没重建出来; 这一点决定了编码器内部的串行依赖,也是并行化的难点之一。 块不只是数据划分,还是一张有向的依赖图。
六、动手 Demo:块越小,数量越多
同一个画面,换一种块大小,处理单位的数量立刻变几倍。
total = 1920 * 1088
for size, px in ((16, 256), (8, 64), (4, 16)):
print("%d×%d 一帧 %6d 个块,是 16×16 的 %2d 倍"
% (size, size, total // px, 256 // px))
实跑输出:
--------------------------------------------------------------------
块越小,数量越多
--------------------------------------------------------------------
同一个画面,换一种块大小,处理单位的数量立刻变几倍。
块大小 一帧块数 相对 16×16 适合
--------------------------------------------------------
16×16 8160 1 倍 细节少、平坦区域
8×8 32640 4 倍 过渡区域
4×4 130560 16 倍 纹理复杂、边缘多
**块越小、数量越多、能贴合细节,但描述每个块的开销(模式、矢量)也越多。**
所以现代标准把它做成**可变块大小**:平坦处用大块、复杂处用小块,
由编码器逐块试出来最优组合——**这也是编码变慢的主要原因之一**。
块越小、数量越多、能贴合细节,但描述每个块的开销也越多。 所以现代标准把它做成可变块大小:平坦处用大块、复杂处用小块。
30 秒实验
- 算一下 720p(1280×720)的宏块总数,和 1080p 的 8160 比一比。
- 注意 720 ÷ 16 = 45 是整数——720p 恰好不需要补边。
常见误区
- 把【宏块】与【块】当成同义词。宏块是 16×16 的地址单位,块是可变的处理单位。
- 以为块越小越好。描述开销会跟着涨,平坦区域用小块是浪费。
- 以为块可以随便并行处理。帧内预测依赖左邻与上邻,顺序不能乱。
自测三问(点开对答案)
1. 经典宏块的尺寸是多少? —— 16×16,H.261 到 H.264 一路沿用。 2. 为什么现代标准要用可变块大小? —— 平坦区域用大块省开销,复杂区域用小块贴细节。 3. 块的处理顺序为什么必须是逐行逐列? —— 帧内预测要用左边和上边已重建的像素,顺序打乱就没有参考。- ☐ 下一节(8.4 运动估计和运动补偿)
相关笔记
- 帧内编码流程 — 块在流程里的位置
- 运动估计和运动补偿 — 帧间也要按块搜索
- 变换 — 为什么变换天然需要块
- 帧内编码 — 预测方向与块的关系
- 🎬 FFmpeg入门详解 · 索引