H.264

MPEG-4/H.264 AVC 编解码标准

H.264,通常也被称之为 H.264/AVC(或者 H.264/MPEG-4 AVC 或 MPEG-4/H.264 AVC),H.264 的出现就是为了创建比以前的视频压缩标准更高效的压缩标准,使用更好高效的视频压缩算法来压缩视频的占用空间,提高存储和传输的效率,在获得有效的压缩效果的同时,使得压缩过程引起的失真最小。MPEG-4 AVC 和 H.264 是目前较为主流的编码标准。主要定义了两方面的内容:视频数据压缩形式的编码表示和用重建视频信息的语法来描述编码方法。其目的是为了保证兼容的编码器能够成功的交互工作,同时也允许制造厂商自由的开发具有竞争力的创新产品。制造厂商只需要注意的事情就是能够获得和标准中采用的方法同样的结果。

提到 H.264 编解码,我们先简单说一下视频压缩算法。视频压缩算法是通过去除时间、空间的冗余来实现的。在一段时间内,相邻的图像的像素、亮度与色温的差别很小,我们没比要对每一个图像进行完成的编码,而是可以选取这段时间的第一张图(也就是第一帧)作为完整的编码,而后面一段时间的图像只需要记录与第一张图(第一帧)在像素、亮度、色温等方面的差别数据即可。通过去除不同类型的冗余,可以明显的压缩数据,代价就是一部分信息失真。

基础概念

在 H.264 定义的结构中,一个视频图像编码后的数据叫做一帧。一帧是由一个或多个片(slice)组成的,一个片是由一个或多个宏块(MB)组成的(宏块是 H264 编码的基本单位),一个宏块是由 16x16 的 yuv 数据组成的。

对于 YUV 的介绍参阅 《Frontend-Notes

帧类型

在 H.264 的协议中,定义了三类帧,分别是 I 帧、B 帧和 P 帧。其中 I 帧就是之前我们所说的一个完整的图像帧,而 B 帧和 P 帧对应的就是之前说的不对全部图像做编码的帧。B 帧和 P 帧的差别在于,P 帧是参考之前的 I 帧生成的,B 帧是参考前后的图像帧生成的。在视频画面播放过程中,若 I 帧丢失了,则后面的 P 帧也就随着解不出来,就会出现视频画面黑屏的现象;若 P 帧丢失了,则视频画面会出现花屏、马赛克等现象。

GOP(画面组)

一个 GOP(Group Of Picture)就是一组连续的画面。GOP 结构一般有两个数字,其中一个是 GOP 的长度(即两个 I 帧之间的 B 帧和 P 帧数),另一个数字为 I 帧和 P 帧之间的间隔距离(即 B 帧数)。在一个 GOP 内 I 帧解码不依赖任何的其它帧,P 帧解码则依赖前面的 I 帧或 P 帧,B 帧解码依赖前面的 I 帧或 P 帧及其后最近的一个 P 帧。

注意:在码率不变的前提下,GOP 值越大,P、B 帧的数量会越多,平均每个 I、P、B 帧所占用的字节数就越多,也就更容易获取较好的图像质量;Reference 越大,B 帧的数量越多,同理也更容易获得较好的图像质量。但是通过提高 GOP 值来提高图像质量是有限度的。H264 编码器在遇到场景切换的情况时,会自动强制插入一个 I 帧,此时实际的 GOP 值被缩短了。另一方面,在一个 GOP 中,P、B 帧是由 I 帧预测得到的,当 I 帧的图像质量比较差时,会影响到一个 GOP 中后续 P、B 帧的图像质量,直到下一个 GOP 开始才有可能得以恢复,所以 GOP 值也不宜设置过大。同时,由于 P、B 帧的复杂度大于 I 帧,所以过多的 P、B 帧会影响编码效率,使编码效率降低。另外,过长的 GOP 还会影响 Seek 操作的响应速度,由于 P、B 帧是由前面的 I 或 P 帧预测得到的,所以 Seek 操作需要直接定位,解码某一个 P 或 B 帧时,需要先解码得到本 GOP 内的 I 帧及之前的 N 个预测帧才可以,GOP 值越长,需要解码的预测帧就越多,seek 响应的时间也越长。

IDR 帧

GOP 中的 I 帧又分为普通 I 帧和 IDR 帧,IDR 帧就是 GOP 的第一个 I 帧,这样区分视为了方便控制编码和解码的流程。IDR 帧一定是 I 帧,但是 I 帧不一定是 IDR 帧。IDR 帧因为附带 SPS、PPS 等信息,解码器在收到 IDR 帧时,需要做的工作就是:把所有的 PPS 和 SPS 参数进行更新。

可以看出来 IDR 帧的作用是让解码器立刻刷新相关数据信息,避免出现较大的解码错误问题。引入 IDR 帧机制是为了解码的重同步,当解码器解码到 IDR 帧时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。这样,如果前一个序列出现错误,在这里可以获得重新同步的机会。IDR 帧之后的帧永远不会使用 IDR 帧之前的数据来解码。

H.264 压缩方式

H264 的核心压缩算法是帧内压缩和帧间压缩,帧内压缩是生成 I 帧的算法,帧间压缩是生成 B 帧和 P 帧的算法。帧内(Intraframe)压缩的原理是:当压缩一帧图像时,仅考虑本帧的数据而不考虑相邻帧之间的冗余信息,一般采用有损压缩算法,由于帧内压缩是编码一个完整的图像,所以可以独立的解码、显示。帧内压缩率一般不高。

