Nesploraw il-magna VoIP Mediastreamer2. Parti 6

Il-materjal tal-artiklu huwa meħud minn tiegħi kanal zen.

It-trażmissjoni ta' sinjal awdjo permezz ta' fluss RTP

Nesploraw il-magna VoIP Mediastreamer2. Parti 6

Fl-aħħar artikolu Immuntajna ċirkwit ta 'kontroll mill-bogħod minn ġeneratur tat-ton u detector tat-ton li joperaw fi ħdan l-istess programm. F'dan l-artikolu se nitgħallmu kif nużaw il-protokoll RTP (RFC 3550 - RTP: Protokoll tat-Trasport għal Applikazzjonijiet f'Ħin Reali) għar-riċeviment/trażmissjoni ta' sinjal awdjo fuq netwerk Ethernet.

protokoll RTP (Protokoll Ħin Reali) tradott ifisser protokoll f'ħin reali, huwa użat biex jittrasmetti awdjo, vidjo, data, dak kollu li jeħtieġ trażmissjoni f'ħin reali. Ejja nieħdu sinjal awdjo bħala eżempju. Il-flessibilità tal-protokoll hija tali li tippermettilek tittrasmetti sinjal awdjo bi kwalità predeterminata.

It-trażmissjoni titwettaq bl-użu ta 'pakketti UDP, li jfisser li t-telf ta' pakkett huwa pjuttost aċċettabbli waqt it-trażmissjoni. Kull pakkett fih header RTP speċjali u blokk tad-dejta tas-sinjal trażmess. L-header fih identifikatur tas-sors tas-sinjal magħżul b’mod każwali, informazzjoni dwar it-tip ta’ sinjal li qed jiġi trażmess, u numru uniku ta’ sekwenza tal-pakketti sabiex il-pakketti jkunu jistgħu jiġu rranġati fl-ordni korretta meta jiġu ddekodifikati, irrispettivament mill-ordni li fiha ġew ikkunsinnati mill- netwerk. L-header jista 'jkun fih ukoll informazzjoni addizzjonali, l-hekk imsejħa estensjoni, li tippermetti li l-header jiġi adattat għall-użu f'kompitu speċifiku ta' applikazzjoni.

Il-blokk tad-dejta fih it-tagħbija tal-pakkett. L-organizzazzjoni interna tal-kontenut tiddependi fuq it-tip ta 'tagħbija, tista' tkun kampjuni ta 'sinjal mono, sinjal stereo, linja ta' immaġni tal-vidjo, eċċ.

It-tip ta 'tagħbija huwa indikat b'numru ta' seba 'bit. Rakkomandazzjoni RFC3551 (Profil RTP għal Konferenzi Awdjo u Vidjo b'Kontroll Minimu) jistabbilixxi diversi tipi ta' tagħbija; it-tabella korrispondenti tipprovdi deskrizzjoni tat-tipi ta' tagħbija u t-tifsira tal-kodiċijiet li bihom huma indikati. Xi kodiċijiet mhumiex strettament marbuta ma 'kwalunkwe tip ta' tagħbija; jistgħu jintużaw biex jinnominaw tagħbija arbitrarja.

Id-daqs ta 'blokk tad-dejta huwa limitat hawn fuq mid-daqs massimu tal-pakkett li jista' jiġi trażmess fuq netwerk partikolari mingħajr segmentazzjoni (parametru MTU). B'mod ġenerali, dan mhux aktar minn 1500 bytes. Għalhekk, sabiex iżżid l-ammont ta 'dejta trażmessa kull sekonda, tista' żżid id-daqs tal-pakkett sa ċertu punt, u mbagħad ikollok bżonn iżżid il-frekwenza li tibgħat pakketti. Fi streamer tal-midja, dan huwa setting konfigurabbli. B'mod awtomatiku huwa 50 Hz, i.e. 50 pakkett kull sekonda. Se nsejħu s-sekwenza ta' pakketti RTP trażmessi fluss RTP.

Biex tibda tittrasmetti dejta bejn is-sors u r-riċevitur, huwa biżżejjed li t-trasmettitur ikun jaf l-indirizz IP tar-riċevitur u n-numru tal-port li juża biex jirċievi. Dawk. mingħajr ebda proċedura preliminari, is-sors jibda jittrasmetti d-dejta, u r-riċevitur, min-naħa tiegħu, ikun lest li jirċieviha u jipproċessaha immedjatament. Skont l-istandard, in-numru tal-port użat biex jittrasmetti jew jirċievi fluss RTP għandu jkun ugwali.

F'sitwazzjonijiet fejn huwa impossibbli li tkun taf l-indirizz tar-riċevitur minn qabel, is-servers jintużaw fejn ir-riċevituri jħallu l-indirizz tagħhom, u t-trasmettitur jista 'jitlobha billi jirreferi għal xi isem uniku tar-riċevitur.

F'każijiet fejn il-kwalità tal-kanal ta 'komunikazzjoni jew il-kapaċitajiet tar-riċevitur mhumiex magħrufa, jiġi organizzat kanal ta' feedback li permezz tiegħu r-riċevitur jista 'jinforma lit-trasmettitur dwar il-kapaċitajiet tiegħu, in-numru ta' pakketti li tilef, eċċ. Dan il-kanal juża l-protokoll RTCP. Il-format tal-pakketti trażmessi f'dan il-kanal huwa definit f'RFC 3605. Relattivament ftit data hija trażmessa fuq dan il-kanal, 200..300 bytes kull sekonda, għalhekk b'mod ġenerali, il-preżenza tagħha mhix ta 'piż. In-numru tal-port li lejh jintbagħtu l-pakketti RTCP għandu jkun fard u wieħed akbar min-numru tal-port li minnu jiġi l-fluss RTP. Fl-eżempju tagħna, aħna mhux se nużaw dan il-kanal, peress li l-kapaċitajiet tar-riċevitur u l-kanal ovvjament jaqbżu l-ħtiġijiet tagħna, s'issa modesti.

Fil-programm tagħna, iċ-ċirkwit tat-trażmissjoni tad-dejta, b'differenza mill-eżempju preċedenti, se jkun maqsum f'żewġ partijiet: mogħdija ta 'trażmissjoni u mogħdija li tirċievi. Għal kull parti se nagħmlu s-sors tal-arloġġ tagħna stess, kif muri fl-istampa tat-titlu.

Il-komunikazzjoni one-way bejniethom se titwettaq bl-użu tal-protokoll RTP. F'dan l-eżempju, m'għandniex bżonn netwerk estern, peress li kemm it-trasmettitur kif ukoll ir-riċevitur se jkunu jinsabu fuq l-istess kompjuter - il-pakketti se jivvjaġġaw ġewwa fih.

Biex jistabbilixxi fluss RTP, il-media streamer juża żewġ filtri: MS_RTP_SEND u MS_RTP_RECV. L-ewwel wieħed jittrasmetti t-tieni wieħed u jirċievi n-nixxiegħa RTP. Sabiex dawn il-filtri jaħdmu, jeħtieġ li jgħaddu pointer għal oġġett ta 'sessjoni RTP, li jista' jew jikkonverti fluss ta 'blokki tad-dejta fi fluss ta' pakketti RTP jew jagħmel l-oppost. Peress li l-format tad-dejta interna tal-media streamer ma jaqbilx mal-format tad-dejta tal-pakkett RTP, qabel ma tittrasferixxi d-dejta lil MS_RTP_SEND, għandek bżonn tuża filtru tal-kodifikatur li jikkonverti kampjuni tas-sinjali tal-awdjo ta’ 16-il bit fi tmien bit kodifikati skont il- u-law (mu-law). Fuq in-naħa li tirċievi, il-filtru tad-decoder iwettaq il-funzjoni opposta.

Hawn taħt hemm it-test tal-programm li jimplimenta l-iskema murija fil-figura (is-# simboli qabel ma tneħħew id-direttivi tal-inklużjoni, tinsiex tinkludihom):

/* Файл 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);
}
}

Aħna niġbru u nħaddmu. Il-programm se jaħdem bħal fl-eżempju preċedenti, iżda d-dejta se tiġi trażmessa permezz ta 'fluss RTP.

Fl-artiklu li jmiss se naqsmu dan il-programm f'żewġ applikazzjonijiet indipendenti - riċevitur u trasmettitur u nnieduhom f'terminals differenti. Fl-istess ħin, se nitgħallmu kif nanalizzaw il-pakketti RTP bl-użu tal-programm TShark.

Sors: www.habr.com

Żid kumment