H264编码压缩的具体实现原理以及压缩后产生的码流分析

目录

 

介绍

一、的解释(I帧,P帧和B帧)

二、GOF(Group of Frame)一组帧 就是一个I帧到下一个I帧、也可以叫一个序列

三、SPS/PPS实际上就是存储GOP的参数

四、片、宏块

五、h264的分层

六、码流的基本概念

七、码流单元(NAL)的基本组成

八、NALU流数据的详细解析


介绍:

H264编码是目前最流行的一种视频压缩技术,学习之前,首先要了解为什么视频需要进行压缩,怎么压缩,其实视频的本质就是有一连串的图片组成的,视频的每一祯就是一张图片,如果不做任何的其他的处理,按照现在的像素来算,一张高清图片算它8M左右,一个10分钟的视频,假如帧率是一秒25帧,那么它的大小就是10*60*25*8 = 120000M,这个大小是很可怕的,所以需要对视频进行压缩。

如果我们详细分析一下,会发现其实一段视频里面,短时间内,画面变化是很小的,但是我们如果把每一祯的图片都保存下来,其实重复率是很高的,这就很浪费空间了,所以视频压缩技术就是这么来的。一段时间内相似度很高的一组画面的所有图片,只记录一张完整的,其他的图片,只保存不同部分的像素,这叫帧间压缩技术

 在H264协议里定义了三种帧,完整的一张图片叫I帧,参考之前的I帧生成的只包含差异部分编码的帧叫P帧,还有一种参考前后的帧编码的帧叫B帧。

H264还包括帧内压缩, 帧内(Intraframe)压缩也称为空间压缩(Spatial compression)。当压缩一帧图像时,仅考虑本帧的数据而不考虑相邻帧之间的冗余信息,这实际上与静态图像压缩类似。帧内一般采用有损压缩算法, 由于帧内压缩是编码一个完整的图像,所以可以独立的解码、显示。帧内压缩一般达不到很高的压缩,跟编码jpeg差不多。  

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

视频数据进行压缩后,产生的数据叫码流

由上面的压缩技术,我们可以延伸出下面一系列的概念:

一、帧的解释(I帧,P帧和B帧)

视频编码有三个帧,分别是I帧,P帧和B帧

  • I帧代表关键帧,存储的是完整的一张图片,也就是如果5张图片为一组,那么这5张图片中,只存储第一张完整的图片

I帧特点:

1)它是一个全帧压缩编码帧。它将全帧图像信息进行JPEG压缩编码及传输;

2)解码时仅用I帧的数据就可重构完整图像;

3)I帧描述了图像背景和运动主体的详情;

4)I帧不需要参考其他画面而生成;

5)I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量);

6)I帧是帧组GOP的基础帧(第一帧),在一组中只有一个I帧;

7)I帧不需要考虑运动矢量;

8)I帧所占数据的信息量比较大。

  • P帧代表向前参考帧,保存的是跟前面一张图片的不同数据,第5张参考第四张,第6参考第5

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帧是双向差别帧,也就是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帧,这样在相同码率下,可以提供更好的画质。

        如果在泛娱乐的直播中,可以接受一定度的延时,需要比较高的压缩比就可以使用B帧.

        如果我们在实时互动的直播,我们需要提高时效性,这时就不能使用B帧了.

二、GOF(Group of Frame)一组帧 就是一个I帧到下一个I帧.这一组的数据.包括B帧/P帧.我们称为GOF(GOP),也可以叫一个序列

在H264中图像以序列为单位进行组织,一个序列是一段图像编码后的数据流,以I帧开始,到下一个I帧结束。

一个序列就是一段内容差异不太大的图像编码后生成的一串数据流。当运动变化比较少时,一个序列可以很长,因为运动变化少就代表图像画面的内容变动很小,所 以就可以编一个I帧,然后一直P帧、B帧了。当运动变化多时,可能一个序列就比较短了,比如就包含一个I帧和3、4个P帧。

三、SPS/PPS实际上就是存储GOP的参数.

SPS: (Sequence Parameter Set,序列参数集)存放帧数,参考帧数目,解码图像尺寸,帧场编码模式选择标识等.

