2. 编码框架:混合编码框架详解与H.265编解码器架构
做视频编码这么多年,我经常被问到一个问题:H.265到底牛在哪?
其实答案就藏在它的框架里。H.265沿用了经典的混合编码框架,但每个模块都做了深度优化。说白了,这个框架就是视频压缩的总指挥——它决定了怎么拆、怎么算、怎么省码率。
2.1 混合编码框架的核心思想
混合编码框架,不是H.265独创的。从H.261开始,这个框架就一直在用。为什么?因为它确实好用。
它的核心思路就两条:
- 利用空间冗余——帧内预测,用周围像素猜当前块
- 利用时间冗余——帧间预测,用参考帧找运动
我刚开始做编码器时,总觉得这框架太老了。后来在优化一个低码率场景时才发现,框架的稳定性比花哨的算法更重要。混合框架之所以能活30年,就是因为它把预测、变换、量化、熵编码这些模块拆得清清楚楚,每个模块都能独立演进。
关键认知:混合编码框架 = 预测(消除冗余)+ 变换量化(压缩能量)+ 熵编码(去除统计冗余)。三者缺一不可。
2.2 H.265编码器整体架构
好,我们直接看编码器的结构。我画了一张图,把核心模块和流程都标出来了。
这张图我画得比较细。你从上往下看,流程很清楚:
- 输入帧先被切成CTU(编码树单元),最大64×64
- 每个CTU走两条路:帧内预测或帧间预测
- RDO(率失真优化)决定到底用哪条路
- 选好后算残差,然后做变换、量化、熵编码
- 别忘了重建环路——解码端也需要参考帧,编码器必须模拟一遍
我的经验:很多初学者会忽略重建环路。我曾经在一个项目中,因为重建环路里的滤波参数没对齐,导致编码器输出码流解码出来全是马赛克。排查了两天才找到问题。记住:编码器里的解码环路必须和真实解码器完全一致。
2.3 各模块深度解析
2.3.1 CTU与四叉树划分
H.265最大的变化之一,就是引入了CTU。H.264最大宏块是16×16,H.265直接干到64×64。
为什么要这么大?
你想啊,4K视频里,一片蓝天可能几百个像素都一样。用16×16的块去编码,要编好几百次。用64×64的块,一次就搞定了。码率自然就省下来了。
但大块也有问题——如果画面细节多,大块反而不准。所以H.265用了四叉树递归划分:
- CTU可以分成4个32×32的CU
- 每个CU还能再分成4个16×16的CU
- 一直分到8×8为止
| 划分深度 | CU大小 | 适用场景 |
|---|---|---|
| 0(不划分) | 64×64 | 平坦区域(天空、墙壁) |
| 1 | 32×32 | 中等纹理 |
| 2 | 16×16 | 细节较多 |
| 3 | 8×8 | 复杂纹理、边缘 |
避坑指南:我曾经在优化编码速度时,试图限制最大划分深度到2(即最小16×16)。结果在文字叠加场景下,码率暴涨了30%。因为文字边缘需要8×8的精细划分。所以不要一刀切限制划分深度,要根据场景动态调整。
2.3.2 帧内预测:35种模式
H.264只有9种帧内预测模式。H.265直接增加到35种。
这35种包括:
- 1种DC模式(平均值)
- 1种Planar模式(平滑渐变)
- 33种角度模式(从2°到34°的方向预测)
为什么需要这么多角度?
你想想看,视频里的边缘方向千变万化。33种角度基本覆盖了所有常见方向。我做过测试,在屏幕内容编码场景下,角度模式比DC模式能省15%-20%的码率。
2.3.3 帧间预测:运动估计与MV预测
帧间预测是H.265的重头戏。它通过运动估计找到当前块在参考帧中的最佳匹配位置,然后只编码运动矢量和残差。
H.265在帧间预测上做了几个关键改进:
- 运动矢量精度提高到1/4像素——H.264也是1/4,但H.265的插值滤波器更优
- Merge模式——直接从相邻块继承运动信息,省掉运动矢量编码
- AMVP(高级运动矢量预测)——用相邻块的运动矢量做预测,只编码差值
性能关键:帧间预测的搜索范围直接影响编码速度。我建议在实时编码场景下,搜索范围控制在±64像素以内;离线编码可以放宽到±128甚至±256。
2.3.4 变换与量化
残差数据在空域上还有相关性,需要通过变换把它转到频域。H.265支持:
- DCT(离散余弦变换)——用于大多数块
- DST(离散正弦变换)——用于4×4帧内预测残差
DST是H.265新增的。为什么加它?因为帧内预测的残差在边界处有特殊的分布特性,DST能更好地集中能量。实测下来,4×4帧内块用DST比DCT能多压缩3%-5%。
量化就更直接了——QP值越大,细节丢得越多,码率越低。H.265的QP范围是0到51,每增加6,码率大约减半。
2.3.5 环路滤波
编码后的图像会有块效应——就是块与块之间的边界不连续。H.265用了两种滤波器:
- 去块滤波(DBF)——平滑块边界
- 样点自适应补偿(SAO)——补偿像素值的偏移
SAO是H.265新增的。它把像素分成几类,每类加一个偏移值。这个技术对渐变区域和文字边缘特别有效。我做过对比,SAO开启后主观质量能提升0.5-1个dB。
2.4 解码器整体架构
解码器比编码器简单得多。它不需要做模式决策,也不需要运动估计。说白了,解码器就是编码器的逆过程。
解码器的流程就五步:
- 熵解码——从码流中解析出量化系数、运动矢量、模式信息
- 反量化 + 反变换——把频域数据转回空域残差
- 加预测——根据码流中的模式信息,生成预测块,加上残差
- 环路滤波——DBF去块效应,SAO补偿像素偏移
- 输出重建帧——同时存入参考帧缓存,供后续帧使用
优化建议:解码器的性能瓶颈通常在熵解码和运动补偿。我建议在解码器实现中,对CABAC的上下文模型做查表优化,对运动补偿的插值滤波用SIMD指令加速。这两步优化好了,解码速度能提升2-3倍。
2.5 编码器与解码器的关键差异
| 模块 | 编码器 | 解码器 |
|---|---|---|
| 模式决策 | 需要RDO,计算量大 | 直接解析码流,无计算 |
| 运动估计 | 需要搜索,最耗时 | 只需要运动补偿 |
| 变换 | 正向DCT/DST | 反向IDCT/IDST |
| 量化 | 正向量化 | 反量化 |
| 熵编码 | CABAC编码 | CABAC解码 |
| 参考帧管理 | 需要维护DPB | 同样需要DPB |
看到没?编码器比解码器复杂得多。这也是为什么编码是计算密集型的,解码相对轻量。我做过统计,同样一个1080p视频,编码时间大约是解码时间的10-20倍。
总结一下:混合编码框架的核心就是预测+残差编码。H.265在这个框架下,把每个模块都做到了极致——更大的块、更细的划分、更多的预测模式、更优的变换和滤波。理解了这个框架,你就掌握了H.265的骨架。后面每一章,都是在这个骨架上填肉。