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/32 精度插值滤波器计算
- 沿预测方向将参考像素值「投影」到当前块内
避坑指南: 我曾经在实现角度预测时,忽略了参考像素的「主参考边」选择。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 步:
- 参考像素准备:从相邻已编码块获取上边和左边的重建像素
- 参考像素滤波:对参考像素做 3 抽头平滑滤波([1,2,1]/4),减少噪声
- 模式决策:用 SATD(Hadamard 变换后的绝对差和)评估每种候选模式的代价
- 预测生成:按选中的模式生成预测块
- 残差编码:原始块减去预测块,对残差做变换、量化、熵编码
这里有个关键点:参考像素滤波不是所有模式都做。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 帧内预测知识体系图
下面这张图展示了帧内预测的整体结构,我把它画成了流程加分类的形式:
这张图把帧内预测拆成了三块:模式分类、编码流程、模式编码。我个人觉得这样看比较清晰——左边是「有什么」,中间是「怎么做」,右边是「怎么传」。
4.8 实际项目中的几点建议
最后分享几个我在项目中踩过的坑:
- 参考像素不可用时的处理:图像边界或 slice 边界处的块,参考像素可能不全。H.265 规定用可用像素的均值填充不可用位置,但实现时要注意填充顺序——先填充上边,再填充左边,最后填充左上角。
- 大块的帧内预测:H.265 支持最大 64x64 的帧内预测块。块越大,参考像素离预测像素越远,预测精度下降。我建议在平坦区域用大块,纹理复杂区域用小块。
- 硬件实现时的流水线设计:帧内预测依赖相邻块的重建值,天然存在数据依赖。做硬件加速时,可以用 4x4 子块流水线来隐藏延迟,这是我个人比较推荐的做法。
帧内预测这块内容不少,但核心就三点:35 种模式怎么选、预测值怎么算、模式信息怎么传。把这三点吃透了,后面看帧间预测会轻松很多。