版权声明:本文为博主原创文章,未经博主允许不得转载。 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. UITextView设置placeholder

    下面是我的代码,可以直接拿来用 #import <UIKit/UIKit.h> @interface CustomTextView : UITextView @property(nonat ...

  2. hibernate 主键生成方式

    1)assigned主键由外部程序负责生成,无需Hibernate参与. 2)hilo通过hi/lo 算法实现的主键生成机制,需要额外的数据库表保存主键生成历史状态. 3)seqhilo与hilo 类 ...

  3. SQL SERVER 2016研究三

    2016 SQL SEVER 全程加密程式 column encryption setting=Enabled; 重点:需要使用.Net Framework 4.6 新建一个程式如下: 1.创建链接数 ...

  4. 003-hive安装

    http://www.aboutyun.com/thread-6902-1-1.html http://www.aboutyun.com/thread-7374-1-1.html

  5. RN-ios模拟器上调出中文输入法

    react-native 项目:在ios模拟器上需要拼写汉字,步骤是, 1.在模拟器的设置-通用-语言与地区-iphone语言设置为:简体中文 2.模拟器的 Hardware-Keyboard-勾选下 ...

  6. K-means &K-medoids 聚类

    k-平均值算法对孤立点很敏感!因为具有特别大的值的对象可能显著地影响数据的分布. k-中心点(k-Medoids): 不采用簇中对象的平均值作为参照点, 而是选用簇中位置最中心的对象, 即中心点(me ...

  7. Django进阶Model篇—数据库操作(ORM)

    一.数据库配置 django 默认支持sqlite.mysql.oracle.postgresql数据库,像db2和sqlserver之类的数据库需要第三方的支持,具体详见https://docs.d ...

  8. (转)EOSIO开发(四)- nodeos、keosd与cleos

    前一篇文章介绍了EOSIO中钱包.账户与账户权限的概念,这一篇文章继续学习EOSIO系统的主要组件,包括nodeos.keosd以及cleos. 本文执行的命令都是基于Docker环境,请先下载Doc ...

  9. VS2010 正在创建“Debug\test2.unsuccessfulbuild”,因为已指定“AlwaysCreate”。

    问题一:VS2010  正在创建“Debug\test2.unsuccessfulbuild”,因为已指定“AlwaysCreate”. 方法解决: The relevant setting is i ...

  10. tp5 auth权限设置

    案例:把所需要的auth类放在一个公共的地方引用,我这里就只是放在了与application同级的extend里面的org所以我在公共控制器里面实例为use \org\Auth; 然后我再公共控制器里 ...