视音频数据处理入门:H.264视频码流解析

音视频系列–H264编解码总结

H264 i帧p帧b帧详解

H264码流分析和打包RTP过程

H264码流中NALU sps pps IDR帧的理解


H264数据

H264 帧的组成

H.264定义的结构中,一个视频图像编码后的数据为一帧:

  • 帧(Frame):一帧由一个或多个片(Slice)组成
  • 片(Slice):一个片是由一个或多个宏块(MB)组成的(宏块是H264编码的基本单位)
  • 宏块(MB:Macro Block):一个宏块是由16x16的yuv数据组成的

帧类型

在H.264的协议中,定义了三类帧,分别是I帧、B帧和P帧。

I帧

定义

帧内编码帧 ,I帧表示关键帧,你可以理解为这一帧画面的完整保留;解码时只需要本帧数据就可以完成(因为包含完整画面)

特点

  1. 它是一个全帧压缩编码帧。它将全帧图像信息进行JPEG压缩编码及传输;
  2. 解码时仅用I帧的数据就可重构完整图像;
  3. I帧描述了图像背景和运动主体的详情;
  4. I帧不需要参考其他画面而生成;
  5. I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量);
  6. I帧是帧组GOP的基础帧(第一帧),在一组中只有一个I帧;
  7. I帧不需要考虑运动矢量; 8)I帧所占数据的信息量比较大。

P帧

Preview Prediction
在视频画面播放过程中,若I帧丢失了,则后面的P帧也就随着解不出来,就会出现视频画面黑屏的现象;若P帧丢失了,则视频画面会出现花屏、马赛克等现象。

定义

P帧:前向预测编码帧。
P帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面。(也就是差别帧,P帧没有完整画面数据,只有与前一帧的画面差别的数据)

P帧的预测与重构
P帧是以I帧为参考帧,在I帧中找出P帧“某点”的预测值和运动矢量,取预测差值和运动矢量一起传送。在接收端根据运动矢量从I帧中找出P帧“某点”的预测值并与差值相加以得到P帧“某点”样值,从而可得到完整的P帧。

特点

  1. P帧是I帧后面相隔1~2帧的编码帧;
  2. P帧采用运动补偿的方法传送它与前面的I或P帧的差值及运动矢量(预测误差);
  3. 解码时必须将I帧中的预测值与预测误差求和后才能重构完整的P帧图像;
  4. P帧属于前向预测的帧间编码。它只参考前面最靠近它的I帧或P帧;
  5. P帧可以是其后面P帧的参考帧,也可以是其前后的B帧的参考帧;
  6. 由于P帧是参考帧,它可能造成解码错误的扩散;
  7. 由于是差值传送,P帧的压缩比较高。

B帧

而B帧和P帧对应的就是之前说的不对全部图像做编码的帧。B帧和P帧的差别在于,P帧是参考之前的I帧生成的,B帧是参考前后的图像帧生成的。

定义

B帧:双向预测内插编码帧。
B帧是双向差别帧,也就是B帧记录的是本帧与前后帧的差别(具体比较复杂,有4种情况,但我这样说简单些),换言之,要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,但是解码时CPU会比较累。

B帧的预测与重构
B帧以前面的I或P帧和后面的P帧为参考帧,“找出”B帧“某点”的预测值和两个运动矢量,并取预测差值和运动矢量传送。接收端根据运动矢量在两个参考帧中“找出(算出)”预测值并与差值求和,得到B帧“某点”样值,从而可得到完整的B帧。

特点

  1. B帧是由前面的I或P帧和后面的P帧来进行预测的;
  2. B帧传送的是它与前面的I或P帧和后面的P帧之间的预测误差及运动矢量;
  3. B帧是双向预测编码帧;
  4. B帧压缩比最高,因为它只反映丙参考帧间运动主体的变化情况,预测比较准确;
  5. B帧不是参考帧,不会造成解码错误的扩散。

注:
I、B、P各帧是根据压缩算法的需要,是人为定义的,它们都是实实在在的物理帧。一般来说,I帧的压缩率是7(跟JPG差不多),P帧是20,B帧可以达到50。可见使用B帧能节省大量空间,节省出来的空间可以用来保存多一些I帧,这样在相同码率下,可以提供更好的画质。

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帧之前的数据来解码。

H264压缩方式

H264的压缩方式

H264 的核心压缩算法是帧内压缩和帧间压缩:

  • 帧内压缩是生成I帧的算法;
  • 帧间压缩是生成B帧和P帧的算法。

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

帧间(Interframe)压缩的原理是:
相邻几帧的数据有很大的相关性,或者说前后两帧信息变化很小的特点。连续的视频其相邻帧之间具有冗余信息,根据这一特性,压缩相邻帧之间的冗余量就可以进一步提高压缩量,减小压缩比。

H264压缩方式说明

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

1). 分组,也就是将一系列变换不大的图像归为一个组,即一个GOP;

2). 定义帧,将每组的图像帧归分为I帧、P帧和B帧三种类型;

3). 预测帧, 以I帧做为基础帧,以I帧预测P帧,再由I帧和P帧预测B帧;

4). 数据传输, 最后将I帧数据与预测的差值信息进行存储和传输。

H264分层结构

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

视频编码层 VCL
网络抽象层面 NAL

VCL

VCL层:包括核心压缩引擎和块,宏块和片的语法级别定义,设计目标是尽可能地独立于网络进行高效的编码;

NAL

NAL层:负责将VCL产生的比特字符串适配到各种各样的网络和多元环境中,覆盖了所有片级以上的语法级别。

NALU(NAL Unit)

H.264原始码流(裸流)是由一个接一个NALU组成,
NALU通常由

三部分组成,其中 Start Code 用于标示这是一个NALU 单元的开始,必须是"00 00 00 01" 或"00 00 01"。

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)(类型)。

forbidden_bit

禁止位,初始为0,当网络发现NAL单元有比特错误时可设置该比特为1,以便接受方纠错或丢掉该单元。

nal_reference_bit

NAL重要性,值越大,越重要,解码器在解码处理不过来的时候,可以丢掉重要性为0的NALU。

nal_unit_type(帧类型)

[笔记]音视频学习之视音频数据处理入门《三》H264_参考帧

常见帧类型判断

00 00 00 01 67

00 00 00 01 是 StartCode
67 是header
type = 7 =>SPS 即关键帧

一般来说 type = 7 + type = 8才可创建一个解码器

00 00 00 01 21

00 00 00 01 是 StartCode
21 是header
type = 1 => 非IDR的片 即 p帧或b帧

00 00 00 01 41

RBSP(Raw Byte Sequence Payload))

SPS

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

PPS

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

总结

IDR帧和I帧

I帧和P帧

NAL、SPS和PPS

NAL层由多个单元NALU组成,NALU由了NALU头(00 00 00 01或者00 00 01)、sps(序列参数集)、pps(图像参数集合)、slice、sei、IDR帧、I帧(在图像运动变化较少时,I帧后面是7个P帧,如果图像运动变化大时,一个序列就短了,I帧后面可能是3个或者4个P帧)、P帧、B帧等数据。