RTCP Packet Send and Receive Rules:
发送和接收 RTCP 包的规则在此列出。允许在多播环境或多点单播环境中运行的实现必须满足第 6.2 节中的要求。这样的实现可以使用本节定义的算法来满足这些要求,或者可以使用其他算法,只要其性能等同或更优即可。在受限于两方单播操作的实现中,仍然应使用 RTCP 传输间隔的随机化,以避免在相同环境中运行的多个实例产生意外的同步,但可以省略第 6.3.3、6.3.6 和 6.3.7 节中的“计时器再考虑(timer reconsideration)”和“反向再考虑(reverse reconsideration)”算法。
为了执行这些规则,会话参与者必须维护几项状态:
-
tp:上一次发送 RTCP 包的时间;
-
tc:当前时间;
-
tn:计划发送下一个 RTCP 包的时间;
-
pmembers:上次重新计算 tn 时估算的会话成员数量;
-
members:当前估算的会话成员数量;
-
senders:当前估算的会话发送者数量;
-
rtcp_bw:RTCP 目标带宽,即该会话所有成员发送 RTCP 包所使用的总带宽,单位为每秒字节数。这个值将是应用启动时提供的“会话带宽”参数的一个指定比例;
-
we_sent:一个标志,如果应用自前两次 RTCP 报告后已发送数据,则该标志为真;
-
avg_rtcp_size:该参与者发送和接收的 RTCP 包的平均复合大小(以字节为单位)。该大小包括较低层传输和网络协议头(如 UDP 和 IP),具体见第 6.2 节的说明;
-
initial:一个标志,如果应用尚未发送任何 RTCP 包,则该标志为真。
这些规则中的许多使用了“计算出的包传输间隔”。此间隔将在接下来的部分中进行描述。
Computing the RTCP Transmission Interval:
为了保持可扩展性,会话参与者发送包的平均间隔应随着组的大小而变化。这个间隔称为“计算出的间隔(calculated interval)”。它是通过结合上面描述的多个状态来获得的。计算出的间隔 TTT 的确定方法如下:
-
如果发送者的数量小于或等于成员(members)数量的 25%,则间隔取决于该参与者是否为发送者(依据 we_sent 的值)。若参与者为发送者(we_sent 为真),则常数 C 设为平均 RTCP 包大小(avg_rtcp_size)除以 RTCP 带宽(rtcp_bw)的 25%,常数 n 设为发送者的数量。如果 we_sent 为假,常数 C 设为平均 RTCP 包大小除以 RTCP 带宽的 75%,常数 n 设为接收者的数量(members - senders)。如果发送者数量超过 25%,则发送者和接收者一起处理。常数 C 设为平均 RTCP 包大小除以总的 RTCP 带宽,n 设为成员总数。正如第 6.2 节所述,一个 RTP 配置文件可以规定 RTCP 带宽由两个独立的参数明确定义(分别称为 S 和 R),分别用于发送者和非发送者。在这种情况下,25% 的比例为 S/(S+R),75% 的比例为 R/(S+R)。注意,如果 R 为零,则发送者的比例永远不会超过 S/(S+R),实现时必须避免除零的情况。
-
如果参与者尚未发送任何 RTCP 包(变量 initial 为真),则常数 Tmin 设为 2.5 秒,否则设为 5 秒。
-
确定性的计算间隔 Td 设为 max(Tmin, n*C)。
-
计算出的间隔 T 设为 0.5 到 1.5 倍的确定性计算间隔之间的一个均匀分布的数值。
-
为了补偿计时器再考虑算法使 RTCP 带宽收敛于低于预期平均值的情况,最终得到的 T 值除以 e^-3/2 = 1.21828。
这个过程得出的间隔是随机的,但平均来看,至少 25% 的 RTCP 带宽分配给发送者,其余分配给接收者。如果发送者数量超过成员的四分之一,则该过程平均上在所有参与者之间平分带宽
Initialization:
加入会话后,参与者将 tp 初始化为 0,tc 初始化为 0,senders 初始化为 0,pmembers 初始化为 1,members 初始化为 1,we_sent 初始化为 false,rtcp_bw 初始化为会话带宽的指定比例,initial 初始化为 true,avg_rtcp_size 初始化为应用程序稍后将构建的第一个 RTCP 包的预计大小。随后计算出间隔 T,并将第一个包的计划发送时间设定为 tn = T。这意味着设置一个传输计时器,使其在时间 T 到期。请注意,应用程序可以使用任何所需的方法来实现该计时器。参与者将其自身的 SSRC 添加到成员表中。
Receiving an RTP or Non-BYE RTCP Packet:
当从一个 SSRC 不在成员表中的参与者接收到 RTP 或 RTCP 包时,该 SSRC 会被添加到表中,并且一旦该参与者按第 6.2.1 节所述验证通过,members 的值将被更新。对于验证通过的 RTP 包中的每个 CSRC,也会进行相同的处理。当从一个 SSRC 不在发送者表中的参与者接收到 RTP 包时,该 SSRC 会被添加到表中,senders 的值将被更新。对于每个接收到的复合 RTCP 包,avg_rtcp_size 的值会被更新:
其中,packet_size 是刚刚接收到的 RTCP 包的大小。
Receiving an RTCP BYE Packet:
除非在第 6.3.7 节中描述的发送 RTCP BYE 的情况外,如果接收到的包是 RTCP BYE 包,则会将其 SSRC 与成员表进行检查。如果该 SSRC 存在于成员表中,则从表中删除该条目,并更新 members 的值。然后,SSRC 将与发送者表进行检查。如果存在,则从表中删除该条目,并更新 senders 的值。
此外,为使 RTCP 包的传输速率能够更适应组成员数的变化,当接收到的 BYE 包使 members 值小于 pmembers 时,应执行以下“反向再考虑”算法:
-
根据以下公式更新 tn 的值:
-
根据以下公式更新 tp 的值:
-
将下一个 RTCP 包的计划发送时间重新设定为 tn,此时该时间比原计划更早。
-
将 pmembers 的值设为与 members 相等。
该算法并不能完全防止在大型会话中的大部分参与者突然离开但部分仍在的情况下,由于过早超时而导致组大小估算短时间内错误地降至零。然而,该算法可以使估算值更快速地恢复到正确值。这种情况非常少见,且后果较为无害,因此被视为次要问题。
Timing Out an SSRC:
参与者必须定期检查其他参与者是否超时。为此,参与者计算接收者的确定性(不含随机因子)计算间隔 TdTdTd,即 we_sent 为 false 的情况。任何自时间 tc−MTdtc - MTdtc−MTd(其中 MMM 为超时倍数,默认值为 5)起未发送 RTP 或 RTCP 包的会话成员将被视为超时。这意味着其 SSRC 会从成员列表中删除,且 members 的值会更新。发送者列表也需进行类似的检查。任何自时间 tc−2Ttc - 2Ttc−2T(即在最近两个 RTCP 报告间隔内)未发送 RTP 包的发送者会从发送者列表中删除,并更新 senders 的值。如果有任何成员超时,应执行第 6.3.4 节中描述的反向再考虑算法。参与者必须至少在每个 RTCP 传输间隔内执行一次此检查。
Expiration of Transmission Timer:
当数据包传输计时器到期时,参与者执行以下操作:
-
按第 6.3.1 节所述计算传输间隔 TTT,包括随机因子。
-
如果 tp+T≤tctp + T \leq tctp+T≤tc,则发送一个 RTCP 包。将 tptptp 设为 tctctc,然后按前一步计算另一个 TTT 值,并将 tntntn 设为 tc+Ttc + Ttc+T。将传输计时器设置为在时间 tntntn 到期。如果 tp+T>tctp + T > tctp+T>tc,则将 tntntn 设为 tp+Ttp + Ttp+T。不发送 RTCP 包,传输计时器设置在时间 tntntn 到期。
-
将 pmembers 设为 members。
如果发送了 RTCP 包,则将 initial 值设为 FALSE。此外,更新 avg_rtcp_size 的值:
其中,packet_size 是刚刚发送的 RTCP 包的大小.
Transmitting a BYE Packet:
当参与者希望离开会话时,会发送一个 BYE 包,以告知其他参与者该事件。为避免当许多参与者离开系统时出现 BYE 包的洪流,如果在参与者选择离开时成员数超过 50,则必须执行以下算法。该算法会改变成员变量的正常作用,将其用于统计 BYE 包的数量:
-
当参与者决定离开系统时,将 tp 重置为 tc(当前时间),并将 members 和 pmembers 初始化为 1,initial 设为 1,we_sent 设为 false,senders 设为 0,avg_rtcp_size 设为复合 BYE 包的大小。随后计算出的间隔 TTT 会被计算出。BYE 包则计划在 tn=tc+Ttn = tc + Ttn=tc+T 的时间发送。
-
每当接收到来自其他参与者的 BYE 包时,不论该参与者是否存在于成员表中,以及在使用 SSRC 采样时 BYE 的 SSRC 是否会包含在样本中,members 的值都会增加 1。接收到其他 RTCP 或 RTP 包时,members 不会增加,且仅会对接收到的 BYE 包更新 avg_rtcp_size。当 RTP 包到达时,senders 的值不会更新,保持为 0。
-
然后,BYE 包的传输遵循与上述常规 RTCP 包传输相同的规则。
这允许立即发送 BYE 包,同时控制其总带宽使用量。在最坏的情况下,RTCP 控制包的带宽使用量可能是正常情况的两倍(10%):非 BYE RTCP 包占 5%,BYE 包占 5%。如果参与者不想等待上述机制允许 BYE 包的传输,则可以选择离开组而不发送 BYE 包。此参与者最终会被其他组成员超时清除。如果成员数估计 members 小于 50 时该参与者决定离开,则可立即发送 BYE 包。或者,参与者也可以选择执行上述 BYE 回退算法。
无论哪种情况,若一个参与者从未发送过 RTP 或 RTCP 包,则在离开组时不得发送 BYE 包。
Updating we_sent:
变量 we_sent 在参与者最近发送了 RTP 包时为 true,否则为 false。该状态的确定机制与管理发送者表中其他参与者的机制相同。如果当 we_sent 为 false 时参与者发送了一个 RTP 包,它会将自己添加到发送者表中,并将 we_sent 设置为 true。应执行第 6.3.4 节中描述的反向再考虑算法,以可能减少发送 SR 包之前的延迟。每次发送另一个 RTP 包时,该包的发送时间都会保存在表中。然后对该参与者应用正常的发送者超时算法 —— 如果自 tc−2Ttc - 2Ttc−2T 以来没有发送过 RTP 包,则该参与者会将自己从发送者表中移除,减少发送者计数,并将 we_sent 设置为 false。
Allocation of Source Description Bandwidth:
本规范定义了几种源描述(SDES)项,除了必需的 CNAME 项之外,还包括 NAME(个人姓名)和 EMAIL(电子邮件地址)。它还提供了定义新的应用程序专用 RTCP 包类型的方法。应用程序在为这些附加信息分配控制带宽时应谨慎,因为这会减慢接收报告和 CNAME 的发送速率,从而影响协议的性能。建议不超过 20% 的单个参与者的 RTCP 带宽用于携带附加信息。此外,并非所有 SDES 项都要包含在每个应用程序中。包含的项应根据其用途分配带宽比例。建议不动态估算这些比例,而是基于项的典型长度,将百分比静态转换为报告间隔计数。
例如,一个应用程序可能仅设计为发送 CNAME、NAME 和 EMAIL,而不发送其他项。由于 NAME 将在应用程序的用户界面中连续显示,可能会比 EMAIL 优先级更高,因为 EMAIL 仅在请求时显示。在每个 RTCP 间隔,都会发送一个 RR 包和一个带有 CNAME 项的 SDES 包。对于在最小间隔运行的小会话,平均每 5 秒会发送一次。每隔第三个间隔(15 秒),SDES 包会包含一项额外的项。在这其中,七分之八的时间是 NAME 项,而每八次(2 分钟)会包含 EMAIL 项。当多个应用程序协同工作,通过每个参与者的公共 CNAME 实现跨应用绑定时,例如在多媒体会议中为每个媒体建立一个 RTP 会话时,附加的 SDES 信息可以仅在一个 RTP 会话中发送。其他会话将仅携带 CNAME 项。特别是,这种方法应适用于分层编码方案的多个会话(见第 2.4 节)。
Sender and Receiver Reports:
RTP 接收者使用 RTCP 报告包提供接收质量反馈,具体形式取决于接收者是否也是发送者。这两种报告形式——发送者报告 (SR) 和接收者报告 (RR) 的唯一区别是,除了包类型代码外,发送者报告包含一个 20 字节的发送者信息部分,供活跃的发送者使用。如果在上一次或前一个报告之后的间隔期间内站点发送了任何数据包,则会发送 SR,否则发送 RR。SR 和 RR 都包含零个或多个接收报告块,每个报告块对应一个自上次报告以来该接收者接收到 RTP 数据包的同步源 (SSRC)。不为 CSRC 列表中的贡献源生成报告。每个接收报告块提供有关从该块指示的特定源接收的数据的统计信息。由于 SR 或 RR 包中最多可以包含 31 个接收报告块,因此在必要时,附加的 RR 包应在初始 SR 或 RR 包之后叠加,以包含自上次报告以来接收到的所有源的接收报告。如果有太多的源以至于无法将所有必要的 RR 包包含在一个复合 RTCP 包中而不超出网络路径的 MTU,则每个间隔应仅包含符合 MTU 限制的子集。这些子集应在多个间隔内以轮询方式选择,以便所有源都能被报告。
接下来的章节定义了这两种报告的格式,如何在特定配置中进行扩展(如果应用程序需要额外的反馈信息),以及如何使用这些报告。第 7 节提供了有关翻译器和混合器的接收报告的详细信息。
SR: Sender Report RTCP Packet:
发送者报告 (SR) 包包含三个部分,如果定义了特定配置的扩展部分,则可能跟随一个第四部分。第一部分是 8 字节长的头部。各字段含义如下:
-
版本 (V):2 位
○ 标识 RTP 版本,与 RTP 数据包中的版本相同。本规范定义的版本为 2。
-
填充 (P):1 位
○ 如果填充位设置为 1,则此 RTCP 包在末尾包含一些附加的填充字节,这些字节不属于控制信息,但包含在长度字段中。填充字节的最后一个字节表示需要忽略的填充字节数,包括自身(将是 4 的倍数)。某些固定块大小的加密算法可能需要填充。在复合 RTCP 包中,仅需在一个 RTCP 包中填充,因为整个复合包会被加密(第 9.1 节方法)。因此,填充仅需添加到最后一个 RTCP 包中,且该包的填充位必须设置为 1。这种方式有助于执行附录 A.2 中描述的头部有效性检查,并允许检测某些早期实现中错误地在第一个 RTCP 包中设置填充位,并在最后一个 RTCP 包中添加填充的情况。
-
接收报告计数 (RC):5 位
○ 表示此包中包含的接收报告块数量。0 也是有效值。
-
包类型 (PT):8 位
○ 包含常数 200,以标识这是 RTCP SR 包。
-
长度:16 位
○ 此 RTCP 包的长度(以 32 位字为单位)减 1,包括头部和填充。(偏移量 1 使得 0 成为有效长度,避免扫描复合 RTCP 包时的无限循环问题,并通过以 32 位字为单位进行计数,避免了 4 的倍数的有效性检查。)
-
SSRC:32 位
○ 此 SR 包发起者的同步源标识符。
第二部分为发送者信息,长 20 字节,存在于每个发送者报告包中,概述了此发送者的数据传输。各字段含义如下:
-
NTP 时间戳:64 位
○ 表示发送报告时的挂钟时间(见第 4 节),可与其他接收者返回的接收报告中的时间戳结合,用于测量到这些接收者的往返传播时间。接收者应注意,时间戳的测量精度可能远低于 NTP 时间戳的分辨率。时间戳的不确定性未指明,因为可能未知。在不具备挂钟时间概念但具备特定系统时钟(如系统启动时间)的系统上,发送者可以使用该时钟作为参考来计算相对 NTP 时间戳。重要的是选择一个常用时钟,以便在使用不同实现生成多媒体会话的各个流时,所有实现都使用相同的时钟。在 2036 年之前,相对和绝对时间戳会在高位有所不同,因此(无效的)比较将显示出较大的差异;到那时,希望不再需要相对时间戳。没有挂钟或经过时间概念的发送者可以将 NTP 时间戳设为 0。
-
RTP 时间戳:32 位
○ 与 NTP 时间戳(上文)对应,但使用与数据包中的 RTP 时间戳相同的单位和随机偏移。对于 NTP 时间戳已同步的源,该对应关系可用于媒体内部和媒体之间的同步,并可用于媒体无关接收者估算标准 RTP 时钟频率。注意,此时间戳在大多数情况下不会等于任何相邻数据包中的 RTP 时间戳,而是必须根据对应的 NTP 时间戳、通过在采样时刻周期性检查挂钟时间来维护的 RTP 时间戳计数器和实际时间的关系进行计算。
-
发送者的数据包计数:32 位
○ 从开始传输至生成此 SR 包时,发送者发送的 RTP 数据包总数。如果发送者更改其 SSRC 标识符,则应重置此计数。
-
发送者的字节数:32 位
○ 从开始传输至生成此 SR 包时,发送者在 RTP 数据包中传输的有效负载字节总数(不包括头部或填充)。如果发送者更改其 SSRC 标识符,则应重置此计数。此字段可用于估算平均有效负载数据速率。
第三部分根据自上次报告以来发送者接收到的其他源数量,包含零个或多个接收报告块。每个接收报告块传达从一个同步源接收的 RTP 数据包的统计信息。当源由于冲突更改其 SSRC 标识符时,接收者不应继续使用之前的统计信息。这些统计信息包括:
-
SSRC_n(源标识符):32 位
○ 与此接收报告块中的信息相关的源的 SSRC 标识符。
-
丢包率:8 位
○ 表示自上次发送 SR 或 RR 包以来,从源 SSRC_n 丢失的 RTP 数据包的比例,按左边缘为二进制点的定点数表示(即丢失比例乘以 256 的整数部分)
RR: Receiver Report RTCP Packet:
接收者报告 (RR) 包的格式与发送者报告 (SR) 包的格式相同,但包类型字段包含常数 201,且省略了五个字的信息(即 NTP 和 RTP 时间戳以及发送者的数据包和字节计数)。其余字段的含义与 SR 包相同。
当没有数据传输或接收需要报告时,必须将一个空的 RR 包(RC = 0)放在复合 RTCP 包的开头。
Extending the Sender and Receiver Reports:
如果有需要定期报告的发送者或接收者的额外信息,配置文件应定义发送者报告和接收者报告的特定扩展。此方法应优先于定义另一种 RTCP 包类型,因为它所需的开销较少:
-
包中所需的字节更少(没有 RTCP 头部或 SSRC 字段);
-
解析更简单快捷,因为运行在该配置文件下的应用程序会编程为始终在接收报告后直接访问扩展字段。
该扩展是发送者报告或接收者报告包的第四部分,在接收报告块(如果有的话)之后的结尾处。如果需要额外的发送者信息,则在发送者报告中会首先包含在扩展部分中,但在接收者报告中则不会出现此信息。如果需要包含接收者的信息,数据应当按照与现有接收报告块数组平行的块数组结构组织;即,块的数量将由 RC 字段指示。
Analyzing Sender and Receiver Reports:
接收质量反馈预计不仅对发送者有用,也对其他接收者和第三方监视器有用。发送者可以根据反馈调整传输;接收者可以确定问题是本地的、区域性的还是全局的;网络管理人员可以使用仅接收 RTCP 包而不接收对应 RTP 数据包的独立配置监视器来评估其网络在多播分发中的性能。
发送者信息和接收者报告块都使用累积计数,这样可以计算任意两个报告之间的差异,以便在长短时间段内进行测量,并提供对报告丢失的韧性保护。最近两次接收到的报告之差可用于估算近期的分发质量。NTP 时间戳的加入,使得可以通过这些差异计算两个报告之间间隔的速率。由于该时间戳独立于数据编码的时钟速率,因此可以实现编码和配置无关的质量监视。一个示例计算是两个接收报告之间的包丢失率。累计丢失包数的差值给出了该间隔内的丢失包数。接收的扩展最高序列号的差值给出了该间隔内期望的包数。两者之比是该间隔的包丢失比例。对于连续的两个报告,这一比例应等于丢失比例字段,否则可能不一致。丢失率每秒可通过将丢失比例除以 NTP 时间戳差值(以秒为单位)获得。接收到的包数是期望包数减去丢失包数。期望包数还可用于评估丢失估算的统计有效性。例如,丢失 5 个包中的 1 个的统计显著性低于丢失 1000 个包中的 200 个。
从发送者信息中,第三方监视器可以在不接收数据的情况下计算间隔内的平均有效负载数据速率和平均包速率。两者的比值给出平均有效负载大小。如果假设包丢失与包大小无关,则特定接收者接收的包数乘以平均有效负载大小(或相应的包大小)给出该接收者的可见吞吐量。
除了允许通过报告间差值进行长期丢包测量的累积计数,丢失比例字段还提供了单个报告中的短期测量。这在会话规模扩大到足以使无法保留所有接收者的接收状态信息,或报告间隔长到仅收到一个特定接收者的报告时显得尤为重要。
到达间抖动 (jitter) 字段提供了第二个短期的网络拥塞测量。丢包跟踪持续性拥塞,而抖动测量跟踪瞬时拥塞。在丢包之前,抖动测量可能预示着拥塞。到达间抖动字段仅是报告时抖动的快照,非量化值。相反,它用于对单个接收者随时间或多个接收者(例如同一网络内的接收者)间的多次报告进行比较。为了便于接收者间比较,所有接收者必须按照相同的公式计算抖动。
由于抖动计算基于 RTP 时间戳,该时间戳表示包中数据首次采样的时刻,因此从采样到包传输的延迟变化会影响计算的抖动值。此延迟变化会出现在不同长度的音频包中,视频编码中也会出现这种情况,因为帧的所有包具有相同的时间戳,但传输时间不同。传输前的延迟变化确实降低了抖动计算作为独立网络行为测量的准确性,但考虑到接收者缓冲区必须适应这一点,将其包括在内是合适的。当抖动计算作为比较测量使用时,传输延迟变化的(恒定)分量会相互抵消,从而可以观察到网络抖动分量的变化,除非该变化非常小。如果变化很小,则可能无关紧要。