WebRTC 带宽探测工作原理以及如何在 gcc 中使用

在不完善的网络上最大限度地提高实时流质量是一种微妙的平衡行为。如果发送过多信息,就会造成拥塞和丢包。如果发送的信息太少,视频(或音频)的质量就会像垃圾一样。但您能发送多少信息呢?“带宽探测 “就是用于发现这一问题的技术之一。

本文由 Kaustav Ghosh 为我们分享带宽探测以及它在 WebRTC 带宽估算中的作用。Kaustav Ghosh 是微软公司的高级软件工程师,在爱沙尼亚塔林工作。Kaustav 介绍了为什么需要探测、探测的工作原理,回顾了谷歌带宽控制 (GCC) 中 libwebrtc 的实现,并回顾了用于调试带宽估计 (BWE) 问题的工具。

WebRTC 带宽探测工作原理以及如何在 gcc 中使用
图片来自webrtchacks

简介

谷歌拥塞控制(GCC)是 WebRTC 中使用的先进拥塞控制算法。它在优化网络性能(尤其是在实时通信中)方面发挥着至关重要的作用。带宽探测是 GCC 中用于帮助估计带宽的技术之一。

遗憾的是,带宽探测是 WebRTC 中记录较少的领域之一。在这篇文章中,我将根据撰写本文时最新的 Chromium WebRTC 源代码,记录带宽探测背后的奥秘。

有关 WebRTC 中 GCC 算法的详细信息,我推荐这份草案文件。它可能已经过时,但它解释了很多基本原理。

拥塞控制中为什么需要带宽探测?

RTC 中的拥塞控制是检测网络拥塞的过程,这样发送方就能控制发送的数据量,而不会造成网络超载和数据包丢失。要做到这一点,WebRTC 协议栈需要对可用带宽的运行估计。如果带宽估计值(BWE)过高,WebRTC 协议栈可能会发送过多信息并造成拥塞,从而降低媒体质量。如果 BWE 太低,WebRTC 可能无法发送足够的比特来获得足够的质量。

WebRTC 客户端发送数据流并从接收方接收 RTCP 反馈,该反馈显示数据包是否成功交付以及何时到达。该反馈被用作 WebRTC 中两种传统带宽估算器的输入,即 (1) 基于延迟的估算器和 (2) 基于损耗的估算器。基于损耗的估算器使用数据包损耗信息,而基于延迟的估算器使用网络中的数据包延迟信息。有关基于延迟的估算器的更多信息,请点击此处;有关基于损耗的估算器的信息,请点击此处。最终的带宽估计值是两个估计值的最小值。

基于延迟的估算器基于加法增加和乘法减少或 AIMD 原理。因此,当网络质量较差时,它可以通过快速减少发送带宽来迅速做出反应。然而,在通话开始时等情况下,估计器通常比较保守,因为它不知道网络能处理多少。同样,在拥塞事件发生后,基于延迟的估算器也不希望网络不堪重负,造成另一次拥塞问题,因此带宽估算只会缓慢增加。但如果实际上有足够的带宽来改善流质量呢?如何知道呢?这就需要使用探测功能。探测是一种测试方法,可以在不使用 “真实 “流量的情况下了解连接能处理多少数据。探测包括在短时间内以高于当前带宽估计值的速率发送 RTP 数据包,以积极提高带宽估计值。

可以忽略探测数据包,而不会降低接收端的媒体质量。

探测技术

WebRTC 使用两种技术进行探测——RTX 探测和填充探测(padding probes)。请注意,前向纠错 (FEC) 数据包也可用于探测,但 WebRTC 没有采用这种方法。

RTP 重传 (RTX) 探测

RTX 探测是重新发送以前的 RTP 数据包,RTX 重传在 RFC4588 中规定为与对等方协商时的有效载荷格式。这些数据包将具有不同的 abs-send-time 或 transport-wide-cc 序列号,并使用与媒体 RTP 流相关联的 RTX RTP 流(即 RTX 有效载荷类型、序列号和时间戳)。

WebRTC 带宽探测工作原理以及如何在 gcc 中使用

RTX 探测使用最近发送的、远端尚未确认的 RTP 数据包。如果原始数据包丢失,再次发送这些数据包及时到达以恢复原始数据包的几率很小。否则不会影响接收方的 RTP 处理。

使用 RTX 进行探测通常是首选。与下一节讨论的 RTP Padding probes 不同,RTX 数据包是真正的 RTP 数据包,因此能有效地模拟 RTP 流。

RTP Padding probes

