Медиа-коммуникация

Медиа-коммуникация #

Что я получаю от медиа-коммуникации WebRTC? #

WebRTC позволяет отправлять и получать неограниченное количество аудио- и видеопотоков. Вы можете добавлять и удалять эти потоки в любой момент во время вызова. Эти потоки могут быть полностью независимыми или объединенными! Вы можете отправлять видеопоток рабочего стола и одновременно включать аудио и видео с веб-камеры.

Протокол WebRTC не зависит от кодека. Базовый транспорт поддерживает все, даже то, что еще не существует! Однако WebRTC-агент, с которым вы общаетесь, может не иметь необходимых инструментов для его принятия.

WebRTC также разработан для работы с динамическими сетевыми условиями. Во время вызова ваша пропускная способность может увеличиваться или уменьшаться. Возможно, вы внезапно испытаете большую потерю пакетов. Протокол разработан для работы со всем этим. WebRTC реагирует на сетевые условия и пытается обеспечить вам наилучший возможный опыт с доступными ресурсами.

Для WebRTC Payload Type является динамическим. VP8 в одном вызове может отличаться от другого. Инициатор вызова определяет сопоставление Payload Types с кодеками в Session Description.

Номер последовательности #

Номер последовательности используется для упорядочивания пакетов в потоке. Каждый раз при отправке пакета Номер последовательности увеличивается на единицу.

RTP разработан для работы в сетях с потерями. Это дает получателю способ обнаруживать потерянные пакеты.

Временная метка #

Момент выборки для этого пакета. Это не глобальные часы, а то, сколько времени прошло в медиапотоке. Несколько RTP-пакетов могут иметь одну и ту же временную метку, например, если они все являются частью одного видеокадра.

Источник синхронизации (SSRC) #

SSRC - это уникальный идентификатор для этого потока. Это позволяет запускать несколько потоков медиа через один RTP-поток.

Источник вклада (CSRC) #

Список, который сообщает, какие SSRC внесли вклад в этот пакет.

Обычно это используется для индикаторов разговора. Допустим, на стороне сервера вы объединили несколько аудиопотоков в один RTP-поток. Затем вы можете использовать это поле, чтобы сказать “Входные потоки A и C говорили в этот момент”.

Полезная нагрузка #

Сами данные полезной нагрузки. Может заканчиваться счетчиком добавленных байтов заполнения, если установлен флаг заполнения.

Расширения #

RTCP #

Формат пакета #

Каждый RTCP-пакет имеет следующую структуру:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|    RC   |       PT      |             length            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                            Payload                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Версия (V) #

Версия всегда равна 2.

Заполнение (P) #

Заполнение - это булево значение, которое контролирует наличие заполнения в полезной нагрузке.

Последний байт полезной нагрузки содержит счетчик добавленных байтов заполнения.

Счетчик отчетов о приеме (RC) #

Количество отчетов в этом пакете. Один RTCP-пакет может содержать несколько событий.

Тип пакета (PT) #

Уникальный идентификатор типа RTCP-пакета. WebRTC-агент не обязан поддерживать все эти типы, и поддержка между агентами может различаться. Однако вот наиболее часто встречающиеся типы:

  • 192 - Запрос полного I-кадра (FIR)
  • 193 - Отрицательные подтверждения (NACK)
  • 200 - Отчет отправителя
  • 201 - Отчет получателя
  • 205 - Общий RTP-отзыв
  • 206 - Отзыв, специфичный для полезной нагрузки

Значимость этих типов пакетов будет описана более подробно ниже.

Запрос полного I-кадра (FIR) и Индикация потери изображения (PLI) #

Сообщения FIR и PLI служат похожей цели. Эти сообщения запрашивают полный ключевой кадр от отправителя. PLI используется, когда частичные кадры были переданы декодеру, но он не смог их декодировать.

Это может произойти из-за большой потери пакетов или, возможно, сбоя декодера.

