定义(definitions)
RTP负载(RTP payload):通过RTP传输的包中的数据,例如,音频样本或压缩好的视频数据。负载格式与解释不在本文讨论范围。
RTP包(RTP packet):一种数据包,其组成部分有:一个固定RTP报头,一个可能为空的作用源(contributing sources)列表(见下文),以及负载数据。一些下层协议可能要求对RTP包的封装进行定义。一般地,下层协议的一个包包含一个RTP包,但若封装方法允许,也可包含数个RTP包(见章节11)。
RTCP包(RTCP packet):一种控制包,其组成部分有:一个类似RTP包的固定报头,后跟一个结构化的部分,该部分具体元素依不同RTCP包的类型而定。格式的定义见章节6。一般地,多个RTCP包将在一个下层协议的包中以合成RTCP包的形式传输;这依靠RTCP包的固定报头中的长度字段来实现。
端口(Port):“传输协议用来在同一主机中区分不同目的地的一种抽象。TCP/IP协议使用正整数来标识不同端口。”[12] OSI传输层使用的传输选择器(TSEL,the transport selectors)等同于这里的端口。RTP需依靠低层协议提供的多种机制,如“端口”用以多路复用会话中的RTP和RTCP包。
传输地址(Transport address):是网络地址与端口的结合,用来标识一个传输层次的终端,例如一个IP地址与一个UDP端口。包是从源传输地址发送到目的传输地址。
RTP媒体类型(RTP media type):一个RTP媒体类型是一个单独RTP会话所载有的负载类型的集合。RTP配置文件把RTP媒体类型指派给RTP负载类型。
多媒体会话(Multimedia session):在一个参与者公共组中,并发的RTP会话的集合。例如,一个视频会议(为多媒体会话)可能包含一个音频RTP会话和一个视频RTP会话。
RTP会话(RTP session):一群参与者通过RTP进行通信时所产生的关联。一个参与者可能同时参与多个RTP会话。在一个多媒体会话中,除非编码方式把多种媒体多路复用到一个单一数据流中,否则每种媒体都将使用各自的RTCP包,通过单独的RTP会话来传送。通过使用不同的目的传输地址对(一个网络地址加上一对分别用于RTP和RTCP的端口,构成了一个传输地址对)来接收不同的会话,参与者能把多个RTP会话区隔开来。单个RTP会话中的所有参与者,可能共享一个公用目的传输地址对,比如IP多播的情况;也可能各自使用不同的目的传输地址对,比如个体单播网络地址加上一个端口对。对于单播的情况,参与者可能使用相同端口对来收听其他所有参与者,也可能对来其他每个参与者使用不同的端口对来收听。
RTP会话间相互区别的特征,在于每个RTP会话都维护一个用于SSRC标识符的独立完整的空间。RTP会话所包含的参与者组,由能接收SSRC标识符的参与者组成,这些SSRC标识符由RTP(同步源或作用源)或RTCP中的任意参与者传递。例如,考虑下述情况,用单播UDP实现的三方会议,每方都用不同的端口对来收听其他两方。如果收到一方的数据,就只把RTCP反馈发送给那一方,则会议就相当于由三个单独的点到点RTP会话构成;如果收到一方的数据,却把RTCP反馈发送另两方,则会议就是由一个多方(multi-party)RTP会话构成。后者模拟了三方间进行IP多播通信时的行为。
R TP框架允许上述规定发生变化,但一个特定的控制协议或者应用程序在设计时常常对变化作出约束。
同步源(SSRC,Synchronization source):RTP包流的源,用RTP报头中32位数值的SSRC标识符进行标识,使其不依赖于网络地址。一个同步源的所有包构成了相同计时和序列号空间的一部分,这样接收方就可以把一个同步源的包放在一起,来进行重放。举些同步源的例子,像来自同一信号源的包流的发送方,如麦克风、摄影机、RTP混频器(见下文)就是同步源。一个同步源可能随着时间变化而改变其数据格式,如音频编码。SSRC标识符是一个随机选取的值,它在特定的RTP会话中是全局唯一(globally unique)的(见章节8)。参与者并不需要在一个多媒体会议的所有RTP会话中,使用相同的SSRC标识符;SSRC标识符的绑定通过RTCP(见章节6.5.1)。如果参与者在一个RTP会话中生成了多个流,例如来自多个摄影机,则每个摄影机都必须标识成单独的同步源。
作用源(CSRC,Contributing source ):若一个RTP包流的源,对由RTP混频器生成的组合流起了作用,则它就是一个作用源。对特定包的生成起作用的源,其SSRC标识符组成的列表,被混频器插入到包的RTP报头中。这个列表叫做CSRC表。相关应用的例子如,在音频会议中,混频器向所有的说话人(talker)指出,谁的话语(speech)将被组合到即将发出的包中,即便所有的包都包含在同一个(混频器的)SSRC标识符中,也可让听者(接收者)可以清楚谁是当前说话人。 终端系统(End system):一种应用程序,它产生发送出的RTP包中内容,或者使用接收到的RTP包中内容。在一个特定的RTP会话中,一个终端系统可以扮演一个或多个同步源角色,但通常是一个。
混频器(Mixer):一种中间系统,它从一个或多个源中接收RTP包,可能改变其数据格式,再按某种方式把这些包组合成一个新的包,然后转发出去。由于多个输入源的计时一般不会同步,所以混频器会对各个流的计时作出调整,并为组合流生成一个新的计时。因此,混频器将被标识成它所产生所有数据包的同步源。
转换器(Translator):一种中间系统,它转发RTP包而不改变各包的同步源标识符。转换器的例子如下:不作混频地转变编码的设备,把多播复制到单播的重复装置,以及防火墙里应用层次的过滤器。
监视器(Monitor):一种应用程序,它接收RTP会话参与者所发送的RTCP包,特别是接收报告(reception report),而且对当前服务质量进行评估,评估结果用于分配监视任务,故障诊断和长期统计。监视器常常被内建到参与会话的应用程序中,但也可以是一个的独立的应用程序——不参加会话、也不发送或接收RTP数据包(因为它们在不同的端口上)。这些被称作第三方监视器。还有一种情况也是可以接受的,第三方监视器只接收但不发送数据包,或者另外地算入到会话中。
非RTP途径(Non-RTP means):为提供一个可用的服务,可能还需要其他的协议和机制。特别地,对多媒体会议来说,一个控制协议可以发布多播地址,发布加密密钥,协商所用的加密算法,以及为没有预定义负载类型值的格式,建立负载类型值和其所代表的负载格式之间的动态映射。
5 RTP数据传输协议
5.1 RTP固定头中的各字段,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个字节出现在每个RTP包中,仅仅在被混合器插入时,才出现CSRC识别符列表。这些域有以下意义:
版本(V):2比特 此域定义了RTP的版本。此协议定义的版本是2。(值1被RTP草案版本使用,值0用在最初"vat"语音工具使用的协议中。)
填充(P):1比特 若填料比特被设置,则此包包含一到多个附加在末端的填充比特,填充比特不算作负载的一部分。填充的最后一个字节指明可以忽略多少个填充比特。填充可能用于某些具有固定长度的加密算法,或者用于在底层数据单元中传输多个RTP包。
扩展(X):1比特 若设置扩展比特,固定头(仅)后面跟随一个头扩展。
CSRC计数(CC):4比特 CSRC计数包含了跟在固定头后面CSRC识别符的数目。
标志(M):1比特 标志的解释由具体协议规定。它用来允许在比特流中标记重要的事件,如帧边界。
负载类型(PT):7比特 此域定义了负载的格式,由具体应用决定其解释。协议可以规定负载类型码和负载格式之间一个默认的匹配。其他的负载类型码可以通过非RTP方法动态定义。RTP发送端在任意给定时间发出一个单独的RTP负载类型;此域不用来复用不同的媒体流。
序列号(sequence number):16比特 每发送一个RTP数据包,序列号加1,接收端可以据此检测丢包和重建包序列。序列号的初始值是随机的(不可预测),以使即便在源本身不加密时(有时包要通过翻译器,它会这样做),对加密算法泛知的普通文本攻击也会更加困难。
时间戳(timestamp):32比特 时间戳反映了RTP数据包中第一个字节的采样时间。(采样时钟必须来源于一个及时的单调、线性递增时钟,以便允许同步和去除网络引起的数据包抖动(见章节6.4.1)。该时钟的分辨率必须满足理想的同步精度和测量数据包到来时的抖动的需要(一种典型的时钟分辨率不满足情况是每个视频帧仅一个时钟周期)时钟频率依赖于负载数据的格式,并在描述文件(profile)中或者是在负载格式描述中(payload format speci_cation)进行静态描述。也可以通过非RTP方法(non-RTP means)对负载格式动态描述。
如果RTP包是周期性产生的,那么将使用由采样时钟决定的名义上的采样时刻,而不是读取系统时间。例如,对一个固定速率的音频,采样时钟(时间戳时钟)将在每个周期内增加1。如果一个音频从输入设备中读取含有160个采样周期的块,那么对每个块,时间戳的值增加160,而不考虑该块是否用一个包传递或是被丢弃。(Example:sess.SetDefaultTimestampIncrement(160);)
时间戳的初始值应当是随机的,就像序号一样。几个连续的RTP包如果(逻辑上)是同时产生的,如:属于同一个视频帧的RTP包,将有相同的序列号。如果数据并不是以它采样的顺序进行传输,那么连续的RTP包可以包含不是单调递增(或递减)的时间戳(RTP包的序列号仍然是单调变化的)。
不同媒体流的RTP时间戳可能以不同的速率增长。而且会有独立的随机偏移量。因此,虽然这些时间戳足以重构一个单独的流的时序,但直接比较不同的媒体流的时间戳不能有效的进行同步。对于每一个媒体,我们把与采样时刻相关联的RTP时间戳与来自于参考时钟上的时间戳(NTP)相关联(相反,对于每一种媒体,RTP时间戳通过与一个参考时间戳wallclock配对的方法来与采样时刻联系起来。)。参考时钟的时间戳表示了(对应于RTP时间戳的)数据的采样时刻。(即:RTP时间戳可用来实现不同媒体流的同步,NTP时间戳解决了RTP时间戳有随机偏移量的问题。)参考时钟用于同步所有媒体的共同时间(参考时间戳为所有媒体所公用,以此来实现同步)。这一时间戳对(RTP时间戳和NTP时间戳),用于判断RTP时间戳和NTP时间戳的对应关系,以进行媒体流的同步。它们不是在每一个数据包中都被发送,而在发送速率更低的RTCP的SR(发送者报告)中。即RTP时间戳记录当前是第几个采样数据,NTP时间戳记录当前数据包相对于参考时钟(1900年1月1日0点算起,当前时间相对于该时刻所经过的秒数)的绝对时间。
选取采样时间作为RTP时间戳的参考点是因为它可以被传输的终节点获知,而且对所有媒体内容有一个相同的定义,再者是它不受编码延迟或其它数据处理的约束。目的是为了对所有在同一时刻采样的媒体进行同步。
如果传输的数据是存贮好的,而不是实时采样得到的,那么会使用从参考时钟得到的虚的表示时间线(virtual presentation timeline虚拟表示时间表)以确定存贮数据中的每个媒体下一帧或下一个单元应该呈现的时间(还是时刻???)。此种情况下RTP时间戳反映了每一个单元应当回放的时间(时刻???)。这就是说,每个单元的RTP时间戳将会和参考时钟相关。真正的回放将由接收者决定。
一个描述了关于预先录制好的视频的现场音频旁白的例子说明了采用采样时间作为参考点的重要性。在这种情况下,视频会在本地提交给解说员观看,同时会通过RTP包向外界传输。通过RTP传输的一帧视频的“采样时刻”将会被建立,建立的方法是在该帧视频提交给解说员的时刻,将RTP包的时间戳与参考时钟比较算出而建立(即当前的采样序号结合绝对时间得出“采样时刻”)。包含有解说员解说的的音频RTP包,它的采样时刻将会在音频被采样的时刻,通过与同一参考时钟相比较而建立。音频和视频甚至可以被不同的主机传输只要这两个主机的参考时钟通过比如NTP之类的途径实现了同步。接受者能够使用RTCP SR包中的时间戳对从而将音频和视频同步。
SSRC:32比特 用以识别同步源。标识符应该被随机生成,以使在同一个RTP会话期中没有任何两个同步源有相同的SSRC识别符。一个用于创造随机标示符的示例算法在A.6第六章讲述。尽管多个源选择同一个SSRC识别符的概率很低,所有RTP实现工具都必须准备检测和解决冲突。第8章讲述了冲突的可能性及其解决机制。若一个源改变本身的源传输地址,必须选择新的SSRC识别符,以避免被当作一个环路源。
CSRC列表:0到15项,每项32比特 CSRC列表指出了对此包中负载内容的所有贡献源。识别符的数目在CC域中给定。若有贡献源多于15个,仅识别15个。CSRC识别符由混合器插入(see Section 7.1),并列出所有贡献源的SSRC识别符。例如语音包,混合产生新包的所有源的SSRC标识符都被列出,以在接收端处正确指示参与者。
h264与RTP
h.264规范中使用了在NAL层使用了RTP的包头形式,下面对RTP的包头做一下解释:
首先我们来看一下H.264中对于RPT的结构封装如下:
typedef struct { unsigned int v; // Version, 2 bits, MUST be 0x2
unsigned int p; // Padding bit, Padding MUST NOT be used unsigned int x; // Extension, MUST be zero unsigned int cc; // CSRC count, normally 0 in the absence of RTP mixers
unsigned int m; // Marker bit unsigned int pt; // 7 bits, Payload Type, dynamically established unsigned int seq; // RTP sequence number, incremented by one for each sent packet
unsigned int old_seq; // to detect wether packets were lost unsigned int timestamp; // timestamp, 27 MHz for H.26L unsigned int ssrc; // Synchronization Source, chosen randomly
byte * payload; // the payload including payload headers unsigned int paylen; // length of payload in bytes byte * packet; // complete packet including header and payload unsigned int packlen; // length of packet, typically paylen+12 } RTPpacket_t;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5.2复用RTP会话
省略第一段
独立的音频和视频流不应该在一个RTP会话中传输然后根据负载的类型或SSRC来解除复用。包含不同RTP媒体类型的交错包,并且这些包使用同一SSRC将会引起下面一系列问题。
1.假设,两个共有相同RTP会话和相同SSRC标识的音频流,其中一个改变了编码,由此需要一个不同的负载类型。这时就没有办法来识别究竟是哪个音频流改变了编码。
2. SSRC标示符是被定义用来确定一个单一的时序和序列号空间。如果媒体的时钟频率不同,那么交错的多种媒体负载类型需要不同的时序空间和不同的序列号空间,由此来指出哪种负载类型发生了数据包丢失。
3. RTCP发送方和接受方报告只能对每一个SSRC标示符表述一种时序和序列号空间,并且不能加载负载类型域。
4. RTP混合器不能够将不兼容的交叉流合并到一种数据流中。
为每一种媒体采用一个不同的SSRC标示符,但是仍然将他们放在一个RTP会话中传输可以避免前两个问题,但无法避免最后两个。
另一方面,复用同一媒体的有联系的源于一个使用不同SSRC标示符的RTP会话中是关于多播会话的规范。上述的问题不适用于:比如说,一个RTP混合器能够合并多种音源,并且同样的待遇适用于所有的音源。在最后两个问题不会发生的其他情况下,同一媒体的数据流复用(这些数据流使用不同的SSRC)也可以是适当的。
5.3对于RTP包头特性说明的修改
已经存在的RTP数据包包头被认为已经满足通常所有应用类型的需要。然而,为了符合ALF设计原则,该包头可以通过修改或作一些定义在特性说明中的增加的方法实现个性定制。同时,仍然允许与特性独立的显示和记录工具产生作用。
标示位和负载类型域携带特性说明信息,但是它们被存储在固定的包头中,因为很多应用程序被预计需要它们,并且可能需要增加另一个32位的字用来存储它们。包含这些域的八位字节可以通过用一个文件来重新定义,从而适应于不同的需求,例如增加和减少标示位。对于每一个标示位,都必须定位于字节的最高位,因此,监视器能够遵守包丢失模式和标示位之间的相互关系。
如果一种特殊的应用需要独立于负载类型的附加功能,那么应用程序运行的文件应该定义附加的固定域,这些固定域应该紧跟在已经存在的固定包头的SSRC域的后面。这些应用程序能够很快很直接的访问这些附加域,而这时那些独立文件的监视器和记录器仍然能够通过解释前12个字节的方法来处理RTP数据包。
如果事实证明一种附加的功能在所有文件中被普遍需求,那时,就需要定义一个新版本的RTP包头。
5.3.1 RTP头扩展
RTP提供扩展机制以允许实现个性化:某些新的与负载格式独立的功能要求的附加信息在RTP数据包头中传输。设计此扩展机制可以使其它没有扩展的交互忽略此头扩展。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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| defined by profile | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| header extension |
| .... |
若RTP头中的扩展比特位置1,则一个长度可变的头扩展部分被加到RTP固定头之后。头扩展包含16比特的长度域,指示扩展项中32比特字的个数,不包括4个字节扩展头(因此零是有效值)。RTP固定头之后只允许有一个头扩展。为允许多个互操作实现独立生成不同的头扩展,或某种特定实现有多种不同的头扩展,扩展项的前16比特用以识别标识符或参数。这16比特的格式由具体实现的上层协议定义。基本的RTP说明并不定义任何头扩展本身。
未完待续....................