WebRTCについて調べてみたまとめ

## WebRTCとは
ブラウザ間でリアルタイムコミュニケーション(RealTimeCommunication)を行うためのオープンソースプロジェクト。
P2P通信を行うことで低レイテンシの実装が可能でローカルネットワーク外でもP2Pで通信できる。

ブラウザだけでなくネイティブアプリへの実装も可能で、ビデオチャットに使用されている。
身近なものだと、GoogleHangOutとかDiscordに使われている技術。

## 仕様
API:[W3C](https://www.w3.org/)
通信仕様:[IETF](https://www.ietf.org/)
がそれぞれ規定している

## 対応ソフト
* WebRTCの対応ブラウザバージョン
 * Edge:15
 * FireFox:22
 * Chrome:23
 * Safari:11
 * Opera:18

仕様に完全準拠しているわけではないため、注意が必要

* Androidでの実装の場合
 * Firefoxとchromegは対応している
 * AndroidのWebViewを使っているその他ブラウザでも利用可能
 * 端末によっては「カメラが使えない」「H.264非対応」などにより使えないものもある


## シグナリング
TCPで言うセッションを貼るまでの処理をシグナリングという。
大きく分けて2つの情報、接続情報とセッション情報をやり取りすることで通信を確率させる。

* 接続情報
 * IPアドレスとポートを指す

* セッション情報
　* 通信形式を一致させるためにやり取りを行う。
　* 後述のSDPというものを互いに交換することで実現する。

```txt:SDP
v=0
o=- 5857680321754400137 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0
a=msid-semantic: WMS io1ttp3fJNqDMVyJXb1BmL99EhK7sW2f4hc4
m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 102 122 127 121 125 107 108 109 124 120 123
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:SZTl
a=ice-pwd:hogehogehogehoge
a=ice-options:trickle
a=fingerprint:sha-256 0F:1D:9E:60:E5:4B:39:AB:72:9E:81:C1:10:5C:5D:DC:7E:2B:B7:F6:59:1F:C4:FB:28:74:A8:3C:FB:23:98:F0
a=setup:active
a=mid:0
a=extmap:14 urn:ietf:params:rtp-hdrext:toffset
a=extmap:13 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:12 urn:3gpp:video-orientation
a=extmap:2 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:11 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
a=extmap:8 http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07
a=extmap:9 http://www.webrtc.org/experiments/rtp-hdrext/color-space
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendrecv
a=msid:io1ttp3fJNqDMVyJXb1BmL99EhK7sW2f4hc4 8e379d68-3afd-4f44-b44f-74cbae500336
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:96 VP8/90000
a=rtcp-fb:96 goog-remb
a=rtcp-fb:96 transport-cc
a=rtcp-fb:96 ccm fir
a=rtcp-fb:96 nack
a=rtcp-fb:96 nack pli
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=96
a=rtpmap:98 VP9/90000
a=rtcp-fb:98 goog-remb
a=rtcp-fb:98 transport-cc
a=rtcp-fb:98 ccm fir
a=rtcp-fb:98 nack
a=rtcp-fb:98 nack pli
a=fmtp:98 profile-id=0
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=98
a=rtpmap:107 rtx/90000
a=fmtp:107 apt=125
a=rtpmap:124 red/90000
a=rtpmap:120 rtx/90000
a=fmtp:120 apt=124
a=rtpmap:123 ulpfec/90000
a=ssrc-group:FID 3985486965 1159696126
a=ssrc:1159696126 cname:HgrSdJEZYNlZ0Ryg
```
## ローカルネットワーク外へのアクセス方法
* ICEサーバ
下の2つ(STUN,TRUN)のサーバのどちらかを使用してP2P接続を行う。
両方をまとめてICE(nteractive Connectivity Establishment)サーバと呼ぶ

* STUNサーバ
 * NATを超えてアクセスできる
  * 通信経路はブラウザが探してくれる
  * ネイティブの場合、OSレベルで経路情報を取れる？
  * Googleが公開サーバを提供
* TURNサーバ
 * クライアント間のパケットをトンネリングしてくれる
 * WebRTC=P2P通信と謳っているが、TURNサーバを経由するため、P2Pではない

## 接続の構成
ビデオチャットを前提にしているため負荷のかかるポイントとしては２つ。
・エンコード、デコードによるCPU負荷
・通信量増加による帯域への負荷

* P2P
 * フルメッシュ
 * 端末の数だけI/OのセッションができるためCPU,帯域ともに高負荷になる
 * サーバが不要
* SFU
 * 各端末はSFUサーバにデータを送信
 * サーバから各端末に映像が配信される
 * 端末ごとの出力が一箇所 = エンコードの数とOutの通信が減るので
 * SFUサーバが必要
* MCU
 * 各端末はMCUサーバへデータを送信
 * MCUサーバは端末から上がってきたデータを合成し、端末へ振り直す。
 * サーバ→端末の出力も一本になるので端末のCPU負荷は更に減る
 * サーバが端末のすべてのデータをエンコードデコードし直すため、処理能力の高いMCUサーバが必要