媒体通信

我可以从WebRTC的媒体通信中得到什么? #

WebRTC允许您发送和接收无限多条音频和视频流。您可以在通话期间随时添加和删除这些流。这些流可以全部独立,也可以捆绑在一起!您甚至可以将网络摄像头的音频/视频放到您桌面的视频流中,然后将此视频流以feed的形式发送出去。

WebRTC协议与编解码器无关。底层传输支持所有格式的内容,即使是还不存在的格式! 但是,您正与之通信的WebRTC代理可能没有必要的工具来接受它。

WebRTC针对动态网络状况也有对应的处理方案。在通话过程中,带宽可能会增加或减少。甚至可能突然间大量丢包。该协议对所有这类问题的处理都做了相应的设计。WebRTC根据网络状况作出响应,并尝试利用可用资源为您提供最佳体验。

它是如何工作的? #

WebRTC使用RFC 1889中定义的两个既有协议RTP和RTCP。

RTP(实时传输协议/Real-time Transport Protocol)是承载媒体的协议。它为视频的实时传输而设计。它没有规定有关延迟或可靠性的任何规则,但是为您提供了实现这些规则的工具。RTP提供了流的设计,因此您可以通过一个连接发布多个媒体源。它还为您提供了完善媒体传递途径所需的计时和排序信息。

RTCP(RTP控制协议/RTP Control Protocol)是用于传达有关呼叫的元数据的协议。其格式非常灵活,并允许您可以添加所需的任何元数据。这点被用来传达有关呼叫的统计信息。也是处理分组丢失和实现拥塞控制的必备特性。它为您提供了响应变化的网络状况所必需的双向通信能力。

延迟与质量 #

实时媒体就是要在延迟和质量之间进行权衡。您愿意忍受的延迟时间越长,可以预期的视频质量就越高。

现实世界的局限性 #

下面这些限制都是由现实世界的局限性引起的。它们都是您需要考虑的网络特性。

视频是复杂的 #

传输视频并不容易。要存储30分钟未压缩的720p的8-bit视频,您需要~110Gb。按照这个数据,4人电话会议就开不成了。我们需要一种缩小尺寸的方法,而答案就是视频压缩。但是,这并非没有缺点。

视频101 #

我们不会深入介绍视频压缩,只需要让大家足以理解为什么RTP是这么设计的。视频压缩会将视频编码为一种新格式,这样可以需要较少的存储空间。

有损和无损压缩 #

视频压缩可以是无损的(没有信息丢失)或有损的(可能有信息丢失)。RTP通常使用有损压缩。在图片中丢失一些细节,总好过图片(因数据太多而)无法传输。

帧内和帧间压缩 #

视频压缩有两种类型。首先是帧内压缩。这是一种压缩单个图片的方法,与JPEG之类的技术相同。

第二种类型是帧间压缩。由于视频是由许多图片组成的,因此我们需要寻找无需将相同信息发送两次的方式。

帧间压缩 #

帧有三种类型

  • I帧 - 一张完整的图片,无需任何其他内容即可解码
  • P帧 - 一张图片的一部分,包含对之前图片的修改
  • B帧 - 一张图片的一部分,包含对之前图片和将来图片的修改

以下是对这三种类型帧的图解。

视频很脆弱 #

压缩后的视频是有状态的,(视频解码)非常依赖其上下文,这使得视频很难通过Internet进行传输。想像一下,如果I帧的一部分丢失了会怎样?这样P帧如何知道要修改的内容? 随着视频压缩变得越来越复杂,这成为一个更大的问题。幸运的是,RTP和RTCP对此都有解决方案。

RTP #

Packet Format(包格式) #

每个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                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Version (V) #

Version总是2

Padding (P) #

Padding是控制有效载荷是否具有填充值的布尔值。

有效负载的最后一个字节包含添加了多少填充字节的计数。

Extension (X) #

如果设置的话,RTP报头将有扩展段(可选)。这点将在下面更详细地描述。

CSRC count (CC) #

SSRC之后,有效负载之前的CSRC标识符的数量。

Marker (M) #

标记位没有预设含义,由用户决定。

在某些情况下,它是在用户讲话时设置的。它还通常用于标记关键帧。

Payload Type (PT) #

Payload Type(负载类型)是此数据包所承载的编解码器的一个唯一标识符。

