3、H265编码基础:H265与H264对比、H265核心技术(CTU、帧内预测、帧间预测、变换量化)、H265码流结构(VPS/SPS/PPS)

好,我们直接进入正题。H265,也叫HEVC,是H264的下一代。做WebRTC的人,迟早要跟它打交道。为什么?因为同样的画质,H265能比H264省一半的带宽。这在实时通信里,太诱人了。

但H265不是简单的升级。它的底层逻辑变了。我刚开始接触时,也以为就是改改参数,结果被CTU和四叉树分区搞得晕头转向。今天我把核心差异和关键技术拆开讲,你跟着走一遍,心里就有底了。

3.1 H265与H264:核心差异对比

先看一张对比表。这是基础,后面所有技术点都围绕这些差异展开。

对比维度 H264 (AVC) H265 (HEVC)
编码单元 宏块 (16x16) CTU (最大64x64,可递归划分)
分区方式 固定网格 四叉树递归分区
帧内预测方向 9种 35种
帧间预测精度 1/4像素 1/4像素 + DCTIF滤波器
变换大小 4x4 / 8x8 4x4 ~ 32x32
码流结构 SPS / PPS VPS / SPS / PPS
压缩率 基准 提升约40%~50%

看到没?H265的编码单元从16x16的宏块,变成了最大64x64的CTU。这意味着什么?对于大块平坦区域,一个CTU就能搞定,码率直接降下来。但对于细节丰富的区域,CTU会递归切到8x8甚至4x4。这种灵活性,是H264做不到的。

我的经验: 在WebRTC里,如果视频源是屏幕共享(比如PPT),H265的优势特别明显。因为PPT里大块纯色区域多,CTU能一次性覆盖,码率能比H264低30%以上。但如果是电影级的高噪点画面,CTU切得很碎,优势就没那么大了。

3.2 H265核心技术拆解

这部分是重点。我按编码流程的顺序讲:CTU分区 → 帧内预测 → 帧间预测 → 变换量化。每一步都有坑,我会把踩过的坑指出来。

3.2.1 CTU与四叉树分区

CTU是H265的基石。它的大小可以是64x64、32x32或16x16。编码器会从最大尺寸开始,判断当前区域是否适合用这个尺寸编码。如果不适合,就递归切成4个子块,每个子块再重复这个过程。

举个例子:一个64x64的CTU,如果左上角是天空(平坦),右下角是树叶(复杂),编码器会这样处理:

  • 先判断整个64x64:不行,右下角细节太多,码率会炸。
  • 切成4个32x32:左上角32x32是天空,直接编码;右下角32x32还是复杂,继续切。
  • 再切成4个16x16:这下每个16x16的纹理相对均匀,可以编码了。

这个递归过程,就是四叉树分区。H265的编码树深度最多4层(64→32→16→8)。

注意: 分区深度不是越深越好。我曾经在项目中为了追求画质,把最小分区设成了4x4。结果码率飙升,画质提升却微乎其微。对于实时通信,建议最小分区控制在8x8,平衡码率和质量。

3.2.2 帧内预测:从9种到35种

帧内预测,说白了就是用周围已经编码的像素,来预测当前块。H264有9种预测方向(8个角度+DC模式)。H265直接增加到35种:33个角度方向 + DC模式 + Planar模式。

为什么增加这么多?因为角度越细,预测越准。比如一个斜45度的纹理,H264只能用相近的26.6度或63.4度去猜,误差大。H265有33个角度,几乎能精确匹配任何纹理方向。

Planar模式是H265新增的亮点。它假设像素值在块内是平滑变化的,适合渐变背景。我做过测试,对于天空、墙壁这类渐变区域,Planar模式比DC模式能省15%的码率。

避坑指南: 帧内预测模式的选择,计算量很大。35种模式全遍历,编码时间会翻倍。我建议在WebRTC场景下,先做粗选:用SATD快速筛选出Top 3候选模式,再在这3个里做精细选择。这样能省70%的计算量,画质损失几乎看不出来。

3.2.3 帧间预测:运动估计的进化

帧间预测,就是找参考帧里的相似块。H265在H264的基础上,做了两个关键改进:

  1. 运动矢量精度: 支持1/4像素精度,但插值算法从双线性升级为DCTIF(离散余弦变换插值滤波器)。DCTIF的插值效果更平滑,运动补偿后的残差更小。
  2. Merge模式增强: H264的Skip模式,在H265里扩展为Merge模式。Merge模式可以从空间相邻块、时间同位块甚至人工构造的候选列表中,直接继承运动矢量。对于静止背景或匀速运动,Merge模式能省掉运动矢量的编码开销。

我记得有一次做监控视频的编码优化。画面里只有一个人走动,背景完全静止。用H265的Merge模式,背景块的运动矢量全部继承,码率直接降了40%。H264的Skip模式做不到这么灵活。

3.2.4 变换与量化:大块变换的威力

变换,就是把像素域的残差,转到频域。H264最大只支持8x8变换。H265支持4x4、8x8、16x16、32x32四种尺寸。

大块变换的好处很明显:对于平坦区域,32x32变换能把能量集中到左上角的低频系数上,高频系数几乎全零。这样量化后,需要编码的系数很少,码率自然低。

但大块变换也有代价。如果残差里有尖锐的边缘,32x32变换会产生很多高频系数,反而比8x8变换更费码率。所以H265的编码器会根据残差的特性,自适应选择变换块大小。

我的建议: 在WebRTC里,如果网络带宽波动大,可以动态调整量化参数(QP)。带宽充足时,QP设小一点(比如22),保留更多细节;带宽紧张时,QP设大一点(比如32),牺牲画质保流畅。H265的32x32变换在QP较大时,对平坦区域的码率节省效果特别明显。

3.3 H265码流结构:VPS/SPS/PPS

H264只有SPS和PPS。H265多了一个VPS(视频参数集)。为什么加这个?因为H265要支持多层编码(比如可伸缩编码SVC),VPS就是描述整个视频序列的全局信息,包括有多少层、层间依赖关系等。

码流结构分三层:

  • VPS(视频参数集): 描述整个视频序列的全局参数,比如层数、档次、级别。解码器必须先解析VPS,才能知道这个码流是单层还是多层。
  • SPS(序列参数集): 描述一个编码序列的参数,比如分辨率、帧率、CTU大小、参考帧数量。每个序列开头都会有一个SPS。
  • PPS(图像参数集): 描述单帧图像的编码参数,比如熵编码模式、初始QP、去块滤波参数。每帧图像可以引用不同的PPS。

在WebRTC里,VPS/SPS/PPS通常作为带外参数发送。也就是说,它们不跟视频帧数据混在一起,而是通过信令通道单独传输。这样接收端可以先解析参数集,再开始解码视频帧。

注意: 如果VPS/SPS/PPS丢失或损坏,解码器无法解码任何帧。我在项目中遇到过一个问题:信令通道偶尔丢包,导致VPS没传过去,接收端一直黑屏。后来我加了重传机制,确保参数集至少传3次,问题才解决。

3.4 H265编码流程全景图

下面这张图,把H265的编码流程串起来了。从原始帧输入,到码流输出,每一步都对应我们刚才讲的技术点。

H265编码流程全景图 H265编码流程全景图 原始帧输入 CTU四叉树分区 帧内/帧间预测 变换 + 量化 熵编码(CABAC) H265码流输出 VPS / SPS / PPS 说明: VPS/SPS/PPS作为带外参数, 通过信令通道单独传输。

流程很清晰:原始帧进来,先做CTU分区,然后对每个分区做帧内或帧间预测,得到残差。残差经过变换和量化,变成频域系数。最后用CABAC熵编码,输出H265码流。同时,VPS/SPS/PPS作为参数集,单独打包发送。

3.5 本章小结

H265的核心,就是CTU分区带来的灵活性,以及帧内预测、帧间预测、变换量化三个环节的全面升级。码流结构多了VPS,是为了支持多层编码。这些技术点,在WebRTC里都有直接的应用场景。