H265编码核心原理:从框架到比特流

各位好,我是老张。今天咱们聊聊H265编码的核心原理。说实话,H265刚出来那会儿,我还在做H264的项目,总觉得这玩意儿就是H264的升级版,没什么大不了的。直到有一次在4K直播项目里,H264死活压不到目标码率,我才真正开始啃H265的细节。

嗯,这一章内容比较多,但都是硬核干货。我会从编码框架讲起,然后深入到帧类型、块划分、预测、变换量化、熵编码。你想想看,搞懂了这些,你就能理解为什么H265能在同样画质下比H264省一半码率。

核心观点:H265的编码效率提升,本质上是通过更灵活的块划分、更精准的预测、更高效的变换和熵编码实现的。它不是H264的简单升级,而是一次架构级的重构。

2.1 H265编码框架:混合编码的进化

H265沿用了混合编码框架,但每个模块都做了深度优化。我习惯把编码器比作一个「压缩工厂」——原始视频进来,经过预测、变换、量化、熵编码这几道工序,最后输出压缩后的比特流。

这个框架的核心流程是这样的:

  1. 分块:把一帧图像切成CTU(编码树单元)
  2. 预测:用帧内或帧间方式,预测当前块的内容
  3. 残差计算:原始块减去预测块,得到残差
  4. 变换量化:对残差做DCT变换,再量化
  5. 熵编码:把量化后的系数压缩成二进制码流

我在做第一个H265编码器移植时,踩过一个坑——没注意参考帧管理。H265的参考帧列表比H264复杂得多,DPB(解码图像缓冲区)的管理逻辑也变了。后来我养成了一个习惯:先画框架图,再写代码。

下面这张图,是我自己总结的H265编码框架:

H265编码框架流程图 H265 混合编码框架 原始视频输入 CTU 分块 帧内/帧间预测 帧内:35种模式 | 帧间:MV + 参考帧 残差计算 DCT变换 + 量化 变换核:4x4 ~ 32x32 | QP:0~51 CABAC 熵编码 H265 比特流 关键特点 • 灵活的CTU/CU/PU/TU划分 • 35种帧内预测模式 • 大尺寸变换核(最大32x32) • 基于上下文的CABAC

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/CU/PU/TU四层划分关系 H265 四层块划分体系 CTU(编码树单元) 大小:64x64(默认) | 可递归划分为更小的CU CU(编码单元) 大小:8x8 ~ 64x64 | 决定采用帧内还是帧间预测 PU(预测单元) 帧内:2Nx2N / NxN | 帧间:对称/非对称划分 TU(变换单元) 大小:4x4 ~ 32x32 | 残差数据的变换和量化

这四层的关系,我打个比方:

  • 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在这方面做了几个重要改进:

  1. 更灵活的PU划分:支持对称(2Nx2N、2NxN、Nx2N、NxN)和非对称(2NxnU、2NxnD、nLx2N、nRx2N)划分
  2. 1/4像素精度运动矢量:通过插值滤波器实现亚像素精度
  3. Merge模式:复用相邻块的运动信息,减少码率开销
  4. 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的核心流程:

  1. 二值化:把语法元素转换成二进制串
  2. 上下文建模:根据已编码的语法元素,更新概率模型
  3. 算术编码:根据概率模型,对二进制串进行算术编码

我刚开始接触CABAC时,觉得这东西太复杂了。后来写了一个简化版的CABAC实现,才真正理解它的工作原理。说白了,CABAC就是根据上下文动态调整概率,然后用算术编码把数据压缩到接近熵极限。

在WebRTC场景中,CABAC的计算开销是个需要权衡的点。我一般建议:

  • 如果CPU资源充足(如PC端),使用完整的CABAC
  • 如果CPU资源受限(如移动端),可以考虑限制CABAC的上下文数量,或者使用低复杂度模式

2.8 本章小结

好了,这一章的内容就这些。H265的核心原理,说白了就是「更灵活的划分 + 更精准的预测 + 更高效的变换和熵编码」。搞懂了这些,你就能理解为什么H265能在同样画质下比H264省一半码率。