H264结构分析

一、H264的NAL单元详解
1、VCL只关心编码部分,重点在于编码算法以及在特定硬件平台的实现

(1)SODB 是VCL输出的是编码后的纯视频流信息,没有任何冗余头信息

2、NAL关心的是VCL的输出纯视频流如何被表达和封包以利于网络传输,

(1)RBSP 是通过SODB封装成nal_unit格式得到的,Nal_unit是一个通用封装格式,可以适用于有序字节流方式和IP包交换方式,具体封装流程:https://blog.csdn.net/d_l_u_f/article/details/7260772

(2)NALU 是针对不同的传送网络(电路交换|包交换),将RBSP 封装成针对不同网络的封装格式(加上NAL header)

3、之间关系:
SODB + RBSP trailing bits = RBSP
NAL header(1 byte) + RBSP = NALU
RTP封装格式(12个字节) + NALU = 最后sendto出去的完整包
RBSP就是H.264编码后出来的裸流文件,给文件加上后缀.h264,得到xxx.h264

2、RBSP的内容

2.1、序列 sequence
(1) 一段h.264的码流其实就是多个sequence组成的

(2)一个sequence是一秒,如果FPS等于30,就有30帧图像(I/P/B帧)

(3)每个sequence均有固定结构单元:1sps+1pps+1sei+1I帧+若干p帧(加上B帧一共有6种单元情况)

2.2、分隔符
(1) H.264在编码的时候,生成一个序列时,序列中每个单元前面就会加上00 00 00 01作为分隔符

2.3、分隔符后第一个字节
(1)分隔符后面紧跟着的第一个字节就是用来判断是什么类型的单元
1、第1位禁止位,值为1表示语法出错
2、第2~3位为参考级别
3、第4~8为是nal单元类型nal_unit_type(比如是0x67(取5位00111表示sps)
播放器算法解码时,就知道这个字节开始到下一个分隔符之间的数据按照sps类型解析数据

2.4、单元之一:sps(序列参数集:固定14个字节)
(1)序列参数集。SPS中保存了一组编码视频序列(Coded video sequence)的全局参数,所谓的编码视频序列即原始视频的一帧一帧的像素数据经过编码之后的结构组成的序列。而每一帧的编码后数据所依赖的参数保存于图像参数集中

(2)里面包含宏块编码方式、图像大小尺寸、宏块个数,播放器通过这些参数,调用播放器里面的对应算法去解码

(3)具体意义参考博客:https://www.cnblogs.com/wainiwann/p/7477794.html

2.5、单元之二:pps(图像参数集:固定4个字节)
(1)H.264中另一重要的参数集合为图像参数集Picture Paramater Set(PPS),具体位意义参考博客

2.6、单元之三:SEI
(1)也是一些图像的额外信息,帮助播放器解析压缩图像

2.7、单元之四、五、六:I帧、P帧、B帧
(1)I帧是关键,丢了I帧当前sequence就废了,每个sequence有且只有1个I帧

(2)帧内编码帧 ,I帧表示关键帧,你可以理解为这一帧画面的完整保留;解码时只需要本帧数据就可以完成(因为包含完整画面),I帧大,说明本身压缩比不高,图像数据更完整,则P帧可以越小,反之I帧越小则P帧会越大

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

(4)B帧:双向预测内插编码帧。B帧是双向差别帧,也就是B帧记录的是本帧与前后帧的差别

具体特点参考:https://www.cnblogs.com/cy568searchx/p/6125031.html

3、CBR(固定码率)和VBR(可变码率)(压缩时候一个sequence参考的码率方式)
(1)一个sequence有30个帧,每个帧就是1/30秒,压缩后的字节数不一样,2000到10000+不等,主要看图像动作是否很大

(2)CBR就是牺牲图像清晰度,保证每帧图像字节数变化不会很大,这样码率就能均衡,网络传输也能稳定

(3)VBR就是牺牲码率,动作变化大的时候,参考VBR,帧数据会很大,保证清晰度,不管码率是否稳定,这样在网络传输的时候,网络带宽有限,带宽给的宽,资源限制,给的小,大的帧传输不完,比如I帧,网络就会不稳定

4、相关概念
(1)时间戳

引自:https://blog.csdn.net/qq_40334837/article/details/81433146

https://blog.csdn.net/chenchong_219/article/details/37990541

https://www.jianshu.com/p/9522c4a7818d

http://www.iosxxx.com/blog/2017-08-09-%E4%BB%8E%E9%9B%B6%E4%BA%86%E8%A7%A3H264%E7%BB%93%E6%9E%84.html#5-GOP

I帧(帧内编码帧)是一种自带全部信息的独立帧,无需参考其它图像便可独立进行解码。视频序列中的第一个帧始终都是I帧。如果所传输的比特流遭到破坏,则需要将I帧用作新查看器的起始点或重新同步点。I帧可以用来实现快进、快退以及其它随机访问功能。如果新的客户端将参与查看视频流,编码器将以相同的时间间隔或者根据要求自动插入I帧。I帧的缺点在于它们会占用更多的数据位,但从另一方面看,I帧不会产生可觉察的模糊现象。I帧是P帧和B帧的参考帧;I帧是组GOP的参考帧,在一组中只有一个I帧;不考虑运动矢量,数据量比较大;

P帧(帧间预测编码帧)需要参考前面的I帧和/或P帧的不同部分才能进行编码。与I帧相比,P帧通常占用更少的数据位,但其缺点是,由于P帧对前面的P和I参考帧有着复杂的依赖性,因此对传输错误非常敏感。P帧属于前向预测的帧间编码,它只参考前面最靠近它 的I帧或者P帧。

H.264编解码器中,量化参数QP和量化步长Qstep的关系:

量化步长Qstep共有52个值。(对于亮度编码而言)

量化参数QP是量化步长Qstep的序号,取值0~51。

QP取最小值0 时,表示量化最精细;相反,QP取最大值51时,表示量化是最粗糙的。

Qstep随着QP的增加而增加,QP每增加6,Qstep增加一倍。

对于色度编码,QP的最大值是39。

、NAL全称Network Abstract Layer, 即网络抽象层。
在H.264/AVC视频编码标准中,整个系统框架被分为了两个层面:视频编码层面(VCL)和网络抽象层面(NAL)。其中,前者负责有效表示视频数据的内容,而后者则负责格式化数据并提供头信息,以保证数据适合各种信道和存储介质上的传输。因此我们平时的每帧数据就是一个NAL单元(SPS与PPS除外)。在实际的H264数据帧中,往往帧前面带有00 00 00 01 或 00 00 01分隔符,一般来说编码器编出的首帧数据为PPS与SPS,接着为I帧……

如下图:

2、如何判断帧类型(是图像参考帧还是I、P帧等)?

 NALU类型是我们判断帧类型的利器,从官方文档中得出如下图:

我们还是接着看最上面图的码流对应的数据来层层分析,以00 00 00 01分割之后的下一个字节就是NALU类型,将其转为二进制数据后,解读顺序为从左往右算,如下:
(1)第1位禁止位,值为1表示语法出错
(2)第2~3位为参考级别
(3)第4~8为是nal单元类型

例如上面00000001后有67,68以及65

其中0x67的二进制码为:
0110 0111
4-8为00111,转为十进制7,参考第二幅图:7对应序列参数集SPS

其中0x68的二进制码为:
0110 1000
4-8为01000,转为十进制8,参考第二幅图:8对应图像参数集PPS

其中0x65的二进制码为:
0110 0101
4-8为00101,转为十进制5,参考第二幅图:5对应IDR图像中的片(I帧)

所以判断是否为I帧的算法为: (NALU类型 & 0001 1111) = 5 即 NALU类型 & 31 = 5

比如0x65 & 31 = 5

三种帧的说明


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

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

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

P帧的预测与重构:P帧是以I帧为参考帧,在I帧中找出P帧“某点”的预测值和运动矢量,取预测差值和运动矢量一起传送。在接收端根据运动矢量从I帧中找出P帧“某点”的预测值并与差值相加以得到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帧是双向差别帧,也就是B帧记录的是本帧与前后帧的差别(具体比较复杂,有4种情况,但我这样说简单些),换言之,要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,但是解码时CPU会比较累。

B帧的预测与重构
B帧以前面的I或P帧和后面的P帧为参考帧,“找出”B帧“某点”的预测值和两个运动矢量,并取预测差值和运动矢量传送。接收端根据运动矢量在两个参考帧中“找出(算出)”预测值并与差值求和,得到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帧,这样在相同码率下,可以提供更好的画质。

原文:https://blog.csdn.net/sjin_1314/article/details/40989173

https://blog.csdn.net/weixin_42462202/article/details/88184272
https://blog.csdn.net/weixin_42462202/article/details/88182605

你可能感兴趣的:(H264结构分析)