3、帧内预测模式优化:35种帧内预测模式详解、模式决策快速算法、RMD与MPM技术

帧内预测,说白了就是利用当前帧里已经编好的像素,去猜还没编的块长什么样。HEVC 把这事做得特别细——它一口气定义了 35 种预测模式。你想想看,一个 4×4 的块就要从 35 个方向里挑一个最好的,这计算量可不是闹着玩的。

我早年刚接触 HEVC 时,觉得这 35 种模式不就是 H.264 那 9 种的简单扩展吗?后来踩了坑才发现,事情远没那么简单。模式多了,决策路径就复杂了,稍不注意编码器就跑不动。今天咱们就把这 35 种模式、快速决策算法、RMD 和 MPM 技术彻底捋清楚。

核心要点:帧内预测优化的本质,是在 35 种候选模式中快速找到率失真代价最小的那个。直接遍历 35 种模式做 RDO 是不现实的,必须用 RMD 粗筛 + MPM 补充 + 细选三步走策略。

3.1 35种帧内预测模式详解

HEVC 的帧内预测分为两大类:角度模式(33 种)和非角度模式(2 种)。非角度模式就是 Planar(模式 0)和 DC(模式 1),剩下的 2~34 全是角度模式。

我个人习惯把角度模式想象成一个圆盘上的刻度。模式 2 对应右下方向,模式 18 是正水平,模式 34 是右上方向。每两个相邻模式之间只差约 5.6 度,精度比 H.264 高了一倍不止。

模式编号 类型 方向描述 适用场景
0 Planar 双线性插值,平滑渐变 平坦区域、渐变纹理
1 DC 参考像素均值填充 大面积均匀区域
2~17 角度(水平偏斜) 从右下到水平偏上 水平纹理、斜向边缘
18~34 角度(垂直偏斜) 从水平到右上偏下 垂直纹理、斜向边缘

这里有个细节容易忽略:角度模式的参考像素不是直接复制,而是通过 1/32 像素精度的插值滤波器生成的。我在项目中遇到过一个问题——同样的纹理,用模式 18 和模式 19 预测出来的残差差别很大,就是因为插值精度导致的细微偏移。

实战技巧:对于 32×32 以上的大块,Planar 模式往往比任何角度模式都稳定。我一般在大块上优先测 Planar 和 DC,如果残差已经很小了,就直接跳过角度模式的遍历。

3.2 模式决策快速算法

直接对 35 种模式做全 RDO 计算,复杂度高得吓人。实际工程中,我们用的是三步走策略:

  1. 粗选阶段(RMD):用 Hadamard 变换快速估算 SATD 代价,从 35 种模式中挑出 N 个候选。
  2. 补充阶段(MPM):把相邻块的预测模式加进来,防止 RMD 漏掉最优解。
  3. 细选阶段(RDO):对候选列表里的模式做完整的率失真优化,选出最终模式。

你可能会问:为什么 RMD 选出来的还不够,还要加 MPM?

嗯,这里有个坑。RMD 用的是 SATD,它只衡量残差的变换域能量,不考虑码率。有时候 SATD 很小的模式,编码比特数却很大。而 MPM 来自相邻块的真实决策,往往能补上 RMD 漏掉的好模式。

避坑指南:我曾经在优化一个低码率场景时,发现 RMD 选出的前 3 个模式全是角度模式,但实际最优解是 Planar。后来查代码才发现,RMD 的 SATD 阈值设得太低了,导致 Planar 被过早淘汰。解决方案是:在 RMD 阶段强制保留 Planar 和 DC,不管它们的 SATD 排名如何。

3.3 RMD技术详解

RMD(Rough Mode Decision)的核心思想很简单:用轻量级的 SATD 代替完整的 RDO 计算。具体流程如下:

// RMD 伪代码示例
for (mode = 0; mode < 35; mode++) {
    // 1. 生成预测块
    pred = intraPredict(pu, mode);
    
    // 2. 计算残差
    residual = original - pred;
    
    // 3. 对残差做 Hadamard 变换
    hadamard = hadamardTransform(residual);
    
    // 4. 计算 SATD 代价
    satdCost = sum(abs(hadamard));
    
    // 5. 加上模式比特数估计
    cost[mode] = satdCost + lambda * bits[mode];
}

// 选出代价最小的 N 个模式
candidateList = selectTopN(cost, N);

这里的 N 取值很关键。我一般这样设:

  • 4×4 块:N = 8(纹理复杂,多留几个候选)
  • 8×8 块:N = 5
  • 16×16 块:N = 3
  • 32×32 块:N = 3

为什么大块反而候选少?因为大块纹理通常更平滑,最优模式往往集中在 Planar、DC 和少数几个角度模式上。

3.4 MPM技术详解

MPM(Most Probable Mode)是利用空间相关性来补充候选模式。HEVC 标准规定最多可以有 3 个 MPM,它们来自:

  • 左侧块(Left PU)的帧内模式
  • 上方块(Above PU)的帧内模式
  • 如果前两个相同,则补充 Planar 或 DC

我见过不少实现直接把 MPM 加到 RMD 候选列表后面,然后去重。但这样做有个问题:如果 MPM 和 RMD 候选完全重合,那 MPM 就没起到补充作用。

我的改进方案:在构建候选列表时,先放 RMD 选出的前 N 个模式,再放 MPM。如果 MPM 已经在列表里了,就把它提到前面,而不是简单去重。这样在后续 RDO 阶段,MPM 会优先被评估,节省了不必要的计算。

3.5 整体决策流程

把上面这些串起来,就是完整的帧内模式决策流程。我画了一张图,方便你理解:

帧内模式决策快速算法流程图 开始:当前 PU 步骤1:RMD粗选 对35种模式计算SATD代价,选Top-N 步骤2:MPM补充 加入左侧/上方块的预测模式 步骤3:去重与排序 合并列表,MPM优先排序 步骤4:RDO细选 对候选列表做完整率失真优化 输出最优模式 关键:RMD保证速度,MPM保证精度,两者缺一不可

3.6 工程优化经验

在实际编码器里,帧内模式决策的优化空间很大。我分享几个实战中验证过的技巧:

  • 提前终止:如果 RMD 阶段 SATD 最小的模式代价已经低于某个阈值,直接用它,跳过 RDO。这个阈值我一般设为 lambda * 256。
  • 模式分组:把 33 个角度模式按方向分成 6 组,先测每组中心模式,再根据结果决定是否测组内其他模式。这招在 64×64 块上能省 40% 的计算量。
  • 参考像素缓存:帧内预测需要频繁读取参考像素,我习惯把当前 CTU 的参考像素全部预取到 L1 cache 里,避免反复访存。

注意:不要为了追求速度而过度简化 RMD。我见过有人把 RMD 的候选数从 8 减到 3,结果 BD-Rate 涨了 2.3%。速度是快了,但压缩效率掉得太多,得不偿失。

好了,帧内预测模式优化这块就聊到这儿。35 种模式、RMD 粗筛、MPM 补充、RDO 细选,这套流程你吃透了,HEVC 帧内编码的核心就算拿下了。实际调优时,记得根据你的应用场景(实时通信、离线编码、硬件实现)来调整候选数量和提前终止阈值——没有银弹,只有不断试出来的最佳实践。