[Перевод] RTCP REMB: подкручиваем настройки видеозвонка в браузере

ztxn0lmscpdwc6gc6fgrbibh7re.jpeg


Находчивые ребята из 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) для управления потоком и обмена внеполосными данными.


vchvbf2auf4s0h_fonovykqwr5a.png


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

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


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

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

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

i5xfgnxweik2mwpvfpwikbcrqdq.png


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

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

zwzx6rosmhlb-ifkumgge6uxxu4.png


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

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

sojp2kmzckrewtzhlftvniyou-4.png


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

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

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

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


rzctlmuvruafi28hexwe2fcngts.jpeg


Формат пакета 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 пакет для управления исходящим битрейтом в браузере:

yh7zerhsmztqzhw-vcmj1emrl3a.png


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

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

7jsc7qumnaqqp0dgksmd_e0kgmw.png


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

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


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

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


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

1dywgdot3jctxxi7a5jz4z5d9nc.png


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


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

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

© Habrahabr.ru