还有一个可有可无的功能,RTCP 可以用来共享小量的 Session 控制信息,例如辨认参与者的身份。通常来说,该功能会被那些管理比较松散的 Session 使用。RTCP 可以作为一个方便的与其他参与者沟通的通道,但是你也别期望 RTCP 可以满足一个应用的所有传输控制需求,这类需求往往是通过一个更高层的 Session 控制协议来满足。
这四个功能中,前三个应该会被所有应用场景使用(IP 组播机制下)。RTP 应用的设计者应该避免自己的应用只能工作在单播模式,RTP 应用应该设计成可拓展的,要考虑大量使用者并发时的情况。此外,RTCP 的传输应该根据发送者和接收者角色的不同而分别进行控制,例如一些单项连接,接收者的反馈信息就发不出来。
提醒:像是指定源组播路由(SSM),只有一个人可以发送数据,其他接收者不能用组播来和其他人直接通讯。对于这种情况,建议完全关闭接收者的原始 RTCP 功能,然后为这个 SSM 设定一个 RTCP 的适配器,来接收所有的反馈。
RTCP 包格式RTCP 定义了许多包类型来传输不同的控制信息:
SR:发送者报告,发送者数据发送和接收的统计。
RR:接收者报告,只接收数据的节点的接收统计。
SDES:Source 描述,包括 CNAME。
BYE:表示退出。
APP:上层应用自定义。
每个 RTCP 包都有一个和 RTP 类似的固定格式的头,后面跟着长度不定的结构化数据,在不同 RTCP 类型时,这些结构化数据各不一样,但是它们必须都要 32-bit 对齐。RTCP 的头部是定长的,而且在头部有一个字段来描述这个 RTCP 数据的长度,因此 RTCP 可以被复合成一组一同发送,还不需要任何分隔符来分割出单个的 RTCP 包。下层协议可能会根据自己的情况决定将多少个 RTCP 报文复合在一起组成一个复合包。
复合包中的每个独立的 RTCP 报文都是无序的,而且可能会被随意复合。为了让协议的功能正常运作,会有如下限制:
接收统计(SR|RR)的发送频率需要达到带宽的最大限制,因此每个周期发送的 RTCP 复合包都需要包含一个这类报文。
一个新来的接收者需要尽可能快地得到数据源的 CNAME,因为它要用 CNAME 来确定每个数据源分别对应哪个人,并将数据源联系在一起进行同步,所以每个 RTCP 复合包必须包含 SDES CNAME(除非这个复合包被拆成两半一半加密,一般明文,这部分后面会介绍)。
复合包中包类型的数量需要限制,这可以减少其他发错的包或者不相关的包被识别成 RTCP 包的可能性,还能增加第一个字中固定比特的数量。
因此,一个复合包中至少需要含有 2 种类型的 RTCP 报文,它的格式如下:
Encryption prefix:当且仅当这个复合包需要加密的时,那复合包在头部插入一个随机的 32-bit 数。如果加密算法需要填充数据的话,需要填充到复合包中的最后一个 RTCP 包后。
SS 或 RR:复合包中第一个 RTCP 包必须是一个报告报文,这可以加速报文头部数据的校验。即便没有 RTP 数据的发送和接收也要有一个报告报文,这种情况下必须发送一个空的 RR 报文,并且即便是这个复合包中的其他 RTCP 报文是 BYE 也要这么做。
Additional RRs:如果接收的 RTP 数据来自超过 31 个不同的源,前 31 个接收报告会写进 SR 或者 RR 报文中,多出来的接收报告应该紧跟着默认的报告报文(SR 或 RR)。
SDES:SDES 包必须包含 CNAME,每个复合包必须包含一个 SDES 包。如果上层应用有需要,也可以加入一些别的 SDES 报文,这视带宽限制而定。
BYE 或 APP:其他 RTCP 包类型(包括协议中还未定义的),可能以任意顺序跟在 SDES 后面,但是希望 BYE 包写在最后面(BYE 包需要和 SSRC/CSRC 一同发送)。
一个单独的 RTP 参与者应该在一个报告周期中只发送一个复合 RTCP 包,该周期每个参与者应该视带宽情况来估算,除非一个复合包被拆分加密。如果数据发送者的数量太多,以至于除了增加 MTU 这个方法之外,没办法将所有 RR 报文塞进一个复合包时,那么一次只会将部分 RR 数据塞进这个复合包,其他的数据就不发送了。当然,为了让所有源的接收情况都得到报告,会在多个周期内以环的形式循环共享所有源的接收情况。
为了减少数据包的开销,一般建议 Translator 和 Mixer 无论何时都能将多个源的 RTCP 报文复合成一个复合包。下图展示的就是一个 Mixer 生成的复合包的例子: