1. 音视频编解码基础:为什么需要编解码?
各位同学好,我是老周。今天咱们正式开讲《编解码与RTP负载封装详解》的第一章。说实话,做了十几年流媒体,我见过太多人一上来就啃H.264标准文档,结果被宏块、变换量化搞得晕头转向。我的建议是——先搞清楚最根本的问题:我们到底为什么要编解码?
1.1 原始音视频到底有多大?
先算一笔账。你想想看,一段未经压缩的1080p视频,每秒30帧,每像素用24bit表示RGB颜色。一帧画面有多大?
1920 × 1080 × 24 = 49,766,400 bit ≈ 6 MB
每秒30帧:6 MB × 30 = 180 MB/s
一部90分钟的电影:180 MB/s × 5400s ≈ 972 GB
接近1TB!这还只是视频,没算音频。一张DVD才4.7GB,蓝光也就50GB。如果不压缩,你连一部电影都存不下,更别说实时传输了。
核心结论:原始音视频数据量巨大,必须通过编解码技术压缩到可存储、可传输的规模。
1.2 为什么能压缩?——冗余的消除
我刚开始做编码器时,总觉得压缩是件很神奇的事。后来才明白,说白了就是去掉冗余信息。视频里存在三种冗余:
- 空间冗余:同一帧里,相邻像素往往很相似。比如蓝天背景,一大片蓝色完全没必要每个像素都存一遍。
- 时间冗余:相邻帧之间变化很小。你想想,镜头不动的时候,前后两帧几乎一模一样。
- 视觉冗余:人眼对亮度敏感,对颜色没那么敏感。对高频细节的感知也有限。丢掉一些不敏感的信息,人眼看不出区别。
我在项目中遇到过一位刚入行的同事,他问我:“既然能压缩,为什么不压到极致?”嗯,这里要注意——压缩是有代价的,后面会讲到。
1.3 有损压缩 vs 无损压缩
这是编解码里最基础的概念区分。我直接上表格,对比一目了然:
| 对比维度 | 无损压缩 | 有损压缩 |
|---|---|---|
| 压缩原理 | 去除统计冗余,保留全部信息 | 去除视觉/听觉冗余,丢弃部分信息 |
| 解压后数据 | 与原始数据完全一致 | 与原始数据近似,有失真 |
| 压缩比 | 通常 2:1 ~ 5:1 | 可达 20:1 ~ 200:1 甚至更高 |
| 典型应用 | ZIP、PNG、FLAC | JPEG、MP3、H.264、AAC |
| 适用场景 | 文本、程序、医学影像 | 流媒体、视频通话、娱乐音视频 |
避坑指南:我曾经在做一个医疗影像项目时,有人提议用H.264压缩X光片。我当场叫停了——医疗影像必须无损,任何失真都可能影响诊断。有损压缩不是万能的,选错压缩方式会出大问题。
1.4 编解码器的基本工作流程
理解了为什么压缩、怎么压缩,接下来看看编解码器到底是怎么工作的。我画了一张流程图,把核心流程串起来:
流程看起来不复杂,但每个环节都有门道。我挑几个重点说说:
1.5 量化——有损压缩的"罪魁祸首"
量化这一步,说白了就是用更少的精度去表示数据。比如一个像素的亮度值是128.7,量化步长设为10,那就变成130。0.7的差异就这么丢了。
量化步长越大,丢的信息越多,压缩比越高,画质越差。这就是码率-失真权衡——你永远在文件大小和画质之间做选择。
我的经验:做视频编码器调优时,我习惯先固定量化参数(QP)跑一遍,看码率和PSNR(峰值信噪比)的关系。QP每增加6,码率大约减半,但PSNR会下降约1dB。这个经验公式帮我快速找到平衡点。
1.6 熵编码——最后的无损压缩
量化之后的数据,其实还有很多统计冗余。比如一串数值:0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0... 直接存太浪费了。
熵编码就是干这个的——给高频出现的符号分配短码字,低频出现的分配长码字。Huffman编码、算术编码、CABAC(H.264/HEVC用的)都属于这类。
我记得刚接触CABAC时,觉得它比Huffman复杂太多。但后来在低码率场景下对比,CABAC能多省10%-15%的码率。嗯,复杂是有道理的。
1.7 解码器——编码器的逆过程
解码器基本是编码器的逆操作:熵解码 → 反量化 → 反变换 → 运动补偿。但有个关键点:解码器必须和编码器保持同步。
为什么会这样?因为编码器做运动补偿时,参考的是本地重建的帧(经过量化失真的),而不是原始帧。如果解码器用不同的参考帧,画面就会漂移、出错。
我曾经调试过一个播放器花屏的问题,查了两天才发现是编码器和解码器的参考帧缓冲区不一致。从那以后,我每次做编解码器联调,第一件事就是检查参考帧同步。
1.8 本章小结
这一章我们聊了:
- 原始音视频数据量巨大,不压缩没法用
- 压缩靠消除空间、时间、视觉三种冗余
- 有损压缩丢信息但压缩比高,无损压缩保真但压缩比低
- 编解码器核心流程:预测/变换 → 量化 → 熵编码(编码器);熵解码 → 反量化 → 反变换/补偿(解码器)
- 量化是唯一有损环节,熵编码是无损的