版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Romantic_Energy/article/details/50508332
本文需要读者对H.264流有一定的了解才可以理解2种格式差异。
    
    首先要理解的是没有标准的H.264基本流格式。文档中的确包含了一个Annex,特别是描述了一种可能的格式Annex B格式,但是这个并不是一个必须要求的格式。标准文档中指定了视频怎样编码成独立的包,但是这些包是怎样存储和传输的却是开放的。

一. Annex B
A.Network Abstraction Layer Units
    视频编码成的包叫做Network Abstraction Layer Units, 也简称为NALU、NAL,每个NALU包都可以被单独的解析和处理,每个NALU包的第一个字节包含了NALU类型,bit3-bit7包含的内容尤其重要(bit 0一定是off的,bit1-2指定了这个NALU是否被其他NALU引用)。
    NALU格式分为2类,VCL和non-VCL,总共有19种不同的NALU格式。

VCL, Video Coding Layer packets contain the actual visual information.  即视频编码后的数据
Non-VCL, contain metadata that may or may not be required to decode the video. 非视频数据,配置信息

一个单独的NALU包、或者甚至一个VCL NALU包都不意味着是一个独立的帧,一帧数据可以被分割成几个NALU,一个或多个NALU组成了一个Access Units(AU),AU包含了一个完整的帧。把帧分割成几个独立的NALU需要耗费许多CPU资源,所以分割帧数据并不经常使用。
    以下是所有定义了的NALU类型:

      Unspecified                                                    non-VCL
Coded slice of a non-IDR picture VCL
Coded slice data partition A VCL
Coded slice data partition B VCL
Coded slice data partition C VCL
Coded slice of an IDR picture VCL
Supplemental enhancement information (SEI) non-VCL
Sequence parameter set non-VCL
Picture parameter set non-VCL
Access unit delimiter non-VCL
End of sequence non-VCL
End of stream non-VCL
Filler data non-VCL
Sequence parameter set extension non-VCL
Prefix NAL unit non-VCL
Subset sequence parameter set non-VCL
Depth parameter set non-VCL
.. Reserved non-VCL
Coded slice of an auxiliary coded picture without partitioning non-VCL
Coded slice extension non-VCL
Coded slice extension for depth view components non-VCL
.. Reserved non-VCL
.. Unspecified non-VCL

有几种NALU格式的包包含了非常有用的信息。

    Sequence Parameter Set (SPS). This non-VCL NALU contains information required to configure the decoder such as profile, level, resolution, frame rate.
Picture Parameter Set (PPS). Similar to the SPS, this non-VCL contains information on entropy coding mode, slice groups, motion prediction and deblocking filters.
Instantaneous Decoder Refresh (IDR). This VCL NALU is a self contained image slice. That is, an IDR can be decoded and displayed without referencing any other NALU save SPS and PPS.
Access Unit Delimiter (AUD). An AUD is an optional NALU that can be use to delimit frames in an elementary stream. It is not required (unless otherwise stated by the container/protocol, like TS), and is often not included in order to save space, but it can be useful to finds the start of a frame without having to fully parse each NALU.

B. NALU Start Codes, NALU包开始码
    一个NALU包中的数据并不包含它的大小(长度)信息,因此不能简单的连接NALU包来建立一个流,因为你不知道一个包从哪里结束,另一个包从哪里开始。
    Annex B格式用开始码来解决这个问题,即给每个NALU加上前缀码:2个或者3个0x00,后面再加一个0x01, 如:0x000001或者0x00000001。
    4字节类型的开始码在在连续的数据传输中非常有用,因为用字节来对齐、分割流数据,比如:用连续的31个bit0后接一个bit1来分割流数据,是很容易的。
如果接下来的bit是0(因为每个NALU都以bit0开始),那么这就是一个NALU包数据的起始位置了。4字节类型的开始码通常只用于标识流中的随机访问点,
如SPS PPS AUD和IDR,然后其他地方都用3字节类型的开始码以减少数据量。

C. Emulation Prevention Bytes, 防竞争字节
    开始码能起作用是因为3字节的序列0x000000,0x000001,0x000002和0x000003(应该是所有的0x0000**)在non-VCL(原文是non-RBSP,译者修改)NALU包中是非法的,所以在构建ANLU包时,必须确保排除这些数值序列,这是由向每个这种类型的序列插入防竞争字节0x03实现的,那么插入防竞争字节后,0x000001变成了0x00000301。
    当解码的时候,查找和去除防竞争字节非常重要。因为防竞争字节可能出现在NALU包的任意位置,在文档中通常更方便的做法是假定它们已经被去除了,Raw Byte Sequence Payload原始字节序列负载 (RBSP)表示没有防竞争字节的数据序列(包)。

D. Example
    以下是一个完整的例子:

<pre><code>0x0000 |        0A AC
0x0010 | CA 3C
0x0020 | E8 8F
0x0030 | 4E 7F DF A5 8B EE A4 E9 B7 6A 6A
0x0040 | B9 0B 2E B5 0E E4 B8 A9
0x0050 | 5E FB E4 6A E9 E2
0x0060 | 9E 4D FF CE 7E B7 CE 2A E1 BE
0x0070 | BA F4 E6 9F DA D8 B1
0x0080 | F3 0C 0B 3C B3 9D BC EB C3 0E
0x0090 | CA EB 3F 3A FA B5 BF A8 6D
0x00A0 | C4 CE 9E 4E E6 4C C7 3E DE A1 0B
0x00B0 | D8 0B B6 B8 BC A9 EB FC 7A
0x00C0 | CA 6B B5 B7 D6 8C C5
0x00D0 | D8 A9 6F 4E DF E3 E2 B1 6B 6B
0x00E0 | BF 9F FB 2E A9 C4 A2 DF FA D9
0x00F0 | 1D 5A 1C D6 7C B6 6C
0x0100 | E6 4C AD BA C7 8E D0 F0 ED 8E F6
0x0110 | A6 A1 DB C8 AE E3 B6 E6 8D BC
0x0120 | A3 7F AF 4A 8A E2 7E 9F
0x0130 | DB D6 5E E1 4A C7 D6
0x0140 | FF C4 FD 9A D1 B2 FB DB A1 C2
0x0150 | F9 9B B2 3F 0C 8C DB A5 B2
0x0160 | 9D 7E 2F D0 E4 0A EF 2D
0x0170 | 3B 3B F5 2C B0 A6 F3 4B
0x0180 | 2F 1C 8F 3B C6 AA 1D D7 2A
0x0190 | 5E 2C D9 0A F5 F5 2C D1 FB 3F F0 4B E9
0x01A0 | DD CF C3 F3 D9 E5 4A
0x01B0 | 6C BC FE C1 9F E5 DB
0x01C0 | 5C 6B D8 D7 A8 A1 DC 9A
0x01D0 | 4F A5 C7 DE BE 6F AB
0x01E0 | 2E F3 D6 1A C2 D1 5D 6C DB 4A 7A E2 CB
0x01F0 | 0B B0 0B BE FC C0 BD 9D F5 F5 F8
0x0200 | A8 D6 B3 E9 BA E5 2C 7B F9 EA
0x0210 | 5A F9 A9 B1 6F 5B 1E 8D F4 CC
0x0220 | B2 6A A9 D0 B8 E2 E3 8B D1 C0 1C
0x0230 | CA B5 AC 3E F1 2C BD AB A8
0x0240 | A9 A4 8E 9C 8B DE F0 AE DB AF D6
0x0250 | F8 5E 9B B3 B3 B3 AC 6F A6 2F 3D
0x0260 | 3A CE FA 6C BB C5 4E F3</code>

这是一个完整的访问单元(AU),包括3个NALU包,如你所见,数据序列以开始码开始,后面接了一个SPS(SPS 以0x67开始),在SPS中,你可以看到有2个防竞争字节。没有这些字节那么非法的数据序列就会出现在这些位置。然后可以看到一个开始码后面接着一个PPS(PPS 以0x68开始),然后是一个最后的开始码,后面跟着一个IDR包。这是一个完整的H.264流,如果你把这些数据以16进制的方式保存到一个以.264为后缀名的文件中,可以把这些数据转换成以下图片:

Annex B格式通常用于实时的流格式,比如说传输流,通过无线传输的广播、DVD等。在这些格式中通常会周期性的重复SPS和PPS包,经常是在每一个关键帧之前,
因此据此建立解码器可以一个随机访问的点,这样就可以加入一个正在进行的流,及播放一个已经在传输的流。

二. AVCC
    另一个存储H.264流的方式是AVCC格式,在这种格式中,每一个NALU包都加上了一个指定其长度(NALU包大小)的前缀(in big endian format大端格式),这种格式的包非常容易解析,但是这种格式去掉了Annex B格式中的字节对齐特性,而且前缀可以是1、2或4字节,这让AVCC格式变得更复杂了,指定前缀字节数(1、2或4字节)的值保存在一个头部对象中(流开始的部分),这个头通常称为'extradata'或者'sequence header',它的基本格式如下:

bits
version ( always 0x01 )
avc profile ( sps[][] )
avc compatibility ( sps[][] )
avc level ( sps[][] )
reserved ( all bits on )
NALULengthSizeMinusOne // 这个值是(前缀长度-1),值如果是3,那前缀就是4,因为4-1=3
reserved ( all bits on )
number of SPS NALUs (usually )
repeated once per SPS:
SPS size
variable SPS NALU data
number of PPS NALUs (usually )
repeated once per PPS
PPS size
variable PPS NALU data

