webrtc RTP控制协议-RTCP

RTP控制协议-RTCP


RTCP-SR rfc3550

/*
        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
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
header |V=2|P|    RC   |   PT=SR=200   |             length            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                         SSRC of sender                        |
       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
sender |              NTP timestamp, most significant word             |
info   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |             NTP timestamp, least significant word             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                         RTP timestamp                         |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                     sender's packet count                     |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                      sender's octet count                     |
       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
report |                 SSRC_1 (SSRC of first source)                 |
block  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1    | fraction lost |       cumulative number of packets lost       |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |           extended highest sequence number received           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                      interarrival jitter                      |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                         last SR (LSR)                         |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                   delay since last SR (DLSR)                  |
       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
report |                 SSRC_2 (SSRC of second source)                |
block  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  2    :                               ...                             :
       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
       |                  profile-specific extensions                  |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct RtcpHeader
{
  uint8_t version : 2;
  uint8_t padding : 1;
  uint8_t count : 5;
  uint8_t packetType;
  uint16_t length;
  
  uint32_t ssrc;
  uint32_t ntpSec;
  uint32_t ntpFrac;
  uint32_t rtpTs;
  uint32_t packetCount;
  uint32_t octetCount;

/* 变长,根据count决定 */
  struct reportHeader report;
};

/* Struct for RTCP report block*/
struct reportHeader
{
  uint32_t ssrc;
  uint8_t  fractionLost; // 丢包率
  uint32_t totalLost : 24;  // 一共丢包的个数
  uint32_t lastSeq;  // sequenceNumber
  uint32_t jitter;  // RTP包到达时间间隔的统计方差
  uint32_t lsr;  // 上一次收到SR的时间戳
  uint32_t dlsr;  // 上次从收到SR包到发送本报告的时间差
};
  • version: 2
  • padding: 置为1表示RTP头有填充。数据的最后一个字节表示填充了几个字节,包含这个字节本身
  • count:reportHeader的个数
  • packetType: 200,SR(Sender Report),发送者报告:包含发送者的发送、接收统计
  • length: 指协议头和数据的长度,单位为字节。数据长度length-4
  • ssrc: 与sdp中的ssrc一致
  • ntpSec: most significant word,高位时间戳,ntpFrac每到最大值就清零,ntpSec加1,
  • ntpFrac: least significant word,低位时间戳,单位是微秒。网络时间戳,用于同步不同源
  • rtpTs: 相对时间戳,与rtp一致
  • packetCount: 一共发送了多少个包
  • octetCount: 一共发送了多少字节
  • report.ssrc: 信息所属的ssrc
  • report.fractionLost: 丢包率
  • report.totalLost: 一共丢包的个数。迟到包不算丢包,重传有可能导致负数
  • report.lastSeq: rtp头的sequenceNumber是16bit,会循环从0开始。此处低位16bit与rtp一致,高位表示循环次数
  • report.jitter: RTP包到达时间间隔的统计方差
  • report.lsr: 上一次收到SR的时间戳,lsr = (ntpSec<<16) + (ntpFrac>>16)
  • report.dlsr: 上次从收到SR包到发送本报告的时间差

RTCP-RR rfc3550

/*
        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
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
header |V=2|P|    RC   |   PT=RR=201   |             length            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                     SSRC of packet sender                     |
       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
report |                 SSRC_1 (SSRC of first source)                 |
block  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1    | fraction lost |       cumulative number of packets lost       |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |           extended highest sequence number received           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                      interarrival jitter                      |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                         last SR (LSR)                         |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                   delay since last SR (DLSR)                  |
       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
report |                 SSRC_2 (SSRC of second source)                |
block  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  2    :                               ...                             :
       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
       |                  profile-specific extensions                  |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct RtcpHeader
{
  uint8_t version : 2;
  uint8_t padding : 1;
  uint8_t count : 5;
  uint8_t packetType;
  uint16_t length;
  
  uint32_t ssrc;
  
/* 变长,根据rtcp.count决定 */
  struct reportHeader report;
};

/* Struct for RTCP report block*/
struct reportHeader
{
  uint32_t ssrc;
  uint8_t  fractionLost;
  uint32_t totalLost : 24;
  uint32_t lastSeq;
  uint32_t jitter;
  uint32_t lsr;
  uint32_t dlsr;
};
  • packetType: 201,RR(Receiver Report),接收者报告:接受者的接收统计
  • 其他字段意思参考RTCP-SR

