这张图的最上面是一串压缩后的视频帧序列, 我们取其中的一帧, 我们可以看到, 每一帧(或者说图像)都是由多个片组成, 每一个片都是由一个个宏块组成, 每一个宏块又可以分成多个子块, 这就是一个H264帧的结构.一个宏块由16x16的yuv数据组成。宏块作为H264编码的基本单位。
二.H264编码分层
NAL层:(Network Abstraction Layer,视频数据网络抽象层): 它的作用是H264只要在网络上传输,在传输的过程每个包以太网是1500字节,而H264的帧往往会大于1500字节,所以要进行拆包,将一个帧拆成多个包进行传输,所有的拆包或者组包都是通过NAL层去处理的。
VCL层:(Video Coding Layer,视频数据编码层): 对视频原始数据进行压缩
三.码流的基本概念
SODB:(String of Data Bits,原始数据比特流):由VCL层产生,数据长度不一定是8的倍数,所以处理起来比较麻烦
RBSP:(Raw Byte Sequence Payload,SODB+trailing bits,编码后的数据流):算法是在SODB最后一位补1,不按字节对齐补0,如果补齐0,不知道在哪里结束,所以补1,如果不够8位则按位补0
EBSP:(Encapsulate Byte Sequence Payload):生成编码后的数据流之后,我们还要在每个帧之前加一个起始位,需要开发者人为添加。起始位一般是十六进制的0001。但是在整个编码后的数据里,可能会出来连续的2个0x00。那这样就与起始位产生了冲突.那怎么处理了? H264规范里说明如果处理2个连续的0x00,就额外增加一个0x03 。这样就能预防压缩后的数据与起始位产生冲突
NALU: (NAL Header(1B)+EBSP).NALU就是在EBSP的基础上加1B的网络头.
四.NALU解析
NALU头结构:NALU类型(5bit)、重要性指示位(2bit)、禁止位(1bit):第1位为禁位,默认固定为0,如果接收到的为1,那么就需要丢弃该单元;第2-3位表示重要性,00表示最不重要,11表示最重要,我们可以在解码来不及的情况下舍弃一些不重要的单元;第4-8位用来表示NALU的类型
NALU类型:1~12由H.264使用,24~31由H.264以外的应用使用:类型图如下:
切片与宏块的关系:每个切片包括切片头和切片数据,每个切片数据包括了很多宏块。每个宏块包括了宏块类型、宏块预测、残差效果:
切片头:包含了一组片的信息,比如片的数量,顺序等等
五.H264码流分层结构图
注:I、B、P各帧是根据压缩算法的需要,是人为定义的,它们都是实实在在的物理帧。一般来说,I帧的压缩率是7(跟JPG差不多),P帧是20,B帧可以达到50。可见使用B帧能节省大量空间,节省出来的空间可以用来保存多一些I帧,这样在相同码率下,可以提供更好的画质。