WebRTCソース分析のRTP/RTCP(二)


WebRTCにおけるRTPとRTCPは1つのUDPポートを共有する
WebRTCのRTPとRTCPは共にudp伝送を用い,RTPとRTCPは同一のudpポートを混合して用いているが,NATをオンにすることは本来容易なことではないため,両ポートを分離すればプログラムの複雑さとNATホール成功の難しさを増す.
WebRTCはどのようにRTP/RTCPパッケージを区別します
webrtc/call/call.cc:

PacketReceiver::DeliveryStatus Call::DeliverPacket(
    MediaType media_type,
    rtc::CopyOnWriteBuffer packet,
    const PacketTime& packet_time) {
  RTC_DCHECK_CALLED_SEQUENTIALLY(&configuration_sequence_checker_);
  if (RtpHeaderParser::IsRtcp(packet.cdata(), packet.size()))
    return DeliverRtcp(media_type, packet.cdata(), packet.size());

  return DeliverRtp(media_type, std::move(packet), packet_time);
}

RTPとRTCPが同じUDPポートを使用している以上、受信したUDPパケットがRTPであるかRTCPパケットであるかを区別し、上記のコードではIsRtcpがRTCPパケットであるか否かを判断する.
RTP/RTCPの関連コードはmodules/rtp_rtcpディレクトリの下にある.RtpHeaderParser::IsRtcpは、RtpHeaderParser::RTCP()を呼び出して、RTCPパケットの有無を判定する.
webrtc/modules/rtp_rtcp/source/rtp_utility.cc:

bool RtpHeaderParser::RTCP() const {
  // 72 to 76 is reserved for RTP
  // 77 to 79 is not reserver but  they are not assigned we will block them
  // for RTCP 200 SR  == marker bit + 72
  // for RTCP 204 APP == marker bit + 76
  /*
  *       RTCP
  *
  * FIR      full INTRA-frame request             192     [RFC2032]   supported
  * NACK     negative acknowledgement             193     [RFC2032]
  * IJ       Extended inter-arrival jitter report 195     [RFC-ietf-avt-rtp-toff
  * set-07.txt] http://tools.ietf.org/html/draft-ietf-avt-rtp-toffset-07
  * SR       sender report                        200     [RFC3551]   supported
  * RR       receiver report                      201     [RFC3551]   supported
  * SDES     source description                   202     [RFC3551]   supported
  * BYE      goodbye                              203     [RFC3551]   supported
  * APP      application-defined                  204     [RFC3551]   ignored
  * RTPFB    Transport layer FB message           205     [RFC4585]   supported
  * PSFB     Payload-specific FB message          206     [RFC4585]   supported
  * XR       extended report                      207     [RFC3611]   supported
  */

  /* 205       RFC 5104
   * FMT 1      NACK       supported
   * FMT 2      reserved
   * FMT 3      TMMBR      supported
   * FMT 4      TMMBN      supported
   */

  /* 206      RFC 5104
  * FMT 1:     Picture Loss Indication (PLI)                      supported
  * FMT 2:     Slice Lost Indication (SLI)
  * FMT 3:     Reference Picture Selection Indication (RPSI)
  * FMT 4:     Full Intra Request (FIR) Command                   supported
  * FMT 5:     Temporal-Spatial Trade-off Request (TSTR)
  * FMT 6:     Temporal-Spatial Trade-off Notification (TSTN)
  * FMT 7:     Video Back Channel Message (VBCM)
  * FMT 15:    Application layer FB message
  */

//RTCP  4  (kRtcpMinHeaderLength)
  const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
  if (length < kRtcpMinHeaderLength) {
    return false;
  }

//RTCP       2(kRtcpExpectedVersion)
  const uint8_t V = _ptrRTPDataBegin[0] >> 6;
  if (V != kRtcpExpectedVersion) {
    return false;
  }

  const uint8_t payloadType = _ptrRTPDataBegin[1];
  switch (payloadType) {
    case 192:
      return true;
    case 193:
      // not supported
      // pass through and check for a potential RTP packet
      return false;
    case 195:
    case 200:
    case 201:
    case 202:
    case 203:
    case 204:
    case 205:
    case 206:
    case 207:
      return true;
    default:
      return false;
  }
}

RTPの2バイト目は、タグビット(M):1ビットペイロードタイプ(PT):7ビット
RTCPの2バイト目はパケットタイプ(PT):8ビット
2バイト目の値が200の場合、バイナリに換算すると11001000になります.RTCPパケットであればPT=SR RTPパケットであればタグビット(M)=1、PT=72であるが72-76はRTCP保留使用と規定されているため、RTPパケットであることは不可能である.具体的なRTP Payload types参考:https://www.ietf.org/assignments/rtp-parameters/rtp-parameters.xml
したがって、PTが200−204に等しい値はいずれもRTCPパケットである.PTが205−207の場合、対応するRTPは77−79であり、RTCPに保留して使用するわけではないが、RTPにおいても定義されて使用されておらず、RTCPがこれらの値に用いられるため、WebRTCではRTCPとする.
PT=192、RTP換算64 PT=193、RTP換算65 PT=195、RTP換算66はRTPにおいてPT値が35-71と明示的に定義されていないが、193に等しい場合、WebRTCはRTCPパケットではないと判断し、RTPではこの値をさらに解析する.
一方、webrtc/pc/rtptransport.ccにおいてPT値が63から96の間であると判定された場合は、RTCPとして直接使用される.
webrtc/pc/rtptransport.cc:

// Check the RTP payload type.  If 63 < payload type < 96, it's RTCP.
// For additional details, see http://tools.ietf.org/html/rfc5761.
bool IsRtcp(const char* data, int len) {
  if (len < 2) {
    return false;
  }
  char pt = data[1] & 0x7F;
  return (63 < pt) && (pt < 96);
}

このIsRtcpメソッドは、同じファイルのvoid RtpTransport::OnReadPacketでのみ呼び出されます.