音视频开发-H264数据组成

H264

H264结构中,一个视频图像编码后的数据叫做一,一帧由一个片(slice)或多个片组成,一个由一个或多个宏块(MB)组成,一个宏块由16x16的yuv数据组成。宏块作为H264编码的基本单位。

一个宏块由一个16×16亮度像素和附加的一个8×8 Cb和一个8×8 Cr彩色像素块组成,我们常见的YUV格式I420

SODB(数据比特串) 最原始的编码数据,即VCL数据;

RBSP(原始字节序列载荷)SODB的后面填加了结尾比特(RBSP trailing bits 一个bit“1”)若干比特“0”,以便字节对齐;

EBSP( 扩展字节序列载荷)RBSP基础上填加了仿校验字节(0X03)它的原因是:在 NALU 加到Annexb上时,需要添加每组NALU之前的开始码StartCodePrefix(0x00000001 or 0x000001),如果该NALU对应的slice一帧的开始则用4位字节表示,0x00000001,否则用3位字节表示0x000001(是一帧的一部分)。另外,为了使NALU主体中不包括与开始码相冲突的,在编码时,每遇到两个字节连续为0,就插入一个字节的0x03。解码时将0x03去掉。也称为脱壳操作

注: 0x00表示16进制2位,则2进制的八位(8bit = 1byte)。即一个字节。所以0x00 00 00 01是4位字节,0x00 00 01是3位字节。

数据构成 NAL

NAL (Network Abstract Layer), 即网络抽象层。
一般来说编码器编出的首帧数据为PPSSPS,接着为I帧,然后是P帧
在这里插入图片描述
在这里插入图片描述
编码器将每个NAL各自独立、完整地放入一个分组,因为分组都有头部,解码器可以方便地检测出NAL的分界,并依次取出NAL进行解码。

起始码、结束码

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

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

0x000000>0x00000300
0x000001>0x00000301
0x000002>0x00000302
0x000003>0x00000303

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

网络传输结构 NALU

H264在网络传输的是NALUNALU的结构是:NAL头+RBSP,实际传输中的数据流如图所示:
在这里插入图片描述
NALU头用来标识后面的RBSP什么类型的数据,是否会被其他帧参考以及网络传输是否有错误。

NAL Header

NALU头结构
长度:1byte(1字节) = 8位
forbidden_bit(1bit) + nal_reference_bit(2bit) + nal_unit_type(5bit)

  1. forbidden_bit:禁止位,初始为0,当网络发现NAL单元有比特错误时可设置该比特为1,以便接收方纠错或丢掉该单元。
  2. nal_reference_bit:nal重要性指示,标志该NAL单元的重要性,值越大,越重要,解码器在解码处理不过来的时候,可以丢掉重要性为0的NALU

例如: 0x65 表示关键帧IDR

0 11 00101
禁止位 = 0
相关性 = 11
NAL类型 = 5

这里以16进制显示 2^4=16,4位,即0110 = 60101 = 5
最后数据为0x65
即一个起始码0x00000001 + 0x65 + RBSP
0x000001的开头一般是当一帧数据比较大时,需要拆分为几个子段,子段的开头就是0x000001开头的,一帧的开头就是3000x00000001 (4位字节)

nal_unit_type

NAL类型

nal_reference_bit

0

未使用

0

1

非IDR的片

此片属于参考帧,则不等于0,

不属于参考帧,则等与0

2

片数据A分区

同上

3

片数据B分区

同上

4

片数据C分区

同上

5

IDR图像的片

6

6

补充增强信息单元(SEI)

0

7

序列参数集

非0

8

图像参数集

非0

9

分界符

0

10

序列结束

0

11

码流结束

0

12

填充

0

13..23

保留

0

24..31

不保留

0

在这里插入图片描述
所谓参考帧,就是在其他帧解码时需要参照的帧。比如一个I帧可能被一个或多个B帧参考,一个B帧可能被某个P帧参考。

