视频编码
Abstract |
Video Codec |
Authors |
Walter Fan |
Status |
WIP |
Updated |
2024-08-21 |
概述
视频压缩
RGB24 -> YUV420
帧内压缩
帧间压缩
视频帧 Video Frame
视频是由一系列图像组成的动作序列,并且该序列中的每个图像都将在要显示的动作序列的时间轴中接替前一个图像。 这些静止图像称为视频帧。
每个视频帧之间的时间差越小,刷新率就越高,并且视频中的运动表现得越自然。
这是因为每秒有更多的视频帧要显示为动作序列的一部分,因此帧之间图像的变化较小,并且运动看起来更平滑。
I-frame 信息帧
信息帧用帧内压缩,用作关键帧
P-frame
预测帧 Predictive Frame 用帧间压缩,反映之前的 I-frame 的变化
B-frame
双向预测帧 Bidirectional Predictive Frames 使得总体压缩更高, 它参考了之前的 I-frame 和之后的 P-frame
视频压缩 Video compress
由于视频是由图像的时间序列组成,视频压缩可以看作具有时间分量的图像压缩。
大多数视频压缩方案都利用了时间相关性来消除冗余。
预测帧与当前帧之间的差异称为预测误差或残差
Intra-Frame 帧内压缩
Inter-Frame 帧间压缩
H.264
Compression and media resilliency feature
Error feedback mechanism
Enhanced motion estimation
Improved entropy coding
Intra-prediction coding for I-frame
4*4 Display Channel Table (DCT)
Network Abstraction Layer
Gradual Decoder Refresh(GDR) frame
Long-Term Reference Picture (LTRP) frame
错误反馈机制
增强的运动估计
改进的熵编码
I帧的帧内预测编码
4 * 4 显示频道表(DCT)
网络抽象层
渐进式解码器刷新(GDR)帧
长期参考图片(LTRP)帧
在对视频进行编码时,大多数编解码器将帧 (frame) 划分为宏块 (macroblocks) – 离散且大部分独立的处理单元。 然后,编解码器可以进一步细分这些宏块以执行特定的变换或预测.
宏块和分辨率
在 H.264 中,宏块是 16x16 正方形中 256 个像素的块(尽管它们可以更小或针对某些内部操作进行细分)。 因此,H.264 编码视频的宽度和高度(以像素为单位)必须是 16 的倍数,因为帧边界必须以宏块结束。
宏块对于 H.264 来说非常重要,因此在协商支持的分辨率时,最大帧大小 max-fs 以总宏块而不是像素来表示。 与 H.263 等早期编解码器不同,在 H.264 中,接收器不需要也没有能力表达它们支持的分辨率或宽高比。 H.264 接收器简单地表示每帧的最大宏块数,然后应该能够解码和渲染包含那么多或更少宏块的任何有效分辨率。
问题在于,根据规范,发送者以不寻常的宽高比发送视频是合法的,甚至可能是极其不寻常的宽高比,例如 5x1。 在实践中,大多数解码器分配一个表面来解码具有最大高度和宽度的视频,并且极端分辨率将不适合该表面并且将不可解码。 关心互操作性的实现者应该警惕发送非标准分辨率,除非有其他机制来表示支持它们,但也应该设法使他们的解码器相对稳健,以接收他们可能收到的合理范围的分辨率。
在视频会议中,电视宽高比 (16:9) 往往比显示器宽高比 (16:10) 更受支持。 较旧的编解码器主要关注 4:3 分辨率。 但请注意,现代系统越来越多地支持各种宽高比,包括纵向视频。 对各种分辨率的强大支持对于可以从各种设备共享的内容或演示视频尤其重要,并且尽可能保留原始分辨率对于确保文本清晰易读尤其重要。
有趣的是,常见的高清分辨率 1080p(名义上为 1920x1080)无法用标准 H.264 进行编码,因为 1080 像素的宽度不允许有整数个宏块(它不能被 16 整除)。 因此,标称 1080p 的 H.264 内容实际上是 1920x1072 或 1920x1088。 这在广告、发送和接收时实际上很重要;
支持 1080p 的实现应该宣传最高支持 1920x1088,并且应该能够处理接收 1920x1072 或 1920x1088。 发送时,实现必须确保它们不超过远端公布的最大值(这可能意味着发送 1920x1072 而不是 1920x1088,如果这是他们公布的支持的最大值),但建议对可操作性感兴趣的实现者选择公布支持 支持 1080p 时至少为 1920x1088。
帧率 framerate
以类似的方式,H.264 协商不涉及最大帧速率的协商,而是涉及每秒最大宏块数 max-mbps。 与 max-fs 的宽高比问题一样,这确实具有发送器在规范内以较高帧速率发送较低分辨率的属性。 例如,720p 对应于 (1280*720)/(16*16)=3600 个宏块,在 30fps 下,其 mbps 为 108000。但是,此最大 mbps 也允许在超过 60fps 时实现 720x576,或者在甚至更低的分辨率下更高的帧率。
与宽高比问题一样,实现实际上很少支持接收任意高的帧速率; 关心互操作性的实现者应该避免发送高于 30fps 的帧速率,除非有其他机制来表示支持它们。
量化参数 Quantization Parameter
分辨率和帧速率并不是影响发送 H.264 流所需比特率的唯一变量,编解码器还可以通过量化参数 QP 改变压缩帧本身的保真度或质量。
QP是用于导出缩放矩阵的索引; QP 值越小,编码器采取的步数越多,因此可以保留原始帧的更多细节,但需要的比特率也越高。 较高的 QP 使用较大的步长并导致保真度损失较大,但可以使用较少的位数对相同分辨率的帧进行编码。 因此,QP 可以被认为是控制编码质量——低 QP 意味着更高的质量,高 QP 意味着更低的质量。
因此,当编码器以给定的最大比特率为目标时,实现必须在帧速率、分辨率和质量之间取得折衷。 大多数实现都会选择根据目标比特率设置帧速率和分辨率,从而允许编码器选择最佳 QP 来达到目标质量。
然而,在需要大量关键帧的情况下(可能是由于丢包导致远端频繁发送关键帧请求),编码器可能被迫使用足够高的 QP 来维持视频会降低的分辨率和帧率 能见度; 这可能会导致“脉冲”质量,因为编码器只能生成低质量的 I 帧,然后能够降低后续增量帧的 QP,然后被迫再次提高下一个关键帧的 QP。 实现可能希望设置 QP 上限来避免这种影响,通过丢帧(从而降低有效帧速率)来避免这种情况过于明显。
配置 Profiles
H.264 标准中有许多可用的工具选项。 其中一些选项允许为某些参数分配额外的位以实现更高的清晰度,但这些很少用于实时媒体编码。更相关的是在给定比特率下允许更高清晰度的选项集,但 CPU 成本明显会更高。
虽然这些选项在视频流被编码一次然后由多个接收者(例如流媒体或磁盘上的媒体)解码的用例中具有很大的价值,但在视频会议的情况下有所不同, 其中编码必须实时地完成,并且编码由少数接收者进行解码。 在这些情况下,实际应用中许多的实现选择不支持这些高级工具选项。
H.264 不是单独协商所有这些工具,而是将它们捆绑到配置文件 (Profiles) 中,其中每个预定义的配置文件 (Profiles)意味着支持许多此类扩展。 视频会议中的 H.264 主要涉及三个配置文件:
约束基线配置 (Constrained Baseline):H.264 最基本的形式,没有任何可选扩展项。 这是视频会议中最常支持的配置文件,与互操作性相关的实现应始终提供 H.264 Constrained Baseline 支持,即使它们还提供其他配置文件。
主要配置 (Main):此配置文件主要增加了对 CABAC(上下文自适应基线算术编码器)的支持,在给定质量下,它往往会导致比特率降低约 10%,而编码的 CPU 成本会增加约 50%。 视频会议中相当一部分的实现支持主要配置文件。
高配置(High):与 Main 中的工具集一样,它允许跨多个宏块进行帧内预测,再次允许在给定质量下降低比特率,但同样会付出更高的 CPU 成本。 视频会议中很少有实现支持 High profile。
还有一个通常在信令协商时用到的一个独立的 Baseline Profile,它实际上等同于 Constrained Baseline Profile (CBP)。 它主要是出于历史原因而用到的; 直到 H.264 Baseline Profile在信令协商中得到很好的建立和应用之后,CBP 才被定义。
可扩展视频编码 Scalable Video Coding (SVC)
H.264 的另一个扩展是Scalable Video Coding (SVC)。 当使用此扩展时,编码器会创建一个视频流,其中还包含一个或多个子流,这些子流可以通过从流中丢弃某些数据包来导出。
这在将编码流发送到多个接收者(其中一些接收者可能具有不同的接收能力)的用例中非常有价值——然后 SFU 交换服务器可以将所有数据包转发到能力更强的接收者,同时丢弃一层或多层 SVC 流 以较低的比特率将子流之一转发到其他能力较弱的接收者。
SVC 编码允许三种类型的层次(layer)或称子流(substream)
Temporal Layer 时间层:每个子层代表流的不同帧速率。 例如,30fps 流可能包含 15fps 子层,方法是每隔一个帧进行预测,而不是根据前一帧,而是根据前一帧。 因此,服务器可以丢弃 50% 没有预测到任何内容的帧,并具有兼容的 15fps 流发送到接收器子集。 这是迄今为止实现起来最简单的 SVC 模式,因此在视频会议中得到了最好的支持。
Spatial Layer 空间层:每个子层代表流的不同分辨率。 这比时间可伸缩性要复杂得多,并且在视频会议中很少受支持。
Quality Layer 质量层:也称为保真度 Fidelity 或信噪比 SNR (Signal to Noise Ratio) 可扩展性,每个子层具有相同的分辨率和帧速率,但质量不同。 这是支持最少的 SVC 形式。
由于 SVC 主要用于将一个源流切换到多个接收者的情况,而目前广泛实施的视频会议标准并未很好地支持这种情况,因此它更常见于专有视频会议解决方案中。
请注意,SVC 确实会降低编码过程的效率:例如,包含 15fps 子层的 30fps 流的 SVC 编码将需要稍高的比特率才能保持与 30fps 相同流的 AVC(标准)编码相同的质量 在相同的分辨率下。
在此及其复杂性之间,一些实现通过联播 Simulcast 解决了相同的问题:以不同的分辨率/帧速率/质量将同一流的多个独立编码发送到交换服务器(SFU),然后交换服务器(SFU)可以将这些编码中最合适的转发到每个接收者。 这通常会导致每个接收者的上行带宽和编码成本较高,但下行带宽较低,并且避免了支持 SVC 的复杂性。
在多个子流的上下文中,非 SVC H.264 通常被称为 AVC(高级视频编码)以进行区分,这是 H.264 编解码器官方术语的一部分。
Packetization mode 打包模式
当 H.264 在 RTP 中发送时,需要将给定帧拆分为多个数据包,因为与音频不同,考虑到 MTU 限制,视频帧很少适合单个 RTP 数据包。 H.264支持多种打包模式。 这些必须配置为编码的一部分,因为不同的打包模式要求以特定方式对帧进行编码。
H.264 有 3 种不同的打包模式
0:最简单的模式,RTP数据包只能包含单个NAL单元(NALU),这是H.264内部的结构。 最简单的实现,涉及互操作性的实现通常应该提供对分组模式 0 的支持。
1:该模式允许NALU跨越多个数据包。 这是视频会议中使用最广泛的分组模式,建议实现确保它们支持和协商分组模式 1。
2:最复杂的模式,在使用 H.264 的视频会议中很少支持或协商该模式