Eksplore motè VoIP Mediastreamer2 la. Pati 6

Materyèl atik la pran nan men mwen zen channel.

Transmèt yon siyal odyo atravè kouran RTP

Eksplore motè VoIP Mediastreamer2 la. Pati 6

Nan tan lontan an Atik Nou te rasanble yon sikwi kontwòl remote soti nan yon dèlko ton ak yon detektè ton ki opere nan menm pwogram nan. Nan atik sa a nou pral aprann kijan pou itilize pwotokòl RTP (RFC 3550 - RTP: Yon pwotokòl transpò pou aplikasyon an tan reyèl) pou resevwa/transmèt yon siyal odyo sou yon rezo Ethernet.

pwotokòl RTP (Pwotokòl an tan reyèl) tradui vle di pwotokòl an tan reyèl, li itilize pou transmèt odyo, videyo, done, tout bagay ki mande transmisyon an tan reyèl. Ann pran yon siyal odyo kòm egzanp. Fleksibilite nan pwotokòl la se tankou ke li pèmèt ou transmèt yon siyal odyo ak yon bon jan kalite Predetermined.

Transmisyon an fèt lè l sèvi avèk pake UDP, ki vle di ke pèt pake se byen akseptab pandan transmisyon. Chak pake gen yon header RTP espesyal ak yon blòk done siyal transmèt la. Tèt la gen yon idantifyan sous siyal chwazi owaza, enfòmasyon sou kalite siyal ke yo te transmèt, ak yon nimewo sekans pake inik pou pake yo ka ranje nan lòd ki kòrèk la lè dekodaj, kèlkeswa lòd yo te delivre pa a. rezo. Header la kapab genyen tou enfòmasyon adisyonèl, sa yo rele ekstansyon an, ki pèmèt header la adapte pou itilize nan yon travay aplikasyon espesifik.

Blòk done a gen chaj pake a. Òganizasyon entèn kontni an depann sou kalite chaj la, li kapab echantiyon yon siyal mono, yon siyal stereo, yon liy imaj videyo, elatriye.

Kalite chaj la endike pa yon nimewo sèt-bit. Rekòmandasyon RFC3551 (RTP Profile pou Konferans odyo ak videyo ak kontwòl minimòm) etabli plizyè kalite chaj; tablo ki koresponn lan bay yon deskripsyon kalite chaj ak siyifikasyon kòd yo deziyen yo. Gen kèk kòd ki pa estrikteman mare nan nenpòt ki kalite chaj; yo ka itilize yo deziyen yon chaj abitrè.

Gwosè yon blòk done limite pi wo a pa gwosè pake maksimòm ki ka transmèt sou yon rezo bay san segmantasyon (paramèt MTU). An jeneral, sa a se pa plis pase 1500 bytes. Se konsa, yo nan lòd yo ogmante kantite done transmèt pou chak segonn, ou ka ogmante gwosè a pake jiska yon sèten pwen, ak Lè sa a, ou pral bezwen ogmante frekans nan voye pake. Nan yon streamer medya, sa a se yon anviwònman configurable. Pa default li se 50 Hz, i.e. 50 pake pou chak segonn. Nou pral rele sekans pake RTP transmèt yo yon kouran RTP.

Pou kòmanse transmèt done ant sous la ak reseptè a, li ase ke transmetè a konnen adrès IP reseptè a ak nimewo pò a ke li itilize pou resevwa. Moun sa yo. san okenn pwosedi preliminè, sous la kòmanse transmèt done, ak reseptè a, nan vire, se pare imedyatman resevwa ak trete li. Dapre estanda a, nimewo pò yo itilize pou transmèt oswa resevwa yon kouran RTP dwe menm.

Nan sitiyasyon kote li enposib konnen adrès reseptè a davans, yo itilize serveurs kote reseptè yo kite adrès yo, epi transmetè a ka mande li lè li refere a kèk non inik nan reseptè a.

Nan ka kote bon jan kalite a nan chanèl kominikasyon an oswa kapasite yo nan reseptè a yo enkoni, yo òganize yon chanèl fidbak nan ki reseptè a ka enfòme transmetè a sou kapasite li yo, kantite pake li rate, elatriye. Chanèl sa a sèvi ak pwotokòl RTCP. Fòma pake ki transmèt nan kanal sa a defini nan RFC 3605. Done relativman ti transmèt sou kanal sa a, 200..300 bytes pou chak segonn, kidonk an jeneral, prezans li pa lou. Nimewo pò kote yo voye pake RTCP yo dwe enpè ak youn ki pi gran pase nimewo pò kote kouran RTP la soti. Nan egzanp nou an, nou pa pral sèvi ak chanèl sa a, depi kapasite yo nan reseptè a ak chanèl evidamman depase bezwen nou yo, byen lwen tèlman modès.

Nan pwogram nou an, sikwi transmisyon done a, kontrèman ak egzanp anvan an, yo pral divize an de pati: yon chemen transmèt ak yon chemen k ap resevwa. Pou chak pati nou pral fè pwòp sous revèy nou, jan yo montre nan foto tit la.

Yon sèl-fason kominikasyon ant yo pral fèt lè l sèvi avèk pwotokòl la RTP. Nan egzanp sa a, nou pa bezwen yon rezo ekstèn, paske tou de transmetè a ak reseptè a pral lokalize sou menm òdinatè a - pake yo pral vwayaje andedan li.

Pou etabli yon kouran RTP, streamer medya a itilize de filtè: MS_RTP_SEND ak MS_RTP_RECV. Premye a transmèt dezyèm lan epi li resevwa kouran RTP. Nan lòd pou filtè sa yo travay, yo bezwen pase yon konsèy nan yon objè sesyon RTP, ki ka swa konvèti yon kouran nan blòk done nan yon kouran nan pake RTP oswa fè opoze a. Piske fòma done entèn streamer medya a pa matche ak fòma done pake RTP a, anvan ou transfere done yo nan MS_RTP_SEND, ou bezwen sèvi ak yon filtè ankode ki konvèti echantiyon siyal odyo 16-bit nan uit-bit kode selon la. u-law (mu-law). Sou bò k ap resevwa a, filtè dekodè a fè fonksyon opoze a.

Anba a se tèks pwogram ki aplike konplo yo montre nan figi a (# senbòl yo anvan yo te retire direktiv enkli yo, pa bliye mete yo):

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

Nou konpile epi kouri. Pwogram nan ap travay tankou nan egzanp anvan an, men done yo pral transmèt atravè yon kouran RTP.

Nan pwochen atik la nou pral divize pwogram sa a an de aplikasyon endepandan - yon reseptè ak yon transmetè epi lanse yo nan tèminal diferan. An menm tan an, nou pral aprann kijan pou analize pake RTP lè l sèvi avèk pwogram TShark la.

Sous: www.habr.com

Add nouvo kòmantè