IDRI帧是非常重要的,他一丢,那么这个序列的所有帧都没办法解码了

序列参数集(SPS)图像参数集(PPS)也很重要,没有序列参数集(SPS),这个序列的帧就没法解;
没有图像参数集(PPS),那用到这个图像参数集(PPS)的帧都没法解。

NALU顺序

H.264/AVC标准对送到解码器的NAL单元顺序是有严格要求的,如果NAL单元的顺序是混乱的,必须将其重新依照规范组织后送入解码器,否则解码器不能够正确解码。

  1. 序列参数集SPS

    必须在传送所有以此参数集为参考的其他NAL单元之前传送,不过允许这些NAL单元中间出现重复的序列参数集NAL单元。

    所谓重复的详细解释为:序列参数集NAL单元都有其专门的标识,如果两个序列参数集NAL单元的标识相同,就可以认为后一个只不过是前一个的拷贝,而非新的序列参数集。

  2. 图像参数集PPS

    必须在所有以此参数集为参考的其他NAL单元之前传送,不过允许这些NAL单元中间出现重复的图像参数集NAL单元,这一点与上述的序列参数集NAL单元是相同的。

  3. 不同基本编码图像中的片段(slice)单元和数据划分片段(data partition)单元在顺序上不可以相互交叉,即不允许属于某一基本编码图像的一系列片段(slice)单元和数据划分片段(data partition)单元中忽然出现另一个基本编码图像的片段(slice)单元片段和数据划分片段(data partition)单元。

  4. 参考图像的影响:如果一幅图像P2以另一幅图像P1为参考,则属于P2的所有片段(slice)单元和数据划分片段(data partition)单元必须在属于P1的片段和数据划分片段之后,无论是基本编码图像还是冗余编码图像都必须遵守这个规则。

  5. 基本编码图像的所有片段(slice)单元和数据划分片段(data partition)单元必须在属于相应冗余编码图像的片段(slice)单元和数据划分片段(data partition)单元之前。

  6. 如果数据流中出现了连续的无参考基本编码图像,则图像序号小的在前面。

  7. 如果 arbitrary_slice_order_allowed_flag 置为1,一个基本编码图像中的片段(slice)单元和数据划分片段(data partition)单元的顺序是任意的,如果 arbitrary_slice_order_allowed_flag 置为零,则要按照片段中第一个宏块的位置来确定片段的顺序,若使用数据划分,则A类数据划分片段在B类数据划分片段之前,B类数据划分片段在C类数据划分片段之前,而且对应不同片段的数据划分片段不能相互交叉,也不能与没有数据划分的片段相互交叉。

  8. 如果存在SEI(补充增强信息)单元的话,它必须在它所对应的基本编码图像的片段(slice)单元和数据划分片段(data partition)单元之前,并同时必须紧接在上一个基本编码图像的所有片段(slice)单元和数据划分片段(data partition)单元后边。假如 SEI 属于多个基本编码图像,其顺序仅以第一个基本编码图像为参照。

  9. 如果存在图像分割符的话,它必须在所有 SEI 单元基本编码图像的所有片段slice)单元和数据划分片段(data partition)单元之前,并且紧接着上一个基本编码图像那些NAL单元

  10. 如果存在序列结束符,且序列结束符后还有图像,则该图像必须是IDR(即时解码器刷新)图像。序列结束符的位置应当在属于这个IDR图像的分割符、SEI 单元等数据之前,且紧接着前面那些图像的NAL单元。如果序列结束符后没有图像了,那么它的就在比特流中所有图像数据之后。

  11. 流结束符在比特流中的最后。

H264的官方文档 :http://read.pudn.com/downloads208/sourcecode/multimedia/981579/H.264%E5%AE%98%E6%96%B9%E4%B8%AD%E6%96%87%E7%89%88.pdf

参考自文章:
https://blog.csdn.net/yuanchunsi/article/details/73194569
https://blog.csdn.net/yangzhongxuan/article/details/8003494

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值