音视频开发笔记

WebRTC 拥塞控制之 REMB - 接收方带宽估计

2021-01-05  本文已影响0人  老瓦在霸都

1. What - REMB 是什么?

Receiver Estimated Max Bitrate (REMB) 是一种RTCP 反馈消息,作为接收方,告诉发送方它可以接收的带宽是多少,它是一种简单的拥塞控制方法,接收不了就发发慢点。

根据 RFC4585 中的定义,它属于 PSFB(Payload Specific FeedBack) 消息,其 payload type 为 206, fmtType 为15.

它同时也定义了一个绝对值时间戳的 RTP 扩展 abs_send_time,用于带宽估计。

  1. RTP 扩展 abs_send_time
  2. RTCP 扩展 REMB

REMB 这个 RTCP 反馈消息用于接收方通知发送方,它们在同一RTP会话上有多个媒体流在传输, 所通知的内容就是该RTP会话的接收方路径上的总的可用带宽的估计值 (比特率)。

在用于 REMB 反馈消息的公共数据包头中(如[RFC4585]的6.1节所定义),“数据包发送者的SSRC” 字段指示通知的来源。 不使用“媒体源的SSRC”,并且应将其设置为0。在其他RFC中也使用零值。

媒体发送方对符合此规范的REMB消息的接收将导致该消息在RTP会话上发送的总比特率等于或低于此消息中的比特率。 新的比特率限制应尽快应用。 发送者可以根据自己的限制和估计自由应用其他带宽限制。

2. Why 为什么要有 REMB?

发送者不知道接收方的带宽情况,它需要有一个机制由接收方告诉它有多少带宽可供传输, 这样发送方可以根据这个估计的带宽来调整分辨率(90p, 180p, 360p, 720p等)和帧率(每秒24, 30, 40, 60帧等)

3. How 怎么实现 REMB?

3.1. SDP 中包含如下属性

a=rtcp-fb:<payload type> goog-remb
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time

3.2. 发送 RTP 包时带下 abs_send_time 头

这是一个 one-byte 扩展,3 个字节的数据,每个包额外携带 4 个字节。还有与其他扩展头共享的 2 字节魔术字节 0xBEDE, 2 字节扩展头个数

       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
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |       0xBE    |    0xDE       |           length=n            |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |  ID   | L=0   |     abs_send_time                             | 
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

abs_send_time 是一个以秒为单位的时间戳,总共 3 个字节(24 bit) , 格式为 6.18 (小数位固定为18位), 每 64s 会溢出环绕,分辨率为 3.8us (在 1Gbps 的网卡上每 477 个字节就会产生一个增量)。

相对于64位的 NTP timestamps,以32位来表示秒数,32位来表示秒的小数部分,转换公式为

abs_send_time_24 = (ntp_timestamp_64 >> 14) & 0x00ffffff

注:RTP 包在要发出到网卡时标记这个时间戳,中继的可能要修改媒体流的节点应该删除这个扩展,或者设置自己的发出时间戳。

3.3. 需要限制带宽时发送 REMB RTCP 消息

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| FMT=15  |   PT=206      |             length            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                  SSRC of packet sender                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                  SSRC of media source                         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Unique identifier 'R' 'E' 'M' 'B'                            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Num SSRC     | BR Exp    |  BR Mantissa                      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   SSRC feedback                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  ...                                                          |

字段含义

最终计算出来的带宽估计为

receiver-bit-rate = mantissa * 2^exp

3.4 如何估算出带宽

这个带宽是怎么估计出来的,在接收方主要就根据延迟 delay 通过一些算法来估算

基于延迟的控制的算法主要分为四个部分:

到达时间模型

两个包发送的间隔 [T(i) - T(i-1)] 和接收的间隔 t(i) - t(i-1)]在理想情况下是相同的,实际上会有不同.也就是说包的到达时间并未保持稳定的速度。在计算的时候可以用以帧分组,对两个组的到达时间进行计算。

d(i) = t(i) - t(i-1) - (T(i) - T(i-1))

还可将数据包组之间的延迟变化建模为

d(i) = w(i)

这里的 w(i) 是一个随机过程 W 的采样,它是一个连接容量,当前交叉流量和当前比特率的函数,我们将 W 建模为一个白高斯过程。如果我们过度使用了传输通道,则 w(i) 的平均值就会增大,如果网络路径中的拥塞队列已经清空了,这个 w(i) 的平均值就会减小,否则 w(i) 的平均值为零。

由此, 我们可以将w(i) 分解为它的平均值加上一个偏差

d(i) = m(i) + v(i)

v(i) 表示网络抖动和其他没有被这个模型捕捉到的延迟

1) Pre-filtering 预先过滤

预滤波旨在处理由信道中断引起的延迟瞬变。在中断期间,由于与拥塞无关的原因,在网络缓冲区中排队的数据包会在中断结束时突发传送。预过滤将突发到达的数据包组合并在一起。

如果满足以下两个条件之一,则数据包将合并到同一组中:

这个 burst_time 的默认值为 5 ms

