Находчивые ребята из Tribe не только нашли свою нишу на стыке конференсинга и gamedev’а (что само по себе уже интересно), но и хорошо знают, что творится под капотом у WebRTC. Менеджер по продукту Тимотэ Ле Борнье периодически описывает техническую сторону своего детища; мы решили перевести его статью про нестандартную, но очень любопытную функциональность WebRTC. Уверены, вам будет интересно. Ну а пока вы читаете, мы продолжим готовить инсайд про наши обновленные видеоконференции… Но это уже другая история.



Тонкая настройка и управление качеством потока с использованием REMB


Итак, сейчас вы скорее всего знаете, что мы работали над созданием кастомного MCU для Tribe – если вдруг не знаете, то вот почему мы решили это сделать и как это у нас получается.

Но ближе к делу: давайте посмотрим, что же происходит под капотом.

  1. WebRTC-соединение начинается с механизма обмена под названием ”SDP offer/answer” – обмен информацией о поддерживаемых кодеках и соответствующих параметрах между участниками.
  2. После этого участники пытаются связаться друг с другом напрямую: начинают слушать UDP-порты и используют ICE, STUN и (в дальнейшем) TURN, чтобы установить UDP-соединение.
  3. Когда UDP-соединение установлено, участники используют его, чтобы обменяться параметрами шифрования по протоколу DTLS-SRTP. После этого участники используют:
    • Протокол SRTP (Secure RTP поверх UDP) чтобы отправлять и получать медиа
    • Протокол SRTCP (Secure RTCP поверх UDP) для управления потоком и обмена внеполосными данными.



Стек WebRTC-протоколов (измененная схема, оригинал тут: webrtc-security.github.io)

Разбираемся с RTCP


Выше упомянуто, что пакеты RTP и RTCP безопасно хранятся в SRTP и SRTCP. Для чего они используются?

RTP обеспечивает сквозной транспорт для данных в реальном времени: аудио и видео. В некотором роде, RTCP это “брат RTP”: он используется вместе с RTP и улучшает протокол передачи данных за счет мониторинга доставки, а также управления и идентификации.

В сессии WebRTC MCU выступает как посредник между участниками: они соединены с MCU, но не напрямую друг с другом.


WebRTC – базовая топология MCU

Например, возьмем сессию с двумя участниками. MCU получает медиапоток от участника FOO, декодирует-кодирует его и отправляет участнику BAR. Одновременно то же самое происходит и с потоком от BAR к FOO.


Протоколы MTP и RTCP

Симметрия очевидна, поэтому сосредоточимся на одном направлении и посмотрим, что там творится:


Фокус на одной из сторон

Когда браузер BAR получает медиапоток от MCU, он также получает статистику от RTCP Sender Reports (SR). Браузер BAR будет использовать RTP’шные последовательные номера пакетов, RTP-таймштампы, собственное время и Sender Reports, чтобы подсчитать то, что мы называем RTCP Receiver Reports (RR).

Браузер со стороны BAR использует все эти данные для расчета максимального ожидаемого битрейта, а затем отправит это значение в MCU, используя RTCP REMB (Remote Estimate Maximum Bitrate).

Используем REMB (эффективно)



Формат пакета RTCP REMB tools.ietf.org/html/draft-alvestrand-rmcat-remb-00#section-2.2

Значение расчетного максимального битрейта кодируется в полях BR Exp и BR Mantissa.

Пример реализации можно посмотреть в коде Хромиум: cs.chromium.org/chromium/src/third_party/webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.cc
В языке Go мы преобразовали это сообщение в структуру PacketALFBRemb:


Когда вам нужно узнать битрейт из такой структуры, можно сделать так:


Если же наоборот, у вас есть битрейт и вы хотите заполнить поля Exp и Mantissa в структуре PacketALFBRemb, то вы сделаете что-то вроде этого:


Пропускная способность и RTCP REMB


Это одно из преимуществ MCU – возможность сделать REMB RTCP пакет для управления исходящим битрейтом в браузере:


MCU отправляет RTCP REMB, чтобы управлять исходящим битрейтом браузера FOO

Также MCU может взять оценку битрейта от получателя и в соответствии с ней поменять свои настройки кодирования, чтобы они совпали с расчетным максимальным битрейтом; также это оптимизирует исходящую пропускную способность MCU:


MCU меняет настройки кодирования, используя значения RTCP REMB от участника BAR

Управляем битрейтом


Как можно протестировать влияние RTCP REMB на битрейт браузера FOO? Довольно легко: просто отправить пакеты REMB с переменным битрейтом, (например, 64Кб и 128Кб каждые 10 секунд), а затем посмотреть на графики chrome://webrtc-internals.

На языке Go это будет так:


Открыв chrome://webrtc-internals, вы увидите что-то вроде этого:


Это явное подтверждение, что вы способны изменять и отслеживать битрейт с вашей стороны в реальном времени. Какие параметры лучше подходят для ваших нужд и надо ли оптимизировать полосу пропускания и качество потока – решать вам :)



Вероятно, вы заметили, что RTCP REMB сейчас в статусе deprecated. Идея была в том, что полосу пропускания должен контролировать источник данных (а не удаленный приемник/участник) – что ж, в статье мы показали, что это все еще возможно и как это делать.

В нашем случае это было полезно – получить точечный контроль над полосой и качеством :)

Комментарии (1)


  1. aylarov
    13.04.2018 16:09

    Да, REMB более не модно (хотя Firefox по-другому и не умеет), теперь модно send side congestion controller (в SDP гордо зовется transport-cc)