Согласно RFC 5104, FIR не должен использоваться при потере пакетов или кадров. Это работа PLI. FIR запрашивает ключевой кадр по причинам, отличным от потери пакетов - например, когда новый участник входит в видеоконференцию. Им нужен полный ключевой кадр, чтобы начать декодирование видеопотока, декодер будет отбрасывать кадры до прихода ключевого кадра.

Хорошей идеей является запрос полного ключевого кадра сразу после подключения, это минимизирует задержку между подключением и появлением изображения на экране пользователя.

PLI-пакеты являются частью сообщений с отзывом, специфичным для полезной нагрузки.

На практике программное обеспечение, способное обрабатывать как PLI, так и FIR-пакеты, будет действовать одинаково в обоих случаях. Оно отправит сигнал кодировщику создать новый полный ключевой кадр.

Отрицательное подтверждение #

NACK запрашивает у отправителя повторную передачу одного RTP-пакета. Обычно это вызвано потерей RTP-пакета, но может произойти и из-за его опоздания.

NACK гораздо эффективнее с точки зрения пропускной способности, чем запрос повторной отправки всего кадра. Поскольку RTP разбивает пакеты на очень маленькие куски, вы фактически запрашиваете только один небольшой отсутствующий фрагмент. Получатель создает RTCP-сообщение с SSRC и номером последовательности. Если отправитель не имеет этого RTP-пакета для повторной отправки, он просто игнорирует сообщение.

Отчеты получателя / Отчеты отправителя #

Первая реализация - это пара Отчетов получателя и его дополнение, Отчеты отправителя. Эти RTCP-сообщения определены в RFC 3550 и отвечают за обмен информацией о сетевом статусе между конечными точками. Отчеты получателя фокусируются на сообщении качеств сети (включая потерю пакетов, время кругового обхода и джиттер), и они сочетаются с другими алгоритмами, которые затем отвечают за оценку доступной пропускной способности на основе этих отчетов.

Отчеты отправителя и получателя (SR и RR) вместе рисуют картину качества сети. Они отправляются по расписанию для каждого SSRC и являются входными данными, используемыми при оценке доступной пропускной способности. Эти оценки делаются отправителем после получения данных RR, содержащих следующие поля:

  • Доля потерь - Какой процент пакетов был потерян с момента последнего Отчета получателя.
  • Совокупное количество потерянных пакетов - Сколько пакетов было потеряно за весь звонок.
  • Расширенный наивысший номер последовательности, полученный - Какой был последний полученный номер последовательности и сколько раз он переполнялся.
  • Межприбытийный джиттер - Текущий джиттер за весь звонок.
  • Временная метка последнего отчета отправителя - Последнее известное время на отправителе, используется для расчета времени кругового обхода.

SR и RR работают вместе для вычисления времени кругового обхода.

Отправитель включает свое локальное время, sendertime1 в SR. Когда получатель получает пакет SR, он отправляет обратно RR. В числе прочего, RR включает sendertime1, только что полученный от отправителя. Между получением SR и отправкой RR будет задержка. Из-за этого RR также включает время “задержки с момента последнего отчета отправителя” - DLSR. DLSR используется для корректировки оценки времени кругового обхода позже в процессе. Как только отправитель получает RR, он вычитает sendertime1 и DLSR из текущего времени sendertime2. Эта разница времени называется задержкой распространения кругового обхода или временем кругового обхода.

rtt = sendertime2 - sendertime1 - DLSR

Время кругового обхода простым языком:

  • Я отправляю вам сообщение с текущим показанием моих часов, скажем, 4:20 вечера, 42 секунды и 420 миллисекунд.
  • Вы отправляете мне обратно эту же временную метку.
  • Вы также включаете время, прошедшее с момента чтения моего сообщения до отправки ответа, скажем, 5 миллисекунд.
  • Когда я получаю время обратно, я смотрю на часы снова.
  • Теперь мои часы показывают 4:20 вечера, 42 секунды 690 миллисекунд.
  • Это означает, что на то, чтобы дойти до вас и вернуться обратно ко мне, ушло 265 миллисекунд (690 - 420 - 5).
  • Следовательно, время кругового обхода составляет 265 миллисекунд.

