H.264编码原理解析(一)基本名词解释

H.264编码原理解析(一)

1、本文主要用来介绍H.264编码原理的一些基本名词,充分理解这些基本概念能更好的了解H.264编码原理。

H.264名词解释

H.264帧类型:分为I帧、B帧、P帧
GOP(图像组)
  • GOP图像组:Group of Picture就是一组变化不大的图像组的集合,在这一组图像中有且只有1个I帧,多个P帧或B帧,两个I帧之间的帧数,就是一个GOP
  • GOP一般设置为编码器每秒输出的帧数,即每秒帧率,一般为25或30,当然也可设置为其他值
  • 在一个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响应的时间也越长
I帧
H.264中规定了两种类型的I帧:普通I帧(normal Iframes)和IDR帧(InstantaneousDecoding Refresh, 即时解码刷新)。 IDR帧实质也是I帧,使用帧内预测。IDR帧的作用是立即刷新,会导致DPB(Decoded Picture Buffer参考帧列表)清空,而I帧不会。所以IDR帧承担了随机访问功能,一个新的IDR帧开始,可以重新算一个新的Gop开始编码,播放器永远可以从一个IDR帧播放,因为在它之后没有任何帧引用之前的帧。如果一个视频中没有IDR帧,这个视频是不能随机访问的。所有位于IDR帧后的B帧和P帧都不能参考IDR帧以前的帧,而普通I帧后的B帧和P帧仍然可以参考I帧之前的其他帧。IDR帧阻断了误差的积累,而I帧并没有阻断误差的积累。
一个GOP序列的第一个图像叫做 IDR 图像(立即刷新图像),IDR 图像都是 I 帧图像,但I帧不一定都是IDR帧,只有GOP序列的第1个I帧是IDR帧。
  • I帧:表示关键帧,是帧内编码帧。I帧是不需要参考其他帧生成,I帧能独立解码重构出完整图像,同样I 帧数据也比较大
  • I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量);
  • I帧是帧组GOP的基础帧(第一帧),在一组中只有一个I帧;
P帧
P帧:前向预测编码帧。P帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面,P帧没有完整画面数据,只有与前一帧的画面差异的数据。P帧的压缩率20
  • P帧是I帧后面相隔1~2帧的编码帧;
  • P帧采用运动补偿的方法传送它与前面的I或P帧的差值及运动矢量(预测误差);
  • 解码时必须将I帧中的预测值与预测误差求和后才能重构完整的P帧图像;
  • P帧属于前向预测的帧间编码。它只参考前面最靠近它的I帧或P帧;
  • P帧可以是其后面P帧的参考帧,也可以是其前后的B帧的参考帧;
  • 由于P帧是参考帧,它可能造成解码错误的扩散;
  • 由于是差值传送,P帧的压缩比较高。
B帧
B帧:双向预测内插编码帧。B帧是双向差别帧,也就是B帧记录的是本帧与前后帧的差别,要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,约为50,但是解码时CPU会比较累。
  • B帧是由前面的I或P帧和后面的P帧来进行预测的
  • B帧传送的是它与前面的I或P帧和后面的P帧之间的预测误差及运动矢量
  • B帧是双向预测编码帧
  • B帧压缩比最高,因为它只反映丙参考帧间运动主体的变化情况,预测比较准确;
  • B帧不是参考帧,不会造成解码错误的扩散。
SPS
SPS即Sequence Paramater Set,又称作序列参数集
SPS中保存了一组编码视频序列(Coded video sequence)的全局参数。存放包括:帧数、参考帧数目、解码图像尺寸、帧场编码模式选择标识等。所谓的编码视频序列即原始视频的一帧一帧的像素数据经过编码之后的结构组成的序列。而每一帧的编码后数据所依赖的参数保存于图像参数集中。一般情况SPS和PPS的NAL Unit通常位于整个码流的起始位置。但在某些特殊情况下,在码流中间也可能出现这两种结构,主要原因可能为:
  • 解码器需要在码流中间开始解码;
  • 编码器在编码的过程中改变了码流的参数(如图像分辨率等);