Padding probes 仅由带有标头扩展(abs-send time 或 transport-wide-cc sequence number)的 RTP 填充数据包组成,并设置 RTP P 位。它们还具有特定的 RTP 有效载荷格式–255 个字节,全部为零,后跟一个值为 255 的字节。参见 RFC3550 第 5.1 节。当协商 RTX 或以其他方式与媒体数据包共享同一 RTP 流时,Padding probes 使用 RTX RTP 流(即有效载荷类型、序列号和时间戳)。

WebRTC 带宽探测工作原理以及如何在 gcc 中使用

这些探测用于以下两种情况:

  • 未协商 RTX(如音频,较少用于视频)或
  • 没有合适的原始数据包用于 RTX 探测。

为避免时间戳混淆,Padding probes 不应与视频帧数据包交错使用。请注意,有可能在带有帧标记位的数据包之后出现具有相同 RTP 时间戳的探测数据包。Padding probes 数据包仅用于带宽估算,不用于 WebRTC 协议栈的其他地方。

这些数据包只有 255 字节的 RTP 有效载荷,体积很小。这导致需要发送更多数据包来测试更高的比特率。从拥塞控制的角度来看,这样做有其弊端,因为在短时间内发送大量数据包可能会造成数据包丢失。

发送探测簇(Sending probe clusters)

在本节中,我们将介绍该算法。如需了解更多详情,请点击此处查看 Chromium 源代码:https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/pacing/。

探测簇由在很短时间内发送的多个探测数据包组成,用于检查是否可以达到目标比特率。由于探测数据包的发送时间较长,因此可以测试较高的比特率(即比特率 = 发送比特/时间结束 – 时间开始)。当需要发送探测数据时,通过调用函数 BitrateProber::CreateProbeCluster 可以创建一个探测簇。

如果允许探测仪进行探测,就会初始化一个新的探测会话。在当前实现中,除非数据包大小足以用于探测,否则不会初始化探测程序。初始化探测程序所需的最小数据包大小默认为 200 字节。该值可通过字段试验 WebRTC-Bwe-ProbingBehavior 进行配置。

还有一个RTPSender::GeneratePadding函数,可以从数据包历史记录中查找合适大小的数据包,并在需要时生成填充数据包。此时,这些选定的探测包不会被发送。相反,它们被放入起搏器队列中。

最后,还有一个 Pacer 组件,用于平滑发送到网络上的数据包流。 Pacer 检查待处理数据包(包括探测数据包)的起搏器队列,并通过调用函数 PacingController :: ProcessPackets将它们转发以发送到网络。

通过探测估计比特率

发送方发送探测簇的探测数据包。然后,接收方通过全传输拥塞控制 RTCP 反馈信息让发送方知道每个数据包的到达时间。

在使用发送方带宽估算时,发送方知道哪些数据包是探测群组的一部分,哪些是普通媒体数据包。有了这些额外信息,发送方就能更好地处理诸如丢失的数据包是探测数据包等情况。而在使用接收方带宽估算时,接收方则没有这些信息。

对于发送方收到反馈的每个探测数据包,发送方都会调用 ProbeBitrateEstimator::HandleProbeAndEstimateBitrate(const PacketResult& packet_feedback)。如果探针数据包完成了一个有效的探针簇,该函数就会返回估计比特率。

首先,该方法计算探测簇的发送间隔、接收间隔、发送速率和接收速率。在下列情况下,探测分组是成功或有效的:

  • 探测簇的发送和接收间隔有效
  • 探测簇的接收速率和发送速率之间的比率有效

估计比特率是探测簇的发送速率和接收速率的最小值。如果我们的接收比特率明显低于发送比特率,则表明我们已经找到了链路的真正容量。在这种情况下,它会将目标比特率设置得稍低一些,以避免立即过度使用。

何时探测

本节概述了通话期间发送探测的主要情况。

通话开始时

在非联播呼叫开始时,WebRTC 硬编码的开始带宽估计值为 300kbps。传统的估算器需要较长的时间才能提升到能够发送高质量视频的带宽估算值,即在良好的网络中以 1.5mbps 的比特率运行 720p 分辨率的视频。

正如您在 GCC 代码中看到的,当没有探测被触发(这是 kInit 状态)且传输已连接(即网络可用)时,ProbeController 会发送两个探测。这些探测会以指数方式提升估计值。两个指数探测的目标比特率分别为 (3 * start_bitrate) = 900kbps 和 (6 * start_bitrate) = 1800kbps,其中 start_bitrate 是硬编码值 300kbps。

如果在上述情况下网络不可用,一旦网络可用,将立即触发两个指数探测。

当视频通道的最大码率增加时

一旦探测完成,如果视频通道的新最大比特率(与SDP中的带宽属性b=AS相同)高于旧的最大比特率和当前估计,则可以发送另一个探测来检查我们是否可以实现这一点更高的比特率。

