H264格式
目前视频中的H.264流行的NALU包装方式有两种,一种叫做annexB,一种叫做avcC。对于这两种格式,不同的厂商支持程度也不太一样,例如,Android硬解码MediaCodec只接受annexB格式的数据,而Apple的VideoToolBox,只支持avcC的格式。
(1)avcc格式也叫AVC1格式,MPEG-4格式,字节对齐,因此也叫Byte-Stream Format。用于mp4、flv、mkv等封装中。
(2)annexB格式也叫MPEG-2 transport stream format格式(ts格式),ElementaryStream格式。用于ts流中(以及使用ts作为切片的hls格式中即".ts"文件中),也是手机视频m3u8(HLS协议的格式)常用的方式
NALU的作用
NALU的最核心的用处就是起到一个承上启下的作用。我们知道,在通常情况下,H.264 码流只存放了原始的画面信息,而不包含其他信息,所以严格来说,H.264 码流和我们通常意义上的“视频”还是有一定差距的。比如,我们通常说的视频要包含音频,H.264 码流里就没有。除了音频之外,我们还需要存放其他辅助信息,比如视频的播放时长,每一帧的播放时间,帧率,画面是否旋转,等等非常多的信息。所以我们日常使用过程中,往往是把 H.264 码流插入到其他视频容器内,比如 mp4,flv等。而 NALU 的作用,就是很好的把 H.264 码流和上层的封装容器进行有效得分割,使得两者可以相互不干扰,相互独立。
RTP
大多情况下,NALU在网络发送时,会封装成RTP格式,有两种方式:
(1)单包模式:rtp payload仅由一个完整NALU组成,这种情况一般用于H264 NALU大小 小于MTU(Maximum Transmission Unit,最大传输单元)。SPS、PPS采用单包模式发送。
(2)分包模式:当H264 NALU 的长度超过MTU时, 就必须对NALU进行分片封包,也称为 Fragmentation Units。
H264之AnnexB
AnnexB格式也叫做MPEG-2 transport stream format格式(ts格式),用于TS流中,以及使用TS作为切片的HLS格式中
它的原理是通过在NALU前面添加一个叫Start Code(起始码)的东西,起始码的内容为三字节的0 0 1或者4字节的0 0 0 1 (其中起始码在NALU为SPS、PPS或NALU为AU的第一个NALU时使用4字节,其他情况使用3字节)
当我们读取一个 H264码流的时候,一旦遇到起始码,就认为一个新的 NALU 开始了。
不过在NALU前加入起始码会引入一个新的问题,因为原始码流中是可能出现和起始码一样的数据,这样就会导致错误的NALU分割。为了防止这种情况发生,AnnexB 引入了防竞争字节(Emulation Prevention Bytes)的概念
具体操作为:编码器编完一个NALU后,检查内部是否出现如下左侧的字节序列,如果存在,则在最后一个字节前插入一个新的字节0x03
解码器在NALU内部检测到防竞争字节后将0x03丢弃来恢复原始数据。
annexB格式下不同帧发送顺序,发送第一个I帧之前,至少要发送一次SPS/PPS。如果码流没有改变,则只发送一次SPS/PPS即可,不用每一个I帧之前都发送SPS/PPS。但是如果码流中间有变,比如分辨率、帧率或者其它编码参数有改变,则要重新发送SPS/PPS。
H264之AVCC
AVCC格式也叫AVC1格式,MPEG-4格式,常用于mp4/flv等封装中
它的原理是在NALU 前面添加固定字节(可能是1字节、2字节或4字节,其中4字节较常见),这几个字节组成一个整数(大端字节序)表示整个 NALU 的长度,在读取的时候,先把这个整数读出来(例如ffmpeg从extradata获取),拿到这个 NALU 的长度,再按照长度读取整个 NALU
AVCC header sequence or extradata
读取 NALULengthSizeMinusOne的值然后加 1 ,我们就得出了后续每个 NALU 前面表示NAL size(也就是上图紫色块length)的字节数,一般NALULengthSizeMinusOne 是 3,那么每个 NALU length就是 4 个字节,然后把这四个字节转成整数,就是这个 NALU 的长度。
学习文档:
【H264/AVC 句法和语义详解】(三):NALU详解二(EBSP、RBSP与SODB)
H264编码基本原理(一)
AnnexB和AVCC的区别
1、NALU的分割方式不同
annexB格式使用start code进行分割,start code为0x000001或0x00000001。
avcC格式使用NALU长度(固定字节,字节数由extradata中的信息给定)进行分割。
2、SPS/PPS的数据结构不同
annexB格式中,SPS/PPS存放在NALU中,以start code作为分隔符。这种格式下SPS/PPS通常放在关键帧之前。
avcC格式中,SPS/PPS存放在extradata中,不是放在NALU中。这种格式下SPS/PPS的存放位置和帧数据无关。例如普通模式下的mp4,SPS/PPS放在MOOV中,在帧数据后面。
3、适用场景不同
annexB格式通常用于实时的流格式,比如说传输流,通过无线传输的广播、DVD等。在这些格式中通常会周期性的重复SPS和PPS包,经常是在每一个关键帧之前。
avcC格式的一个优点是在开始配置解码器的时候可以跳到流的中间播放,这种格式通常用于可以被随机访问的多媒体数据,如存储在硬盘的文件。也因为这个特性,MP4、FLV、MKV通常用avcC格式来存储。(H.264流媒体协议格式中的Annex B格式和AVCC格式深度解析-CSDN博客)