网络流媒体协议之——RTP协议概述

网络流媒体协议系列:

网络流媒体协议之——MPEG-DASH协议简述

网络流媒体协议之——HLS概述

网络流媒体协议之——UDP协议概述

今天来整理一下RTP。

RTP(Real-time Transport Protocol,实时传输协议)是用于Internet上针对多媒体数据流的一种传输协议,由IETF提出,对应的标准文档是RFC3550。RTP协议和RTCP(Real-time Transport Control Protocol)一起使用。RTP使用偶数端口号收发数据,相应的RTCP则使用相邻的下一位奇数端口号。

RTP

RTP传输基于IP协议,所以最大传输单元(MTU)最大为1500字节,在使用IP/UDP/RTP的协议层次结构的时候,这其中包括至少20字节的IP头,8字节的UDP头,以及12字节的RTP头。这样,头信息至少要占用40个字节,那么RTP载荷的最大尺寸为1460字节。以H.264 为例,如果一帧数据大于1460,则需要分片打包,然后到接收端再拆包,组合成一帧数据,进行解码播放。

RTP的使用场景包括:

(1)   简单多播音频会议(SimpleMulticast Audio Conference)

(2)   音频和视频会议(Audioand Video Conference)

(3)   混频器和转换器(Muxersand Translators)

(4)   分层编码(LayeredEncoding)

其中,混频器(Mixer)是一种中间系统,它从一个或多个源中接收RTP包,可能会改变其数据格式,再按某种方式把这些包组合成一个新的包,然后转发出去。由于多个输入源的计时一般不同步,所以混频器对各个流的计时做出调整,并为组合流生成一个新的计时。

转换器(Translator)也一种中间系统,它转发RTP包而不改变包的同步源标识符。转换器的例子如,不做混频的转码器,多播复制到单播的重复装置,以及防火墙里应用层次的过滤器。

RTP数据协议负责对流媒体数据进行封包并实现媒体流的实时传输,每一个RTP数据报都由头部(Header)和负载(Payload)两个部分组成,其中头部前12个字节的含义是固定的,而负载则可以是音频或者视频数据。

RTP报头格式如下:

网络流媒体协议之——RTP协议概述_第1张图片

报头的前12bits出现在每个RTP包中,仅仅在使用混合器插入时,才出现CSRC识别符列表。报头各个域的含义解释如下:

  • 版本(V):2 bits,定义了RTP的版本,以上版本为2。
  • 填充(P):1 bit,若被置为1,则此RTP包包含一个到多个附加在末端的填充比特,填充比特不作为负载的一部分。填充可能用于某些固定长度的加密算法,或者用于在低层数据单元中传输多个RTP包。
  • 扩展(X):1 bit,若设置扩展比特,则固定报头后面跟随一个扩展报头。
  • CSRC计数(CC):4 bit,CSRC计数包含了跟在固定头后面CSRC识别符的数目。
  • 标志(M):1 bit,含义由具体协议规定,它用来允许在比特流中标记重要的事件,如帧边界。
  • 负载类型(PT):7 bits,定义了负载的格式,由具体应用决定其含义。协议可以规定负载类型码和负载格式之间一个默认的匹配,其他的负载类型码可以通过非RTP方法动态定义。RTP发送端在任意给定时间发出一个单独的RTP负载类型,此域不用来复用不同的媒体流。例如我们常用的开源框架FFMPEG中,有以下支持的负载类型:

