H265编码核心原理:从框架到比特流
各位好,我是老张。今天咱们聊聊H265编码的核心原理。说实话,H265刚出来那会儿,我还在做H264的项目,总觉得这玩意儿就是H264的升级版,没什么大不了的。直到有一次在4K直播项目里,H264死活压不到目标码率,我才真正开始啃H265的细节。
嗯,这一章内容比较多,但都是硬核干货。我会从编码框架讲起,然后深入到帧类型、块划分、预测、变换量化、熵编码。你想想看,搞懂了这些,你就能理解为什么H265能在同样画质下比H264省一半码率。
核心观点:H265的编码效率提升,本质上是通过更灵活的块划分、更精准的预测、更高效的变换和熵编码实现的。它不是H264的简单升级,而是一次架构级的重构。
2.1 H265编码框架:混合编码的进化
H265沿用了混合编码框架,但每个模块都做了深度优化。我习惯把编码器比作一个「压缩工厂」——原始视频进来,经过预测、变换、量化、熵编码这几道工序,最后输出压缩后的比特流。
这个框架的核心流程是这样的:
- 分块:把一帧图像切成CTU(编码树单元)
- 预测:用帧内或帧间方式,预测当前块的内容
- 残差计算:原始块减去预测块,得到残差
- 变换量化:对残差做DCT变换,再量化
- 熵编码:把量化后的系数压缩成二进制码流
我在做第一个H265编码器移植时,踩过一个坑——没注意参考帧管理。H265的参考帧列表比H264复杂得多,DPB(解码图像缓冲区)的管理逻辑也变了。后来我养成了一个习惯:先画框架图,再写代码。
下面这张图,是我自己总结的H265编码框架:
2.2 帧类型:I/P/B帧的职责分工
H265的帧类型和H264基本一致,但细节上有差异。我简单说说:
| 帧类型 | 预测方式 | 压缩比 | 典型场景 |
|---|---|---|---|
| I帧 | 仅帧内预测 | 最低 | 随机访问点、场景切换 |
| P帧 | 前向帧间预测 | 中等 | 一般运动场景 |
| B帧 | 双向帧间预测 | 最高 | 低运动、高压缩需求 |
这里有个坑,我当年在WebRTC项目里踩过——B帧在实时通信中要慎用。为什么?因为B帧需要参考未来的帧,会引入额外的编码延迟。WebRTC对延迟极其敏感,一般只开P帧,或者用层次化P帧结构。
注意:在WebRTC场景中,B帧的引入可能导致编码延迟增加1~2帧。对于30fps的视频,这就是33~66ms的额外延迟。在实时通话中,这个延迟可能让用户体验明显下降。
我个人的建议是:如果是点播或直播,放心用B帧;如果是实时通信,优先考虑P帧+层次化编码。
2.3 CTU/CU/PU/TU:四层块划分体系
这是H265最核心的改进之一。H264用的是16x16的宏块,而H265引入了更灵活的块划分体系。说白了,就是让编码器能根据图像内容,自适应地选择块大小。
我画了个图,帮你理解这四层的关系:
这四层的关系,我打个比方:
- CTU 就像一块地皮(64x64)
- CU 是地皮上的建筑地块,可以大也可以小
- PU 是每个地块上的预测方案(怎么盖)
- TU 是每个地块上的装修方案(怎么处理细节)
我在做移动端编码器优化时,发现一个规律:对于1080p以上的视频,CTU用64x64能显著提升编码效率;但对于720p以下的视频,32x32的CTU反而更优。原因很简单——分辨率越低,图像细节越集中,太大的块反而浪费。
2.4 帧内预测:35种模式的精细选择
H265的帧内预测从H264的9种扩展到了35种。这35种包括:
- Planar模式(模式0):平滑渐变,适合平坦区域
- DC模式(模式1):平均值填充,适合大面积均匀区域
- 33种角度模式(模式2~34):覆盖从近水平到近垂直的各种方向
你想想看,为什么需要这么多模式?因为自然图像中的纹理方向千变万化。H265通过增加角度模式的密度,能更精准地匹配纹理方向,从而减少残差。
经验之谈:在实际编码中,Planar和DC模式的使用频率最高,大约占帧内模式的60%~70%。但真正提升画质的是那些角度模式——它们对边缘和纹理的预测效果远好于Planar和DC。
2.5 帧间预测:运动估计与补偿
帧间预测的核心是运动估计(ME)和运动补偿(MC)。H265在这方面做了几个重要改进:
- 更灵活的PU划分:支持对称(2Nx2N、2NxN、Nx2N、NxN)和非对称(2NxnU、2NxnD、nLx2N、nRx2N)划分
- 1/4像素精度运动矢量:通过插值滤波器实现亚像素精度
- Merge模式:复用相邻块的运动信息,减少码率开销
- AMVP(高级运动矢量预测):从候选列表中选取最优运动矢量预测值
我记得有一次做视频会议优化,发现运动剧烈的场景下,非对称PU划分能节省约15%的码率。但代价是编码时间增加了30%。所以,在实时场景中,我一般会限制PU的划分深度,避免过度搜索。
2.6 变换量化:从残差到频域系数
H265的变换模块支持4x4、8x8、16x16、32x32四种大小的DCT变换。相比H264的最大8x8,H265的大尺寸变换能更好地利用图像的空间相关性。
量化部分,H265使用标量量化,量化参数QP的范围是0~51。QP每增加6,量化步长翻倍,码率大约减半。
| QP值 | 量化步长 | 典型码率(1080p 30fps) | 画质 |
|---|---|---|---|
| 0 | 最小 | ~50 Mbps | 无损/近无损 |
| 22 | 中等 | ~8 Mbps | 高画质 |
| 32 | 较大 | ~2 Mbps | 中等画质 |
| 42 | 很大 | ~500 Kbps | 低画质(有可见块效应) |
这里有个细节要注意:H265的量化矩阵(Scaling List)是可选的。默认情况下,编码器使用平坦量化矩阵,即所有频率分量使用相同的量化步长。但如果你对画质有更高要求,可以开启自定义量化矩阵,对高频分量做更精细的量化。
避坑指南:我曾经在移动端测试时,发现开启自定义量化矩阵后,解码器的计算负载增加了约20%。对于低端设备,这可能导致解码卡顿。所以,在WebRTC场景中,我建议关闭自定义量化矩阵,使用默认的平坦量化。
2.7 熵编码:CABAC的全面应用
H265的熵编码只支持CABAC(上下文自适应二进制算术编码),不再支持CAVLC。CABAC的压缩效率比CAVLC高10%~15%,但计算复杂度也更高。
CABAC的核心流程:
- 二值化:把语法元素转换成二进制串
- 上下文建模:根据已编码的语法元素,更新概率模型
- 算术编码:根据概率模型,对二进制串进行算术编码
我刚开始接触CABAC时,觉得这东西太复杂了。后来写了一个简化版的CABAC实现,才真正理解它的工作原理。说白了,CABAC就是根据上下文动态调整概率,然后用算术编码把数据压缩到接近熵极限。
在WebRTC场景中,CABAC的计算开销是个需要权衡的点。我一般建议:
- 如果CPU资源充足(如PC端),使用完整的CABAC
- 如果CPU资源受限(如移动端),可以考虑限制CABAC的上下文数量,或者使用低复杂度模式
2.8 本章小结
好了,这一章的内容就这些。H265的核心原理,说白了就是「更灵活的划分 + 更精准的预测 + 更高效的变换和熵编码」。搞懂了这些,你就能理解为什么H265能在同样画质下比H264省一半码率。