Омӯзиши муҳаррики Mediastreamer2 VoIP. Қисми 6

Материали макола аз ман гирифта шудааст канали zen.

Интиқоли сигнали аудио тавассути ҷараёни RTP

Омӯзиши муҳаррики Mediastreamer2 VoIP. Қисми 6

Дар охир мақола Мо як схемаи идоракунии дурдастро аз генератори оҳанг ва детектори оҳанг, ки дар доираи як барнома кор мекунанд, ҷамъ кардем. Дар ин мақола мо мефаҳмем, ки чӣ тавр истифода бурдани протоколи RTP (RFC 3550 - RTP: Протоколи интиқол барои замимаҳои вақти воқеӣ) барои қабул/интиқоли сигнали аудиоӣ тавассути шабакаи Ethernet.

протоколи RTP (Протоколи вақти воқеӣ) тарҷумашуда маънои протоколи воқеиро дорад, ки он барои интиқоли аудио, видео, маълумот, ҳама чизест, ки интиқолро дар вақти воқеӣ талаб мекунад. Биёед як сигнали аудиоиро ҳамчун мисол гирем. Табиати протокол аз он иборат аст, ки он ба шумо имкон медиҳад, ки сигнали аудиоиро бо сифати пешакӣ муайяншуда интиқол диҳед.

Интиқол бо истифода аз бастаҳои UDP анҷом дода мешавад, ки маънои онро дорад, ки талафоти бастаҳо ҳангоми интиқол қобили қабул аст. Ҳар як баста дорои сарлавҳаи махсуси RTP ва блоки додаҳои сигнали интиқолшаванда мебошад. Сарлавҳа дорои идентификатори ба таври тасодуфӣ интихобшудаи манбаи сигнал, маълумот дар бораи навъи сигнали интиқолшаванда ва рақами пайдарпайии ягонаи бастаҳо мебошад, то ин ки бастаҳо ҳангоми рамзкушоӣ, новобаста аз тартиби интиқоли онҳо, бо тартиби дуруст ҷойгир карда шаванд. шабака. Сарлавҳа инчунин метавонад маълумоти иловагӣ дошта бошад, ба истилоҳ васеъшавӣ, ки имкон медиҳад сарлавҳа барои истифода дар вазифаи мушаххаси барнома мутобиқ карда шавад.

Блоки маълумот бори пурборкунандаи бастаро дар бар мегирад. Ташкили дохилии мундариҷа аз намуди сарборӣ вобаста аст, он метавонад намунаҳои моносигнал, сигнали стерео, хати тасвири видео ва ғайра бошад.

Навъи сарборӣ бо рақами ҳафт-бит нишон дода мешавад. Тавсия RFC3551 (Профили RTP барои конфронсҳои аудио ва видео бо назорати ҳадди ақал) якчанд намуди сарборро мукаррар мекунад, чадвали дахлдор тавсифи навъхои бор ва маънои рамзхоеро, ки аз руи онхо онхо таъин шудаанд, медихад. Баъзе рамзҳо ба ягон намуди сарборӣ сахт алоқаманд нестанд; онҳо метавонанд барои таъин кардани сарбории худсарона истифода шаванд.

