🎬 第九章 H.264编解码基础
📄 一句话概括

H.264 的帧间预测多出三个自由度:七种分块、1/4 像素精度、最多 16 帧参考——让编码器多几个选择,残差就小一截,代价是搜索量暴涨。

📝 本节和前面几节的关系

9.2.3 讲了帧内那一半,这一节讲把压缩比拉上去的那一半。

一、第一个维度:分块方式

真实运动不是均匀的,所以 H.264 允许逐块选择分块大小: 16×16、16×8、8×16、8×8 —— 第一层四种; 8×8 还能再细分为 8×4、4×8、4×4 —— 合计 七种分块; 分块的道理很直观:物体整体平移就用大块,运动边界处切成小块,避免一个块里混进两种运动; 代价是每个分块都要写一个运动矢量——分得越碎,矢量越多,开销越大。 所以编码器是用率失真代价在【残差】与【矢量开销】之间找平衡。

二、第二个维度:1/4 像素精度

运动很少恰好落在整数像素上,这一条带来的收益常被低估: 实际运动是连续的,而像素是离散的格子; 差半个像素,残差就能明显变大——尤其是细节丰富或缓慢平移的画面; 所以 H.264 把亮度精确到 1/4 像素、色度到 1/8 像素; 但像素位置并不存在这些点,必须先插值造出来:亮度用 6 抽头滤波做半像素,再线性插值出 1/4 像素。 精度提升靠计算量换来——每个候选点都多了一次插值。

三、第三个维度:多参考帧

前面两个维度都在【同一帧里找】,第三个维度是扩大搜索的帧范围: 参考帧列表最多可放 16 帧,编码器可以从中挑最像的那一帧; 什么时候有用?周期性运动——比如车轮转动、扇叶旋转,隔几帧的画面反而更接近; 遮挡反复出现时也有用——被挡住又露出来的区域,可以从更早的帧里找到完整的参考; 代价是参考帧缓冲变大、搜索量成倍增加,所以实践中常见的是 1~4 帧,而不是顶格 16 帧。

四、三个维度为什么能叠加出【砍半】

单看每一个维度,收益都不算惊人,但它们作用在同一个环节上、可以叠加: 分块让残差贴合运动边界; 亚像素让残差贴合真实位移; 多参考让残差找到更远的相似画面; 三者都直接减小要编码的残差量,而残差正是后面所有步骤的输入; 残差小了,变换后的非零系数少、熵编码的符号也少——收益一路传下去。 这就是【预测是压缩比主战场】最具体的证据。

五、和运动估计的账

把这一节和第 8.4 节接起来,就能理解编码器的负担有多重: 三个维度各自成倍放大搜索空间——分块 7 种 × 亚像素精度 × 参考帧数; 第 8.4 节算过,单帧全搜索就是几十亿次运算; 所以 H.264 实现的核心竞争力,就在【怎么在这么多候选里快速找到够好的那个】; 这正是 x264 相对 JM 快出几个数量级的原因(第 9.1.5 节)。 标准的自由度,最终都变成了实现的算法竞赛。

六、动手 Demo:帧间预测的三个可调维度

H.264 的帧间预测比前代多出了三个自由度。

parts = ["16×16", "16×8", "8×16", "8×8", "8×4", "4×8", "4×4"]
print("亮度分块共 %d 种:%s" % (len(parts), "、".join(parts)))
print("运动矢量精度:亮度 1/4 像素,色度 1/8 像素")
print("多参考帧:最多 16 帧")

实跑输出:

--------------------------------------------------------------------
帧间预测的三个可调维度
--------------------------------------------------------------------

H.264 的帧间预测比前代多出了三个自由度。

  一是 **分块方式**:亮度共有 **7 种**——
    16×16、16×8、8×16、8×8、8×4、4×8、4×4
    (其中 8×8 还能再细分,**越碎的块越贴合运动边界**)

  二是 **运动矢量精度**:
    亮度精确到 **1/4 像素**、色度精确到 **1/8 像素**;
    实际不是整数点,所以要用**插值**造出这些亚像素位置再匹配。

  三是 **参考帧数量**:
    参考帧列表最多可放 **16 帧**,编码器可以从中挑最像的那一帧。
    多参考在**周期性运动、遮挡反复出现**时特别有效。

  **三个维度都是【让编码器多几个选择】——代价自然也是搜索量暴涨。**

三个维度都是【让编码器多几个选择】——代价自然也是搜索量暴涨。 这与第 8.4 节的账对得上:单帧全搜索就是几十亿次运算。

30 秒实验

  1. 用 FFmpeg 的 -refs 参数把参考帧数从 1 调到 4,对比文件大小与耗时。
  2. 再试试 -me_method 换成更细的搜索,感受【更准的匹配】值多少码率。

常见误区

  1. 以为分块越细越好。每个分块都要写运动矢量,开销会吃光收益。
  2. 以为亚像素是【画面里真有那些点】。它们全是插值出来的虚拟位置。
  3. 以为参考帧越多越好。缓冲与搜索量成倍增长,实践中常用 1~4 帧。
自测三问(点开对答案) 1. H.264 亮度共几种分块方式? —— 七种:16×16、16×8、8×16、8×8、8×4、4×8、4×4。 2. 亚像素位置是怎么得到的? —— 用周围整数像素插值得到,亮度半像素用 6 抽头滤波。 3. 多参考帧在什么内容上最有效? —— 周期性运动(车轮、扇叶)与遮挡反复出现的画面。

相关笔记