前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >rtp协议详解

rtp协议详解

作者头像
全栈程序员站长
发布2022-09-07 16:17:41
1.2K0
发布2022-09-07 16:17:41
举报

大家好,又见面了,我是你们的朋友全栈君。

一 rtp概述

RTP全名是Real-time Transport Protocol(实时传输协议)。它是IETF提出的一个标准,对应的RFC文档为RFC3550。RFC3550不仅定义了RTP,而且定义了配套的相关协议RTCP(Real-time Transport Control Protocol,即实时传输控制协议)。RTP用来为IP网上的语音、图像、传真等多种需要实时传输的多媒体数据提供端到端的实时传输服务。RTP为Internet上端到端的实时传输提供时间信息和流同步,但并不保证服务质量,服务质量由RTCP来提供。

rtp协议详解
rtp协议详解
rtp协议详解
rtp协议详解

RTP的头部格式

前12字节是固定的,CSRC可以有多个或者0个。

1)V:RTP协议的版本号,占2位,当前协议版本号为2

2)P:填充标志,占1位,如果P=1,则在该报文的尾部填充一个或多个额外的八位组,它们不是有效载荷的一部分

3)X:扩展标志,占1位,如果X=1,则在RTP报头后跟有一个扩展报头

4)CC:CSRC计数器,占4位,指示CSRC标识符个数

5)M:标志,占1位,不同的有效载荷有不同的含义,对于视频,标记一帧的结束;对于音频,标记会话的开始。

6)PT(payload type):有效荷载类型,占7位,用于说明RTP报文中有效载荷的类型,如GSM音频、JPEM图像等,在流媒体中大部分是用来区分音频流和视频流,这样便于客户端进行解析。

7)序列号:占16位,用于标识发送者所发送的RTP报文的序列号,每发送一个报文,序列号增1。这个字段当下层的承载协议用UDP的时候,网络状况不好的时候可以用来检查丢包。当出现网络抖动的情况可以用来对数据进行重新排序。序列号的初始值是随机的,同时音频包和视频包的sequence是分别计数的。

8)时戳(Timestamp):占32位,必须使用90kHZ时钟频率(程序中的90000)。时戳反映了该RTP报文的第一个八位组的采样时刻。接受者使用时戳来计算延迟和延迟抖动,并进行同步控制。可以根据RTP包的时间戳来获得数据包的时序。

9)同步信源(SSRC)标识符:占32位,用于标识同步信源。同步信源是指产生媒体流的信源,他通过RTP报头中的一个32为数字SSRC标识符来标识,而不依赖网络地址,接收者将根据SSRC标识符来区分不同的信源,进行RTP报文的分组。

10)提供信源(CSRC)标识符:每个CSRC标识符占32位,可以有0~15个CSRC。每个CSRC标识了包含在RTP报文有效载荷中的所有提供信源。

提供信源用来标识对一个RTP混合器产生的新包有贡献的所有RTP包的源。是指当混合器接收到一个或多个同步信源的RTP报文后,经过混合处理产生一个新的组合RTP报文,并把混合器作为组合RTP报文的SSRC,将原来所有的SSRC都作为CSRC传送给接收者,是接受者知道组成组合报文的各个SSRC。

二 rtp码流

rtp载荷h264媒体流:rtp协议头和h264码流

rtp协议详解
rtp协议详解

rtp头后是rtp载荷,rtp载荷第一个字节格式和NALU头一样。

rtp协议详解
rtp协议详解

SODB(String Of Data Bits):最原始的编码数据, 长度不一定是8的倍数,此时需要对齐.  RBSP:在SODB后添加结尾比特(RBSP trailing bits 一个bit“1”)若干比特“0”,以便字节对齐。 EBSP:在 RBSP 的基础上增加了防止伪起始码字节(0X03) NALU是对RBSP的封装,而RTP是对NALU的封装。

rtp协议详解
rtp协议详解

F和NRI也跟NALU头一样,只有Type有些不一样:拓展24 – 31

0 没有定义; 1-23 NAL单元 单个 NAL 单元包.

24 STAP-A 单一时间的组合包; 25 STAP-B 单一时间的组合包

26 MTAP16 多个时间的组合包; 27 MTAP24 多个时间的组合包

28 FU-A 分片的单元; 29 FU-B 分片的单元; 30-31 没有定义

1) 单个NAL单元包:荷载中只包含一个NAL单元。NAL头类型域等于原始 NAL单元(NALU)类型,即Type在范围1到23之间。

rtp协议详解
rtp协议详解

对于NALU(NAL单元)的长度小于MTU大小的包,一般采用单一NAL单元模式

定义在此的NAL单元包必须只包含一个。RTP序号必须符合NAL单元的解码顺序。这种情况下,NAL单元的第一字节和RTP荷载头第一个字节重合。如上图所示。

对于一个原始H264的NALU单元常由[start code] [NALU Header] [NALU Payload]三部分组成,其中start code用于标识这是一个NALU单元的开始,必须是“00 00 00 01”或“00 00 01”,NALU头仅一个字节,其后都是NALU单元载荷。

打包时去除“00 00 01”或“00 00 00 01”的开始码,把其他数据封装成RTP包即可。

如有一个 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)组合包:本类型用于聚合多个NAL单元到单个RTP荷载中。本包有四种版本,单时间聚合包类型A(STAP-A)单时间聚合包类型B(STAP-B),多时间聚合包类型(MTAP)16位位移(MTAP16),多时间聚合包类型(MTAP)24位位移(MTAP24)。赋予STAP-A,STAP-B,MTAP16,MTAP24的NAL单元类型号(Type)分别是24 25 26 27