对于WebRTC,Payload Type是动态的。一个呼叫中的VP8的PT可能与另一个呼叫中的不同。呼叫中的Offerer确定Payload TypeSession Description(会话描述符)中的编解码器的映射。

Sequence Number #

Sequence Number(序列号)用于对流中的数据包进行排序。每次发送数据包时,Sequence Number都会增加1。

RTP被设计为可以在有损网络上使用。这为接收器提供了一种检测数据包何时丢失的方法。

Timestamp #

此数据包的采样时刻。这不是全局时钟,而是在当前媒体流中所经过的时间。

Synchronization Source (SSRC) #

SSRC是此流的唯一标识符。 这使您可以在单个流上传输多个媒体流。

Contributing Source (CSRC) #

一个列表,用于表示哪些SSRC参与到了这个数据包中。

这通常用于语音指示器。假设在服务器端,您将多个音频源组合到一个单独的RTP流中。然后,您可以在此字段中表示输入流A和C此时正在讲话

Payload #

实际有效负载数据。如果设置了填充(padding)标记,则可能以添加的填充字节数结尾。

Extensions(扩展) #

RTCP #

Packet Format #

每个RTCP数据包都具有以下结构:

 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|    RC   |       PT      |             length            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                            Payload                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Version (V) #

Version总是2

Padding (P) #

Padding是控制有效载荷是否具有填充值的布尔值。

有效负载的最后一个字节包含添加了多少填充字节的计数。

Reception Report Count (RC) #

此数据包中的报告数。单个RTCP数据包可以包含多个事件。

Packet Type (PT) #

指示RTCP数据包类型的唯一标识符。WebRTC代理不需要支持所有这些类型,并且代理之间的支持能力可以是不同的。下面这些是您可能经常看到的类型。

  • 完整的帧内请求(FIR)-192
  • 否定确认(NACK)-193
  • 发送方报告-200
  • 接收方报告-201
  • 通用RTP反馈-205

这些分组类型的意义将在下面更详细地描述。

Full INTRA-frame Request(完整的帧内请求) #

此RTCP消息通知发送者它需要发送完整图像。这适用于编码器为您提供了帧的一部分,但您无法对其进行解码的情况。

之所以会发生这种情况,是因为您有很多数据包丢失,或者解码器崩溃了。

Negative ACKnowledgements(否定确认) #

NACK请求发送方重新发送单个RTP数据包。这通常是由于RTP数据包丢失而引起的,但是也可能由于延迟而发生。

与请求重新发送整个帧相比,NACK的带宽效率要高得多。由于RTP将数据包分解成很小的块,因此您实际上只是在请求丢失的一个很小的部分。

Sender/Receiver Reports(发送方/接收方报告) #

这些报告用于在代理之间发送统计信息。它传达了实际接收到的和抖动的数据包数量。

这些报告可用于诊断以及控制拥塞。

RTP/RTCP是如何协作解决问题的 #

RTP和RTCP需要协同解决网络引起的所有问题。这些技术仍在不断进化中!

Negative Acknowledgment(否定确认) #

也称为NACK。这是使用RTP处理数据包丢失的一种方法。

NACK是回给发送方以请求重发的RTCP消息。接收方使用SSRC和序列号制作RTCP消息。如果发送方没有可用于重新发送的RTP数据包,则忽略该消息。

Forward Error Correction(前向纠错) #

简称为FEC。处理丢包的另一种方法。FEC指的是发送方多次重复发送相同的数据,甚至是在接收方没有要求的情况下发送。这是在RTP协议层级完成的,甚至也可以在编解码器以下的层级完成。

在呼叫的数据丢包率比较稳定的情况下,作为延迟处理方案,FEC比NACK好的多。对于NACK,必须先请求,然后重新传输数据包,数据往返的时间对性能的影响可能是很明显的。

自适应比特率和带宽估计 #

正如搭建实时网络中讨论的那样,网络是不可预测且不可靠的。带宽的可用性在整个会话中可能会多次变化。 在一秒钟之内看到可用的带宽急剧变化(差别达到数量级),这样的情况并不少见。

这里的主要思路是根据预测的,当前的和将来的可用网络带宽来调整编码比特率。 这样可以确保传输质量最佳的视频/音频信号,并且不会因为网络拥塞而断开连接。 对网络行为建模并尝试对其进行预测的启发式方法称为带宽估计。

