RTCP REMB:ブラウザーのビデオ通話設定を調整します







Tribeの機知に富んだ人たちは、カンファレンスとgamedevの交差点でニッチを見つけただけでなく(それ自体は既に興味深い)、WebRTCの裏側で何が起こっているかを知っています。 プロダクトマネージャーのTimote Le Bornierは、彼の発案の技術的な側面について定期的に説明しています。 WebRTCの非標準だが非常に奇妙な機能に関する彼の記事を翻訳することにしました。 きっと興味を持っていただけるでしょう。 さて、あなたが読んでいる間、私たちは更新されたビデオ会議についてインサイダーを準備し続けます...






REMBを使用したフロー品質の微調整と制御



ですから、Tribe向けのカスタムMCUの作成に取り組んでいることはご存知でしょう。もしあなたが知らないのなら、それをやろう決めた理由です。



しかし、ポイントに近い:フードの下で何が起こるか見てみましょう。



  1. WebRTC接続は、「SDPオファー/アンサー」と呼ばれる交換メカニズムで始まります-参加者間でサポートされるコーデックと関連パラメーターに関する情報の交換。
  2. その後、参加者は互いに直接通信しようとします。UDPポートのリッスンを開始し、ICE、STUN、および(後で)TURNを使用してUDP接続を確立します。
  3. UDP接続が確立されると、参加者はそれを使用して、DTLS-SRTPプロトコルを使用して暗号化パラメーターを交換します。 その後、参加者は次を使用します。

    • メディアを送受信するためのSRTP(Secure RTP over UDP)プロトコル
    • フロー制御および帯域外通信用のSRTCP(UDPを介したセキュアRTCP)。










WebRTCプロトコルスタック(変更されたスキーマ、オリジナルはここ: webrtc-security.github.io



RTCPを扱っています



RTPおよびRTCPパケットがSRTPおよびSRTCPに安全に保存されることは上記で言及されています。 彼らは何のために使われますか?



RTPは、リアルタイムデータ(オーディオとビデオ)のエンドツーエンドのトランスポートを提供します。 ある意味では、RTCPは「RTP兄弟」です。RTPで使用され、配信と管理および識別を監視することにより、データ転送プロトコルを改善します。



WebRTCセッションでは、MCUは参加者間の仲介者として機能します。参加者はMCUに接続されますが、相互に直接接続されません。









WebRTC-MCUベーストポロジ



たとえば、2人の参加者とのセッションに参加します。 MCUは、FOO参加者からメディアストリームを受信し、デコード、エンコードし、BAR参加者に送信します。 同時に、BARからFOOへのフローでも同じことが起こります。









MTPおよびRTCP



対称性は明らかなので、一方向に焦点を当てて、そこで何が起こるかを見てみましょう。









片側に焦点を当てる



BARブラウザは、MCUからメディアストリームを受信すると、RTCP Sender Reports(SR)から統計情報も受信します。 BARブラウザは、RTP'sh連続パケット番号、RTPタイムスタンプ、ネイティブ時間、および送信者レポートを使用して、RTCP受信者レポート(RR)を計算します。



BARブラウザは、このすべてのデータを使用して最大予想ビットレートを計算し、RTCP REMB(リモート推定最大ビットレート)を使用してこの値をMCUに送信します。



REMBの使用(効果的)









パッケージ形式RTCP REMB tools.ietf.org/html/draft-alvestrand-rmcat-remb-00#section-2.2



計算された最大ビットレート値は、BR ExpおよびBR仮数フィールドにエンコードされます。



実装例はChromiumコードにあります: cs.chromium.org/chromium/src/third_party/webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.cc

Goでは、このメッセージをPacketALFBRemb構造に変換しました。



type PacketALFBRemb struct {
...
BRExp uint8
BRMantissa uint32
...
}
view raw f4.go hosted with ❤ by GitHub


そのような構造からビットレートを知る必要があるとき、これを行うことができます:



func (p *PacketALFBRemb) GetBitrate() uint32 {
return p.BRMantissa << p.BRExp
}
view raw f1.go hosted with ❤ by GitHub


逆に、ビットレートがあり、PacketALFBRemb構造体のExpフィールドと仮数フィールドに入力する場合は、次のようにします。



func (p *PacketALFBRemb) SetBitrate(bitrate uint32) {
var kMaxMantissa uint32 = 0x3ffff
var exponenta uint8 = 0
mantissa := bitrate
for mantissa > kMaxMantissa {
mantissa = mantissa >> 1
exponenta++
}
p.BRMantissa = mantissa
p.BRExp = exponenta
}
view raw f2.go hosted with ❤ by GitHub


帯域幅とRTCP REMB



これはMCUの利点の1つです。ブラウザで発信ビットレートを制御するためにREMB RTCPパッケージを作成する機能:









MCUはRTCP REMBを送信して、FOOブラウザーの発信ビットレートを制御します



また、MCUは受信者からビットレートの推定値を取得し、それに応じて、推定最大ビットレートと一致するようにエンコード設定を変更できます。 また、MCUの送信スループットも最適化します。









MCUは、BARメンバーからのRTCP REMB値を使用してエンコード設定を変更します



ビットレートを制御します



FOOブラウザのビットレートに対するRTCP REMBの効果をテストするにはどうすればよいですか? 非常に簡単:可変ビットレート(たとえば、10秒ごとに64Kbと128Kb)でREMBパケットを送信し、次にchrome:// webrtc-internals chartsを見てください



Go言語では、次のようになります。



ticker := time.NewTicker(time.Millisecond * 10000)
go func() {
flipflap := 1
for range ticker.C {
remb := rtcp.NewPacketALFBRemb()
remb.SetSSRC(video.ssrcId)
if flipflap == 1 {
remb.SetBitrate(64000)
} else {
remb.SetBitrate(128000)
}
rtcpPacketRemb := &RtpUdpPacket{
RAddr: w.stunCtx.RAddr,
Data: remb.Bytes(),
}
// send the packet (webrtcsession.connection)
w.c.writeSrtpRtcpTo(ctx, rtcpPacketRemb)
//
flipflap = -flipflap
}
}()
view raw f3.go hosted with ❤ by GitHub


chrome:// webrtc-internalsを開くと、次のようなものが表示されます。









これは、リアルタイムで自分のビットレートを変更および監視できることの明確な確認です。 どのパラメーターがニーズに最適で、帯域幅とストリームの品質を最適化する必要があるかどうかは、決定する必要があります:)






おそらくRTCP REMBが非推奨になったことにお気づきでしょう。 アイデアは、データソース(リモートレシーバー/参加者ではなく)が帯域幅を制御するというものでした-さて、この記事では、これはまだ可能であり、その方法を示しました。



私たちの場合、ストリップと品質を正確に制御できると便利でした:)



All Articles