前面几篇文章主要介绍了YUV,RGB的像素处理以及简单介绍了一下JPEG的压缩原理。接下来开始介绍视频码流的解析代码。
一、什么是NALU
H264裸流由一个个NALU组成,它们的结构如下图所示。
所以这里有必要介绍一下NALU是什么
NALU (Network Abstraction Layer Unit) 翻译过来就是网络抽象层单元。在 H.264/AVC 视频编码标准中,所有的码流数据,最终都被封装成了一个一个的 NALU(Network Abstract Layer Unit)就是网络抽象层单元。
既然是视频流,那么NALU里面存放的必然有视频数据,除此之外,还有一些其他的信息,比如说时间戳,帧率,画面是否翻转等等信息。这些数据以每个NALU为一个单元,可以进行网络传输(推流),或者本地解码(播放)。
二、H264常用的封装形式
H264流行的封装形式有两种,分别为AnnexB和AVCC。对于这两种格式,与硬件编解码的支持厂家有关。比如Android硬解码只支持AnnexB,Apple的VideoBox只支持AVCC格式。本文先对AnnexB做出展开性讨论。
三、AnnexB封装格式浅析
在第一小节说了H264是由一个个NALU组成的,在AnnexB封装格式中,为了区分前后的NALU,每个NALU数据的头部都设置了起始码(Startcode)以便于分隔。数据的具体格式为0x00 00 01(占3个字节)或0x00 00 00 01(占4个字节)。下面来查看一下一段H264裸流的二进制文件
其中0x00 00 00 01就代表着起始码,后面的数据就是每个NALU里面的数据。每个NALU通过起始码来标记这个NALU的开始,嗯,就是这么简单。可能这时候有问题了,如果NALU数据里面也出现了0x00 00 01这种数据,该怎么区分呢。稍安勿躁,下一小节会继续解释。
四、防竞争字节
刚刚说了,如果在NALU数据中出现了0x00 00 01这种数据,会导致读取程序将一个NALU误分隔为多个NALU,为了防止这种情况发生,AnnexB引入了防竞争字节的概念。具体的实现如下:
0x 00 00 00 ====> 0x00 00 03 00
0x 00 00 01 ====> 0x00 00 03 01
0x 00 00 02 ====> 0x00 00 03 02 (0x000002作保留用,暂时也用不到)
0x 00 00 03 ====> 0x00 00 03 03 (避免原始数据中出现0x00 00 03,冲突)
也就是在0x00 00的后面插入一个03,这样就不会引起读取程序的误会了。不会再和起始码(0x00 00 01, 0x00 00 00 01)重复而发生冲突。
注意:在解包后进行解码时,要将防竞争字节去掉。
转载:https://blog.csdn.net/Stone831143/article/details/115487235