http://wmnmtm.blog.163.com/blog/static/382457142011920102618122/
实际应用中,码流中一般不会出现复杂的情况,所以可以直接判断 slice_type 是否等于 2 或 7 就可以了。
H.264的NALU,RTP封包说明(转自牛人)
H.264 RTP payload 格式
H.264 视频 RTP 负载格式
1. 网络抽象层单元类型 (NALU)
NALU 头由一个字节组成, 它的语法如下:
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+
F: 1 个比特.
forbidden_zero_bit. 在 H.264 规范中规定了这一位必须为 0.
NRI: 2 个比特.
nal_ref_idc. 取 00 ~ 11, 似乎指示这个 NALU 的重要性, 如 00 的 NALU 解码器可以丢弃它而不影响图像的回放. 不过一般情况下不太关心
这个属性.
Type: 5 个比特.
nal_unit_type. 这个 NALU 单元的类型. 简述如下:
0 没有定义
1-23 NAL单元 单个 NAL 单元包.
24 STAP-A 单一时间的组合包
25 STAP-B 单一时间的组合包
26 MTAP16 多个时间的组合包
27 MTAP24 多个时间的组合包
28 FU-A 分片的单元
29 FU-B 分片的单元
30-31 没有定义
2. 打包模式
下面是 RFC 3550 中规定的 RTP 头的结构.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|X| CC |M| PT | sequence number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| synchronization source (SSRC) identifier |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
| contributing source (CSRC) identifiers |
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
负载类型 Payload type (PT): 7 bits
序列号 Sequence number (SN): 16 bits
时间戳 Timestamp: 32 bits
H.264 Payload 格式定义了三种不同的基本的负载(Payload)结构. 接收端可能通过 RTP Payload
的第一个字节来识别它们. 这一个字节类似 NALU 头的格式, 而这个头结构的 NAL 单元类型字段
则指出了代表的是哪一种结构,
这个字节的结构如下, 可以看出它和 H.264 的 NALU 头结构是一样的.
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+
字段 Type: 这个 RTP payload 中 NAL 单元的类型. 这个字段和 H.264 中类型字段的区别是, 当 type
的值为 24 ~ 31 表示这是一个特别格式的 NAL 单元, 而 H.264 中, 只取 1~23 是有效的值.
24 STAP-A 单一时间的组合包
25 STAP-B 单一时间的组合包
26 MTAP16 多个时间的组合包
27 MTAP24 多个时间的组合包
28 FU-A 分片的单元
29 FU-B 分片的单元
30-31 没有定义
可能的结构类型分别有:
1. 单一 NAL 单元模式
即一个 RTP 包仅由一个完整的 NALU 组成. 这种情况下 RTP NAL 头类型字段和原始的 H.264的
NALU 头类型字段是一样的.
2. 组合封包模式
即可能是由多个 NAL 单元组成一个 RTP 包. 分别有4种组合方式: STAP-A, STAP-B, MTAP16, MTAP24.
那么这里的类型值分别是 24, 25, 26 以及 27.
3. 分片封包模式
用于把一个 NALU 单元封装成多个 RTP 包. 存在两种类型 FU-A 和 FU-B. 类型值分别是 28 和 29.
2.1 单一 NAL 单元模式
对于 NALU 的长度小于 MTU 大小的包, 一般采用单一 NAL 单元模式.
对于一个原始的 H.264 NALU 单元常由 [Start Co
NALU 单元的开始, 必须是 "00 00 00 01" 或 "00 00 01", NALU 头仅一个字节, 其后都是 NALU 单元内容.
打包时去除 "00 00 01" 或 "00 00 00 01" 的开始码, 把其他数据封包的 RTP 包即可.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|F|NRI| type | |
+-+-+-+-+-+-+-+-+ |
| |
| Bytes 2..n of a Single NAL unit |
| |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| :...OPTIONAL RTP padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
如有一个 H.264 的 NALU 是这样的:
[00 00 00 01 67 42 A0 1E 23 56 0E 2F ... ]
这是一个序列参数集 NAL 单元. [00 00 00 01] 是四个字节的开始码, 67 是 NALU 头, 42 开始的数据是 NALU 内容.
封装成 RTP 包将如下:
[ RTP Header ] [ 67 42 A0 1E 23 56 0E 2F ]
即只要去掉 4 个字节的开始码就可以了.
2.2 组合封包模式
其次, 当 NALU 的长度特别小时, 可以把几个 NALU 单元封在一个 RTP 包中.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RTP Header |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|STAP-A NAL HDR | NALU 1 Size | NALU 1 HDR |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NALU 1 Da
: :
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | NALU 2 Size | NALU 2 HDR |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NALU 2 Da
: :
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| :...OPTIONAL RTP padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2.3 Fragmentation Units (FUs).
而当 NALU 的长度超过 MTU 时, 就必须对 NALU 单元进行分片封包. 也称为 Fragmentation Units (FUs).
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| FU indicator | FU header | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| |
| FU payload |
| |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| :...OPTIONAL RTP padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 14. RTP payload format for FU-A
The FU indicator octet has the following format:
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+
The FU header has the following format:
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|S|E|R| Type |
+---------------+
3. SDP 参数
下面描述了如何在 SDP 中表示一个 H.264 流:
. "m=" 行中的媒体名必须是 "video"
. "a=rtpmap" 行中的编码名称必须是 "H264".
. "a=rtpmap" 行中的时钟频率必须是 90000.
. 其他参数都包括在 "a=fmtp" 行中.
如:
m=video 49170 RTP/AVP 98
a=rtpmap:98 H264/90000
a=fmtp:98 pro
下面介绍一些常用的参数.
3.1 packetization-mode:
表示支持的封包模式.
当 packetization-mode 的值为 0 时或不存在时, 必须使用单一 NALU 单元模式.
当 packetization-mode 的值为 1 时必须使用非交错(non-interleaved)封包模式.
当 packetization-mode 的值为 2 时必须使用交错(interleaved)封包模式.
这个参数不可以取其他的值.
3.2 sprop-parameter-sets:
这个参数可以用于传输 H.264 的序列参数集和图像参数 NAL 单元. 这个参数的值采用 Base64 进行编码. 不同的参数集间用","号隔开.
3.3 pro
这个参数用于指示 H.264 流的 pro
三个字节表示 H.264 的 Pro
3.4 max-mbps:
这个参数的值是一个整型, 指出了每一秒最大的宏块处理速度.
【转】 H264关于RTP协议的实现
完整的C/S架构的基于RTP/RTCP的H.264视频传输方案。此方案中,在服务器端和客户端分别进行了功能模块设计 。服务器端 :RTP封装模块主要是对H.264码流进行打包封装;RTCP分析模块负责产牛和发送RTCP包并分析接收到的RTCP包;QoS反馈控制模块则根据RR报文反馈信息动态的对发送速率进行调整;发送缓冲模块则设置端口发送RTP、RTCP包。客户端 :RTP模块对接收到的RTP包进行解析判断;RTCP模块根据SR报文统计关键信息,产牛并发送RR包。然后,在VC++6.0下用Socket编程,完成基于RTP/UDP/IP的H.264视频传输,并在局域网内运行较好。
基于RTP/UDP/lP的H.264视频传输结构设计
对于H.264视频的实时传输应用来说,TCP的重传机制引入的时延和抖动是无法容忍的,因此我们采用UDP传输协议。但是UDP协议本身是面向无连接的,不能提供质量保证。而基于UDP之上的高层协议RTP/RTCP可以一起提供流量控制和拥塞控制 服务。图给出了基于RTP/UDP/IP的H.264视频传输的框架。
H.264视频流的RTP封装策略
从图4—1可以看出,H.264视频数据首先经RTP进行封装 ,打包成适合网络传输的数据包才能进行传输。所以,如何设计合适的RTP封装策略对H.264视频数据进行封装是十分重要的。一般来说,在H.264中,RTP封装应该遵循几个设计原则:
1、较低的开销,因此MTU的尺寸应该限制在100—64K字节范围内。
2、易于区分分组的重要性,而不必对分组内的数据解码。
3、应能检测到数据的类型,而不需解码整个数据流,并能根据编码流之间的相关性丢弃无用数据,如网关应能检测A型分割的丢失,并能丢弃相应的B型和C型分割。
4、应支持将一个NALU拆分为若干个RTP包:不同大小的输入图片决定了NALU的长度可能会大于MTU,只有拆分后才会避免IP层在传输时出现分片。
5、支持将多个NALU汇集在一个RTP分组中,即在一个RTP包中传输超过一个NALU,当多个图片的编码输出小于M1IU时就考虑此模式,以提高网络传输效率。
RTP载荷封装设计
本文的网络传输是基于IP协议,所以最大传输单元(MTU )最大为1500字节,在使用IP/UDP/RTP的协议层次结构的时候,这其中包括至少20字节的IP头 ,8字节的UDP头 ,以及12字节的RTP头 。这样,头信息至少要占用40个字节,那么RTP载荷的最大尺寸为1460字节。
一方面,如果每个IP分组都填满1500字节,那么协议头的开销为2.7%,如果RTP载荷的长度为730字节,协议头的开销仍达到5.3%,而假设 RTP载荷的长度不到40字节,那么将有50%的开销用于头部,这将对网络造成严重资源浪费。另一方面,如果将要封装进RTP载荷的数据大于1460字 节,并且我们没有在应用层数据装载迸RTP包之前进行载荷分割 ,将会产生大于MTU的包。在IP层其将会被分割成几个小于MTU尺寸的包 , 这样将会无法检测数据是否丢失。因为IP和UDP协议都没有提供分组到达的检测,如果分割后第一个包成功接收而后续的包丢失,由于只有第一个包中包含有完 整的RTP头信息,而RTP头中没有关于载荷长度的标识,因此判断不出该RTP包是否有分割丢失,只能认为完整的接收了。并且在IP层的分割无法在应用层 实现保护从而降低了非平等包含方案的效果。由于UDP数据分组小于64K字节,而且一个片的长度对某些应用场合来说有点太小,所以应用层的打包 也是RTP打包机制的一个必要部分。最新的RFC3984标准中提供了针对H.246媒体流的RTP负载格式,主要有三种:
单个NAL单元分组、聚合分组、片分组。
NAL单元单一打包
将一个NAL单元封装进一个包中,也就是说RTP负载中只包含一个NAL单元,NAL头部兼作RTP头部。RTP头部类型即NAL单元类型1-23,如下图所示:
NAL单元的重组
此分组类型用于将多个NAL单元聚合在一个RTP分组 中。一些H.264的NAL单元的大小,如SEI NAL单元 、参数集等都非常小,有些只有几个字节,因此应该把它们组合到一个RTP包中,将会有利于减小头标(RTP/UDP/IP)的开销。目前存在着两种类型聚合分组:
NAL单元的分割
将一个NAL单元分割,使用多个RTP分组 进行传输。共有两个类型FU—A和FU—B,单元类型中分别为28和29。根据IP层MTU的大小,对大尺寸的NALU必须要进行分割,可以在分别在两个层次上进行分割:
1)视频编码层VCL上的分割
为了适应网络MTU的尺寸,可以使用编码器来选择编码Slice NALU 的大小,从而使其提供较好的性能。一般是对编码Slice的大小进行调整,使其小于1460字节 ,以免IP层的分割。
2)网络提取层NAL上的分割
在网络提取层上对NALU的分割主要是采用分片单元方案 ,H.264标准中提出了分割机制,可以使NAL单元的尺寸小于1460字节。注意:此方式是针对同一个NAL单元进行分割的 ,不适用于聚合分组。一个NAL单元采用分割分组后,每个RTP分组序列号依次递增l,RTP时间戳相同且惟一 。NAL单元的分割是RTP打包机制的一个重要环节,总结其分割机制主要有如下几个特点:
①分割NALU时,是以RTP次序号升序进行 传输。在序列号不循环的前提下,属于前一帧图像的所有图像片包以及A/B/C数据分割包的序列号要小于后帧图像中的图像片及数据分割包的序列号。
②一个符号机制来标记一个分割的NALU是第一个还是最后一个NAL单元。
3.存在另外一个符号机制用来检测是否有丢失的分块。
④辅助增强信息包和头信息包可以任意时间发送。
⑤同一帧图像中的图像片可以以任意顺序发送,但是对于低时延要求的网络系统,最好是以他们原始的编码顺序来发送。
1)单一时间聚合分组 (STAP):包括单一时间聚合分组A(STAP—A)和单一时间聚合分组B(STAP—B),按时间戳进行组合,他们的NAL单元具有相同的时间戳,一般用于低延迟环境。STAP—ASTAP—B的单元类型分别为24和25。
2)多时间聚合分组 (MTAP):包括16比特偏移多时间聚合分组(MTAPl6)和24比特偏移多时间聚合分组 (MTAP24)不同时间戳也可以组合,一般用于高延迟的网络环境,比如流媒体应用.它的打包方案相对复杂,但是大大增强了基于流媒体的H.264的性 能。MTAPl6 MTAP24的单元类型分别为26和27。
RTP包的封装流程设计
根据H.264NAL单元的分割重组的性质以及RTP打包规则,本文实行的对RTP打包的设计 如下:
1、若接收到的NAL单元小于MAX—SIZE(此时MAX-sIZE为设定的最大传输单元 ),则对它进行单一打包,也就是将此NAL单元直接放进RTP包的载荷部分,生成一个RTP包。
2、若接收到的NAL单元大于MAx—SIZE字节,则对它进行分割,然后对分割后的NAL单元进行步骤1方式打包。分割方案如下:
其中Nsize是分割前的NAL单元大小 ,N是分割后NAL单元的大小 。K分割后的单元数 。分割后最后一个单元的大小可能会小于N,这时必须使用RTP载荷填充 是其同前面的分块大小相同,此时RTP头中的填充标识位值为 1。
3、对SEI,参数集等小NAL单元重组,将它们合并到一个RTP 包中。虽然步骤3中的重组方案可以减小IP/UDP/RTP头部开销,但是对于包丢失率比较高的网络环境,这意味着一个RTP包的丢失可能会导致多片的丢失,往往一个片中就有一个P图像,解码后的视频质量必然会严重下降。因此,在丢失率的网络中可以采用NAL单元的重组方案 ,而在高丢失率的网络环境中采用NAL单元重组时要进行有效的差错控制.在本文中不使用重组方案。
RTP/RTCP包的封装实现
RTP包封装设计
RTcP包的封装设计
RTCP报文封装在UDP数据报 中进行传输,发送时使用比它所属的RTP流的端口号大1 的协议号(RTP使用偶数号,RTCP使用奇数号)。以下是RTCP头部数据结构:
------------------------------------
H264实时编码及NALU,RTP传输(ZZ)
2010-07-25 11:46
Standards Track [Page 2] RFC 3984 RTP Payload Format for H.264 Video February 2005 1.
按照RFC3984协议实现H264视频流媒体
nalu单元 包起始 0x 00 00 00 01
H.264 NAL格式及分析器
http://hi.baidu.com/zsw_davy/b ... c409cc7cd92ace.html
http://hi.baidu.com/zsw_davy/blo ... 081312c8fc7acc.html
----------------------------------比特流信息 ----------------------------------------------
①NALU(Network Abstract Layer Unit):两标准中的比特流都是以NAL为单位,每个NAL单元包含一个RBSP,NALU的头信息定义了RBSP所属类型。类型一般包括序列参数集 (SPS)、图像参数集(PPS)、增强信息(SEI)、条带(Slice)等,其中,SPS和PPS属于参数集,两标准采用参数集机制是为了将一些主要 的序列、图像参数(解码图像尺寸、片组数、参考帧数、量化和滤波参数标记等)与其他参数分离,通过解码器先解码出来。此外,为了增强图像的清晰 度,AVS-M添加了图像头(Picture head)信息。读取NALU流程中,每个NALU前有一个起始码0x000001,为防止 内部0x000001序列竞争,H.264编码器在最后一字节前插入一个新的字节——0x03,所以解码器检测到该序列时,需将0x03删掉,而AVS- M只需识别出起始码0x000001。
②读取宏块类型(mb type)和宏块编码模板(cbp):编解码图像以宏块划分,一个宏块由一个16*16亮度块和相应的一个8*8cb和一个8*8cr色度块组成。
(a) 两标准的帧内、帧间预测时宏块的划分是有区别的。H.264中,I_slice亮度块有Intra_4*4和Intra_16*16两种模式,色度块只有 8*8模式;P_slice宏块分为16*16、16*8、8*16、8*8、8*4、4*8、4*4共7种模式。而AVS-M中,I_slice亮度块 有I_4*4和I_Direct两模式,P_slice时宏块的划分和H.264中的划分一致。
(b) 两标准的宏块cbp值计算也不相同。H.264中,Intra_16*16宏块的亮度(色度)cbp直接通过读mb type得到;非Intra_16*16宏块的亮度cbp=coded_block_pattern,色度 cbp=coded_block_pattern/16 。其中,亮度cbp最低4位有效,每位决定对应宏块的残差系数能不能为0;色度cbp为0时,对应残差系数为0,cbp为1时,DC残差系数不为0,AC 系数为0,cbp为2时,DC、AC残差系数都不为0。AVS-M中,当宏块类型不是P_skip时,直接从码流中得到cbp的索引值,并以此索引值查表 得到codenum值,再以codenum查表分别得到帧内/帧间cbp。此cbp为6位,每位代表宏块按8*8划分时能不能包含非零系数,当变换系数不 为0时,需进一步读cbp_4*4中每位值来判断一个8*8块中4个4*4块的系数能不能为0。
---------------------------------------------------------------------------------------------
总的来说H264的码流的打包方式有两种,一种为 annex-b byte stream format 的格式,这个是绝大部分编码器的默认输出格式,就是每个帧的开头的3~4个字节是H264的start_co
另一种是原始的NAL打包格式,就是开始的若干字节(1,2,4字节)是NAL的长度,而不是start_co
----------------------------------------------------------------------------
AVC vs. H.264
AVC and H.264 are synonymous. The standard is known by the full names "ISO/IEC 14496-10" and "ITU-T Recommendation H.264". In addition, a number of alternate names are used (or have been) in reference to this standard. These include:
- MPEG-4 part 10
- MPEG-4 AVC
- AVC
- MPEG-4 (in the broadcasting world MPEG4 part 2 is ignored)
- H.264
- JVT (Joint Video Team, nowadays rarely used referring to actual spec)
- H.26L (early drafts went by this name)
All of the above (and those I've missed) include the Annex B byte-stream format . Unlike earlier MPEG1/2/4 and H.26x codecs, the H.264 specification proper does not define a full bit-stream syntax. It describes a number of NAL (Network Abstraction Layer) units, a sequence of which can be decoded into video frames. These NAL units have no boundary markers, and rely on some unspecified format to provide framing.
Annex B of of the document specifies on
The H.264 spec suffers from a deficiency. It defines several header-type NAL units (SPS and PPS) without specifying how to pack them into the single codec da
在网络传输h264数据时,一个UDP包就是一个NALU,解码器可以很方便的检测出NAL分界和解码。但是如果编码数据存储为一个文件,原来的解码器将 无法从数据流中分别出每个NAL的起始位置和终止位置,为此h.264用起始码来解决这一问题。
H.264编码时,在每个NAL前添加起始码 0x000001,解码器在码流中检测到起始码,当前NAL结束。为了防止NAL内部出现0x000001的数据,h.264又提出'防止竞争 emulation prevention"机制,在编码完一个NAL时,如果检测出有连续两个0x00字节,就在后面插入一个0x03。当解码器在NAL内部检测到 0x000003的数据,就把0x03抛弃,恢复原始数据。
0x000000 >>>>>> 0x00000300
0x000001 >>>>>> 0x00000301
0x000002 >>>>>> 0x00000302
0x000003 >>>>>> 0x00000303
附上h.264解码nalu中检测起始码的算法流程
for(;;)
{
if next 24 bits are 0x000001
{
startCodeFound = true
break;
}
else
{
flush 8 bits
}
}// for(;;)
if(true == startCodeFound)
{
//startcode found
// Flush the start co
flush 24 bits
//Now navigate up to next start co
// in the nal structure.
for(;;)
{
get next 24 bits & check if it equals to 0x000001
if(false == (next 24 bits == 000001))
{
// search for pattern 0x000000
check if next 24 bits are 0x000000
if(false == result)
{
// copy the byte into the buffer
copy on
}
else
{
break;
}
}
else
{
break;
}
}//for(;;)
}
2. MPEG4起始码
MPEG4的特色是VOP,没有NALU的概念,仍使用startcode对每帧进行分界。MPEG4的起始码是0x000001. 另外MPEG4中很多起始码也很有用,比如video_object_sequence_start_co
H.264的主要目标:
1.高的视频压缩比
2.良好的网络亲和性
解决方案:
VCL video coding layer 视频编码层
NAL network abstraction layer 网络提取层
VCL:核心算法引擎,块,宏块及片的语法级别的定义
NAL:片级以上的语法级别(如序列参数集和图像参数集),同时支持以下功能:独立片解码,起始码唯一保证,SEI以及流格式编码数据传送
VCL设计目标:尽可能地独立于网络的情况下进行高效的编解码
NAL设计目标:根据不同的网络把数据打包成相应的格式,将VCL产生的比特字符串适配到各种各样的网络和多元环境中。
NALU头结构:NALU类型(5bit)、重要性指示位(2bit)、禁止位(1bit)。
NALU类型:1~12由H.264使用,24~31由H.264以外的应用使用。
重要性指示:标志该NAL单元用于重建时的重要性,值越大,越重要。
禁止位:网络发现NAL单元有比特错误时可设置该比特为1,以便接收方丢掉该单元。
2.NAL语法语义
NAL层句法:
在编码器输出的码流中,数据的基本单元是句法元素。
句法表征句法元素的组织结构。
语义阐述句法元素的具体含义。
分组都有头部,解码器可以很方便的检测出NAL的分界,依次取出NAL进行解码。
但为了节省码流,H.264没有另外在NAL的头部设立表示起始位置的句法元素。
如果编码数据是存储在介质上的,由于NAL是依次紧密相连的,解码器就无法在数据流中分辨出每个NAL的起始位置和终止位置。
解决方案:在每个NAL前添加起始码:0X000001
在某些类型的介质上,为了寻址的方便,要求数据流在长度上对齐,或某个常数的整数倍。所以在起始码前添加若干字节的0来填充。
检测NAL的开始:
0X000001和0X000000
我们必须考虑当NAL内部出现了0X000001和0X000000
解决方案:
H.264提出了“防止竞争”机制:
0X000000——0X00000300
0X000001——0X00000301
0X000002——0X00000302
0X000003——0X00000303
为此,我们可以知道:
在NAL单元中,下面的三字节序列不应在任何字节对齐的位置出现
0X000000
0X000001
0X000002
Forbidden_zero_bit =0;
Nal_ref_idc:表示NAL的优先级。0~3,取值越大,表示当前NAL越重要,需要优先受到保护。如果当前NAL是属于参考帧的片,或是序列参 数集,或是图像参数集这些重要的单位时,本句法元素必需大于0。
Nal_unit_type:当前NAL 单元的类型
3.H.264的NAL层处理
结构示意图:
NAL以NALU(NAL unit)为单元来支持编码数据在基于分组交换技术网络中传输。
它定义了符合传输层或存储介质要求的数据格式,同时给出头信息,从而提供了视频编码和外部世界的接口。
NALU:定义了可用于基于分组和基于比特流系统的基本格式
RTP封装:只针对基于NAL单元的本地NAL接口。
三种不同的数据形式:
SODB 数据比特串-->最原始的编码数据
RBSP 原始字节序列载荷-->在SODB的后面填加了结尾比特(RBSP trailing bits 一个bit“1”)若干比特“0”,以便字节对齐
EBSP 扩展字节序列载荷-->在RBSP基础上填加了仿校验字节(0X03)它的原因是: 在NALU加到Annexb上时,需要添加每组 NALU之前的开始码StartCodePrefix,如果该NALU对应的slice为一帧的开始则用4位字节表示,ox00000001,否则用3位 字节表示ox000001.为了使NALU主体中不包括与开始码相冲突的,在编码时,每遇到两个字节连续为0,就插入一个字节的0x03。解码时将 0x03去掉。也称为脱壳操作
处理过程:
1. 将VCL层输出的SODB封装成nal_unit, Nal_unit是一个通用封装格式,可以适用于有序字节流方式和IP包交换方式。
2. 针对不同的传送网络(电路交换|包交换),将nal_unit 封装成针对不同网络的封装格 式。
第一步的具体过程:
VCL层输出的比特流SODB(String Of Da
1.SODB字节对齐处理后封装成RBSP(Raw Byte Sequence Payload)。
2.为防止RBSP的字节流与有序字节流传送方式下的SCP(start_co
nal_unit( NumBytesInNALunit ) {
forbidden_zero_bit
nal_ref_idc
nal_unit_type
NumBytesInRBSP = 0
for( i = 1; i < NumBytesInNALunit; i++ ) {
if( i + 2 < NumBytesInNALunit && next_bits( 24 ) = = 0x000003 ) {
rbsp_byte[ NumBytesInRBSP++ ]
rbsp_byte[ NumBytesInRBSP++ ]
i += 2
emulation_prevention_three_byte
} else
rbsp_byte[ NumBytesInRBSP++ ]
}
}
3. 防字节竞争处理后的RBSP再加一个字节的header(forbidden_zero_bit+ nal_ref_idc+ nal_unit_type),封装成nal_unit.
第二步的具体过程:
case1:有序字节流的封装
byte_stream_nal_unit( NumBytesInNALunit ) {
while( next_bits( 24 ) != 0x000001 )
zero_byte
if( more_da
start_co
}
}
类似H.320和MPEG-2/H.222.0等传输系统,传输NAL作为有序连续字节或比特流,同时要依靠数据本身识别NAL单元边界。在这样的应用系 统中,H.264/AVC规范定义了字节流格式,每个NAL单元前面增加3个字节的前缀,即同步字节。在比特流应用中,每个图像需要增加一个附加字节作为 边界定位。还有一种可选特性,在字节流中增加附加数据,用做扩充发送数据量,能实现快速边界定位,恢复同步
Case2:IP网络的RTP打包封装
分组打包的规则
(1)额外开销要少,使MTU尺寸在100~64k字节范围都可以;
(2)不用对分组内的数据解码就可以判别该分组的重要性;
(3)载荷规范应当保证不用解码就可识别由于其他的比特丢失而造成的分组不可解码;
(4)支持将NALU分割成多个RTP分组;
(5)支持将多个NALU汇集在一个RTP分组中。
RTP的头标可以是NALU的头标,并可以实现以上的打包规则。
一个RTP分组里放入一个NALU,将NALU(包括同时作为载荷头标的NALU头)放入RTP的载荷中,设置RTP头标值。为了避免IP层对大分组的再 一次分割,片分组的大小一般都要小于MTU尺寸。由于包传送的路径不同,解码端要重新对片分组排序,RTP包含的次序信息可以用来解决这一问题。
NALU分割
对于预先已经编码的内容,NALU可能大于MTU尺寸的限制。虽然IP层的分割可以使数据块小于64千字节,但无法在应用层实现保护,从而降低了非等重保 护方案的效果。由于UDP数据包小于64千字节,而且一个片的长度对某些应用场合来说太小,所以应用层打包是RTP打包方案的一部分。
新的讨论方案(IETF)应当符合以下特征:
(1)NALU的分块以按RTP次序号升序传输;
(2)能够标记第一个和最后一个NALU分块;
(3)可以检测丢失的分块。
NALU合并
一些NALU如SEI、参数集等非常小,将它们合并在一起有利于减少头标开销。已有两种集合分组:
(1)单一时间集合分组(STAP),按时间戳进行组合;
(2)多时间集合分组(MTAP),不同时间戳也可以组合。
NAL规范视频数据的格式,主要是提供头部信息,以适合各种媒体的传输和存储。NAL支持各种网络,包括:
1.任何使用RTP/IP协议的实时有线和无线Internet 服务
2.作为MP4文件存储和多媒体信息文件服务
3.MPEG-2系统
4.其它网
NAL规定一种通用的格式,既适合面向包传输,也适合流传送。实际上,包传输和流传输的方式是相同的,不同之处是传输前面增加了一个起始码前缀
在类似Internet/RTP面向包传送协议系统中,包结构中包含包边界识别字节,在这种情况下,不需要同步字节。
NAL单元分为VCL和非VCL两种
VCL NAL单元包含视频图像采样信息,
非VCL包含各种有关的附加信息,例如参数集(头部信息,应用到大量的VCL NAL单元)、提高性能的附加信息、定时信息等
参数集:
参数集是很少变化的信息,用于大量VCL NAL单元的解码,分为两种类型:
1.序列参数集,作用于一串连续的视频图像,即视频序列。
两个IDR图像之间为序列参数集。IDR和I帧的区别见下面。
2. 图像参数集,作用于视频序列中的一个或多个个别的图像
序列和图像参数集机制,减少了重复参数的传送,每个VCL NAL单元包含一个标识,指
向有关的图像参数集,每个图像参数集包含一个标识,指向有关的序列参数集的内容
因此,只用少数的指针信息,引用大量的参数,大大减少每个VCL NAL单元重复传送的信息。
序列和图像参数集可以在发送VCL NAL单元以前发送,并且重复传送,大大提高纠错能力。序列和图像参数集可以在“带内”,也可以用更为可靠的其他“带外”通道传送。
H264实时编码及NALU,RTP传输(续)(ZZ)
- 修改版:H.264 视频 RTP 负载格式
- H264分包组包
- 直接用udp实现简单的RTP思路
- x264编码得到的文件,在文件头部的一些东西,有了新发现
- 张int x264_nal_encode( void *p_data, int *pi_data, int b_annexeb, x264_nal_t *nal )
- H.264 NAL单元流和字节流之间的关系,二者均称作比特流。
- jrtplib介绍
- jrtplib介绍 [转]
- H264易混概念
- x264_nal_decode:nal 代码详解
- RTP传输H264时的sps和pps的获取
- 图像、帧、片、NALU
- 摄像头视频采集压缩及传输原理
- 转:x264编码详细文字全过程