RTCP-SDES rfc3550

/*
        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
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
header |V=2|P|    SC   |  PT=SDES=202  |             length            |
       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
chunk  |                          SSRC/CSRC_1                          |
  1    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           SDES items                          |
       |                              ...                              |
       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
chunk  |                          SSRC/CSRC_2                          |
  2    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           SDES items                          |
       |                              ...                              |
       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*/
struct RtcpHeader
{
  uint8_t version : 2;
  uint8_t padding : 1;
  uint8_t count : 5;
  uint8_t packetType;
  uint16_t length;
  
/* 变长,根据rtcp.count决定 */
  uint32_t ssrc;
  struct SdesItem sdes;
};

struct SdesItem
{
  uint8_t type;
  uint8_t length;
  char value[N]; // N=length
};
enum SdesType
{
  END = 0,
  CNAME,  // cname与SSRC对应,cname为源的唯一表示,详情参考sdp描述
  NAME,     // 用户名
  EMAIL,    // email地址
  PHONE,  // 电话号码
  LOC,       // 位置
  TOOL,    // 工具
  NOTE,    // 备注
  PRIV      // 私有扩展
};
  • version: 2
  • padding: 置为1表示RTP头有填充。数据的最后一个字节表示填充了几个字节,包含这个字节本身
  • count:ssrcsdes的个数
  • packetType: 202,SDES(SourceDescription),数据源的信息
  • length: 指协议头和数据的长度,单位为字节。数据长度length-4
  • ssrc: 与sdp中的ssrc一致
  • sdes.type: 取值SdesType
  • sdes.length: value长度
  • sdes.value:

RTCP-BYE rfc3550

/*
       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|    SC   |   PT=BYE=203  |             length            |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                           SSRC/CSRC                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      :                              ...                              :
      +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
(opt) |     length    |               reason for leaving            ...
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct RtcpHeader
{
  uint8_t version : 2;
  uint8_t padding : 1;
  uint8_t count : 5;
  uint8_t packetType;
  uint16_t length;
  
/* 变长,根据count决定有多少个ssrc */
  uint32_t ssrc;
  
/* 可选 */
  uint8_t length;
  uint8_t reason[N]; // N=length
};
  • version: 2
  • padding: 置为1表示RTP头有填充。数据的最后一个字节表示填充了几个字节,包含这个字节本身
  • count:ssrc的个数
  • packetType: 203,BYE(goodbye),结束RTP传输
  • length: 指协议头和数据的长度,单位为字节。数据长度length-4
  • ssrc: 与sdp中的ssrc一致
  • length: reason的长度
  • reason: 退出原因,可选

RTCP-APP rfc3550

/*
    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| subtype |   PT=APP=204  |             length            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                           SSRC/CSRC                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                          name (ASCII)                         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                   application-dependent data                ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct RtcpHeader
{
  uint8_t version : 2;
  uint8_t padding : 1;
  uint8_t count : 5;
  uint8_t packetType;
  uint16_t length;

  uint32_t ssrc;
  
/* 变长,根据count决定 */
  uint32_t name;
  struct AppData data;
};

/* 消息格式可以自定义,我这里只是自己列举的一个数据格式类型 */
struct AppData
{
  uint8_t type;
  uint8_t length;
  char value[N]; // N=length
};

  • version: 2
  • padding: 置为1表示RTP头有填充。数据的最后一个字节表示填充了几个字节,包含这个字节本身
  • count:namedata的个数
  • packetType: 204,APP(application),应用层定义的传输控制类型
  • length: 指协议头和数据的长度,单位为字节。数据长度length-4
  • ssrc: 与sdp中的ssrc一致
  • name: 自定义消息名
  • data: 自定义数据

RTCP-RTPFB rfc4585

/*
    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|   FMT   |       PT      |          length               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                  SSRC of packet sender                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                  SSRC of media source                         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   :            Feedback Control Information (FCI)                 :
   :                                                               :
*/
struct RtcpHeader
{
  uint8_t version : 2;
  uint8_t padding : 1;
  uint8_t count : 5;
  uint8_t packetType;
  uint16_t length;
  
