H.264编码原理解析(一)
1、本文主要用来介绍H.264编码原理的一些基本名词,充分理解这些基本概念能更好的了解H.264编码原理。
GOP(图像组)
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帧。
P帧
P帧:前向预测编码帧。P帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面,P帧没有完整画面数据,只有与前一帧的画面差异的数据。P帧的压缩率20
B帧
B帧:双向预测内插编码帧。B帧是双向差别帧,也就是B帧记录的是本帧与前后帧的差别,要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,约为50,但是解码时CPU会比较累。
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。
以下是例子:
关于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。对视频的原始数据进行压缩
参考文档:
1、H264的基本原理(一)------视频的基本知识
(https://blog.csdn.net/qq_28090573/article/details/89874751)