zl程序教程

您现在的位置是:首页 >  其它

当前栏目

H264码流之AnnexB和AVCC

H264 码流
2023-06-13 09:13:01 时间

引言

H264的主要目标是实现高的视频压缩比和提供良好的网络亲和性(可适用于各种网络传输),因此在功能层面上划分为视频编码层VCL和网络提取层NAL两层

其中预测(帧内预测和帧间预测)、DCT、量化、编码和切片等步骤都属于VCL,VCL最终会被包装为NAL

NAL由一系列NAL Unit组成

不过接下来并不对NALU进行展开,而是关注另一个问题,即:在H264码流中是如何将NALU进行分割的

要搞清楚这点,就需要了解目前H264主流的码流组织方式AnnexB和AVCC两种格式,其中Android的硬解码MediaCodec只支持AnnexB格式的数据,而Apple的VideoToolBox只支持AVCC

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

0x00   => 0x00   
0x00   => 0x00   
0x00   => 0x00   
0x00   => 0x00   

解码器在NALU内部检测到防竞争字节后将0x03丢弃来恢复原始数据

AVCC

AVCC格式也叫AVC1格式,MPEG-4格式,常用于mp4/flv等封装中

它的原理是在NALU 前面添加固定字节(可能是1字节、2字节或4字节,其中4字节较常见),这几个字节组成一个整数(大端字节序)表示整个 NALU 的长度,在读取的时候,先把这个整数读出来(例如ffmpeg从extradata获取),拿到这个 NALU 的长度,再按照长度读取整个 NALU

AVCC header sequence or extradata

按位读取
8 version ( always 0x01 ) 
8 avc profile ( sps[0][1] ) 
8 avc compatibility ( sps[0][2] ) 
8 avc level ( sps[0][3] ) 
6 reserved ( all bits on ) 
2 NALULengthSizeMinusOne // 每个NALU数据长度所占byte-1
3 reserved ( all bits on ) 
5 number of SPS NALUs (usually 1) 
        repeated once per SPS: 
16 SPS size 
        variable SPS NALU data 
8 number of PPS NALUs (usually 1) 
        repeated once per PPS 
16 PPS size 
        variable PPS NALU data

读取 NALULengthSizeMinusOne的值然后加 1 ,我们就得出了后续每个 NALU 前面表示NAL size(也就是上图紫色块length)的字节数,一般NALULengthSizeMinusOne 是 3,那么每个 NALU length就是 4 个字节,然后把这四个字节转成整数,就是这个 NALU 的长度

参考

1.【ISO-14496-10】

http://www.staroceans.org/e-book/ISO-14496-10.pdf

2.【H264编码格式整理】

https://zhuanlan.zhihu.com/p/71928833

3.【逐字节详解H.264 AVCC header】

https://www.jianshu.com/p/4f95617f30d0

~~END~~

技术交流欢迎扫码添加我的微信:wxid_alaiye