static const struct {
    int pt;
    const char enc_name[6];
    enum AVMediaType codec_type;
    enum AVCodecID codec_id;
    int clock_rate;
    int audio_channels;
} rtp_payload_types[] = {
  {0, "PCMU",        AVMEDIA_TYPE_AUDIO,   AV_CODEC_ID_PCM_MULAW, 8000, 1},
  {3, "GSM",         AVMEDIA_TYPE_AUDIO,   AV_CODEC_ID_NONE, 8000, 1},
  {4, "G723",        AVMEDIA_TYPE_AUDIO,   AV_CODEC_ID_G723_1, 8000, 1},
  {5, "DVI4",        AVMEDIA_TYPE_AUDIO,   AV_CODEC_ID_NONE, 8000, 1},
  {6, "DVI4",        AVMEDIA_TYPE_AUDIO,   AV_CODEC_ID_NONE, 16000, 1},
  {7, "LPC",         AVMEDIA_TYPE_AUDIO,   AV_CODEC_ID_NONE, 8000, 1},
  {8, "PCMA",        AVMEDIA_TYPE_AUDIO,   AV_CODEC_ID_PCM_ALAW, 8000, 1},
  {9, "G722",        AVMEDIA_TYPE_AUDIO,   AV_CODEC_ID_ADPCM_G722, 8000, 1},
  {10, "L16",        AVMEDIA_TYPE_AUDIO,   AV_CODEC_ID_PCM_S16BE, 44100, 2},
  {11, "L16",        AVMEDIA_TYPE_AUDIO,   AV_CODEC_ID_PCM_S16BE, 44100, 1},
  {12, "QCELP",      AVMEDIA_TYPE_AUDIO,   AV_CODEC_ID_QCELP, 8000, 1},
  {13, "CN",         AVMEDIA_TYPE_AUDIO,   AV_CODEC_ID_NONE, 8000, 1},
  {14, "MPA",        AVMEDIA_TYPE_AUDIO,   AV_CODEC_ID_MP2, -1, -1},
  {14, "MPA",        AVMEDIA_TYPE_AUDIO,   AV_CODEC_ID_MP3, -1, -1},
  {15, "G728",       AVMEDIA_TYPE_AUDIO,   AV_CODEC_ID_NONE, 8000, 1},
  {16, "DVI4",       AVMEDIA_TYPE_AUDIO,   AV_CODEC_ID_NONE, 11025, 1},
  {17, "DVI4",       AVMEDIA_TYPE_AUDIO,   AV_CODEC_ID_NONE, 22050, 1},
  {18, "G729",       AVMEDIA_TYPE_AUDIO,   AV_CODEC_ID_NONE, 8000, 1},
  {25, "CelB",       AVMEDIA_TYPE_VIDEO,   AV_CODEC_ID_NONE, 90000, -1},
  {26, "JPEG",       AVMEDIA_TYPE_VIDEO,   AV_CODEC_ID_MJPEG, 90000, -1},
  {28, "nv",         AVMEDIA_TYPE_VIDEO,   AV_CODEC_ID_NONE, 90000, -1},
  {31, "H261",       AVMEDIA_TYPE_VIDEO,   AV_CODEC_ID_H261, 90000, -1},
  {32, "MPV",        AVMEDIA_TYPE_VIDEO,   AV_CODEC_ID_MPEG1VIDEO, 90000, -1},
  {32, "MPV",        AVMEDIA_TYPE_VIDEO,   AV_CODEC_ID_MPEG2VIDEO, 90000, -1},
  {33, "MP2T",       AVMEDIA_TYPE_DATA,    AV_CODEC_ID_MPEG2TS, 90000, -1},
  {34, "H263",       AVMEDIA_TYPE_VIDEO,   AV_CODEC_ID_H263, 90000, -1},
  {-1, "",           AVMEDIA_TYPE_UNKNOWN, AV_CODEC_ID_NONE, -1, -1}
};
  • 序列号(Sequence Number):16 bits,每发送一个RTP数据包,序列号增1,接收端可以据此检测丢包和重建包序列。序列号初始值是随机的。

  • 时间戳(Timestamp):32 bits,反映了RTP数据包中第一个字节的采样时间。时钟频率依赖于负载数据格式,并在描述文件(profile)中进行描述,也可以通过RTP方法对负载格式动态描述。时间戳的初始值应当是随机的,就像序列号一样。同时产生的几个连续的RTP包,例如属于同一个视频帧的RTP包,将有相同的时间戳。不同媒体流的RTP时间戳可能会有独立的随机偏移量,并且可能以不同的速率增长,因此需要与参考时钟上的时间戳(NTP)相关联来实现不同媒体时间上的同步。

  • 同步源(SSRC):32 bits,用于识别同步源,是一个随机数。来自同一信号源的包流发送方,例如麦克风、摄影机等就是同步源。如果参与者在一个会话中生成了多个流,例如这些流来自多个摄像机,则每个流都必须标识成单独的同步源。若一个源改变本身的源传输地址,必须选择新的SSRC标识符。一个同步源的所有包构成了相同计时和序列号空间的一部分,这样接收方就可以把一个同步源的包放在一起进行重放。SSRC的绑定通过RTCP。

  • 作用源(CSRC)列表:0~15个,每个32 bits,用于标识该RTP包中的作用源。标识符的数目在CC域中给定,若作用源多于15个,则仅识别15个。若一个RTP包流的源,对RTP混频器生成的组合流起了作用,则它是一个作用源。对特定包的生成起作用的源组成的SSRC列表,被混频器插入到包的RTP报头中,即CSRC列表。

