跳到主要内容

5. RTP 数据传送协议 (RTP Data Transfer Protocol)

5.1 RTP 固定头部字段 (RTP Fixed Header Fields)​

RTP 头部具有如下格式:

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|X| CC |M| PT | sequence number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | timestamp | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | synchronization source (SSRC) identifier | +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | contributing source (CSRC) identifiers | | .... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

前 12 个字节 (octet) 在每个 RTP 包中都存在, 而 CSRC 标识符列表仅在混合器插入时才存在。各字段含义如下:

version (V): 2 位 该字段标识 RTP 的版本。本规范所定义的版本为 2 (2)。(值 1 由 RTP 的第一个草案版本使用, 值 0 由最初在 "vat" 音频工具中实现的协议使用。)

padding (P): 1 位 如果设置了填充位, 则该包在末尾包含一个或多个额外的填充字节, 它们不属于负载。填充的最后一个字节包含一个计数, 指明有多少个填充字节 (包含其自身) 应当被忽略。某些具有固定块尺寸的加密算法, 或为了在单个下层协议数据单元中承载多个 RTP 包, 可能需要填充。

extension (X): 1 位 如果设置了扩展位, 则固定头部之后 MUST 恰好跟随一个头部扩展, 其格式在第 5.3.1 节中定义。

CSRC count (CC): 4 位 CSRC 计数字段包含跟随在固定头部之后的 CSRC 标识符的数量。

marker (M): 1 位 标记位的解释由配置文件定义。其意图是允许在包流中标出诸如帧边界之类的重要事件。一个配置文件 MAY 通过更改负载类型字段的位数 (见第 5.3 节) 来定义额外的标记位, 或规定不存在标记位。

payload type (PT): 7 位 该字段标识 RTP 负载的格式, 并决定应用对其的解释。一个配置文件 MAY 规定负载类型代码到负载格式的默认静态映射。额外的负载类型代码 MAY 通过非 RTP 手段 (见第 3 节) 动态定义。音频和视频的一组默认映射在配套文档 RFC 3551 [1] 中规定。一个 RTP 源 MAY 在会话过程中改变负载类型, 但该字段 SHOULD NOT 被用于多路复用相互独立的媒体流 (见第 5.2 节)。

  接收方 MUST 忽略那些其负载类型它无法理解的包。

sequence number: 16 位 序列号对每个发送的 RTP 数据包递增 1, 接收方可以据此检测丢包并重建包序列。序列号的初始值 SHOULD 是随机 (不可预测) 的, 以使针对加密的已知明文攻击更加困难, 即使源本身并未按照第 9.1 节的方法加密, 因为包可能流经某个会这样做的转换器。关于选择不可预测数字的技术在 [17] 中讨论。

timestamp: 32 位 时间戳反映 RTP 数据包中第一个字节的采样时刻。采样时刻 MUST 从一个随时间单调递增且线性的时钟导出, 以便进行同步和抖动计算 (见第 6.4.1 节)。该时钟的分辨率 MUST 足以满足所需的同步精度以及测量包到达抖动的需要 (每个视频帧一个 tick 通常是不够的)。时钟频率依赖于作为负载承载的数据格式, 并在定义该格式的配置文件或负载格式规范中静态规定, 或者 MAY 针对通过非 RTP 手段定义的负载格式动态规定。如果 RTP 包是周期性生成的, 则应使用由采样时钟确定的标称采样时刻, 而非系统时钟的读数。例如, 对于固定速率的音频, 时间戳时钟很可能对每个采样周期递增 1。如果某个音频应用从输入设备读取覆盖 160 个采样周期的数据块, 则每个这样的数据块时间戳应增加 160, 无论该块是被放进包中发送, 还是作为静音被丢弃。

  时间戳的初始值 SHOULD 是随机的, 如同序列号那样。如果多个连续的 RTP 包是 (逻辑上) 同时生成的, 例如属于同一视频帧, 它们将具有相同的时间戳。如果数据不是按其被采样的顺序传输 (如 MPEG 插值视频帧的情形), 连续的 RTP 包 MAY 包含非单调的时间戳。(传输时的包序列号仍将保持单调。)

