Материал статьи взят с моего дзен-канала.   В прошлой статье мы собрали схему дистанционного управления из генератора и детектора тональных сигналов, которые работают внутри одной программы. В этой статье мы научимся использовать протокол RTP (RFC 3550 — RTP: A Transport Protocol for Real-Time Applications) для приема/передачи звукового сигнала по Ethernet-сети.  Протокол RTP (Real Time Protocol) в переводе означает протокол реального времени, он используется для передачи звука, видео, данных, всего того, что требует передачи в режиме реального времени. В качестве примера возьмем звуковой сигнал. Гибкость протокола такова, что позволяет передавать звуковой сигнал с наперед заданным качеством. Передача выполняется с помощью UDP-пакетов, что означает что при передаче вполне допускается потеря пакетов. В каждый пакет вкладывается специальный RTP-заголовок и блок данных передаваемого сигнала. В заголовке содержится случайно выбираемый идентификатор источника сигнала, информация о типе передаваемого сигнала, уникальный порядковый номер пакета, для того чтобы пакеты при декодировании могли быть выстроены в правильном порядке, независимо от того в каком порядке их доставила сеть. Заголовок также может содержать дополнительную информацию, так называемое расширение, которое позволяет адаптировать заголовок к применению в конкретной прикладной задаче. Блок данных содержит полезную нагрузку пакета. Внутренняя организация содержимого зависит от типа нагрузки, это могут быть отсчеты монофонического сигнала, стереосигнал, строка видео изображения и т.д. Тип нагрузки обозначается семибитным числом. Рекомендация RFC3551 (RTP Profile for Audio and Video Conferenceswith Minimal Control) устанавливает несколько типов нагрузки в соответствующей таблице приведены описание типов нагрузки и значение кодов которыми они обозначаются. Часть кодов не имеют жёсткой привязки к какому-либо типу нагрузки-они могут использоваться для обозначения произвольной нагрузки. Размер блока данных ограничен сверху максимальным размером пакета, который может быть передан в данной сети без сегментирования (параметр MTU). В общем случае это не более 1500 байт. Таким образом, чтобы увеличить количество передаваемых в секунду данных можно до определенного момента увеличивать размер пакета, а затем уже потребуется увеличивать частоту отправки пакетов. В медиастримера это настраиваемый параметр. По умолчанию он равен 50 Гц, т.е. 50 пакетов в секунду. Последовательность передаваемых RTP-пакетов будем называть RTP-потоком. Чтобы начать передачу данных между источником и приемником, достаточно, чтобы передатчик знал IP-адрес приёмника и номер порта, который тот использует для приема. Т.е. без всяких предварительный процедур источник начинает передавать данные, а приёмник в свою очередь готов немедленно их принять и обработать. По стандарту, номер порта используемый для передачи или приема RTP-потока должен быть четным. В ситуациях, когда нельзя наперед знать адрес приёмника, используются сервера, на которых приемники оставляют свой адрес, а передатчик может его запросить, сославшись на некое уникальное имя приемника. В случаях, когда качество канала связи или возможности приёмника неизвестны организуется канал обратной связи, по которому приёмник может информировать передатчик о своих возможностях, количество пакетов, которых он не досчитался и т.д. В таком канале используется RTCP-протокол. Формат пакетов передаваемых в этом канале определяется в RFC 3605. По этому каналу передаётся сравнительно немного данных 200..300 байт в секунду, поэтому в целом, его наличие необременительно. Номер порта, на который отправляются RTCP-пакеты должен быть нечетным и на единицу больше номера порта, с которого приходит RTP-поток. В нашем примере мы не будем использовать этот канал, так как возможности приёмника и канала заведомо превышают наши, пока скромные, потребности. В нашей программе схема передачи данных, в отличие от схемы предыдущего примера, будет разделена на две части: на передающий тракт и приемный тракт. Для каждой части мы сделаем свой источник тактов, как показано на заглавной картинке. Односторонняя связь между ними будет осуществляться с помощью RTP-протокола. В данном примере нам не потребуется внешняя сеть, так как и передатчик и приёмник будут располагаться на одном компьютере — пакеты будут ходить у него внутри. Для установления RTP-потока в медиастримере используются два фильтра: MS_RTP_SEND и MS_RTP_RECV. Первый выполняет передачу второй прием RTP-потока. Чтобы эти фильтры начали работать, им нужно передать указатель на объект RTP-сессии, которая может выполнять как преобразование потока блоков данных в поток RTP-пакетов так и выполнять обратное действие. Поскольку внутренний формат данных медиастримера не совпадает с форматом данных RTP-пакета, то перед передачей данных в MS_RTP_SEND нужно использовать фильтр конвертера (encoder), который преобразует 16-битные отсчеты звукового сигнала в восьмибитные, кодированные по u-закону (мю-закону). На приемной стороне обратную функцию выполняет фильтр decoder. Ниже приведен текст программы, реализующей схему показанную на рисунке (символы # перед директивами include убран, не забудьте их поставить): Компилируем, запускаем. Программа будет работать как в прошлом примере, но при этом данные будут передаваться через RTP-поток. В следующей статье мы разделим эту программу на два независимых приложения — приемник и передатчик и запустим их в разных терминалах. Параллельно научимся анализировать RTP-пакеты с помощью программы TShark. Разработчик ПО для радиосвязи