前面我们提到,若扩展位X的1 bit被置位,则固定报头后面跟随一个头扩展(header extension),下面我们就来看看头扩展是个什么东东。

RTP提供了一个扩展机制以实现定制化:某些与负载格式独立的新功能的附加信息可以在头扩展中传输。头扩展格式如下,

网络流媒体协议之——RTP协议概述_第2张图片

若RTP头中的扩展比特位置1,则一个长度可变的头扩展部分被添加到固定RTP头之后。头扩展包含16 bits的长度域,指示32 bits header extension字的个数,不包含4个字节扩展头。length域之前的16 bits域是为了在多个互操作独立生成不同的头扩展时,用以识别各个头扩展的标识符或参数,该16 bits的格式由具体实现的上层协议定义。

RTCP

下面我们来简单介绍一下RTCP协议,RTCP虽然占用流量很少,但其实现逻辑较RTP复杂得多,因此,本篇限于篇幅,只介绍一下基础概念,后面再开一篇专门介绍RTCP。

控制协议RTCP,用于QoS反馈和同步流媒体,相对RTP来说,RTCP所占带宽非常小,通常只有5%。RTCP控制协议需要与RTP数据协议一起配合使用,当应用程序启动一个RTP会话时将同时占用两个端口,分别供RTP和RTCP使用。RTP本身并不能为按序传输数据包提供可靠的保证,也不提供流量控制和拥塞控制,这些都由RTCP来负责完成。通常RTCP会采用与RTP相同的分发机制,向会话中的所有成员周期性地发送控制信息,应用程序通过接收这些数据,从中获取会话参与者的相关资料,以及网络状况、分组丢失概率等反馈信息,从而能够对服务质量进行控制或者对网络状况进行诊断。

RTCP协议的功能是通过不同的RTCP数据报来实现的,主要有如下几种类型:

  • SR:发送端报告,所谓发送端是指发出RTP数据报的应用程序或者终端,发送端同时也可以是接收端。(SERVER定时间发送给CLIENT)。
  • RR:接收端报告,所谓接收端是指仅接收但不发送RTP数据报的应用程序或者终端。(SERVER接收CLIENT端发送过来的响应)。
  • DES:源描述,主要功能是作为会话成员有关标识信息的载体,如用户名、邮件地址、电话号码等,此外还具有向会话成员传达会话控制信息的功能。
  • BYE:通知离开,主要功能是指示某一个或者几个源不再有效,即通知会话中的其他成员自己将退出会话。

  • APP:由应用程序自己定义,解决了RTCP的扩展性问题,并且为协议的实现者提供了很大的灵活性。

今天先写到这里,周末愉快!
本篇主要参考RFC3550。


你可能感兴趣的:(流媒体)