来自不同媒体流的 RTP 时间戳可能以不同速率推进, 并且通常具有相互独立的随机偏移。因此, 虽然这些时间戳足以重建单一流的定时, 但直接比较来自不同媒体的 RTP 时间戳对于同步并不有效。相反, 对于每种媒体, RTP 时间戳通过与一个参考时钟 (挂钟) 的时间戳配对而与采样时刻相关联, 该参考时钟表示对应于该 RTP 时间戳的数据被采样的时间。该参考时钟被所有需要同步的媒体所共享。这些时间戳对并非在每个数据包中都传输, 而是以第 6.4 节所描述的较低速率在 RTCP SR 包中传输。

选择采样时刻作为 RTP 时间戳的参考点, 是因为发送端知道它, 并且对所有媒体都有共同的定义, 与编码延迟或其他处理无关。其目的在于允许对同时采样的所有媒体进行同步呈现。

传输存储的数据 (而非实时采样的数据) 的应用, 通常使用从挂钟时间导出的虚拟呈现时间线, 来确定存储数据中每种媒体的下一帧或其他单位应当何时呈现。在这种情况下, RTP 时间戳将反映每个单位的呈现时间。也就是说, 每个单位的 RTP 时间戳将关联到该单位在虚拟呈现时间线上成为当前项时的挂钟时间。实际呈现发生在稍后由接收方确定的某个时刻。

一个描述预录视频的现场音频解说 (live audio narration) 的例子, 说明了选择采样时刻作为参考点的重要性。在此场景中, 视频将被本地呈现给解说员观看, 并同时使用 RTP 传输。在 RTP 中传输的视频帧的 "采样时刻" 将通过将其时间戳关联到该视频帧被呈现给解说员时的挂钟时间而建立。包含解说员语音的音频 RTP 包的采样时刻, 将通过关联音频被采样时的同一挂钟时间而建立。如果两台主机的参考时钟通过诸如 NTP 之类的某种手段同步, 音频和视频甚至可以由不同的主机传输。接收方于是可以通过使用 RTCP SR 包中的时间戳对, 关联它们的 RTP 时间戳, 从而同步呈现音频和视频包。

SSRC: 32 位 该 SSRC 字段标识同步源。该标识符 SHOULD 随机选取, 其意图是在同一 RTP 会话内没有任何两个同步源会具有相同的 SSRC 标识符。生成随机标识符的一个示例算法见附录 A.6。尽管多个源选择相同标识符的概率很低, 但所有 RTP 实现都必须准备好检测并解决冲突。第 8 节描述了冲突的概率, 以及基于 SSRC 标识符唯一性来解决冲突、检测 RTP 层面转发环路的机制。如果一个源改变了它的源传输地址, 它还必须选择一个新的 SSRC 标识符, 以避免被解释为被环回的源 (见第 8.2 节)。

CSRC list: 0 到 15 项, 每项 32 位 该 CSRC 列表标识本包中负载的贡献源。标识符的数量由 CC 字段给出。如果贡献源超过 15 个, 则仅有 15 个可被标识。CSRC 标识符由混合器 (见第 7.1 节) 使用贡献源的 SSRC 标识符插入。例如, 对于音频包, 列出了所有被混合在一起以创建该包的源的 SSRC 标识符, 从而在接收方处实现正确的发言者指示。

5.2 多路复用 RTP 会话 (Multiplexing RTP Sessions)​

为获得高效的协议处理, 应使多路复用点的数量最小化, 这正如应用层成帧 (integrated layer processing) 设计原则 [10] 中所描述的那样。在 RTP 中, 多路复用由目的传输地址 (网络地址和端口号) 提供, 该地址对于每个 RTP 会话都不同。例如, 在一个由音频和视频媒体分别编码的电话会议中, 每种媒体 SHOULD 承载于一个独立的 RTP 会话中, 拥有其自身的目的传输地址。

独立的音频和视频流 SHOULD NOT 被承载于单个 RTP 会话中, 并基于负载类型或 SSRC 字段进行分解多路复用。交错传输具有不同 RTP 媒体类型但使用相同 SSRC 的包, 会引发若干问题:

  1. 例如, 如果两个音频流共享同一个 RTP 会话和相同的 SSRC 值, 其中一个改变了编码从而获得不同的 RTP 负载类型, 那么将无法以通用方式确定是哪个流改变了编码。

  2. SSRC 被定义为标识单一的定时和序列号空间。如果媒体时钟速率不同, 交错多种负载类型将需要不同的定时空间, 并且需要不同的序列号空间以分辨哪个负载类型发生了丢包。

  3. RTCP 发送方和接收方报告 (见第 6.4 节) 每个 SSRC 只能描述一个定时和序列号空间, 并且不携带负载类型字段。

  4. RTP 混合器将无法把不兼容媒体的交错流组合成单一流。

  5. 在单个 RTP 会话中承载多种媒体, 排除了以下可能: 在适当时使用不同的网络路径或网络资源分配; 在需要时接收媒体子集, 例如当视频超出可用带宽时只接收音频; 以及使用为不同媒体分配独立进程的接收方实现, 而使用独立的 RTP 会话则允许单进程或多进程实现中的任意一种。