使用上面的例子,那么AVCC extradata看起来像是这样的:

0x0000 |    0A FF E1      0A AC
0x0010 | CA 3C
0x0020 | E8 8F

你会发现SPS和PPS被存储在了非NALU包中(out of band带外),即独立于基本流数据。这些数据的存储和传输是文件容器的任务,超出了本文的范畴。
注意:虽然AVCC格式不使用起始码,防竞争字节还是有的。

另外,extradata中有一个命名比较容易让人困惑的变量NALULengthSizeMinusOne,这个变量告诉我们用几个字节来存储NALU的长度(前缀:1、2或4),如果NALULengthSizeMinusOne是0,那么每个NALU使用一个字节的前缀来指定长度,那么每个NALU包的最大长度是255字节,这个明显太小了,这种方式对于存储一个完整的关键帧来说太小了。使用2个字节的前缀来指定长度,那么每个NALU包的最大长度是64K字节,这个对于我们的例子来说是足够了,但是限制还是比较大;3字节是比较完美的,但是因为一些原因没有被广泛支持;因此,4字节长度的前缀是目前使用最多的方式,也是这里我们使用的方式:

0x0000 |          4E 7F  DF  A5 8B
0x0010 | EE A4 E9 B7 6A 6A B9 0B 2E
0x0020 | B5 0E E4 B8 A9 5E FB
0x0030 | E4 6A E9 E2 9E 4D FF CE 7E
0x0040 | B7 CE 2A E1 BE BA F4
0x0050 | E6 9F DA D8 B1 F3 0C 0B 3C B3
0x0060 | 9D BC EB C3 0E CA EB
0x0070 | 3F 3A FA B5 BF A8 6D C4 CE 9E
0x0080 | 4E E6 4C C7 3E DE A1 0B D8 0B B6 B8 BC
0x0090 | A9 EB FC 7A CA 6B B5
0x00A0 | B7 D6 8C C5 D8 A9 6F
0x00B0 | 4E DF E3 E2 B1 6B 6B BF 9F FB 2E A9
0x00C0 | C4 A2 DF FA D9 1D 5A
0x00D0 | 1C D6 7C B6 6C E6 4C AD BA
0x00E0 | C7 8E D0 F0 ED 8E F6 A6 A1
0x00F0 | DB C8 AE E3 B6 E6 8D BC A3 7F AF 4A 8A
0x0100 | E2 7E 9F DB D6 5E
0x0110 | E1 4A C7 D6 FF C4 FD 9A D1
0x0120 | B2 FB DB A1 C2 F9 9B B2
0x0130 | 3F 0C 8C DB A5 B2 9D 7E 2F D0
0x0140 | E4 0A EF 2D 3B 3B F5 2C
0x0150 | B0 A6 F3 4B 2F 1C 8F 3B
0x0160 | C6 AA 1D D7 2A 5E 2C D9 0A F5 F5
0x0170 | 2C D1 FB 3F F0 4B E9 DD CF C3
0x0180 | F3 D9 E5 4A 6C
0x0190 | BC FE C1 9F E5 DB 5C 6B D8
0x01A0 | D7 A8 A1 DC 9A 4F A5 C7 DE BE
0x01B0 | 6F AB 2E F3 D6 1A C2
0x01C0 | D1 5D 6C DB 4A 7A E2 CB 0B B0 0B BE
0x01D0 | FC C0 BD 9D F5 F5 F8 A8 D6 B3 E9
0x01E0 | BA E5 2C 7B F9 EA 5A F9 A9 B1 6F 5B
0x01F0 | 1E 8D F4 CC B2 6A A9 D0
0x0200 | B8 E2 E3 8B D1 C0 1C CA B5 AC 3E
0x0210 | F1 2C BD AB A8 A9 A4 8E 9C 8B DE
0x0220 | F0 AE DB AF D6 F8 5E 9B B3 B3
0x0230 | B3 AC 6F A6 2F 3D 3A CE FA
0x0240 | 6C BB C5 4E F3

AVCC格式的一个优点是在开始配置解码器的时候可以跳到流的中间播放,这种格式通常用于可以被随机访问的多媒体数据,如存储在硬盘的文件。
也因为这个特性,MP4、MKV通常用AVCC格式来存储