Время кругового обхода

TMMBR, TMMBN, REMB и TWCC, сопряженные с GCC #

Google Congestion Control (GCC) #

Алгоритм Google Congestion Control (GCC) (описанный в draft-ietf-rmcat-gcc-02) решает задачу оценки пропускной способности. Он сочетается с различными другими протоколами для облегчения связанных коммуникационных требований. Следовательно, он хорошо подходит для работы как на стороне получателя (при работе с TMMBR/TMMBN или REMB), так и на стороне отправителя (при работе с TWCC).

Чтобы прийти к оценкам доступной пропускной способности, GCC фокусируется на потере пакетов и флуктуациях времени прибытия кадров как на двух основных метриках. Он пропускает эти метрики через два связанных контроллера: контроллер, основанный на потерях, и контроллер, основанный на задержках.

Первый компонент GCC, контроллер, основанный на потерях, прост:

  • Если потеря пакетов выше 10%, оценка пропускной способности уменьшается.
  • Если потеря пакетов между 2-10%, оценка пропускной способности остается той же.
  • Если потеря пакетов ниже 2%, оценка пропускной способности увеличивается.

Измерения потери пакетов производятся часто. В зависимости от сопряженного коммуникационного протокола, потеря пакетов может быть либо явно сообщена (как с TWCC), либо выведена (как с TMMBR/TMMBN и REMB). Эти проценты оцениваются в окнах времени около одной секунды.

Контроллер, основанный на задержках, сотрудничает с контроллером, основанным на потерях, и смотрит на вариации времени прибытия пакетов. Этот контроллер, основанный на задержках, стремится определить, когда сетевые каналы становятся все более перегруженными, и может уменьшать оценки пропускной способности даже до возникновения потери пакетов. Теория состоит в том, что самый загруженный сетевой интерфейс вдоль пути будет продолжать накапливать пакеты, пока интерфейс не исчерпает емкость своих буферов. Если этот интерфейс продолжает получать больше трафика, чем он способен отправить, он будет вынужден отбрасывать все пакеты, которые не могут поместиться в его буферное пространство. Этот тип потери пакетов особенно разрушителен для коммуникации с низкой задержкой/в реальном времени, но он также может снизить пропускную способность для всей коммуникации через этот канал и должен, по возможности, избегаться. Таким образом, GCC пытается определить, растут ли сетевые каналы по глубине очередей перед фактической потерей пакетов. Он уменьшит использование пропускной способности, если наблюдает увеличение задержек очередей с течением времени.

Чтобы достичь этого, GCC пытается вывести увеличение глубины очереди, измеряя тонкие увеличения времени кругового обхода. Он записывает “межприбытийное время” кадров, t(i) - t(i-1): разницу во времени прибытия двух групп пакетов (обычно последовательных видеокадров). Эти группы пакетов часто отправляются с регулярными интервалами времени (например, каждые 1/24 секунды для видео с 24 кадрами в секунду). В результате измерение межприбытийного времени сводится к простой записи разницы времени между началом первой группы пакетов (т.е. кадра) и первым кадром следующей.

На диаграмме ниже медианное увеличение задержки между пакетами составляет +20 мс, что является четким индикатором сетевой перегрузки.

TWCC с задержкой

Если межприбытийное время увеличивается со временем, это считается предполагаемым доказательством увеличения глубины очереди на соединительных сетевых интерфейсах и рассматривается как сетевая перегрузка. (Примечание: GCC достаточно умен, чтобы контролировать эти измерения с учетом флуктуаций размеров кадров.) GCC уточняет свои измерения задержки, используя фильтр Калмана, и делает много измерений времени кругового обхода сети (и его вариаций) перед обозначением перегрузки. Можно рассматривать фильтр Калмана GCC как замену линейной регрессии: помогающую делать точные прогнозы даже когда джиттер добавляет шум в измерения времени. При обнаружении перегрузки GCC уменьшит доступный битрейт. В качестве альтернативы, при стабильных сетевых условиях, он может медленно увеличивать оценки пропускной способности, чтобы проверить более высокие значения нагрузки.