帧间(Interframe)压缩的原理是:相邻几帧的数据有很大的相关性,或者说前后两帧信息变化很小的特点。连续的视频其相邻帧之间具有冗余信息,根据这一特性,压缩相邻帧之间的冗余量就可以进一步提高压缩量,减小压缩比。而帧间压缩也称为时间压缩(Temporalcompression),它通过比较时间轴上不同帧之间的数据进行压缩。帧间压缩是无损的,它通过比较本帧与相邻帧之间的差异,仅记录本帧与其相邻帧的差值,这样可以大大减少数据量。

H.264 压缩视频数据时的具体方式如下:

  • 分组,也就是将一系列变换不大的图像归为一个组,即一个 GOP;
  • 定义帧,将每组的图像帧归分为 I 帧、P 帧和 B 帧三种类型;
  • 预测帧,以 I 帧做为基础帧,以 I 帧预测 P 帧,再由 I 帧和 P 帧预测 B 帧;
  • 数据传输,最后将 I 帧数据与预测的差值信息进行存储和传输。

H.264 分层结构

H.264 的主要目标是为了有高的视频压缩比和良好的网络亲和性,H264 将系统框架分为两个层面,分别是视频编码层面(VCL)和网络抽象层面(NAL)。

  • VLC 层(Video Coding Layer):包括核心压缩引擎和块,宏块和片的语法级别定义,设计目标是尽可能地独立于网络进行高效的编码;
  • NAL 层(Network Abstraction Layer):负责将 VCL 产生的比特字符串适配到各种各样的网络和多元环境中,覆盖了所有片级以上的语法级别。
  • NALU(NAL Unit):H.264 原始码流(裸流)是由一个接一个 NALU 组成,结构如下图,一个 NALU = 一组对应于视频编码的 NALU 头部信息 + 一个原始字节序列负荷(RBSP,Raw Byte Sequence Payload)。

NALU 结构

一个原始的 H.264 NALU 单元常由 [StartCode] [NALU Header] [NALU Payload] 三部分组成。

  • Start Code:Start Code 用于标示这是一个 NALU 单元的开始,必须是”00 00 00 01” 或”00 00 01”。
  • NAL Header:NAL Header 由三部分组成,forbidden_bit(1bit),nal_reference_bit(2bits)(优先级),nal_unit_type(5bits)(类型)。
  • RBSP(Raw Byte Sequence Payload))

下图是 RBSP 的序列的样例及相关类型参数的描述表:

RBSP 参数描述表

  • SPS 是序列参数集,包含的是针对一连续编码视频序列的参数,如标识符 seq_parameter_set_id、帧数及 POC 的约束、参考帧数目、解码图像尺寸和帧场编码模式选择标识等等。

  • PPS 是图像参数集,对应的是一个序列中某一幅图像或者某几幅图像,其参数如标识符 pic_parameter_set_id、可选的 seq_parameter_set_id、熵编码模式选择标识、片组数目、初始量化参数和去方块滤波系数调整标识等等。

参数集是一个独立的数据单位,不依赖于参数集之外的其他句法元素。一个参数集不对应某一个特定的图像或者序列,同一个序列参数集可以被一个或者多个图像参数集引用。同理,一个图像参数集也可以被一个或者多个图像引用。只有在编码器认为需要更新参数集的内容时,才会发出新的参数集。

H.264 局限性

随着数字视频应用产业链的快速发展,视频应用向以下几个方向发展的趋势愈加明显:

  • 高清晰度(HigherDefinition):数字视频的应用格式从 720P 向 1080P 全面升级,而且现在 4K 的数字视频格式也已经成为常见。
  • 高帧率(Higherframe rate):数字视频帧率从 30fps 向 60fps、120fps 甚至 240fps 的应用场景升级;
  • 高压缩率(HigherCompression rate):传输带宽和存储空间一直是视频应用中最为关键的资源,因此,在有限的空间和管道中获得最佳的视频体验一直是用户的不懈追求。

但是面对视频应用不断向高清晰度、高帧率、高压缩率方向发展的趋势,当前主流的视频压缩标准协议 H.264 的局限性不断凸显。主要体现在:

  • 宏块个数的爆发式增长,会导致用于编码宏块的预测模式、运动矢量、参考帧索引和量化级等宏块级参数信息所占用的码字过多,用于编码残差部分的码字明显减少。
  • 由于分辨率的大大增加,单个宏块所表示的图像内容的信息大大减少,这将导致相邻的 4 x 4 或 8 x 8 块变换后的低频系数相似程度也大大提高,导致出现大量的冗余。
  • 由于分辨率的大大增加,表示同一个运动的运动矢量的幅值将大大增加,H.264 中采用一个运动矢量预测值,对运动矢量差编码使用的是哥伦布指数编码,该编码方式的特点是数值越小使用的比特数越少。因此,随着运动矢量幅值的大幅增加,H.264 中用来对运动矢量进行预测以及编码的方法压缩率将逐渐降低。
  • H.264 的一些关键算法例如采用 CAVLC 和 CABAC 两种基于上下文的熵编码方法、deblock 滤波等都要求串行编码,并行度比较低。针对 GPU/DSP/FPGA/ASIC 等并行化程度非常高的 CPU,H.264 的这种串行化处理越来越成为制约运算性能的瓶颈。

于是面向更高清晰度、更高帧率、更高压缩率视频应用的 HEVC(H.265)协议标准应运而生。H.265 在 H.264 标准 2 ~ 4 倍的复杂度基础上,将压缩效率提升一倍以上。

上一页