基础传输结构

rtp中对于h264数据的存储分为两层,分别是

  • VCL: video coding layer 视频编码层

    这是h264中block, macro block 以及 slice级别的定义,目的是为了独立网络传输,进行高效的编解码

  • NAL: network abstraction layer 网络提取层

    NAL层的不同是为了根据不同的网络把VCL数据进行打包成不同的格式,进行传输

NAL

H264中的数据分组有头部(譬如: pkt->data),解码器可以很方便的检测到NAL的分界,依次去除NAL进行解码,但为了节省码流,NAL没有在数据头部设立特定元素,如果编码数据存储在介质上,NAL依次紧密相连(这时就无法通过对象取读取一个nal数据了),就无法区分出不同的nal单元,为了解决该问题,存储的时候会在每一个nal前添加0x000001或0x000000。

但数据内部也可能出现0x000001或0x000000,为此nal中规定不能出现0x000001或0x000000,源数据需要进行如下变换:

原数据 替换数据
0X000000 0X00000300
0X000001 0X00000301
0X000002 0X00000302
0X000003 0X00000303

在网络传输过程中, NAL中的数据被分成NALU(nal unit)单元,然后由RTP进行封装传输

如上图所示,VCL的数据经过上图所示

  • 在SODB的后面添加了结尾若干比特"0",以用字节对齐成了RBSP
  • 在RBSP的基础上,对数据进行循环检测替换上述的0x000000 ~ 0x000002,避免nal单元边界被破坏,成了EBSP(扩展字节序列载荷,在 RBSP 基础上填加了仿校验字节(0x03),它的原因是:在 NALU 加到 Annexb 上时,需要添加每组 NALU 之前的开始码 StartCodePrefix,如果该 NALU 对应的 slice 为一帧的开始(即为 IDR 帧)则用 4 位字节表示:0x00000001,否则用 3 位字节表示:0x000001。为了使 NALU 主体中不包括与开始码相冲突的,在编码时,每遇到两个字节连续为 0,就插入一个字节的 0x03。解码时将 0x03 去掉。也称为 "脱壳操作"。)
  • 在EBSP上添加一个字节的header后成了 NALU,

NALU

上述EBSP添加的一个字节的header的结构如下所示:

+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+

F:0表示payload 内容没有错误,1表示payload中的内容可能有错误内容或语法错误。

NRI:用来表示当前NALU单元的重要性(从00 ~11),00最低,表示这不是一个用于帧间预测的参考帧,可以丢弃。

Type:表示当前NALU的类型,这些类型如下表所示


Table 1. Summary of NAL unit types and the corresponding packet
types NAL Unit Packet Packet Type Name Section
Type Type
-------------------------------------------------------------
0 reserved -
1-23 NAL unit Single NAL unit packet 5.6
24 STAP-A Single-time aggregation packet 5.7.1
25 STAP-B Single-time aggregation packet 5.7.1
26 MTAP16 Multi-time aggregation packet 5.7.2
27 MTAP24 Multi-time aggregation packet 5.7.2
28 FU-A Fragmentation unit 5.8
29 FU-B Fragmentation unit 5.8
30-31 reserved

再具体一点如下所示:

nal_unit_type	NAL类型
1 非IDR图像中不采用数据划分的片段
2 非IDR图像中A类数据划分片段
3 非IDR图像中B类数据划分片段
4 非IDR图像中C类数据划分片段
5 IDR图像的片
6 补充增强信息单元(SEI)
7 序列参数集
8 图像参数集
9 分界符
10 序列结束
11 码流结束
12 填充
13…23 保留
24…31 不保留(RTP打包时会用到)

比较重要的是

nal_unit_type = 7 RTP 负载的是序列参数集

nal_unit_type = 8 RTP 负载的是图像参数集

nal_unit_type = 5 IDR图像的片 (立即刷新图像,I帧给P帧和B帧作为参考)