TMMBR, TMMBN и REMB #

Для TMMBR/TMMBN и REMB сторона получателя сначала оценивает доступную входящую пропускную способность (используя протокол, такой как GCC), а затем сообщает эти оценки пропускной способности удаленным отправителям. Им не нужно обмениваться подробностями о потере пакетов или других качествах сетевой перегрузки, потому что работа на стороне получателя позволяет им напрямую измерять межприбытийное время и потерю пакетов. Вместо этого TMMBR, TMMBN и REMB обмениваются только самими оценками пропускной способности:

  • Временный максимальный запрос скорости потока медиа - Мантисса/экспонента запрошенной скорости передачи для одного SSRC.
  • Временное максимальное уведомление о скорости потока медиа - Сообщение для уведомления о получении TMMBR.
  • Максимальная скорость, оцененная получателем - Мантисса/экспонента запрошенной скорости передачи для всей сессии.

TMMBR и TMMBN появились первыми и определены в RFC 5104. REMB появился позже, был представлен черновик в draft-alvestrand-rmcat-remb, но он никогда не был стандартизирован.

Пример сеанса, использующего REMB, может выглядеть следующим образом:

REMB

Этот метод отлично работает на бумаге. Отправитель получает оценку от получателя, устанавливает битрейт кодировщика на полученное значение. Вуаля! Мы адаптировались к сетевым условиям.

Однако на практике подход REMB имеет несколько недостатков.

Первый - неэффективность кодировщика. Когда вы устанавливаете битрейт для кодировщика, он не обязательно выведет точно запрошенный битрейт. Кодирование может выводить больше или меньше битов в зависимости от настроек кодировщика и кодируемого кадра.

Например, использование кодировщика x264 с tune=zerolatency может значительно отклоняться от указанного целевого битрейта. Вот возможный сценарий:

  • Допустим, мы начинаем с установки битрейта на 1000 кбит/с.
  • Кодировщик выводит только 700 кбит/с, потому что недостаточно высокочастотных признаков для кодирования. (Или - “смотрит на стену”.)
  • Допустим также, что получатель получает видео 700 кбит/с с нулевой потерей пакетов. Затем он применяет правило REMB 1 для увеличения входящего битрейта на 8%.
  • Получатель отправляет REMB-пакет с предложением 756 кбит/с (700 кбит/с * 1,08) отправителю.
  • Отправитель устанавливает битрейт кодировщика на 756 кбит/с.
  • Кодировщик выводит еще меньший битрейт.
  • Этот процесс продолжает повторяться, снижая битрейт до абсолютного минимума.

Вы можете видеть, как это вызовет тяжелую настройку параметров кодировщика и удивит пользователей неприемлемым видео даже при отличном подключении.

Контроль перегрузки по всей транспортной сети #

Контроль перегрузки по всей транспортной сети (Transport Wide Congestion Control) является последним достижением в коммуникации сетевого статуса RTCP. Он определен в draft-holmer-rmcat-transport-wide-cc-extensions-01, но также никогда не был стандартизирован.

TWCC использует довольно простой принцип:

TWCC

С REMB получатель инструктирует сторону отправки о доступной скорости загрузки. Он использует точные измерения о выведенной потере пакетов и данные, которые есть только у него, о межпакетном времени прибытия.

TWCC - это почти гибридный подход между поколениями протоколов SR/RR и REMB. Он возвращает оценки пропускной способности на сторону отправки (похоже на SR/RR), но техника оценки пропускной способности более близка к поколению REMB.

С TWCC получатель сообщает отправителю время прибытия каждого пакета. Этой информации достаточно для того, чтобы отправитель измерил вариацию задержки межпакетного прибытия, а также определил, какие пакеты были потеряны или пришли слишком поздно, чтобы внести вклад в аудио- или видеопоток. При частом обмене этими данными отправитель может быстро адаптироваться к изменяющимся сетевым условиям и варьировать свою выходную пропускную способность, используя такой алгоритм, как GCC.

