音视频开发-RTP协议
基于WebRTC
的音视频直播框架,使用RTP/RTCP
,这里记录下。
RTP/RTCP
一般情况下,在实时互动直播系统传输音视频数据流时,我们并不直接将音视频数据流交给 UDP 传输
,而是先给音视频数据加个RTP 头
,然后再交给 UDP
进行传输。为什么要这样做呢?
以太网的 MTU 最大传输单元
为 1500
字节 约为1.5K,意味着传输一个I帧就需要几十个包。意味着就需要拆包,然后重新组装。
RTP协议
-
版本号(V)
:2比特,用来标志使用的RTP版本。 -
填充位(P)
:1比特,如果该位置位,则该RTP包的尾部就包含附加的填充字节。 -
扩展位(X)
:1比特,如果该位置位的话,RTP固定头部后面就跟有一个扩展头部。 -
CSRC计数器(CC)
:4比特,含有固定头部后面跟着的CSRC
的数目。 -
标记位(M)
:1比特,该位的解释由配置文档(Profile
)来承担. -
载荷类型(PT)- Payload Type
:7比特,标识了RTP载荷的类型。音频流的 PT 值与视频的 PT 值是不同的,通过它就可以知道这个包存放的是什么类型的数据。 -
sequence number
:序号,用于记录包的顺序。这与上面我们自己实现拆包、组包是同样的道理。 -
timestamp
:时间戳,同一个帧的不同分片的时间戳是相同的。这样就省去了前面所讲的起始标记和结束标记。一定要记住,不同帧的时间戳肯定是不一样的。
假设你从网上接收一组音视频数据
...
{V=2,P=0,X=0,CC=0,M=0,PT:98,seq:13,ts:1122334455,ssrc=2345},
{V=2,P=0,X=0,CC=0,M=0,PT:111,seq:14,ts:1122334455,ssrc=888},
{V=2,P=0,X=0,CC=0,M=0,PT:98,seq:14,ts:1122334455,ssrc=2345},
{V=2,P=0,X=0,CC=0,M=0,PT:111,seq:15,ts:1122334455,ssrc=888},
{V=2,P=0,X=0,CC=0,M=0,PT:98,seq:15,ts:1122334455,ssrc=2345},
{V=2,P=0,X=0,CC=0,M=0,PT:111,seq:16,ts:1122334455,ssrc=888},
{V=2,P=0,X=0,CC=0,M=0,PT:98,seq:16,ts:1122334455,ssrc=2345},
{V=2,P=0,X=0,CC=0,M=0,PT:111,seq:17,ts:1122334455,ssrc=888},
{V=2,P=0,X=0,CC=0,M=0,PT:98,seq:17,ts:1122334455,ssrc=2345},
{V=2,P=0,X=0,CC=0,M=0,PT:111,seq:18,ts:1122334455,ssrc=888},
{V=2,P=0,X=0,CC=0,M=0,PT:98,seq:18,ts:1122334455,ssrc=2345},
{V=2,P=0,X=0,CC=0,M=0,PT:111,seq:19,ts:1122334455,ssrc=888},
{V=2,P=0,X=0,CC=0,M=0,PT:98,seq:19,ts:1122334455,ssrc=2345},
{V=2,P=0,X=0,CC=0,M=0,PT:111,seq:20,ts:1122334455,ssrc=888},
{V=2,P=0,X=0,CC=0,M=1,PT:98,seq:20,ts:1122334455,ssrc=2345},
...
PT=98
是视频数据,PT=111
是音频数据,那么按照上面的规则很容易就能将视频帧组装起来。
RTCP 协议
在使用 RTP
包传输数据时,难免会发生丢包、乱序、抖动等问题,下面我们来看一下使用的网络一般都会在什么情况下出现问题:
- 网络线路质量问题引起丢包率高;
- 传输的数据超过了带宽的负载引起的丢包问题;
- 信号干扰(信号弱)引起的丢包问题;
- 跨运营商引入的丢包问题 ;
- ……
WebRTC
对这些问题在底层都有相应的处理策略,但在处理这些问题之前,它首先要让各端都知道它们自己的网络质量到底是怎样的,这就是 RTCP
的作用。
RTCP
有两个最重要的报文:RR(Reciever Report)和 SR(Sender Report)
。通过这两个报文的交换,各端就知道自己的网络质量到底如何了。
这里我们以SR 报文为例,看看 SR 报文中都包括哪些信息。
下面我就简要说明一下该报文中字段的含义:
-
V=2
,指报文的版本。 -
P
,表示填充位,如果该位置 1,则在 RTCP 报文的最后会有填充字节(内容是按字节对齐的)。 -
RC
,全称 Report Count,指 RTCP 报文中接收报告的报文块个数。 -
PT=200,Payload Type
,也就是说 SR 的值为 200。
……
从上图中我们可以了解到,SR
报文分成三部分:Header、Sender info和Report block
。在 NTP
时间戳之上的部分为 SR
报文的 Header
部分,SSRC_1
字段之上到 Header 之间的部分为 Sender info
部分,剩下的就是一个一个的 Report Block
了。那这每一部分是用于干什么的呢?
- Header 部分用于标识该报文的类型,比如是 SR 还是 RR。
- Sender info 部分用于指明作为发送方,到底发了多少包。
- Report block 部分指明发送方作为接收方时,它从各个 SSRC 接收包的情况。
通过以上的分析,你可以发现SR
报文并不仅是指发送方发了多少数据,它还报告了作为接收方
,它接收到的数据的情况。当发送端收到对端的接收报告时,它就可以根据接收报告来评估它与对端之间的网络质量了,随后再根据网络质量做传输策略的调整。
SR 报文
与RR 报文
无疑是RTCP
协议中最重要的两个报文,不过 RTCP
中的其他报文也都非常重要的,如果你想学好 WebRTC
,那么 RTCP
中的每个报文你都必须掌握。
比如,RTCP 类型
为 206
、子类型为 4 的 FIR
报文,其含义是 Full Intra Request (FIR) Command
,即完整帧请求命令。会紧接发送一帧I帧
该报文也是一个特别关键的报文,我为什么这么说呢?试想一下,在一个房间里有 3 个人进行音视频聊天,然后又有一个人加入到房间里,这时如果不做任何处理的话,那么第四个人进入到房间后,在一段时间内很难直接看到其他三个人的视频画面了,这是为什么呢?
原因就在于解码器在解码时有一个上下文。在该上下文中,必须先拿到一个 IDR 帧之后才能将其后面的 P 帧、B 帧进行解码。也就是说,在没有 IDR 帧的情况下,对于收到的 P 帧、B 帧解码器只能干瞪眼了。
如何解决这个问题呢?这就引出了 FIR 报文。当第四个人加入到房间后,它首先发送 FIR 报文,当其他端收到该报文后,便立即产生各自的 IDR 帧发送给新加入的人,这样当新加入的人拿到房间中其他的 IDR 帧后,它的解码器就会解码成功,于是其他人的画面也就一下子全部展示出来了。
附图
RTP协议头
RTCP 协议头:
RTCP PT 类型:
对于 205 和 206 两种不同的反馈消息,又在 RFC5104 中做了更详细的定义:
推荐阅读
-
IoTClient开发3 - ModBusTcp协议客户端实现
-
.Net WInform开发笔记(二)Winform程序运行结构图及TCP协议在Winform中的应用
-
.Net WInform开发笔记(二)Winform程序运行结构图及TCP协议在Winform中的应用
-
IoTClient开发4 - ModBusTcp协议服务端模拟
-
IoTClient开发3 - ModBusTcp协议客户端实现
-
Python Web开发中的WSGI协议简介
-
moviepy音视频开发专栏文章目录
-
Agora获5000万美元B轮融资 帮助开发者为应用添加语音视频功能
-
Java开发笔记(一百一十六)采用UDP协议的Socket通信
-
java之接口开发-初级篇-webservice协议