Skip to main content

8. SSRC 标识符的分配和使用 (SSRC Identifier Allocation and Use)

RTP 头部和 RTCP 数据包的各个字段中携带的 SSRC 标识符是一个随机的 32 位数字, 该数字在 RTP 会话中必须是全局唯一的。谨慎选择这个数字至关重要, 以确保在同一网络上或同时启动的参与者不太可能选择相同的数字。

仅使用本地网络地址 (例如 IPv4 地址) 作为标识符是不够的, 因为该地址可能不是唯一的。由于 RTP 转换器 (translators) 和混音器 (mixers) 能够实现具有不同地址空间的多个网络之间的互操作, 两个地址空间内的地址分配模式可能导致比随机分配更高的碰撞率。在一台主机上运行的多个源也会发生冲突。

同样, 仅通过调用 random() 而不仔细初始化状态来获取 SSRC 标识符也是不够的。附录 A.6 中给出了如何生成随机标识符的示例。

8.1 碰撞概率 (Probability of Collision)

由于标识符是随机选择的, 两个或多个源可能会选择相同的数字。当所有源同时启动时碰撞概率最高, 例如当由某个会话管理事件自动触发时。如果 N 是源的数量, L 是标识符的长度 (此处为 32 位), 则两个源独立选择相同值的概率对于大 N 可近似为 [26] 1 - exp(-N2 / 2(L+1))。对于 N=1000, 概率约为 10**-4。

典型的碰撞概率远低于上述最坏情况。当一个新源加入 RTP 会话, 而所有其他源已经具有唯一标识符时, 碰撞概率只是使用的数字占空间的比例。同样, 如果 N 是源的数量, L 是标识符的长度, 则碰撞概率为 N / 2L。对于 N=1000, 概率约为 2*10-7。

新源在发送第一个数据包 (数据或控制) 之前有机会从其他参与者接收数据包, 进一步降低了碰撞概率。如果新源跟踪其他参与者 (通过 SSRC 标识符), 则在传输其第一个数据包之前, 新源可以验证其标识符不与已接收的任何标识符冲突, 否则重新选择。

8.2 碰撞解决和环路检测 (Collision Resolution and Loop Detection)

尽管 SSRC 标识符碰撞的概率很低, 但所有 RTP 实现必须 (MUST) 准备好检测碰撞并采取适当的措施来解决它们。如果源在任何时候发现另一个源正在使用与自己相同的 SSRC 标识符, 它必须 (MUST) 为旧标识符发送 RTCP BYE 数据包, 并选择另一个随机标识符。(如下所述, 在环路的情况下此步骤仅执行一次。) 如果接收者发现两个其他源发生碰撞, 当可以通过不同的源传输地址或 CNAME 检测到时, 它可以 (MAY) 保留来自一个源的数据包并丢弃来自另一个源的数据包。预计这两个源会解决碰撞, 因此这种情况不会持续。

由于随机 SSRC 标识符在每个 RTP 会话中保持全局唯一, 因此它们也可用于检测混音器或转换器可能引入的环路。环路会导致数据和控制信息的重复, 无论是未修改的还是可能混合的, 如以下示例所示:

  • 转换器可能错误地将数据包转发到接收该数据包的同一组播组, 直接或通过转换器链。在这种情况下, 同一数据包会多次出现, 来自不同的网络源。

  • 两个转换器在两侧具有相同组播组的情况下错误地并行设置, 两者都会将数据包从一个组播组转发到另一个组播组。单向转换器会产生两个副本; 双向转换器会形成环路。

  • 混音器可以通过直接或通过另一个混音器或转换器发送到其接收数据包的同一传输目标来形成环路。在这种情况下, 源可能同时显示为数据包上的 SSRC 和混合数据包中的 CSRC。

源可能发现其自己的数据包正在环回, 或者来自另一个源的数据包正在环回 (第三方环路)。环路和源标识符随机选择中的碰撞都会导致数据包以相同的 SSRC 标识符但不同的源传输地址到达, 该地址可能是发起数据包的终端系统或中间系统的地址。

因此, 如果源更改其源传输地址, 它也可以 (MAY) 选择新的 SSRC 标识符以避免被解释为环回源。(这不是 MUST, 因为在 RTP 的某些应用中, 源可能会在会话期间更改地址。) 请注意, 如果转换器重新启动并因此更改其转发数据包的源传输地址 (例如, 更改 UDP 源端口号), 则所有这些数据包对接收者来说都会显示为环回, 因为 SSRC 标识符由原始源应用且不会更改。通过在重新启动时保持源传输地址固定可以避免此问题, 但无论如何都会在接收者超时后得到解决。

如果所有数据包副本都通过转换器或混音器, 则无法使用源传输地址检测转换器或混音器远端发生的环路或碰撞, 但是, 当来自两个 RTCP SDES 数据包的块包含相同的 SSRC 标识符但不同的 CNAME 时, 仍然可以检测到碰撞。

为了检测和解决这些冲突, RTP 实现必须 (MUST) 包含类似于下面描述的算法, 尽管实现可以 (MAY) 为保留来自碰撞第三方源的哪些数据包选择不同的策略。下面描述的算法忽略来自与已建立源碰撞的新源或环路的数据包。它通过为旧标识符发送 RTCP BYE 并选择新标识符来解决与参与者自己的 SSRC 标识符的碰撞。但是, 当碰撞是由参与者自己的数据包环路引起时, 算法只会选择一次新标识符, 此后忽略来自环回源传输地址的数据包。这是为了避免 BYE 数据包泛滥所必需的。

此算法需要保留一个按源标识符索引的表, 其中包含从接收到具有该标识符的第一个 RTP 数据包和第一个 RTCP 数据包的源传输地址, 以及该源的其他状态。需要两个源传输地址, 因为例如 RTP 和 RTCP 数据包上的 UDP 源端口号可能不同。但是, 可以假设两个源传输地址中的网络地址相同。

在 RTP 或 RTCP 数据包中接收到的每个 SSRC 或 CSRC 标识符都在源标识符表中查找, 以便处理该数据或控制信息。将数据包中的源传输地址与表中相应的源传输地址进行比较, 以检测它们不匹配时的环路或碰撞。对于控制数据包, 具有其自己的 SSRC 标识符的每个元素 (例如 SDES 块) 都需要单独查找。(接收报告块中的 SSRC 标识符是一个例外, 因为它标识报告者听到的源, 并且该 SSRC 标识符与报告者发送的 RTCP 数据包的源传输地址无关。) 如果找不到 SSRC 或 CSRC, 则创建新条目。当收到具有相应 SSRC 标识符的 RTCP BYE 数据包并通过匹配的源传输地址验证时, 或者在相对较长的时间内没有数据包到达后 (参见第 6.2.1 节), 这些表条目将被删除。

8.3 与分层编码一起使用 (Use with Layered Encodings)

对于分层编码, 可以使用多个 RTP 会话来传输不同的层。在这种情况下, 建议在所有层中使用单一的 SSRC 标识符空间, 并且同一参与者在不同层中应使用相同的 SSRC 标识符。这样可以跨层关联来自同一源的数据包, 并允许在所有层上进行一致的碰撞检测和解决。