PPS:(Picture Parameter Set,图像参数集).存放熵编码模式选择标识,片组数目,初始量化参数和去方块滤波系数调整标识等.(与图像相关的信息) 大家只要记住,在一组帧之前我们首先收到的是SPS/PPS数据.如果没有这组参数的话,我们是无法解码.

四、片、宏块

上面说到一组视频中,帧的分类包括I帧,B帧,P帧。然后把每一帧分成一个片或者多个片,每个片又包括片头和片数据部分。每个片又分成一个宏块或者多个宏块,每个宏块又分成多个子块,宏块的类型包括宏块预测和宏块残差值,一个宏块是由16*16的YUV数据组成

I祯只会包含I宏块:

P祯会包含I或者P宏块

B祯只会包含B或者I宏块

组成架构图:

片:

片是由宏块组成,片的目的是为了限制无码的扩散和传输,是编码片之间是相互独立的

宏块:

I宏块利用当前从当前片中已经解码的像素作为参考,进行祯内预测

p宏块利用前面已经编码的像素进行祯内预测

B宏块则利用双向的图像进行参考(前一祯和后一祯),进行祯内预测

宏块是h264编码后的最小的基本单位

五、h264的分层,分为两层

h264分为网络数据传输抽象层和数据编码层

1、网络数据传输抽象层,主要做的事情就是对视频进行传输前的拆包,组包

2、VCL层:对视频原始数据进行压缩

六、码流的基本概念

视频数据进行压缩后,产生的数据叫码流

SODB,原始数据比特流,长度不一定是8的倍数,是由VCL层产生的,因为是非8的倍数,所以处理起来比较麻烦。

RBSP、是在sodb最后一位补1,不按字节对齐补0,以1为结束标志。

VCL层对数据进行压缩后,就会产生码流数据:SODB:(String of Data Bits,原始数据比特流),长度不一定是8的倍数.因为非8的倍数所以处理比较麻烦.

  • SODB:(String of Data Bits,原始数据比特流),长度不一定是8的倍数.它是由VCL层产生的.因为非8的倍数所以处理比较麻烦.
  • RBSP:(Raw Byte Sequence Payload,SODB+trailing bits).算法是在SODB最后一位补1.不按字节对齐补0. 如果补齐0,不知道在哪里结束.所以补1.如果不够8位则按位补0.

RBSP、是在sodb最后一位补1,不按字节对齐补0,以1为结束标志。

  • EBSP:(Encapsulate Byte Sequence Payload).就是生成压缩流之后,我们还要在每个帧之前加一个起始位.起始位一般是十六进制的0001.但是在整个编码后的数据里,可能会出来连续的2个0x00.那这样就与起始位产生了冲突.那怎么处理了? H264规范里说明如果处理2个连续的0x00,就额外增加一个0x03 .这样就能预防压缩后的数据与起始位产生冲突.

每个NAL(流单元)前有一个起始码 0x00 00 01(或者0x00 00 00 01),解码器检测每个起始码,作为一个NAL的起始标识,当检测到下一个起始码时,当前NAL结束。

同时H.264规定,当检测到0x00 00 01时,也可以表征当前NAL的结束。那么NAL中数据出现0x000001或0x000000时怎么办?H.264引入了防止竞争机制,如果编码器检测到NAL数据存在0x000001或0x000000时,编码器会在最后个字节前插入一个新的字节0x03,这样:

解码器检测到0x000003时,把03抛弃,恢复原始数据(脱壳操作)。解码器在解码时,首先逐个字节读取NAL的数据,统计NAL的长度,然后再开始解码。

  • NALU: NAL Header(1B)+EBSP.NALU就是在EBSP的基础上加1B的网络头.

NALU就是编码后产生的一个一个的码流单元

七、码流单元(NAL)的基本组成

八、NALU流数据的详细解析

     

NALU = NAL Header +NAL Body

h.264 码流在网络中传输实际就是以NALU的形式进行传输的,每个NALU由一个字节的Header和RBSP组成

一、NAL header解析

NAL Header 为一个字节(8位)

第一位:F

第1-2位:NRI,表示当前数据的重要性,000最不重要,111最重要,当数据处理不过来的时候,有可能会丢掉低的数据

第3-7位:流类型数据

发布了79 篇原创文章 · 获赞 42 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/s12117719679/article/details/102368953