这里有很多细微的差别,因此我们来探索一下更多细节。

传递网络状态 #

实施拥塞控制的第一个障碍是UDP和RTP不会传递网络状态。作为发送方,我不知道我的数据包在什么时候到达,甚至根本不知道它们到达了没有!

针对此问题,RTP/RTCP有3种不同的解决方案。每种都有自己的优点和缺点。使用什么方案取决于您面向的客户类型、使用的网络拓扑、甚至是您有多少开发时间。

接收方报告 #

接收方报告是一些RTCP消息,这是传递网络状态的最原始的方法。您可以在RFC 1889中找到它们。按照时间计划,它们会被发送给每个SSRC,并包含以下字段:

  • 丢包率 – 自上次接收者报告以来丢失了数据包的百分比。
  • 累计丢包数 – 在整个通话过程中丢了多少包。
  • 接收到的最高序列号扩展 – 接收到的最后一个序列号,以及它滚动的次数。
  • 到达间隔抖动(Interarrival Jitter) – 整个通话过程中的抖动滚动。(译注:RTP数据包到达时间的统计方差的估计值,以时间戳为单位进行度量,并表示为无符号整数。)

TMMBR,TMMBN和REMB #

下一代的网络状态消息都是接收方通过带有显式比特率请求的RTCP消息传递给发送方。

  • TMMBR(临时最大媒体码率请求) - 单个SSRC请求码率的尾数/指数。(译注:接收端当前带宽受限,告诉发送端控制码率。)
  • TMMBN(临时最大媒体码率通知) - (发送端)通知(接收端)已经收到TMMBR的消息。
  • REMB(接收方估计的最大码率) - 整个会话中请求码率的尾数/指数。

TMMBR和TMMBN是先出现的,它们在RFC 5104中定义。REMB是后来出现的,是在draft-alvestrand-rmcat-remb中提交的一个草案,但从未被标准化。

使用REMB的会话如下图所示

传输范围内的拥塞控制(TWCC) #

传输范围内的拥塞控制是RTCP网络状态通信技术的最新进展。

TWCC使用一个非常简单的原则:

与REMB不同,TWCC的接收方不会尝试估计自己的传入比特率。它只是让发送方知道哪些包被收到了,是在什么时间收到的。基于这些报告,发送方可以了解网络的最新的状况。

  • 发送方创建带有特殊的TWCC标头扩展的RTP数据包,其中包含一个数据包序列号的列表。
  • 接收方以特殊的RTCP反馈消息进行响应,以使发送方知道每个数据包是否以及何时被接收。

发送方跟踪已发送的数据包,包括它们的序列号,大小和时间戳。 当发送方从接收方收到RTCP消息时,它将发送数据包间的延迟与接收延迟进行比较。 如果接收延迟增加,则意味着网络正在发生拥塞,发送者必须对此采取行动。

在下图中,数据包间延迟的中位数增长了+20毫秒,这清楚地表明网络正在发生拥塞。

TWCC提供了原始数据和实时网络状况的绝佳视图:

  • 几乎是即时的丢包统计信息,不仅包括丢失的百分比,还包括丢失的确切数据包。
  • 准确的发送比特率。
  • 准确的接收比特率。
  • 抖动估计。
  • 发送和接收数据包延迟之间的差异。

一种简单的,用于估计从发送方到接收方的传输比特率的拥塞控制算法是,将接收到的数据包大小相加,然后将其除以接收方一端经过的时间。

生成带宽估计值 #

现在,我们掌握了有关网络状态的信息,可以针对可用带宽进行估算了。IETF在2012年成立了RMCAT(RTP媒体拥塞避免技术)工作组。 该工作组包含了已提交的多个拥塞控制算法的标准。在此之前,拥塞控制算法是专有的。

部署最多的实现是’用于实时通信的Google拥塞控制算法(GCC)',定义于draft-alvestrand-rmcat-congestion。 它可以分两次运行。第一次运行是’基于损失’的,仅使用接收方报告。如果TWCC是可用的,它也会将其数据加入。 它通过使用Kalman过滤器预测当前和将来的网络带宽。

还有几种GCC的替代品,例如:NADA:一种实时媒体的统一拥塞控制方案SCReAM- 多媒体的自时钟速率自适应