This post is a No.12 article of WebRTC Advent Calendar 2014 この記事は、WebRTC 2014 アドベントカレンダーの12日目の記事です。


TL;DR

  • RTCPで通信状況(統計情報)を送受信側で伝え合って、音声・映像の品質にフィードバック
  • 特にWebRTCでは、RTCPを暗号化したSRTCPを利用

はじめに

WebRTC Meetup Tokyo #3で、WebRTCを支えているプロトコルについて、簡単なLTをしました。 LTの中でDTLS、RTP、SCTPについて喋ったのですが、LTという時間の都合上、説明を端折ったところがあるので、本記事ではその補足をします。

ちなみに、資料は以下にあります:

WebRTCを支えるマイナーなプロトコル SRTP/DTLS/SCTPを分かった気になる from iwashi86

RTPは再送を諦めているだけじゃない

Slide27枚目で、パケットロスが起きた場合の対応として、「再送をGiveUp」すると説明していますが、RTPにおけるパケットロスは実は大切な役割を果たしています。それは何なのかというと、UDPのヘッダを思い返してみるとわかります。

UDPはIPの薄いラッパで、以下のヘッダしかありません:

  • Source Port
  • Destination Port
  • Length
  • Checksum

上記の状態しか保持していない状態で、音声・映像ストリームのパケットロスが起きると、大事なことが1つ分からないのです。それは、パケットロスが起きたこと自体が分からないということ。UDPはTCPと異なり、シーケンス番号を保持していないためです。

パケットロスの発生有無がわからないと、何が問題かということ、送信側でどの程度の品質の音声・映像を流していいか分からないのです。ネットワークが混雑しているのならば、ビットレートを落として送るべきですが、そもそもネットワークの混雑を知らないと、それも出来ません。

RTPにはシーケンス番号がある

UDP単体だとダメだったんですが、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自体だけでも足りない

前述の通り、RTPにはシーケンス番号がありますが、RTP単独でもダメです。というのも、RTPはあくまで音声・映像のメディアを送受信するプロトコルであって、RTPの制御(コントロール)を担っているわけではないためです。そこで、RTPに加えてRTCP(Real-time Transport Control Protocol)というプロトコルが使われています。

RTCPには何が入っている?

RTCPでは、いくつかのパケットタイプ(RTCPで伝え合うメッセージのフォーマットみたいなもの)が規定されています。その中でも代表的なのが、SR(Sender Report)とRR(Receiver Report)です。

SRには、送信側と受信側の情報を含めます。例えば、これまでに送ったパケットの数や、タイムスタンプを含めます:

        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)                 |
                                    以下略

RRには、受信側の情報を含めます。例えば、欠落したパケットの数や、ジッタの推定値を含めます:

        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                  |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                                    以下略

忘れちゃいけない暗号化

WebRTCは、メディアの暗号化が必須です。RTCPも例にもれず、暗号化対象であり、その場合はRTCPじゃなくてSRTCPになります。詳細はRFC5764辺りを参考にしてください。

まとめ

RTPだけじゃ物足りないので、RTCPで通信状況(統計情報)を送受信側で伝え合って、音声・映像の品質にフィードバックしています。 特にWebRTCでは、RTCPを暗号化して、SRTCPが使われてます。

以上、WebRTCの裏側で動いているマイナーなプロトコルの紹介でした。