PPS
PPS:图像参数集Picture Paramater Set(PPS)
图像相关的参数集,存放包括:熵编码模式选择标识、片组数目、初始量化参数和去方块滤波系数调整标识等。通常情况下,PPS类似于SPS,在H.264的裸码流中单独保存在一个NAL Unit中,只是PPS NAL Unit的nal_unit_type值为8;而在封装格式中,PPS通常与SPS一起,保存在视频文件的文件头中。
***在一组帧之前,首先要收到SPS 和 PPS ,不然的话是无法解码的。这两组数据划分为I帧,是不能丢的。***

SODB
SODB:String of Data Bits,数据 bit 流,最原始的编码数据即(VCL数据),由于是流式数据没有结尾的概念,长度就不一定是8的倍数。它是由 VLC 层产生的。由于我们计算机是以8倍数去处理数据所以计算机在处理H264时,就需要增加一个结尾比特(RBSP trailing bits 一个bit“1”)若干比特“0”,以便字节对齐,这样就生成了RSBP。
RBSP,
它是由SODB + tailing bits (原始字节序列载荷)
由于它是一个压缩流,SODB 不知道是在何处结束,所以算法在SODB最后一位补一个1,没有按字节对齐的则补 0
EBSP (扩展字节序列载荷)
在生成压缩流之后,在每一帧的开头加一个起始位,这个起始位一般是 00 00 00 01 或者是 00 00 01。所以在h264码流中规定每有两个连续的00 00,就增加一个0x03。
以下是例子:
H.264编码原理解析(一)基本名词解释
文章图片

关于RBSP与EBSP的思考:
EBSP相较于RBSP,多了防止竞争的一个字节:0x03。
我们知道,NALU的起始码为0x000001或0x00000001,同时H264规定,当检测到0x000000时, 也可以表示当前NALU的结束。那这样就会产生一个问题,就是如果在NALU的内部,出现了0x000001或0x000000时该怎么办?所以H264就提出了“防止竞争”这样一种机制,当编码器编码完一个NAL时,应该检测NALU内部, 是否出现如下左侧的四个序列。当检测到它们存在时,编码器就在最后一个字节前,插入一个新的字节:0x03。这样一来,当我们拿到EBSP时,就需要检测EBSP内是否有序列:0x000003,如果有,则去掉其中的0x03。这样一来,我们就能得到原始字节序列载荷:RBSP。

NALU和EBSP的关系
NALU(NAL Unit)
在EBSP的基础上,加1字节的NAL 头 NAL Header(1Byte) + EBSP

NALU UNIT单元:H264的主要目标是为了有高的视频压缩比和良好的网络亲和性,为了达成这两个目标,H264的解决方案是将系统框架分为两个层面,分为VCL(视频编码层)和 NAL(网络提取层)
(1)NAL层(Network Abstraction Layer视频数据网络抽象层) NAL层定义了片级以上的语法级别(如序列参数集和图像参数集),负责以网络所要求的恰当方式去格式化数据并提供 头信息,以保证数据适合各种信道和存储介质上的传输。NAL层将SODB打包成RBSP然后加上NAL头组成一个NALU 单元。 因为H264最终还是要在网络上进行传输,在传输的时候,网络包的最大传输单元是1500字节, 一个H264的帧往往是大于1500字节的,所以需要将一个帧拆成多个包进行传输。这些拆包、组包等工作都在NAL层 去处理。(2)VCL层 (Video Coding Layer 视频数据编码层) VLC层是对核心算法引擎、块、宏块及片的语法级别的定义,负责有效表示视频数据的内容, 最终输出编码完的数据SODB。对视频的原始数据进行压缩

参考文档:
【H.264编码原理解析(一)基本名词解释】1、H264的基本原理(一)------视频的基本知识
(https://blog.csdn.net/qq_28090573/article/details/89874751)

    推荐阅读