RTP 包中的 timestamp 是与媒体采集和回放相关的时间戳,并不是包发送的时间,发送时间通过上面提到的 RTP 包头的扩展 abs_send_time 发到接收方去。

2) 到达时间滤波器 arrival time filter

根据到达时间模型,我们可以通过 Kalman Filter 或者 Trendline Filter
来求得网络排队延迟 [m(i)]{.title-ref}

m(i+1) = m(i) + u(i)
q(i) = E{u(i)^2}
d(i) = m(i) + v(i)

其中

注:

卡尔曼滤波器递归地更新这个估计值 m_hat(i)

z(i) = d(i) - m_hat(i-1)

m_hat(i) = m_hat(i-1) + z(i) * k(i)

                   e(i-1) + q(i)
k(i) = ----------------------------------------
           var_v_hat(i) + (e(i-1) + q(i))

e(i) = (1 - k(i)) * (e(i-1) + q(i))

var_v_hat(i) = max(alpha * var_v_hat(i-1) + (1-alpha) * z(i)^2, 1)

alpha = (1-chi)^(30/(1000 * f_max))

3) 过度使用检测器 The over-use detector

每次接收到视频帧 t_i 时,过度使用检测器都会产生一个信号
s,该信号基于排队延迟 m(t_i) 和阈值 \gamma 来驱动 FSM
(下面的有限状态机) 的状态 \sigma,算法 1 详细显示了 s 是如何生成的 :

m(t_i) > \gamma 时,算法通过增加帧间隔时间 \Delta T 的变量
t_{OU} 来跟踪在这种情况下花费的时间。 当 t_{OU} 达到
\bar{t}_{OU}=100msm(t_i) > m(t_{i-1})` 时,产生过度使用信号。

另一方面,如果 m(t_i) 减小到 \gamma 以下,则产生未充分利用信号,而当
-\gamma \leq m(t_i) \leq \gamma 时触发正常信号。

4) 速率控制器 Rate controller

发送速率控制器分为两部分:

  1. 根据延迟估计的带宽来控制发送速率, 这个放在接收方 (WebRTC 在后续版本中也改到了发送方)

通过下面的公式来计算 A_r

A_{r}(t_{i})=\cases{\eta A_{r}(t_{i-1}) & ${\rm Increase}$\cr \alpha R(t_{i}) & ${\rm Decrease}$\cr A(t_{i-1}) & ${\rm Hold}$}

  1. 根据丢失估计的带宽来控制发送速率, 这个放在发送方
+----+--------+-----------+------------+--------+
|     \ State |   Hold    |  Increase  |Decrease|
|      \      |           |            |        |
| Signal\     |           |            |        |
+--------+----+-----------+------------+--------+
|  Over-use   | Decrease  |  Decrease  |        |
+-------------+-----------+------------+--------+
|  Normal     | Increase  |            |  Hold  |
+-------------+-----------+------------+--------+
|  Under-use  |           |   Hold     |  Hold  |
+-------------+-----------+------------+--------+

相关参数的默认配置

+-----------------+-----------------------------------+-------------+
| Parameter       | Description                       | RECOMMENDED |
|                 |                                   | Value       |
+-----------------+-----------------------------------+-------------+
| burst_time      | Time limit in milliseconds        | 5 ms        |
|                 | between packet bursts which       |             |
|                 | identifies a group                |             |
| q               | State noise covariance matrix     | q = 10^-3   |
| e(0)            | Initial value of the  system      | e(0) = 0.1  |
|                 | error covariance                  |             |
| chi             | Coefficient used  for the         | [0.1,       |
|                 | measured noise variance           | 0.001]      |
| del_var_th(0)   | Initial value for the adaptive    | 12.5 ms     |
|                 | threshold                         |             |
| overuse_time_th | Time required to trigger an       | 10 ms       |
|                 | overuse signal                    |             |
| K_u             | Coefficient for the adaptive      | 0.01        |
|                 | threshold                         |             |
| K_d             | Coefficient for the adaptive      | 0.00018     |
|                 | threshold                         |             |
| T               | Time window for measuring the     | [0.5, 1] s  |
|                 | received bitrate                  |             |
| beta            | Decrease rate factor              | 0.85        |
+-----------------+-----------------------------------+-------------+

       Table 1: RECOMMENDED values for delay based controller

4. Example

REMB 的实现可以参考 webrtc 的源码:

带宽的计算代码为

uint8_t exponenta = payload[13] >> 2;
uint64_t mantissa = (static_cast<uint32_t>(payload[13] & 0x03) << 16) |
                      ByteReader<uint16_t>::ReadBigEndian(&payload[14]);
bitrate_bps_ = (mantissa << exponenta);

5. Conclusion

网络状况变化多端,时好时坏,在发送音视频不能由着性子随便发,需要根据接收者反馈的 RTCP 消息中包含的最大带宽估计调整自己的发送采样率/分辨率/帧率,也就是调整发送的码率,以满足基本的通信需求。

上一篇 下一篇

猜你喜欢

热点阅读