23之前的都是signal-nalu单rtp就可以传输完毕,只是对其细分了说明nalu中的数据类型,而超过23的时候多RTP打包开始用到,此时NALU太大了,决定NALU如何拆分打包进 RTP。(因为NALU 大小有可能远远小于RTP payload,也有可能正好等于RTP payload,或者远大于RTP payload) ,那么NALU 就需要再次拆分包,即一帧拆开发送,拆开发送时,rtp的markbit就可以用上来判断当前这个单元是否为一帧的结束,nalu被拆分的时候,timestamp是不变的

 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 |
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|F|NRI| type | |
+-+-+-+-+-+-+-+-+ |
| |
| Bytes 2..n of a Single NAL unit |
| |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| :...OPTIONAL RTP padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

聚合包 nal_unit_type = 24~27

本类型用于聚合多个NAL单元到单个RTP荷载中。本包有四种版本,单时间聚合包类型A (STAP-A),单时间聚合包类型B (STAP-B),多时间聚合包类型(MTAP)16位位移(MTAP16), 多时间聚合包类型(MTAP)24位位移(MTAP24)。赋予STAP-A, STAP-B, MTAP16, MTAP24的NAL单元类型号分别是 24,25, 26, 27;

下图的单时间聚合包

     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 Data |
: :
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | NALU 2 Size | NALU 2 HDR |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NALU 2 Data |
: :
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| :...OPTIONAL RTP padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Figure 7. An example of an RTP packet including an STAP-A
containing two single-time aggregation units

分片单元 nal_unit_type = 28 或者 29

将NALU 单元拆分到多个RTP包中发送 典型的就是FU-A或者FU-B

     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

其中FU indicator的格式如下

   +---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|S|E|R| Type |
+---------------+ S:1表示第一包
E:1表示是最后一个包
R:1表示中间
Type:类型

RTP负载PS



H264通常以NALU的方式进行传输,但是H264还有另一种数据组织和传输方式但是使用较少, 其在NALU的基础上又进行了封装,由于每个IDR NALU 前一般都会包含SPS、PPS 等NALU,因此将SPS、PPS、IDR 的NALU 封装为一个PS 包,包括ps 头,然后加上PS system header,PS system map,PES header+h264 raw data。所以一个IDR NALU PS 包由外到内顺序是:PSheader| PS system header | PS system Map | PES header | h264 raw data。对于其它非关键帧的PS 包,就简单多了,直接加上PS头和PES 头就可以了。顺序为:PS header | PES header | h264raw data。以上是对只有视频video 的情况,如果要把音频Audio也打包进PS 封装,也可以。当有音频数据时,将数据加上PES header 放到视频PES 后就可以了。顺序如下:PS 包=PS头|PES(video)|PES(audio),再用RTP 封装发送就可以了。如上图,其中:

  • ES流(Elementary Stream原始流),是音、视频信号经过编码器之后或数据信号的基本码流。只包含一种内容。每个ES都由若  干个存取单元(AU)组成,每个视频或音频AU都是由头部和编码数据两部分组成,1个AU相当于编码的1幅视频图像或1个  音频帧  也可以说,每个AU实际上是编码数据流的显示单元,即相当于解码的1幅视频图像或1个音频帧的取样。
  • PES(Paketized Elementary Stream)是ES经过打包后的码流,长度可变。视频一般一帧一个包,音频一般不超过64KB.
  • PTS--(presentation time stamp)显示时间戳,表示显示单元出现在系统目标解码器(H.264、MJPEG等)的时间。
  • DTS--(Decoding Time Stamp)解码时间戳,表示将存取单元全部字节从解码缓存器移走的时间。
  • PTS和DTS打在PES包头内,是解决音视频同步,防止解码器输入缓存上溢或下溢的关键。每一个pes header都包含pts和dts,是相对SCR(系统参考)的时间戳,以90000为单位,系统时钟频率(H264采样频率)



    最后由rtp将ps包传输出去,RFC2250中建议96 表示PS 封装,建议97 为MPEG-4,建议98 为H264

REF