Андозаи блоки додаҳо дар боло бо андозаи максималии бастаҳо маҳдуд аст, ки метавонад дар шабакаи додашуда бидуни сегментатсия интиқол дода шавад (параметри 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, шумо бояд филтри рамзгузорро истифода баред, ки намунаҳои сигнали аудиоии 16-битро ба ҳашт-бити мувофиқи у-қонун (му-қонун). Дар тарафи қабулкунанда филтри декодер вазифаи муқобилро иҷро мекунад.

Дар зер матни барномае оварда шудааст, ки схемаи дар расм нишон додашударо амалӣ мекунад (# аломатҳои пеш аз директиваҳои дохилкунӣ хориҷ карда шудаанд, дохил кардани онҳоро фаромӯш накунед):

/* Файл mstest6.c Имитатор пульта управления и приемника. */
#include <mediastreamer2/msfilter.h>
#include <mediastreamer2/msticker.h>
#include <mediastreamer2/dtmfgen.h>
#include <mediastreamer2/mssndcard.h>
#include <mediastreamer2/msvolume.h>
#include <mediastreamer2/mstonedetector.h>
#include <mediastreamer2/msrtp.h>
#include <ortp/rtpsession.h>
#include <ortp/payloadtype.h>
/* Подключаем заголовочный файл с функциями управления событиями
* медиастримера.*/
include <mediastreamer2/mseventqueue.h>
#define PCMU 0
/* Функция обратного вызова, она будет вызвана фильтром, как только он
обнаружит совпадение характеристик входного сигнала с заданными. */
static void tone_detected_cb(void *data, MSFilter *f, unsigned int event_id,
MSToneDetectorEvent *ev)
{
printf("Принята команда: %sn", ev->tone_name);
}
/*----------------------------------------------------------------------------*/
/* Функция регистрации типов полезных нагрузок. */
void register_payloads(void)
{
/*Регистрируем типы нагрузок в таблице профилей. Позднее, по индексу
взятому из заголовка RTP-пакета из этой таблицы будут извлекаться
параметры нагрузки, необходимые для декодирования данных пакета. */
rtp_profile_set_payload (&av_profile, PCMU, &payload_type_pcm8000);
}
/*----------------------------------------------------------------------------*/
/* Эта функция создана из функции create_duplex_rtpsession() в audiostream.c
медиастримера2. */
static RtpSession *
create_rtpsession (int loc_rtp_port, int loc_rtcp_port,
bool_t ipv6, RtpSessionMode mode)
{
RtpSession *rtpr;
rtpr = rtp_session_new ((int) mode);
rtp_session_set_scheduling_mode (rtpr, 0);
rtp_session_set_blocking_mode (rtpr, 0);
rtp_session_enable_adaptive_jitter_compensation (rtpr, TRUE);
rtp_session_set_symmetric_rtp (rtpr, TRUE);
rtp_session_set_local_addr (rtpr, ipv6 ? "::" : "0.0.0.0", loc_rtp_port,
loc_rtcp_port);
rtp_session_signal_connect (rtpr, "timestamp_jump",
(RtpCallback) rtp_session_resync, 0);
rtp_session_signal_connect (rtpr, "ssrc_changed",
(RtpCallback) rtp_session_resync, 0);
rtp_session_set_ssrc_changed_threshold (rtpr, 0);
rtp_session_set_send_payload_type(rtpr, PCMU);
/* По умолчанию выключаем RTCP-сессию, так как наш пульт не будет использовать её. */
rtp_session_enable_rtcp (rtpr, FALSE);
return rtpr;
}
/*----------------------------------------------------------------------------*/
int main()
{
ms_init();
/* Создаем экземпляры фильтров. */
MSFilter *voidsource = ms_filter_new(MS_VOID_SOURCE_ID);
MSFilter *dtmfgen = ms_filter_new(MS_DTMF_GEN_ID);
MSFilter *volume = ms_filter_new(MS_VOLUME_ID);
MSSndCard *card_playback =
ms_snd_card_manager_get_default_card(ms_snd_card_manager_get());
MSFilter *snd_card_write = ms_snd_card_create_writer(card_playback);
MSFilter *detector = ms_filter_new(MS_TONE_DETECTOR_ID);
/* Очищаем массив находящийся внутри детектора тонов, он описывает
* особые приметы разыскиваемых сигналов.*/
ms_filter_call_method(detector, MS_TONE_DETECTOR_CLEAR_SCANS, 0);
/* Подключаем к фильтру функцию обратного вызова. */
ms_filter_set_notify_callback(detector,
(MSFilterNotifyFunc)tone_detected_cb, NULL);
/* Создаем массив, каждый элемент которого описывает характеристику
* одного из тонов, который требуется обнаруживать: Текстовое имя
* данного элемента, частота в герцах, длительность в миллисекундах,
* минимальный уровень относительно 0,775В. */
MSToneDetectorDef scan[6]=
{
{"V+",440, 100, 0.1}, /* Команда "Увеличить громкость". */
{"V-",540, 100, 0.1}, /* Команда "Уменьшить громкость". */
{"C+",640, 100, 0.1}, /* Команда "Увеличить номер канала". */
{"C-",740, 100, 0.1}, /* Команда "Уменьшить номер канала". */
{"ON",840, 100, 0.1}, /* Команда "Включить телевизор". */
{"OFF", 940, 100, 0.1}/* Команда "Выключить телевизор". */
};
/* Передаем "приметы" сигналов детектор тонов. */
int i;
for (i = 0; i < 6; i++)
{
ms_filter_call_method(detector, MS_TONE_DETECTOR_ADD_SCAN,
&scan[i]);
}
/* Создаем фильтры кодера и декодера */
MSFilter *encoder = ms_filter_create_encoder("PCMU");
MSFilter *decoder=ms_filter_create_decoder("PCMU");
/* Регистрируем типы нагрузки. */
register_payloads();
/* Создаем RTP-сессию передатчика. */
RtpSession *tx_rtp_session = create_rtpsession (8010, 8011, FALSE, RTP_SESSION_SENDONLY);
rtp_session_set_remote_addr_and_port(tx_rtp_session,"127.0.0.1", 7010, 7011);
rtp_session_set_send_payload_type(tx_rtp_session, PCMU);
MSFilter *rtpsend = ms_filter_new(MS_RTP_SEND_ID);
ms_filter_call_method(rtpsend, MS_RTP_SEND_SET_SESSION, tx_rtp_session);
/* Создаем RTP-сессию приемника. */
MSFilter *rtprecv = ms_filter_new(MS_RTP_RECV_ID);
RtpSession *rx_rtp_session = create_rtpsession (7010, 7011, FALSE, RTP_SESSION_RECVONLY);
ms_filter_call_method(rtprecv, MS_RTP_RECV_SET_SESSION, rx_rtp_session);
/* Создаем источники тактов - тикеры. */
MSTicker *ticker_tx = ms_ticker_new();
MSTicker *ticker_rx = ms_ticker_new();
/* Соединяем фильтры передатчика. */
ms_filter_link(voidsource, 0, dtmfgen, 0);
ms_filter_link(dtmfgen, 0, volume, 0);
ms_filter_link(volume, 0, encoder, 0);
ms_filter_link(encoder, 0, rtpsend, 0);
/* Соединяем фильтры приёмника. */
ms_filter_link(rtprecv, 0, decoder, 0);
ms_filter_link(decoder, 0, detector, 0);
ms_filter_link(detector, 0, snd_card_write, 0);
/* Подключаем источник тактов. */
ms_ticker_attach(ticker_tx, voidsource);
ms_ticker_attach(ticker_rx, rtprecv);
/* Настраиваем структуру, управляющую выходным сигналом генератора. */
MSDtmfGenCustomTone dtmf_cfg;
dtmf_cfg.tone_name[0] = 0;
dtmf_cfg.duration = 1000;
dtmf_cfg.frequencies[0] = 440;
/* Будем генерировать один тон, частоту второго тона установим в 0. */
dtmf_cfg.frequencies[1] = 0;
dtmf_cfg.amplitude = 1.0;
dtmf_cfg.interval = 0.;
dtmf_cfg.repeat_count = 0.;
/* Организуем цикл сканирования нажатых клавиш. Ввод нуля завершает
* цикл и работу программы. */
char key='9';
printf("Нажмите клавишу команды, затем ввод.n"
"Для завершения программы введите 0.n");
while(key != '0')
{
key = getchar();
if ((key >= 49) && (key <= 54))
{
printf("Отправлена команда: %cn", key);
/* Устанавливаем частоту генератора в соответствии с
* кодом нажатой клавиши. */
dtmf_cfg.frequencies[0] = 440 + 100*(key-49);
/* Включаем звуковой генератор c обновленной частотой. */
ms_filter_call_method(dtmfgen, MS_DTMF_GEN_PLAY_CUSTOM,
(void*)&dtmf_cfg);
}
/* Укладываем тред в спячку на 20мс, чтобы другие треды
* приложения получили время на работу. */
ms_usleep(20000);
}
}

Мо тартиб медиҳем ва иҷро мекунем. Барнома мисли мисоли қаблӣ кор хоҳад кард, аммо маълумот тавассути ҷараёни RTP интиқол дода мешавад.

Дар мақолаи навбатӣ мо ин барномаро ба ду замимаи мустақил - қабулкунанда ва интиқолдиҳанда тақсим мекунем ва онҳоро дар терминалҳои гуногун оғоз мекунем. Ҳамзамон, мо бо истифода аз барномаи TShark чӣ гуна таҳлили пакетҳои RTP-ро меомӯзем.

Манбаъ: will.com

Илова Эзоҳ