  uint32_t senderSsrc;
  uint32_t mediaSsrc;

/* FCI字段*/
};
enum FeedbackRtp
{
  NACK   = 1,  // Generic nack。请求丢包重传
  TMMBR  = 3,  // Temp, max media stream Bitrate Request。最大媒体流请求
  TMMBN  = 4,  // Temp, max media stream Bitrate Notification。最大媒体流响应
  SR_REQ = 5,
  RAMS   = 6,
  TLLEI  = 7,
  ECN    = 8,
  PS     = 9,
  TCC    = 15, // transport-cc
  EXT    = 31
};
  • version: 2
  • padding: 置为1表示RTP头有填充。数据的最后一个字节表示填充了几个字节,包含这个字节本身
  • count: 取值为FeedbackRtp
  • packetType: 205,RTPFB(Generic RTP Feedback),RTP反馈包,传输的控制
  • length: 指协议头和数据的长度,单位为字节。数据长度length-4
  • senderSsrc: 数据包发送方的ssrc
  • mediaSsrc: 媒体源的ssrc
  FCI字段,NACK消息的格式
    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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |            PID                |             BLP               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  PID: 丢包的RTP sequenceNumber
  BLP: 继第一个序号之后的16个包的丢失情况,当丢失之后置为1

RTCP-PSFB rfc4585

图像和流媒体 -- I 帧,B帧,P帧,IDR帧的区别

/*
    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|   FMT   |       PT      |          length               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                  SSRC of packet sender                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                  SSRC of media source                         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   :            Feedback Control Information (FCI)                 :
   :                                                               :
*/
struct SDESHeader
{
  uint8_t version : 2;
  uint8_t padding : 1;
  uint8_t count : 5;
  uint8_t packetType;
  uint16_t length;
  
  uint32_t senderSsrc;
  uint32_t mediaSsrc;

/* FCI字段*/
};

enum FeedbackPs
{
  PLI   = 1,  // Picture Loss Indication,请求i帧,FCI字段中必须仅包含一个PLI
  SLI   = 2,  // Slice Loss Indication,请求一个slice包
  RPSI  = 3,  // Reference Picture Selection Indication。请求b帧
  FIR   = 4, // Full Intra Request Command。请求一个idr帧
  TSTR  = 5,  // Temporal-Spatial Trade-off Request。空间换时间或时间换空间的请求
  TSTN  = 6,  // Temporal-Spatial Trade-off Notification。空间换时间或时间换空间的响应
  VBCM  = 7,
  PSLEI = 8,
  ROI   = 9,
  AFB   = 15,
  EXT   = 31
};

  • version: 2
  • padding: 置为1表示RTP头有填充。数据的最后一个字节表示填充了几个字节,包含这个字节本身
  • count: 取值为FeedbackPs
  • packetType: 206,PSFB(Payload-specific Feedback),payload反馈包,编解码的控制
  • length: 指协议头和数据的长度,单位为字节。数据长度length-4
  • senderSsrc: 数据包发送方的ssrc
  • mediaSsrc: 媒体源的ssrc
  FCI字段,SLI消息的格式
    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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |            First        |        Number           | PictureID |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  First: 第一个丢失的宏块的宏块地址
  Number: 丢失的宏块数
  PictureID: 编解码器特定标识符的六个最低有效位
  
  FCI字段,RPSI消息的格式
    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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      PB       |0| Payload Type|    Native RPSI bit string     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   defined per codec          ...                | Padding (0) |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

DTLS-SRTP


SRTP与RTP包的主要区别是payload数据加密、SRTP MKI(主密钥标由密钥管理协议决定)、认证标签

  • payload加密 加密后的数据依然保持对齐
  • SRTP MKI webrtc基本没用,为0
  • 认证标签 rtp头和加密payload进行哈希计算得来的

DTLS握手

  • 第一次客户端发送ClientHello
  • 第二次服务端发送ServerHello,发送服务端证书,服务端key,请求客户端证书,发送ServerHelloDone
  • 第三次客户端发送客户端证书,客户端key,验证证书,发送加密套件,发送Finished
  • 第四次服务端发送协商好的加密套件,发送Finished

数据传输

DTLS进行握手交换得到key、加密套件。然后在使用RTP进行传输,仅对payload数据进行加密

你可能感兴趣的:(webrtc RTP控制协议-RTCP)