Playing with RTCP REMB #WebRTC

Controlling & fine-tuning stream quality using REMB

Timothée Le Borgne
Inside Tribe
Published in
5 min readFeb 1, 2018

--

So, by now, you should already know we’ve been working on building a custom WebRTC MCU for Tribe — if not, you should check out why we decided to do it, and how we’re proceeding :-)

Let’s get a bit more ‘hands-on’ now, and see what actually happens behind the curtains.

  1. A WebRTC communication starts with an exchange mechanism called “SDP offer/answer” — it’s an exchange of capabilities — supported codecs and associated parameters — between participating peers, to set up the session up.
  2. Once the exchange is set, peers will try to communicate directly with each other: they’ll start listening to UDP ports, and use ICE, STUN and eventually TURN to establish a UDP connection.
  3. Once the UDP connection is established, peers will use it to exchange cryptographic parameters using the DTLS-SRTP protocol. Once they’re sent, they’ll use both:
  • the SRTP protocol (Secure RTP, on top of UDP) to send and receive media
  • the SRTCP protocol (Secure RTCP, on top of UDP) to exchange flow control and out-of-band statistics
WebRTC protocol stack • (image modified. Original at: http://webrtc-security.github.io/ )

Focus on RTCP

As said, RTP & RTCP packets are securely contained in SRTP & SRTCP. What are they used for?

Well, RTP provides end-to-end network transport functions for transmitting real-time data: audio & video. In a way, RTCP is the “sister protocol of RTP”: it’s used alongside RTP and enhances the data transport protocol with monitoring of the data delivery, as well as control and identification capabilities.

During a WebRTC session, the MCU acts as a substitute for a peer: all peers actually connect to the MCU, and not directly to each other (≠ mesh).

WebRTC — basic MCU Topology

Let’s take a 2-peer session, as an example. The MCU receives a media stream (audio/video) from FOO, decodes it, encodes it and sends it to BAR. It does exactly the same thing at the same time, with the media stream received from BAR, to FOO.

Media transport protocol & RTP control protocol

Now, we know it’s a perfectly symmetrical situation, so let’s just focus on one side, to see what happens there:

Focus on one side

When BAR’s browser receives a media stream from the MCU, it also receives at the same time stats from RTCP Sender Reports (SR). BAR’s browser will use the RTP packet sequence numbers, RTP Packet timestamps, its own clock time, and the Sender Reports to compute what we call RTCP Receiver reports (RR).

BAR’s browser will use all these stats to compute a maximum estimated bitrate, and will then send this info to the MCU using RTCP REMB (Remote Estimate Maximum Bitrate).

Making (good!) use of REMB

RTCP REMB packet format • https://tools.ietf.org/html/draft-alvestrand-rmcat-remb-00#section-2.2

The estimated maximum bitrate value is encoded in BR Exp & BR Mantissa fields.

You can see an example implementation looking at chromium code: https://cs.chromium.org/chromium/src/third_party/webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.cc

In golang, we mapped this message to a PacketALFBRemb struct:

In such case where you want to read the bitrate from that structure, you can do:

If instead, you have the bitrate value and want to write the Exp and Mantissa fields into into a PacketALFBRemb struct, you’ll do something like this:

Optimizing bandwidth using RTCP REMB

That’s one of the perks of using an MCU: it can forge a REMB RTCP packet to take control over the browser’s output bitrate:

MCU sending a RTCP REMB to control FOO’s browser bitrate output

Also, the MCU can use the receiver browser’s estimation to change its own encoder parameters to match the maximum estimate bitrate, and optimize the MCU output bandwidth:

MCU modulating its encoder output using BAR’s RTCP REMB stats

Controlling the bitrate

So, how to can you actually test the impact of RTCP REMB packet on FOO’s bitrate? Well, simply enough: simply send REMB packets with alternate bitrates of, let’s say, 64kb & 128kb every 10 seconds, and have a look to chrome://webrtc-internals graphs to see how it behaves.

Implementing this using Go would look like this:

Open chrome://webrtc-internals and you should see something like:

…which will definitely confirm that you’re able to monitor and manipulate your peer’s stream bitrate, real-time. It’s up to you to find out what parameters will best fit your use cases, and help optimize bandwidth and stream quality :-)

Now, you’ll have probably noticed that RTCP REMB is now deprecated. There’s this idea that bandwidth management should be done by the publisher himself (instead of a remote peer) — well, the goal here was to show that it’s certainly still possible to make good use of it, as just demonstrated.

In our case, we found it really useful to gain granular control over both bandwidth consumption and peers stream quality :-)

(With ❤️ from Tim, Sébastien, Marc & Germán @Tribe Video)

--

--

Timothée Le Borgne
Inside Tribe

VP Product @Jellysmack • CPO @RATPGroup • Product Director @Doctolib • Product @Tribe • Founder & CEO @NomadCast & GamaSix. We do magic with code.