rtp协议详解
rtp协议详解

当NALU的长度特别小时,可以把几个NALU单元封在一个RTP包中。这种模式下,有多个NALU头和NALU载荷。

3)分片包:用于分片单个NAL单元到多个RTP包。现存两个版本FU-A,FU-B,用NAL单元类型(Type)28 29标识

常用的打包时的分包规则:如果小于MTU采用单个NAL单元包,如果大于MTU就采用FUs分片方式

rtp协议详解
rtp协议详解

当NALU的长度超过MTU时,就必须对NALU单元进行分片封包,也称为Fragmentation Units (FUs)NAL单元的一个分片由整数个连续NAL单元字节组成。每个NAL单元字节必须正好是该NAL单元一个分片的一部分。相同NAL单元的分片必须使用递增的RTP序号连续顺序发送(第一和最后分片之间没有其他的RTP包)。同时,NAL单元必须按照RTP顺序号的顺序装配。STAPs,MTAPs不可以被分片。 FUs不可以嵌套。 即, 一个FU 不可以包含另一个FU。

S(开始位): 1 bit, 当设置成1,指示分片NAL单元的开始。当跟随的FU荷载不是分片NAL单元荷载的开始,开始位设为0。

E(结束位): 1 bit, 当设置成1,指示分片NAL单元的结束,即,荷载的最后字节也是分片NAL单元的最后一个字节。当跟随的 FU荷载不是分片NAL单元的最后分片,结束位设置为0。

R(保留位): 1 bit, 保留位必须设置为0,接收者必须忽略该位。

Type(类型):5 bit, 是NAL Header中的Type。

打包时,原始的NAL头的前三位为FU indicator的前三位,原始的NAL头的后五位(Type)为FU header的后五位(Type)。

取一段rtp码流分析如下:

80 60 01 0f 00 0e 10 00 00 00 00 00 7c 85 88 82 €`……….|???

00 0a 7f ca 94 05 3b7f 3e 7f fe 14 2b 27 26 f8 …??.;.>.?.+’&?

89 88 dd 85 62 e1 6dfc 33 01 38 1a 10 35 f2 14 ????b?m?3.8..5?.

84 6e 21 24 8f 72 62f0 51 7e 10 5f 0d 42 71 12 ?n!$?rb?Q~._.Bq.

17 65 62 a1 f1 44 dc df 4b 4a 38 aa 96 b7 dd 24 .eb??D??KJ8????$

前12字节是RTP Header,7c是FU indicator,85是FU Header

FU indicator(0x7C)和FU Header(0x85)二进制 0111 1100 1000 0101

按顺序解析如下:

0 是F

11 是NRI

11100 是FU Type,这里是28,即FU-A

1 是S,Start,说明是分片的第一包

0 是E,End,如果是分片的最后一包,设置为1,这里不是

0 是R,Remain,保留位,总是0

00101 是NAL Type,这里是5,说明是关键帧

打包时,FU indicator的F、NRI是NAL Header中的F、NRI,Type是28(FU-A);FU Header的S、E、R分别按照分片起始位置设置,Type是NAL Header中的Type。

解包时,取FU indicator的前三位和FU Header的后五位,即0110 0101(0x65)为NAL类型。

4)SPS/PPS

一个frame分割成多个slice,一个slice分割成多个宏块。一个Slice编码之后被打包进一个NAL单元。不过NAL单元除了容纳Slice编码的码流外,还可以容纳其他数据,比如序列参数集SPS。

NALU头由一个字节组成:forbidden_zero_bit(1bit) + nal_ref_idc(2bit) + nal_unit_type(5bit)

forbidden_zero_bit: 禁止位,初始为0,当网络发现NAL单元有比特错误时可设置该比特为1,以便接收方纠错或丢掉该单元。 nal_ref_idc:nal重要性指示,标志该NAL单元的重要性,值越大,越重要,解码器在解码处理不过来的时候,可以丢掉重要性为0的NALU。

nal_unit_type:NALU常用类型取值如下表所示:

5 IDR图像中的片 6 补充增强信息单元(SEI) 7 SPS 8 PPS 9 分割符 10 序列结束符 11 流结束符 12 填充数据

H.264码流第一个 NALU是 SPS(序列参数集Sequence Parameter Set)

H.264码流第二个 NALU是 PPS(图像参数集Picture Parameter Set)

SPS和PPS都是特殊的NALU。一个MP4文件只有一个SPS,但是有很多PPS,SPS必须在所有NALU的最开头。

H.264码流第三个 NALU 是 IDR(即时解码器刷新),第一个I帧称为IDR帧,IDR帧的作用是立刻刷新,使错误不致传播,从IDR帧开始,重新算一个新的序列开始编码。解码器收到IDR帧时,将所有的参考帧队列丢弃,把所有的PPS和SPS参数进行更新。

rtp协议详解
rtp协议详解
rtp协议详解
rtp协议详解
rtp协议详解
rtp协议详解

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

总的来说,H264的码流的打包方式有两种,一种为annex-b byte stream format 的格式,这个是绝大部分编码器的默认输出格式,就是每个帧的开头的3~4个字节是H264的start_code,0x00000001或者0x000001;另一种是原始的NAL打包格式,就是开始的若干字节(1,2,4字节)是NAL的长度,而不是start_code,此时必须借助某个全局的数据来获得编 码器的profile,level,PPS,SPS等信息才可以解码。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/153953.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一 rtp概述
  • 二 rtp码流
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档