对每种媒体使用不同的 SSRC、但在同一个 RTP 会话中发送它们, 可以避免前三个问题, 但无法避免最后两个。

另一方面, 在多播会话中, 使用不同的 SSRC 值在同一 RTP 会话中多路复用同一媒体的多个相关源是常态。上面列出的问题并不适用: 例如, 一个 RTP 混合器可以组合多个音频源, 并且对它们都适用相同的处理方式。在其他最后两个问题不适用的场景中, 使用不同的 SSRC 值多路复用同一媒体的流也可能是恰当的。

5.3 对 RTP 头部的配置文件特定修改 (Profile-Specific Modifications to the RTP Header)​

现有的 RTP 数据包头部, 被认为对于所有 RTP 可能支持的应用类别所共同需要的功能集合而言是完整的。然而, 为与 ALF 设计原则保持一致, 该头部 MAY 通过配置文件规范中所定义的修改或增补而进行裁剪, 同时仍允许与配置文件无关的监视和记录工具正常工作。

o 标记位和负载类型字段承载了配置文件特定的信息, 但它们被分配在固定头部中, 因为预期许多应用都需要它们, 否则可能不得不另加一个 32 位字来仅仅存放它们。包含这些字段的字节 MAY 由配置文件重新定义, 以满足不同需求, 例如使用更多或更少的标记位。如果存在任何标记位, 其中一个 SHOULD 位于该字节的最高有效位, 因为与配置文件无关的监视器或许能够观察到包丢失模式与标记位之间的相关性。

o 某一特定负载格式 (例如某种视频编码) 所需的额外信息, SHOULD 承载于包的负载部分。它可能位于负载部分开头总是存在的某个头部中, 也可能由数据模式中的某个保留值来指示。

o 如果某一类应用需要独立于负载格式的功能, 那么这些应用所运行的配置文件 SHOULD 定义额外的固定字段, 紧跟在现有固定头部的 SSRC 字段之后。那些应用将能够快速、直接地访问这些额外字段, 而与配置文件无关的监视器或记录器仍可以通过只解释前 12 个字节来处理 RTP 包。

如果发现所有配置文件中共同需要额外功能, 那么应当定义新版本的 RTP, 以对固定头部做永久性修改。

5.3.1 RTP 头部扩展 (RTP Header Extension)​

提供了一种扩展机制, 以允许个别实现试验那些需要额外信息承载于 RTP 数据包头部、且与负载格式无关的新功能。该机制设计成这样: 头部扩展可以被其他未做扩展、能够互操作的实现所忽略。

注意, 此头部扩展仅用于有限的用途。该机制的多数潜在用途, 最好用另一种方式实现, 即使用前一节中所描述的方法。例如, 对固定头部的配置文件特定扩展, 由于它不是条件性的、也不在可变位置, 处理开销更小。某一特定负载格式所需的额外信息 SHOULD NOT 使用该头部扩展, 而 SHOULD 承载于包的负载部分。

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

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | defined by profile | length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | header extension | | .... |

如果 RTP 头部中的 X 位为 1, 则 MUST 将一个变长头部扩展附加到 RTP 头部之后, 在 CSRC 列表 (如果存在) 之后。该头部扩展包含一个 16 位的长度字段, 其计数为扩展中 32 位字的数量, 不包括这 4 个字节的扩展头部 (因此零是有效的长度)。只能向 RTP 数据头部附加单个扩展。为了使多个能够互操作的实现各自独立地试验不同的头部扩展, 或使某个特定实现能够试验多于一种类型的头部扩展, 头部扩展的前 16 位被留作区分标识符或参数之用。这 16 位的格式由实现所运行的配置文件规范定义。本 RTP 规范本身不定义任何头部扩展。