2、编码基础理论:视频编码基本原理、预测编码、变换编码、量化、熵编码、率失真优化
视频编码这事儿,说白了就是在「画质」和「码率」之间找平衡。你想想看,一段 1080p 的原始视频,一秒钟的数据量能到 1.5 Gbps 左右,不压缩根本没法存、没法传。H.265 能把这个数字压到 10 Mbps 以下,靠的就是下面这套组合拳。
我个人习惯把编码器比作一个「有损压缩工厂」。原料是原始帧,经过预测、变换、量化、熵编码这几道工序,最后输出一个紧凑的码流。每一道工序都有它的使命,也有它的坑。咱们一个一个来看。
2.1 视频编码基本原理
视频之所以能压缩,核心在于三个冗余:
- 空间冗余:同一帧里,相邻像素通常很相似。比如蓝天背景,一大片都是蓝色。
- 时间冗余:相邻帧之间,内容变化很小。比如静止的摄像头,连续几帧几乎一样。
- 视觉冗余:人眼对某些细节不敏感。比如高频纹理、颜色差异,去掉一点看不出来。
编码器的工作,就是把这些冗余尽可能地去掉。去掉空间冗余靠帧内预测,去掉时间冗余靠帧间预测,去掉视觉冗余靠量化和变换。嗯,这里要注意,去掉冗余不等于随便丢数据,得讲究方法。
核心思想:编码不是「记录画面」,而是「记录画面之间的差异」和「如何从差异重建画面」。
2.2 预测编码
预测编码是视频编码的基石。它的思路很简单:用已经编解码过的像素,去预测当前要编的像素。然后只编码「预测值和真实值之间的差值」,也就是残差。
残差的数据量通常远小于原始数据。为什么呢?因为预测做得准,残差就小,甚至接近零。我在项目中遇到过一种情况:监控场景下,摄像头固定不动,背景几乎不变。这时候帧间预测的残差几乎全是零,编码效率极高。
2.2.1 帧内预测
帧内预测利用的是空间冗余。H.265 支持 35 种帧内预测模式,包括 33 种角度模式、DC 模式和 Planar 模式。
| 模式类型 | 数量 | 说明 |
|---|---|---|
| 角度模式 | 33 | 从不同方向复制参考像素,覆盖 360° 方向 |
| DC 模式 | 1 | 取参考像素的平均值,适合平坦区域 |
| Planar 模式 | 1 | 双线性插值,适合渐变区域 |
编码器会遍历所有模式,选一个残差最小的。当然,全遍历计算量很大,实际工程里会用快速算法,比如只检查相邻角度和几个候选模式。
2.2.2 帧间预测
帧间预测利用的是时间冗余。它通过运动估计,在参考帧里找到当前块最匹配的位置,然后编码运动矢量(MV)和残差。
H.265 的帧间预测比 H.264 更灵活:
- 运动补偿块大小:从 64x64 到 8x8,支持非对称划分(AMP)。
- 亚像素精度:支持 1/4 像素精度,插值滤波器更复杂。
- Merge 模式:直接从相邻块继承运动信息,省掉编码 MV 的比特。
避坑指南:我曾经在运动估计的搜索范围上吃过亏。范围设太大,编码速度慢得离谱;设太小,运动剧烈的场景残差大,画质崩。后来我根据视频分辨率和帧率动态调整搜索范围,效果好了很多。
2.3 变换编码
预测做完之后,我们得到的是残差块。残差块里仍然有空间相关性,直接量化效率不高。这时候就需要变换编码上场了。
变换编码的核心思想:把像素域的残差转换到频域。在频域里,能量集中在低频系数上,高频系数接近零。这样量化的时候,可以保留低频、丢弃高频,压缩效果更好。
H.265 用的是整数 DCT(离散余弦变换),块大小支持 4x4、8x8、16x32、32x32。大块变换适合平坦区域,小块变换适合纹理丰富的区域。
我记得刚接触 H.265 时,看到它支持 32x32 变换还挺惊讶的。后来在 4K 视频测试中发现,大块变换对背景平滑区域的压缩效率提升很明显,但也会带来振铃效应。嗯,凡事都有代价。
关键点:变换本身是无损的,损失发生在后面的量化步骤。变换只是把数据重新排列,让能量更集中。
2.4 量化
量化是编码过程中唯一的有损步骤。它的原理很简单:把连续的系数值映射到有限的离散值上。说白了,就是「四舍五入」。
H.265 使用标量量化,量化步长由量化参数(QP)控制。QP 范围是 0 到 51,每增加 6,量化步长翻倍,码率大约减半。
| QP 值 | 量化步长 | 码率影响 | 画质影响 |
|---|---|---|---|
| 0 | 最小 | 最高 | 无损 |
| 22 | 中等 | 中等 | 视觉无损 |
| 32 | 较大 | 较低 | 轻微损失 |
| 51 | 最大 | 极低 | 严重块效应 |
量化带来的失真主要是块效应和振铃效应。块效应是因为相邻块的量化误差不一致,振铃效应是因为高频系数被粗暴地砍掉了。
注意:量化参数不是越小越好。QP 太小,码率暴增,带宽扛不住。QP 太大,画质惨不忍睹。实际工程中,QP 通常设在 22 到 32 之间。
2.5 熵编码
量化之后,我们得到的是量化系数、运动矢量、模式信息等语法元素。这些元素还有统计冗余,需要用熵编码进一步压缩。
H.265 使用两种熵编码方式:
- CABAC(上下文自适应二进制算术编码):主流选择,压缩率高,但计算量大。
- CAVLC(上下文自适应变长编码):备用方案,压缩率低,但计算量小。
CABAC 的原理是:根据已编码的上下文,动态调整每个符号的概率模型,然后用算术编码压缩。我建议在实际项目中,除非硬件资源极度受限,否则都用 CABAC。它的压缩率比 CAVLC 能高 10% 到 15%。
熵编码的输出就是最终的码流了。码流的结构由 H.265 的语法规范定义,包括 NAL 单元、SPS、PPS、Slice 头等。
2.6 率失真优化
率失真优化(RDO)是编码器的「大脑」。它负责在码率和失真之间做权衡,决定每个编码参数的最优选择。
RDO 的核心公式很简单:
J = D + λ * R
其中:
- J:率失真代价
- D:失真(通常用 SSE 或 SAD 衡量)
- R:码率(编码该块需要的比特数)
- λ:拉格朗日乘子,由 QP 决定
编码器会遍历所有候选模式(帧内模式、帧间模式、划分方式等),计算每个模式的 J 值,选最小的那个。
我在项目中遇到过一个问题:RDO 的计算量太大了,尤其是 4K 视频,遍历所有模式根本跑不动。后来我们用了快速 RDO 算法,比如提前终止、跳过低概率模式、用近似失真度量代替精确 SSE。效果还不错,编码速度提升了 3 倍,画质损失不到 0.1 dB。
经验之谈:λ 的取值很关键。λ 太大,编码器倾向于低码率,画质差;λ 太小,码率失控。H.265 参考模型里 λ 和 QP 的关系是 λ = 0.85 * 2^(QP/3 - 2),你可以在这个基础上根据应用场景微调。
2.7 本章知识体系
下面这张图总结了编码基础理论的整体流程和各个模块的关系:
从这张图可以看得很清楚:原始帧先经过预测编码得到残差,残差经过变换和量化变成量化系数,最后用熵编码压缩成码流。而率失真优化贯穿整个过程,指导每个模块的参数选择。