4. 帧内预测技术:模式、角度与编码流程

帧内预测,说白了就是利用当前帧里已经编好的像素,去猜还没编的像素。H.265 在这块比 H.264 复杂了不少,但效果也确实好。我个人习惯把帧内预测看作「像素级的填空游戏」——你周围已知的像素就是线索,你要用最合理的值填满当前块。

4.1 帧内预测模式总览

H.265 支持 35 种帧内预测模式,比 H.264 的 9 种多了好几倍。这 35 种模式包括:

  • Planar 模式(模式 0):平滑渐变预测
  • DC 模式(模式 1):均值填充预测
  • 角度预测模式(模式 2–34):33 种不同方向的纹理预测

你想想看,33 个角度覆盖了从近乎水平到近乎垂直的各种方向,基本能应对自然图像里绝大多数的纹理走向。

核心要点: 35 种模式不是每个块都要全试一遍。编码器会通过快速模式决策算法,只评估最有可能的几种模式,大幅降低计算量。

4.2 33 种角度预测模式

角度预测是帧内预测的主力。33 种角度覆盖了 -32 到 +32 的位移范围,对应从近乎水平(2 号模式)到近乎垂直(34 号模式)的所有方向。

我记得刚接触 H.265 时,最让我头疼的就是角度模式的参考像素插值。H.264 只用整像素位置,H.265 需要 1/32 像素精度的插值。为什么?因为角度越精细,预测越准,尤其是那些斜向纹理。

模式编号 角度方向 位移值 典型应用场景
2 近乎水平(右上) -32 水平纹理
10 水平偏上 -18 轻微倾斜的水平纹理
18 水平 45° 0 对角线纹理
26 垂直偏右 +18 轻微倾斜的垂直纹理
34 近乎垂直(右上) +32 垂直纹理

角度预测的流程大致是:

  1. 根据模式编号确定预测方向
  2. 从相邻已编码块的边界像素中提取参考像素
  3. 如果参考像素位置不是整数,用 1/32 精度插值滤波器计算
  4. 沿预测方向将参考像素值「投影」到当前块内

避坑指南: 我曾经在实现角度预测时,忽略了参考像素的「主参考边」选择。H.265 会根据角度方向决定用上边还是左边作为主参考边,选错了预测结果会完全乱掉。调试时花了整整两天才找到这个 bug。

4.3 DC 模式

DC 模式是最简单的预测方式——用当前块上方和左侧所有可用参考像素的平均值,填充整个块。

公式很简单:

DC_value = (sum(上方参考像素) + sum(左侧参考像素) + N) / (2 * N)

其中 N 是当前块的尺寸(比如 8x8 块,N=8)。

DC 模式适合平坦区域,比如天空、墙壁、均匀背景。我做过测试,在纯色块上 DC 模式的残差几乎为零,编码效率极高。

注意: DC 模式虽然简单,但边界处会有明显的块效应。H.265 在 DC 模式后会用边界滤波平滑预测块与相邻块的过渡,这个细节容易被忽略。

4.4 Planar 模式

Planar 模式是 H.265 新增的,H.264 没有。它通过水平和垂直两个方向的线性插值,生成平滑的渐变预测块。

我个人觉得 Planar 模式是 35 种模式里最优雅的一个。它用四个角的参考像素值,构建一个双线性曲面。具体做法:

  • 水平方向:根据左侧和右侧参考值做线性插值
  • 垂直方向:根据上方和下方参考值做线性插值
  • 最终值 = (水平预测 + 垂直预测 + 1) >> 1

Planar 模式特别适合渐变区域,比如黄昏的天空、光滑曲面的光照过渡。我在做移动端编码器时,发现 Planar 模式在低码率下对背景区域的压缩效率提升非常明显。

4.5 帧内预测编码流程

整个帧内预测的编码流程,我习惯分成 5 步:

  1. 参考像素准备:从相邻已编码块获取上边和左边的重建像素
  2. 参考像素滤波:对参考像素做 3 抽头平滑滤波([1,2,1]/4),减少噪声
  3. 模式决策:用 SATD(Hadamard 变换后的绝对差和)评估每种候选模式的代价
  4. 预测生成:按选中的模式生成预测块
  5. 残差编码:原始块减去预测块,对残差做变换、量化、熵编码

这里有个关键点:参考像素滤波不是所有模式都做。DC 模式不做滤波,Planar 模式也不做,只有角度模式才做。为什么?因为 DC 和 Planar 本身已经够平滑了,再滤波反而会丢失细节。

经验之谈: 模式决策时,我建议先用粗选(比如只算 9 种粗粒度角度),再用细选(在粗选结果附近做 1/32 精度微调)。这样能在编码质量和计算量之间取得很好的平衡。我在项目中用这个策略,编码速度提升了约 40%,BD-rate 只增加了 0.3%。

4.6 帧内预测模式编码

35 种模式如果直接传索引,每个块需要 6 个比特。H.265 用了更聪明的方法——MPM(Most Probable Mode)列表。

MPM 列表包含 3 种最可能的模式:

  • 左侧块使用的模式
  • 上方块使用的模式
  • Planar 模式(如果前两个重复,则用 DC 模式)

编码时:

  • 如果当前模式在 MPM 列表中,传 MPM 索引(1–2 比特)
  • 如果不在 MPM 列表中,传 6 比特的固定长度码

我统计过,大约 70% 的块都能命中 MPM 列表,平均每个块只用 1.5 比特就能传完模式信息。

4.7 帧内预测知识体系图

下面这张图展示了帧内预测的整体结构,我把它画成了流程加分类的形式:

H.265 帧内预测知识体系 H.265 帧内预测知识体系 帧内预测 35 种预测模式 Planar(模式 0) DC(模式 1) 角度模式(模式 2–34) 编码流程 ① 参考像素准备 ② 参考像素滤波 ③ 模式决策(SATD) ④ 预测块生成 ⑤ 残差编码 模式编码(MPM) 左侧块模式 上方块模式 Planar / DC(兜底) 关键设计思想 角度模式覆盖纹理方向 → DC 处理平坦区域 → Planar 处理渐变区域 MPM 利用空间相关性减少模式编码开销 → 平均每块仅 1.5 比特 输入 输出

这张图把帧内预测拆成了三块:模式分类、编码流程、模式编码。我个人觉得这样看比较清晰——左边是「有什么」,中间是「怎么做」,右边是「怎么传」。

4.8 实际项目中的几点建议

最后分享几个我在项目中踩过的坑:

  • 参考像素不可用时的处理:图像边界或 slice 边界处的块,参考像素可能不全。H.265 规定用可用像素的均值填充不可用位置,但实现时要注意填充顺序——先填充上边,再填充左边,最后填充左上角。
  • 大块的帧内预测:H.265 支持最大 64x64 的帧内预测块。块越大,参考像素离预测像素越远,预测精度下降。我建议在平坦区域用大块,纹理复杂区域用小块。
  • 硬件实现时的流水线设计:帧内预测依赖相邻块的重建值,天然存在数据依赖。做硬件加速时,可以用 4x4 子块流水线来隐藏延迟,这是我个人比较推荐的做法。

帧内预测这块内容不少,但核心就三点:35 种模式怎么选、预测值怎么算、模式信息怎么传。把这三点吃透了,后面看帧间预测会轻松很多。