2. 视频编码基础

在学习 H.264 之前,必须先建立一套“视频的度量体系”。因为 H.264 的所有压缩工具——帧内预测、运动补偿、变换量化、熵编码——本质上都是在处理数字视频的像素阵列、色彩分量和时间序列。如果对模拟与数字、像素与分辨率、帧率与码率、色彩空间与采样格式这些基础概念没有清晰认识,后续的 SPS/PPS 参数、宏块划分、色度预测就会变成一堆没有物理意义的符号。

一、从模拟信号到数字信号:视频为什么要“采样”

模拟视频信号是随时间连续变化的电压或电流,例如早期的复合视频、S-Video、分量视频。它的优点是波形连续、理论上无量化台阶;缺点是易受干扰、多次复制会累积噪声、不便于存储和计算。数字视频则通过三个步骤把连续信号变成离散数据:

  1. 采样:在时间轴上按固定间隔取值,间隔的倒数就是采样频率。
  2. 量化:把每个采样点的幅度映射到有限个离散等级,例如 8 bit 对应 0~255。
  3. 编码:把量化后的整数按一定规则组织成码流,例如 YUV 排列、行场同步、打包为帧。

采样定理告诉我们:采样频率必须大于信号最高频率的两倍,才能无失真恢复。对视频而言,空间上的采样对应“像素”,时间上的采样对应“帧率”。因此,像素和帧率并不是凭空出现的参数,而是数字化过程中两个最基本的采样维度。

理解这一点非常关键:H.264 压缩的是“已经离散化后的数字样本”,它不能恢复采样时已经丢失的信息。如果源视频分辨率过低或帧率不足,编码器再强也无法凭空生成细节。

二、像素、分辨率与帧率:空间与时间的度量

像素是数字图像的最小单位,每个像素通常由亮度 Y 和色度 U、V 组成。像素本身没有物理尺寸,只有“数量”概念。分辨率描述一帧图像包含多少像素,常见写法是“宽×高”,例如 1920×1080 表示水平 1920 个像素、垂直 1080 个像素,总像素约 207 万。分辨率越高,空间细节越丰富,但编码计算量和码率需求也越大。

帧率表示每秒显示或采集多少帧,单位 fps。常见有 24 fps(电影)、25 fps(PAL)、30 fps(NTSC 系)、50/60 fps(体育、游戏、高流畅场景)。帧率越高,运动越顺滑,但单位时间内需要编码的帧数更多,码率也会上升。需要注意的是,帧率与分辨率共同决定“像素吞吐量”:

像素吞吐量 ≈ 宽 × 高 × 帧率
1920 × 1080 × 30 ≈ 62,208,000 像素/秒
1280 × 720  × 60 ≈ 55,296,000 像素/秒

可以看到,720p60 的像素吞吐量与 1080p30 接近,因此二者对编码器的压力也可能相近。这也是为什么在实时通信中,有时降低分辨率、提高帧率,反而比提高分辨率更划算。

三、码率:视频的“数据预算”

码率(bitrate)是单位时间内视频码流的数据量,常用 kbps 或 Mbps。它决定了视频的文件大小和传输带宽需求。码率与画质并非简单线性关系:同样的码率下,分辨率越高,单像素分配到的比特越少,压缩越剧烈,容易出现块效应和模糊;反之,分辨率较低时,单像素比特更充足,画面可能更干净。

码率控制方式主要有 CBR(恒定码率)、VBR(可变码率)、ABR(平均码率)和 CRF(恒定质量因子)。H.264 编码器中常见的参数包括:

ffmpeg -i input.yuv -c:v libx264 -b:v 2M -maxrate 2.5M -bufsize 5M output.mp4
# -b:v 目标平均码率
# -maxrate 峰值码率上限
# -bufsize 码率控制缓冲区大小

码率、分辨率、帧率三者构成“不可能三角”:在带宽受限时,必须牺牲其中一项或多项。理解这个关系,才能在实战中做出合理取舍。

四、色彩空间与采样格式:YUV 与 4:2:0

人眼对亮度细节敏感,对色度细节相对不敏感。因此视频编码普遍采用 YCbCr(常称 YUV)色彩空间,把亮度 Y 与色度 Cb、Cr 分离,并对色度进行下采样,从而在几乎不损失主观画质的前提下大幅减少数据量。

常见采样格式如下表所示:

采样格式 含义 每 4 个 Y 对应的色度样本 数据量相对 4:4:4
4:4:4 色度不降采样 4 个 Cb + 4 个 Cr 100%
4:2:2 水平方向色度减半 2 个 Cb + 2 个 Cr 约 67%
4:2:0 水平和垂直均减半 1 个 Cb + 1 个 Cr 约 50%
4:1:1 水平方向色度四分之一 1 个 Cb + 1 个 Cr 约 50%

H.264 最常用的就是 4:2:0。它意味着每 2×2 的亮度块共享一组色度样本。这也是为什么 H.264 的宏块是 16×16 亮度像素,对应 8×8 色度像素。理解 4:2:0 的排列方式,对后续理解帧内色度预测、色度 QP 偏移、以及为什么色度块比亮度块小,都非常重要。

在 FFmpeg 中可以用 -pix_fmt yuv420p 指定 4:2:0 输出。如果源是 RGB,需要先转换为 YUV,否则编码器可能拒绝或产生错误颜色。

五、案例与常见误区

假设我们要把一段 1080p30 的摄像头视频通过 2 Mbps 网络传输。若直接以 4:4:4 编码,色度数据量翻倍,码率压力很大;改为 4:2:0 后,色度数据减半,主观画质几乎不变。再配合适当降低帧率到 25 fps 或使用 CRF 模式,就能在有限带宽下获得可接受的画面。

常见误区包括:

  • 只看分辨率不看码率:4K 低码率可能比 1080p 高码率更模糊。
  • 认为帧率越高越好:高帧率会挤占单帧码率,暗光下噪声更明显。
  • 忽略色彩空间转换:RGB 与 YUV 转换公式错误会导致颜色偏绿或偏紫。
  • 把 4:2:0 当成“颜色减半”:它减的是色度采样密度,不是颜色种类。
在 H.264 编码前,务必确认输入像素格式与 SPS 中声明的 chroma_format_idc 一致。若声明 4:2:0 却输入 4:2:2,解码端会出现色度错位或花屏。

六、本节知识关系图

下图把模拟信号、数字信号、像素、分辨率、帧率、码率、色彩空间与采样格式之间的关系集中呈现,帮助你在进入 H.264 语法细节前建立整体坐标系。

视频编码基础概念关系图 模拟信号 连续时间 / 连续幅度 采样 + 量化 离散时间 / 离散幅度 数字信号 0/1 码流 空间维度 像素 · 分辨率 1920×1080 = 207 万像素 时间维度 帧率 fps 24 / 25 / 30 / 60 色彩维度 YUV / 4:2:0 亮度 + 色度下采样 码率 bitrate 分辨率 × 帧率 × 色彩采样 → 数据预算 H.264 压缩对象 = 数字化的 YUV 像素阵列 + 时间序列 + 码率约束

把这张图记在脑中,后续学习 H.264 的 SPS 中的 pic_width_in_mbs_minus1、frame_rate、chroma_format_idc、bit_rate 等字段时,就能立刻知道它们分别对应现实中的哪个物理量,而不是孤立地记忆语法。