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 |
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
每个RTP数据包的前12个八位组都是固定的,而CSRC标识符列表仅在由混音器插入时才存在。字段的含义如下:
版本 (V - Version): 2个比特
该字段标识RTP的版本。此规范定义的版本为2。第一个草案版本使用的值为1,最初在"vat"音频工具中实现的协议使用的值为0。
填充 (P - Padding): 1个比特
如果填充位设置,则数据包末尾会包含一个或多个额外的填充八位组,这些八位组不属于有效负载。填充的最后一个八位组包含应忽略的填充八位组的计数,包括自身在内。某些具有固定块大小的加密算法可能需要填充,或者用于在低层协议数据单元中载入多个RTP数据包。
扩展 (X - Extension): 1个比特
如果扩展位设置,则固定头必须后跟一个扩展头,格式见5.3.1节。
CSRC计数 (CC - CSRC Count): 4个比特
CSRC计数包含固定头后面跟随的CSRC标识符的数量。
标记位 (M - Marker): 1个比特
标记的解释由配置文件定义。它旨在允许在数据包流中标记诸如帧边界之类的重要事件。配置文件可以为其他标记位指定附加的标记位,或通过更改有效负载类型字段中的位数来指定没有标记位。
有效负载类型 (PT - Payload Type): 7个比特
该字段标识RTP有效负载的格式,并确定应用程序如何解释有效负载。配置文件可以通过非RTP方式动态定义附加的有效负载类型代码,或指定默认的静态有效负载类型代码到有效负载格式的映射。在附带的RFC 3551 [1]中指定了一组用于音频和视频的默认映射。RTP源可以在会话期间更改有效负载类型,但是不应该使用该字段来进行多路复用的单独媒体流(参见5.2节)。
序列号 (Sequence Number): 16个比特
序列号在发送每个RTP数据包时递增,并可由接收者用于检测数据包丢失并恢复数据包顺序。序列号的初始值应该是随机的(不可预测的),以使对加密的已知明文攻击更加困难,即使源本身不按照第9.1节中的方法进行加密,因为数据包可能流经一个进行加密的翻译器。有关选择不可预测数字的技术,请参见[17]。
时间戳 (Timestamp): 32个比特
时间戳反映了RTP数据包中第一个八位组的采样时刻。采样时刻必须来自一个按时间递增和线性递增的时钟,以允许同步和抖动计算(参见6.4.1节)。时钟的分辨率必须足够达到所需的同步精度和测量包到达抖动(每帧一个滴答通常不足够)。时钟频率取决于作为有效负载的数据格式,并在定义该格式的配置文件或有效负载格式规范中静态指定,或者可以通过非RTP方式动态指定。
如果定期生成RTP数据包,则应使用从采样时钟确定的名义采样时刻,而不是系统时钟的读数。例如,对于固定速率音频,时间戳时钟可能在每个采样周期增加一次。如果音频应用程序从输入设备读取覆盖160个采样周期的块,则每个这样的块的时间戳将增加160,无论该块是以数据包的形式传输还是作为静默状态丢弃。
时间戳的初始值应该是随机的,与序列号一样。如果(逻辑上)同时生成多个RTP数据包,例如属于同一视频帧,则几个连续的RTP数据包的时间戳将相等。如果数据不按照它的采样顺序传输,例如MPEG插值视频帧的情况下,连续的RTP数据包可以包含时间戳不是递增的情况。(按传输顺序)对数据包的序列号仍然是递增的。
来自不同媒体流的RTP时间戳可能以不同的速率前进,并且通常具有独立的随机偏移量。因此,尽管这些时间戳足以重构单个流的定时,但是直接比较来自不同媒体的RTP时间戳对于同步是无效的。相反,对于每个媒体,RTP时间戳与从表示采样与RTP时间戳相应的数据的参考时钟(挂钟)的时间戳配对相关。参考时钟由要同步的所有媒体共享。时间戳对不会在每个数据包中传输,而是由RTCP SR数据包中的时间戳对低速传输,如6.4节中所述。
选择采样时刻作为RTP时间戳的参考点,是因为传输端点已知并且对所有媒体都有一个统一的定义,与编码延迟或其他处理无关。目的是允许在同一时间采样的所有媒体实现同步呈现。
而不是实时采样数据,而是传输存储的数据的应用程序通常使用从挂钟时间派生的虚拟演示时间线,以确定存储数据中的下一个帧或其他媒体单元应该呈现的时间。在这种情况下,RTP时间戳将反映每个单元的呈现时间。也就是说,每个单元的RTP时间戳将与单元在虚拟演示时间线上变为当前的挂钟时间相关。实际呈现在稍后的时间进行,由接收器确定。
描述预先录制视频的实时音频讲解的示例说明了选择采样时刻作为参考点的重要性。在此场景中,视频将以供叙述者查看的方式本地呈现,并同时使用RTP进行传输。以RTP形式传输的视频的"采样时刻"将通过将其时间戳参考为视频帧呈现给叙述者时的挂钟时间来建立。包含讲述者语音的音频RTP数据包的"采样时刻"将通过将其时间戳参考为采样时音频的同一挂钟时间来建立。如果两个主机的参考时钟通过某种方式(例如NTP)进行同步,则即使音频和视频由不同主机发送,接收者也可以通过在RTCP SR数据包中的时间戳对中将它们的RTP时间戳进行同步。
SSRC: 32个比特
SSRC字段标识同步源。应随机选择此标识符,并且在同一RTP会话中的两个同步源不得具有相同的SSRC标识符。附录A.6中提供了生成随机标识符的示例算法。虽然多个源选择相同标识符的概率很低,但是所有RTP实现都必须准备好检测和解决冲突。第8节描述了冲突的概率,以及基于SSRC标识符的唯一性来解决冲突和检测RTP级转发环的机制。如果源更改其源传输地址,则还必须选择新的SSRC标识符,以避免被解释为循环源(参见8.2节)。
CSRC列表 (CSRC List): 0到15个项目,每个项目32个比特
CSRC列表标识包含在此数据包中的有效负载的贡献源。标识符的数量由CC字段给出。如果有超过15个贡献源,则只能识别15个。混音器插入CSRC标识符,使用贡献源的SSRC标识符。例如,对于音频包,列出了用于创建数据包的所有源的SSRC标识符,允许接收方正确指示说话者。
5.2 多路复用RTP会话 (Multiplexing RTP Sessions)
为了进行高效的协议处理,应尽量减少多路复用点,如集成层处理设计原则[10]所述。在RTP中,多路复用由目标传输地址(网络地址和端口号)提供,每个RTP会话都有一个不同的目标传输地址。例如,由单独编码的音频和视频媒体组成的电话会议,每个媒体应在一个具有自己的目标传输地址的单独的RTP会话中进行传输。
不应将单独的音频和视频流在一个RTP会话中传输,并根据有效负载类型或SSRC字段进行分复用。混合具有以下问题:
-
如果,例如,两个音频流共享相同的RTP会话和相同的SSRC值,并且其中一个更改了编码并因此获得了不同的RTP有效负载类型,则没有一般的方法来识别哪个流更改了编码。
-
定义了一个SSRC来标识单个时间和序列号空间。如果媒体时钟速率不同,则交错多个有效负载类型将需要不同的时态空间,如果数据包丢失将需要不同的序列号空间来确定哪个有效负载类型遭受了数据包丢失。
-
RTCP发送方和接收方报告(参见6.4节)每个SSRC只能描述一个时序和序列号空间,并且不带有效负载类型字段。
-
RTP混音器将无法将不兼容媒体的交错流合并为一条流。
-
将多个媒体传输到一个RTP会话中会禁止: 使用不同的网络路径或网络资源分配(如果适用); 如果视频带宽超过可用带宽,则只接收子集的媒体,例如仅音频; 以及使用为不同媒体分别使用单个或多个进程的接收器实现,而使用单独的RTP会话使得单个或多个进程的实现都是可能的。
使用不同的SSRC来传输每种介质,但将它们发送到同一个RTP会话中将避免前三个问题,但不包括后两个问题。
另一方面,在多播会话中,使用不同的SSRC值将同一媒体的多个相关源进行多路复用是正常情况。不适用于上述问题: RTP混合器可以将多个音频源组合在一起,并且相同的处理适用于它们。在其他不适用最后两个问题的场景中,以不同的SSRC值多路复用相同介质的流可能是合适的。
5.3 针对RTP头的配置文件特定修改 (Profile-Specific Modifications to the RTP Header)
现有的RTP数据包头被认为已经涵盖了RTP可能支持的所有应用程序类别中共同需要的功能集。然而,根据ALF设计原则,在仍然允许配置文件独立的监视和记录工具正常工作的前提下,配置文件可以通过对固定头的修改或添加来定制头部。
-
标记位和有效负载类型字段携带配置文件特定的信息,但是它们分配在固定头中,因为许多应用程序预计会需要它们,否则可能必须添加另外32位字来保存它们。该八位组中可以重新定义这些字段以适应不同的要求,例如具有更多或更少标记位。如果存在任何标记位,则应将其放置在八位组的最高有效位中,因为配置文件独立的监视器可能能够观察到丢包模式和标记位之间的相关性。
-
针对特定有效负载格式所需的其他信息,例如视频编码,应该包含在数据包的有效负载部分中。这可以是始终位于有效负载部分开头的标头,或者可以在数据模式中使用保留值来指示。
-
如果某个特定类别的应用程序需要与有效负载格式无关的附加功能,操作依然独立于有效负载部分的监视器或记录器应该定义在现有固定头的SSRC字段之后的附加固定字段。这些应用程序将能够快速直接地访问附加字段,而配置文件独立的监视器或记录器只需解释前12个八位组即可处理RTP数据包。
如果发现所有配置文件都需要的其他功能,则应定义RTP的新版本,以对固定头进行永久更改。
5.3.1 RTP头部扩展 (RTP Header Extension)
提供了一个扩展机制,允许各个实现尝试在RTP数据包头中携带额外信息的新的与有效负载格式无关的功能。该机制设计成让其他不能被扩展的互操作实现忽略头部扩展。
请注意,此头部扩展仅用于有限的用途。此机制的大多数潜在用途最好通过以前一节中描述的方法以其他方式完成。例如,特定于配置文件的对固定头的扩展处理成本更低,因为它不是条件的,也不是在可变位置的。不应该使用此头部扩展来传递特定有效负载格式所需的附加信息,而应该在数据包的有效负载部分中进行。
如果RTP头中的X比特为1,则必须在RTP头后附加一个可变长度的头部扩展,如果存在,则紧随CSRC列表。扩展头包含一个16位长度字段,该字段计数扩展中的32位字数,不包括四字节扩展头(因此零是有效的长度)。RTP数据头仅能附加一个扩展。为了允许多个互操作实现分别尝试不同的头部扩展类型,或者允许特定实现尝试多种类型的头部扩展,扩展的前16位留给区别标识符或参数。该部分的格式由实施操作的配置文件规范进行定义。RTP规范本身不定义任何头部扩展。