Отправитель отслеживает отправленные пакеты, их последовательные номера, размеры и временные метки. Когда отправитель получает RTCP-сообщения от получателя, он сравнивает межпакетные задержки отправки с задержками получения. Если задержки получения увеличиваются, это сигнализирует о сетевой перегрузке, и отправитель должен принять корректирующие меры.

Предоставляя отправителю необработанные данные, TWCC обеспечивает превосходный обзор сетевых условий в реальном времени:

  • Почти мгновенное поведение потери пакетов вплоть до отдельных потерянных пакетов
  • Точная скорость отправки
  • Точная скорость получения
  • Измерение джиттера
  • Различия между задержками отправки и получения пакетов
  • Описание того, как сеть справлялась с импульсной или стабильной доставкой пропускной способности

Одним из самых значительных вкладов TWCC является гибкость, которую он предоставляет разработчикам WebRTC. Консолидируя алгоритм контроля перегрузки на стороне отправки, он позволяет использовать простой клиентский код, который может быть широко использован и требует минимальных улучшений со временем. Сложные алгоритмы контроля перегрузки затем могут быстрее итерироваться на оборудовании, которое они напрямую контролируют (например, на Selective Forwarding Unit, обсуждаемом в разделе 8). В случае браузеров и мобильных устройств это означает, что эти клиенты могут извлечь выгоду из улучшений алгоритма без необходимости ожидания стандартизации или обновлений браузера (которые могут занять очень много времени, чтобы стать широко доступными).

Альтернативы оценки пропускной способности #

Наиболее распространенной реализацией является “Алгоритм Google Congestion Control для коммуникации в реальном времени”, определенный в draft-alvestrand-rmcat-congestion.

Существует несколько альтернатив GCC, например, NADA: Унифицированная схема контроля перегрузки для медиа в реальном времени и SCReAM - Самосинхронизирующаяся адаптация скорости для мультимедиа.

Задержка против Качества #

Медиа в реальном времени - это компромисс между задержкой и качеством. Чем больше задержки вы готовы терпеть, тем более высокого качества видео вы можете ожидать.

Реальные ограничения #

Все эти ограничения вызваны ограничениями реального мира. Это все характеристики вашей сети, которые вам нужно преодолеть.

Видео сложно #

Транспортировка видео - это не просто. Чтобы сохранить 30 минут несжатого 720p 8-битного видео, вам нужно около 110 ГБ. С такими цифрами видеоконференция из 4 человек не состоится. Нам нужен способ сделать это меньше, и ответ - сжатие видео. Но это не обходится без недостатков.

Видео 101 #

Мы не будем подробно рассматривать сжатие видео, а только настолько, чтобы понять, почему RTP устроен именно так. Сжатие видео кодирует видео в новый формат, который требует меньше битов для представления того же видео.

Сжатие с потерями и без потерь #

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

Внутрикадровое и межкадровое сжатие #

Сжатие видео бывает двух типов. Первый - внутрикадровое. Внутрикадровое сжатие уменьшает количество битов, используемых для описания одного видеокадра. Те же методы используются для сжатия неподвижных изображений, например, метод сжатия JPEG.

Второй тип - межкадровое сжатие. Поскольку видео состоит из множества картинок, мы ищем способы не отправлять одну и ту же информацию дважды.

Типы межкадрового сжатия #

Затем у вас есть три типа кадров:

  • I-кадр - Полная картинка, может быть декодирована без чего-либо еще.
  • P-кадр - Частичная картинка, содержащая только изменения от предыдущей картинки.
  • B-кадр - Частичная картинка, является модификацией предыдущих и будущих картинок.

Ниже представлена визуализация трех типов кадров.

Типы кадров

Видео хрупко #

Сжатие видео крайне зависимо от состояния, что делает его сложным для передачи через интернет. Что произойдет, если вы потеряете часть I-кадра? Как P-кадр узнает, что модифицировать? По мере усложнения видеосжатия эта проблема становится еще более актуальной. К счастью, RTP и RTCP имеют решение.