当探测正在进行并且通道有更多容量时

当探测正在进行时,如果新的估计比特率大于进一步探测所需的最小比特率并且信道具有更多容量,则ProbeController可以在等待探测结果的同时继续进一步探测。

带宽估计大幅下降后

带宽估计器可以对瞬时网络异常做出反应并放弃带宽估计。理想情况下,估计器根本不应对与拥塞无关的问题做出反应。然而,由于估算器希望快速反应,因此并不总是有时间确定问题是否持续存在。如果暂时性问题导致比特率大幅下降,则可能需要很长时间才能通过正常的提升过程完全恢复。

一旦从带宽估计的大幅下降返回到正常状态,就会调用函数ProbeController::RequestProbe()。它以0.85 * bitrate_before_last_large_drop_启动单个探测会话(如果尚未探测)。如果探测会话失败,则假设此丢弃是来自竞争流或网络更改的真实丢弃。

当 max_total_alulated_bitrate 更改时

当调用ProbeController::OnMaxTotalAllocationBitrate()函数时,会显示max_total_allocated_bitrate(所有活动发送流的配置比特率之和)已更改。该算法发送探测来检查是否可以达到该比特率。

这是在高目标比特率探测之后可能触发低目标比特率探测的示例之一。如果max_total_allocated_bitrate价值下降,可能会发生这种情况。

应用受限区域 (ALR) 探测

发送到网络的数据可能受限于应用程序产生流量的能力,而不是带宽限制,例如,当共享一个静态内容的浏览器标签页时。这种情况称为应用受限区域(ALR)。当处于 ALR 时,由于没有足够的数据,传统的拥塞控制方法无法保持较高的带宽估计值。

在这种情况下,ProbeController 会定期发送探测,以生成足够的数据来保持较高的带宽估计值。

WebRTC 带宽探测工作原理以及如何在 gcc 中使用

例如,上图是一个启用了视频屏幕共享功能的通话。根据静态视频屏幕共享的设计,网络流量受到应用程序的限制。蓝线显示,大部分时间发送的比特率低于 400kbps。因此,libwebrtc 每 5 秒发送一次定期探测,以保持较高的带宽估计值。

探测行动

使用 Fippo 的在线可视化工具或 Google 的 RTC 事件日志可视化工具,可以快速了解探测在 WebRTC 呼叫中是如何工作的。这两种工具都是通过解析 RTC 事件日志来绘制图表的。不过,在线可视化工具对探测簇的可视化支持更好。我从一个 WebRTC 视频通话示例中捕获了 RTC 事件日志,并在下面的示例中使用了在线可视化工具。

WebRTC 带宽探测工作原理以及如何在 gcc 中使用

探测成功后带宽估计如何变

呼叫开始时,带宽估计从硬编码的 300kbps 值开始。但随着视频的启用,发送者希望尽快发送高质量的视频。因此,它发送 3 个具有不同比特率的探测簇(簇 ID 1、2 和 3)。这些被标记为浅蓝色点。一旦这些探测簇成功(深蓝色点),带宽估计值会在不到一秒的时间内大幅增加到 1mbps 以上。之后,它会再发送两个探测簇(簇 ID 4 和 5),一旦成功,它会将估计值推至 3mbps 以上。

WebRTC 带宽探测工作原理以及如何在 gcc 中使用

探测簇详细信息

如果将鼠标悬停在图表中的探测簇上,就可以看到与探测簇相关的详细信息,即该群集部分 RTP 数据包的序列号和大小、簇 ID 以及探测目标比特率。 将鼠标悬停在图表中的探测簇结果上,即可查看相关的延迟和估计带宽。

还可以从该工具下载 RTP 数据包转储,以便在 Wireshark 中仔细查看单个探测数据包。在撰写本文时,该工具还不完全支持新的事件日志格式。因此,请考虑使用 --force-fieldtrials=WebRTC-RtcEventLogNewFormat/Disabled/ 启动 Chrome 浏览器,以获得完整的 RTP 数据包转储和其他有用的功能。

结论

总之,带宽探测的原理是发送额外的数据包来测量可用带宽。通过像侦察员一样进行探测,可确保流畅、愉快的通话体验。

libwebrtc 可能会决定在呼叫期间的各种情况下发送不同目标比特率的探测。随着 libwebrtc 的不断发展,带宽探测仍在进一步改进和完善。

作者:Kaustav Ghosh
译自:https://webrtchacks.com/probing-webrtc-bandwidth-probing-why-and-how-in-gcc/

本文来自作者投稿,版权归原作者所有。如需转载,请注明出处:https://www.nxrte.com/jishu/webrtc/48157.html

(0)

相关推荐

发表回复

登录后才能评论