H.264流媒体协议格式中的Annex B格式和AVCC格式深度解析的更多相关文章

  1. 视频基础知识:浅谈视频会议中H.264编码标准的技术发展

    浅谈视频会议中H.264编码标准的技术发展 浅谈视频会议中H.264编码标准的技术发展 数字视频技术广泛应用于通信.计算机.广播电视等领域,带来了会议电视.可视电话及数字电视.媒体存储等一系列应用,促 ...

  2. 【转】实现RTP协议的H.264视频传输系统

    1.  引言       随着信息产业的发展,人们对信息资源的要求已经逐渐由文字和图片过渡到音频和视频,并越来越强调获取资源的实时性和互动性.但人们又面临着另外一种不可避免的尴尬,就是在网络上看到生动 ...

  3. 基于RTP协议的H.264传输

    1.  引言        随 着信息产业的发展,人们对信息资源的要求已经逐渐由文字和图片过渡到音频和视频,并越来越强调获取资源的实时性和互动性.但人们又面临着另外一种不可避免 的尴尬,就是在网络上看 ...

  4. H.264 RTP 封包格式

    H.264 视频 RTP 负载格式 1. 网络抽象层单元类型 (NALU) NALU 头由一个字节组成, 它的语法如下: +---------------+      |0|1|2|3|4|5|6|7 ...

  5. H.264 RTPpayload 格式------ H.264 视频 RTP 负载格式

    H.264 RTPpayload 格式------ H.264 视频 RTP 负载格式 1. 网络抽象层单元类型 (NALU) NALU 头由一个字节组成, 它的语法如下: +------------ ...

  6. H.264 RTP PAYLOAD 格式

    H.264 视频 RTP 负载格式 1. 网络抽象层单元类型 (NALU) NALU 头由一个字节组成, 它的语法如下: +---------------+      |0|1|2|3|4|5|6|7 ...

  7. H.264 RTPpayload 格式------ H.264 视频 RTP 负载格式(包含AAC部分解析)

    H.264 RTPpayload 格式------ H.264 视频 RTP 负载格式 1. 网络抽象层单元类型 (NALU) NALU 头由一个字节组成, 它的语法如下: +------------ ...

  8. (转载)H.264码流的RTP封包说明

    H.264的NALU,RTP封包说明(转自牛人) 2010-06-30 16:28 H.264 RTP payload 格式 H.264 视频 RTP 负载格式 1. 网络抽象层单元类型 (NALU) ...

  9. 流媒体协议之RTSP详解20170922

    一.RTSP协议介绍 1.什么是rtsp? RTSP协议以客户服务器方式工作,,如:暂停/继续.后退.前进等.它是一个多媒体播放控制协议,用来使用户在播放从因特网下载的实时数据时能够进行控制, 因此 ...

随机推荐

  1. hdu1240/poj2225 BFS广搜的再理解

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/guodongxiaren/article/details/37756347 原题地址 pid=124 ...

  2. 20180409 Code First

    many people use DB First,Today I see Code First.  这部分,百度上面有更多详细的资料,虽然不明白Migrations内部的机制,但是还是可以记录一下 打 ...

  3. dxRibbonRadialMenu控件使用

    设计视图 双击dxRibbonRadialMenu1增加项目 增改显示文字 增加图标列表 代码很简单,从当前鼠标位置打开,屏蔽系统右键 procedure TForm1.cxMemo1ContextP ...

  4. 【PCA】周志华

    一.书籍

  5. vue.js 兄弟组件传值

    另:  在vue里,组件之间的作用域是独立的,父组件跟子组件之间的通讯可以通过prop属性来传参,但是在兄弟组件之间通讯就比较麻烦了,虽然可以使用事件监听的方式,但还是不如vuex专业.比如A组件要告 ...

  6. cookie、session和token

    https://zhuanlan.zhihu.com/p/25495290?utm_source=wechat_session&utm_medium=social 一.cookie 众所周知, ...

  7. Linux系统查看日志信息总结

    命令: cat tail -f #系统日志文件存放路径: /var/log/message #系统启动后的信息和错误日志 /var/log/secure #与安全相关的日志信息 /var/log/ma ...

  8. Ubuntu下orbbec mini 无法正常显示图像问题

    最近用orbbec的深度摄像头采集RGBD图像,Windows下一切OK.但是Ubuntu下出现了不少问题.总结一下 1.将设备插到USB,先确定电脑能否正常识别设备 Ubuntu下是不需要安装驱动的 ...

  9. cocos2d-x android工程接入第三方支付宝SDK

    1. 首先去支付宝官网下载开发者文档 2. 然后按着开发者文档将支付宝的sdk导入到你的工程中,并关联到工程中,步骤入下图: (1)将从支付宝官方网站获得的支付宝的sdk的jar包拷贝到工程中的lib ...

  10. 部署一个不依赖tomcat容器的应用

    一个task项目,应用里边都是一些定时任务.我和新入职的高开商定程序部署不依赖于tomcat. 计划赶不上变化,任务开发完成还没等上线呢,哥们要离职了.工作交接时大概说了一下上线怎么部署. 结果呢,当 ...