1. What - REMB 是什么?
Receiver Estimated Max Bitrate (REMB) 是一种RTCP 反馈消息,作为接收方,告诉发送方它可以接收的带宽是多少,它是一种简单的拥塞控制方法,接收不了就发发慢点。
根据 RFC4585 中的定义,它属于 PSFB(Payload Specific FeedBack) 消息,其 payload type 为 206, fmtType 为15.
它同时也定义了一个绝对值时间戳的 RTP 扩展 abs_send_time,用于带宽估计。
- RTP 扩展 abs_send_time
- 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=2 | 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 消息格式如下:
- 首先看它的 Payload Type,206 意谓 PSFB 即荷载特定的反馈 Payload-specific Feedback, 参见 http://www.rfcreader.com/#rfc5104 Codec Control Feedback 编码层反馈
- 其次看它的 FMT type, 15 意谓应用层反馈 Application layer feedback
- 然后看它的 Unique Identifier 唯一标识符 “REMB”
- 最后看相关的 SSRC number, 即RTP流个数,计算估计出带宽为
mantissa * 2 ^ exp
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 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ... |
字段含义
版本 version (V): (2 bits): RTP 当前的版本为 2.
是否填充 padding (P) (1 bit): 这里不用填充,总是为 0.
反馈消息类型 Feedback message type (FMT) (5 bits): 因为这是一个应用层的反馈消息,所以总是填 15
荷载类型: Payload type (PT) (8 bits): 因为这是一个 Payload-specific FB message, 所以总是填 206
- 长度 Length (16 bits): 这个包的总长度(32bit)-1, 包括包头和填充值
包发送者的同步源: SSRC of packet sender (32 bits)
媒体源的 SSRC 值: SSRC of media source (32 bits): 这里总是填 0
唯一的标识符 Unique identifier (32 bits): 总是为 'R' 'E' 'M' 'B' (4 ASCII 字符).
同步源的个数 Num SSRC (8 bits)
带宽的指数 BR Exp (6 bits): The exponential scaling of the mantissa for the maximum total media bit rate value, ignoring all packet overhead. The value is an unsigned integer [0..63], as in RFC 5104 section 4.2.2.1.
带宽的底数 BR Mantissa (18 bits): The mantissa of the maximum total media bit rate (ignoring all packet overhead) that the sender of the REMB estimates. The BR is the estimate of the traveled path for the SSRCs reported in this message. The value is an unsigned integer in number of bits per second.
所反馈的SSRC 一个或多个值 SSRC feedback (32 bits) Consists of one or more SSRC entries which this feedback message applies to.
最终计算出来的带宽估计为
receiver-bit-rate = mantissa * 2^exp
3.4 如何估算出带宽
这个带宽是怎么估计出来的,在接收方主要就根据延迟 delay 通过一些算法来估算
基于延迟的控制的算法主要分为四个部分:
- pre-filtering 预先过滤
- arrival-time filter 到达时间过滤器
- over-use detector 过度使用检测器
- rate-control 速率控制器
到达时间模型
两个包发送的间隔 [T(i) - T(i-1)]
和接收的间隔 t(i) - t(i-1)]
在理想情况下是相同的,实际上会有不同.也就是说包的到达时间并未保持稳定的速度。在计算的时候可以用以帧分组,对两个组的到达时间进行计算。
- 发送时间间隔与到达时间间隔之间的延时的观测公式,称为单向延迟变化
还可将数据包组之间的延迟变化建模为
这里的 w(i) 是一个随机过程 W 的采样,它是一个连接容量,当前交叉流量和当前比特率的函数,我们将 W 建模为一个白高斯过程。如果我们过度使用了传输通道,则 w(i) 的平均值就会增大,如果网络路径中的拥塞队列已经清空了,这个 w(i) 的平均值就会减小,否则 w(i) 的平均值为零。
由此, 我们可以将w(i) 分解为它的平均值加上一个偏差
v(i) 表示网络抖动和其他没有被这个模型捕捉到的延迟
1) Pre-filtering 预先过滤
预滤波旨在处理由信道中断引起的延迟瞬变。在中断期间,由于与拥塞无关的原因,在网络缓冲区中排队的数据包会在中断结束时突发传送。预过滤将突发到达的数据包组合并在一起。
如果满足以下两个条件之一,则数据包将合并到同一组中:
- 在一个 burst_time 间隔内发送的数据包序列构成一个组。
- 具有小于 burst_time 的到达间隔时间和小于0 的组间延迟变化d(i)
的数据包被认为是当前数据包组的一部分。
- 具有小于 burst_time 的到达间隔时间和小于0 的组间延迟变化d(i)
这个 burst_time 的默认值为 5 ms
RTP 包中的 timestamp 是与媒体采集和回放相关的时间戳,并不是包发送的时间,发送时间通过上面提到的 RTP 包头的扩展 abs_send_time 发到接收方去。
2) 到达时间滤波器 arrival time filter
根据到达时间模型,我们可以通过 Kalman Filter 或者 Trendline Filter
来求得网络排队延迟 [m(i)]{.title-ref}
其中
- q(i) 为状态噪声 u(i) 方差的期望,推荐值是 10^-3
- u(i) 是指状态噪声,
把它建模为具有零均值和方差的高斯统计模拟的平稳过程 - v(i) 是指测量噪声,它是具有方差 [var_v = E{v(i)^2}]{.title-ref}
的零均值高斯白测量噪声
注:
- 中心化(又叫零均值化):是指变量減去它的均值。其实就是一个平移的过程,平移后所有数据的中心是(0,0)
- 标准化(又叫归一化): 是指數值減去均值,再除以标准差。
卡尔曼滤波器递归地更新这个估计值 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
每次接收到视频帧 时,过度使用检测器都会产生一个信号
s,该信号基于排队延迟 和阈值 来驱动 FSM
(下面的有限状态机) 的状态 ,算法 1 详细显示了 s 是如何生成的 :
当 时,算法通过增加帧间隔时间 的变量
来跟踪在这种情况下花费的时间。 当 达到
且 ` 时,产生过度使用信号。
另一方面,如果 减小到 以下,则产生未充分利用信号,而当
时触发正常信号。
4) 速率控制器 Rate controller
发送速率控制器分为两部分:
- 根据延迟估计的带宽来控制发送速率, 这个放在接收方 (WebRTC 在后续版本中也改到了发送方)
通过下面的公式来计算
- 根据丢失估计的带宽来控制发送速率, 这个放在发送方
- 状态转换表 ( 空白处表示保持状态)
+----+--------+-----------+------------+--------+
| \ 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 消息中包含的最大带宽估计调整自己的发送采样率/分辨率/帧率,也就是调整发送的码率,以满足基本的通信需求。