[h264 基础](https://www.cnblogs.com/jimodetiantang/p/9110647.html)

H264 NALunit

RTP包 NALU FU-A等之间的关系

WEBRTC 接收H264 RTP数据流小结

RTP PS PES ES H264协议学习

RTP Payload Format for H.264 Video

RTP Payload Format for H264 Video的更多相关文章

  1. RTP Payload Format for VP8 Video

    整体结构 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 +-+-+-+-+-+-+-+-+-+-+-+ ...

  2. RTP Payload Format for Opus Speech and Audio Codec

    [Docs] [txt|pdf] [Tracker] [WG] [Email] [Diff1] [Diff2] [Nits] Versions: (draft-spittka-payload-rtp- ...

  3. RTP Payload Format for Transport of MPEG-4 Elementary Streams over http

    1.SDP (1)Http Request GET /getSdpForUrl?HttpUrl=nphMpeg4/g726-640x480 HTTP/1.0/r/n Host: 58.63.71.90 ...

  4. RFC3984: RTP Payload Format for H.264 Video(中文版)

    转载地址:https://blog.csdn.net/h514434485/article/details/51010950 官方文档,中文版本地址:http://www.rosoo.net/File ...

  5. 多媒体开发之---h264中 的RTP PAYLOAD 格式

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

  6. H.264 RTP PAYLOAD 格式

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

  7. 用实例分析H264 RTP payload

    用实例分析H264 RTP payload H264的RTP中有三种不同的基本负载(Single NAL,Non-interleaved,Interleaved) 应用程序可以使用第一个字节来识别. ...

  8. RTP 有效负载(载荷)类型,RTP Payload Type

    转自:http://blog.csdn.net/caoshangpa/article/details/53008018 版权声明:本文为灿哥哥http://blog.csdn.net/caoshang ...

  9. wireshark 获取RTP payload

    wireshark 抓包获取RTP TS流数据,保存为TS文件 首先解析RTP流 2.点击菜单栏[Statistics]-[RTP]-[Show All Streams] 3.在Wireshark:R ...

随机推荐

  1. zabbix系列-Grafana4.6.3+Zabbix 的安装部署

    zabbix系列(五) Grafana4.6.3+Zabbix 的安装部署 伟创享 2019-07-31 11:27:18 使用了一段时间Grafana,感觉还挺好用的.部分效果图如下: ​ zabb ...

  2. mysql 根据某个值叠加查询

    今天看到需求 根据输入用户ID由近到远排列 怎么会有这种需求??? 直接上代码 SELECT * FROM Member, ( (SELECT ABS(ID-900) as Sorting,ID FR ...

  3. Android WebView 基本设置与H5 交互

    mWebView.setDrawingCacheEnabled(true); WebChromeClient webChromeClient = new WebChromeClient(); mWeb ...

  4. 两个变量值交换的方法总结(js,python)

    方法一: 临时变量法 <script> var num1 = 10; var num2 = 20; var temp;//定义临时变量 temp = num1; num1 = num2; ...

  5. python基础知识第二篇(字符串)

    基本数据类型 数字                  整形 int                             ---int                            将字符串 ...

  6. VS2019 开发Django(十)------JavaScript与Django的数据交互

    导航:VS2019开发Django系列 这一篇介绍如何使用BootStrap Table这个组件来绑定渲染数据, 1)先来看一下BootStrap Table是怎么绑定数据的. 通过数据属性 给定da ...

  7. Cesium专栏-百度地图加载(附源码下载)

    Cesium 是一款面向三维地球和地图的,世界级的JavaScript开源产品.它提供了基于JavaScript语言的开发包,方便用户快速搭建一款零插件的虚拟地球Web应用,并在性能,精度,渲染质量以 ...

  8. MySQL MHA /usr/share/perl5/vendor_perl/MHA/ServerManager.pm, ln301] install_driver(mysql) failed: Attempt to reload DBD/mysql.pm aborted

    在公司随便找3台测试机搭个MHA,下面这个问题折腾了三天,之前没遇到过,查了OS版本发现一致,可能是不同人弄的OS吧,知道是cpan的问题就是搞不定,郁闷...[root@test247 ~]# ma ...

  9. Linux下快速手动产生core文件

    原文链接:https://blog.csdn.net/jctian000/article/details/79695006 当我们配置好自动生成core文件的环境后,若不想写导致崩溃的程序验证,那要怎 ...

  10. java开发,入职半年。对未来迷茫,如何发展?

    蛮多人私密我一些问题,关于面试,关于技术的,我只能说有些路只能靠自己去走,没人可以帮到自己,哪怕偶尔帮一到两次,但是技术的路这么长,总归需要自己独自成长的.附一张自己藏书的照片,与各位共勉 工作三年多 ...