A’ sgrùdadh einnsean Mediastreamer2 VoIP. Pàirt 6

Tha stuth an artaigil air a thoirt bho mo seanail zen.

A’ sgaoileadh comharra claisneachd tro shruth RTP

A’ sgrùdadh einnsean Mediastreamer2 VoIP. Pàirt 6

Anns an àm a dh ’fhalbh artaigil Tha sinn air cuairt smachd iomallach a chruinneachadh bho ghineadair tòna agus lorgaire tòna a bhios ag obair taobh a-staigh an aon phrògram. San artaigil seo ionnsaichidh sinn mar a chleachdas tu am protocol RTP (RFC 3550 -). RTP: Pròtacal Còmhdhail airson Tagraidhean Fìor-ùine) airson comharra claisneachd fhaighinn / a chuir thairis air lìonra Ethernet.

protocol RTP (Pròtacal fìor-ùine) Tha eadar-theangachadh a’ ciallachadh protocol fìor-ùine, tha e air a chleachdadh gus claisneachd, bhidio, dàta, a h-uile dad a dh’ fheumas tar-chuir ann an àm fìor a tharraing. Gabhamaid comharra claisneachd mar eisimpleir. Tha sùbailteachd a’ phròtacal cho mòr is gun leig e leat comharra claisneachd a chuir thairis le càileachd ro-shuidhichte.

Tha an tar-chuir air a dhèanamh le bhith a’ cleachdadh phasganan UDP, a tha a’ ciallachadh gu bheilear a’ gabhail ri call pacaid aig àm an tar-chuir. Anns gach pacaid tha bann-cinn RTP sònraichte agus bloc dàta den chomharra tar-chuir. Anns a’ bhann-cinn tha aithnichear stòr chomharran a chaidh a thaghadh air thuaiream, fiosrachadh mun t-seòrsa comharra a thathas a’ tar-chuir, agus àireamh sreath pacaid sònraichte gus an tèid na pacaidean a chuir air dòigh san òrdugh cheart nuair a thèid an còdachadh, ge bith dè an òrdugh san deach an lìbhrigeadh leis an lìonra. Faodaidh fiosrachadh a bharrachd a bhith anns a ’cheann-cinn cuideachd, an leudachadh ris an canar, a leigeas leis a’ bhann-cinn atharrachadh airson a chleachdadh ann an gnìomh tagraidh sònraichte.

Anns a’ bhloc dàta tha uallach pàighidh a’ phacaid. Tha eagrachadh an t-susbaint a-staigh an urra ris an t-seòrsa luchd, faodaidh e a bhith na shamhlaichean de chomharradh mono, comharra stereo, loidhne ìomhaigh bhidio, msaa.

Tha an seòrsa luchd air a chomharrachadh le àireamh seachd-bit. Moladh RFC3551 (Pròifil RTP airson co-labhairtean claisneachd is bhidio le glè bheag de smachd) a’ stèidheachadh grunn sheòrsaichean luchdan; tha an clàr co-fhreagarrach a’ toirt cunntas air na seòrsaichean luchdan agus brìgh nan còdan leis a bheil iad air an ainmeachadh. Chan eil cuid de chòdan ceangailte gu teann ri seòrsa sam bith de luchd; faodar an cleachdadh gus luchd neo-riaghailteach ainmeachadh.

Tha meud bloca dàta air a chuingealachadh gu h-àrd leis a’ mheud pacaid as àirde a ghabhas a chraoladh air lìonra sònraichte gun sgaradh (parameter MTU). San fharsaingeachd, chan eil seo nas fhaide na 1500 bytes. Mar sin, gus an àireamh de dhàta a thèid a ghluasad gach diog a mheudachadh, faodaidh tu meud a ’phacaid àrdachadh gu ìre sònraichte, agus an uairsin feumaidh tu tricead cur pacaidean àrdachadh. Ann an sruthan meadhanan, is e suidheachadh rèiteachaidh a tha seo. Gu gnàthach is e 50 Hz a th’ ann, i.e. 50 pacaidean gach diog. Canaidh sinn sreath de phasganan RTP tar-chuir mar shruth RTP.

Gus tòiseachadh air dàta a chuir a-mach eadar an stòr agus an cuidhteas, tha e gu leòr gum bi fios aig an inneal-sgaoilidh seòladh IP a ’ghlacadair agus an àireamh port a bhios e a’ cleachdadh airson faighinn. An fheadhainn sin. às aonais modhan tòiseachaidh sam bith, bidh an stòr a ’tòiseachadh a’ sgaoileadh dàta, agus tha an neach-glacaidh, an uair sin, deiseil airson fhaighinn sa bhad agus a phròiseasadh. A rèir na h-ìre, feumaidh an àireamh port a thèid a chleachdadh gus sruth RTP a tharraing no fhaighinn a bhith cothromach.

Ann an suidheachaidhean far a bheil e do-dhèanta fios a bhith agad air seòladh a’ ghlacadair ro-làimh, bidh frithealaichean air an cleachdadh far am fàg luchd-glacaidh an seòladh aca, agus faodaidh an neach-sgaoilidh iarraidh le bhith a’ toirt iomradh air ainm sònraichte a’ ghlacadair.

Ann an cùisean far nach eil fios air càileachd an t-seanail conaltraidh no comasan an neach-glacaidh, thèid sianal fios-air-ais a chuir air dòigh tron ​​​​urrainn don ghlacadair innse don neach-sgaoilidh mu na comasan aige, an àireamh de phasganan a chaill e, msaa. Bidh an sianal seo a’ cleachdadh protocol RTCP. Tha cruth pacaidean a thèid a ghluasad san t-sianal seo air a mhìneachadh ann an RFC 3605. Is e glè bheag de dhàta a tha air a ghluasad thairis air an t-sianal seo, 200..300 bytes gach diog, agus mar sin san fharsaingeachd, chan eil a làthaireachd trom. Feumaidh an àireamh port dhan tèid pacaidean RTCP a chuir a-steach a bhith neònach agus aon nas motha na àireamh a’ phuirt às a bheil an sruth RTP a’ tighinn. Anns an eisimpleir againn, cha chleachd sinn an sianal seo, leis gu bheil comasan a’ ghlacadair agus an t-seanail gu follaiseach a’ dol thairis air na feumalachdan againn, gu ruige seo beag.

Anns a ’phrògram againn, bidh an cuairteachadh tar-chuir dàta, eu-coltach ris an eisimpleir roimhe, air a roinn ann an dà phàirt: slighe tar-chuir agus slighe faighinn. Airson gach pàirt nì sinn ar stòr cloc fhèin, mar a chithear san dealbh tiotal.

Thèid conaltradh aon-shligheach eatorra a dhèanamh a’ cleachdadh protocol RTP. Anns an eisimpleir seo, chan eil feum againn air lìonra a-muigh, oir bidh an dà chuid an inneal-sgaoilidh agus an cuidhteas air an aon choimpiutair - bidh na pacaidean a ’siubhal a-staigh.

Gus sruth RTP a stèidheachadh, bidh an streapadair mheadhanan a’ cleachdadh dà chriathrag: MS_RTP_SEND agus MS_RTP_RECV. Bidh a 'chiad fhear a' toirt seachad an dàrna fear agus a 'faighinn sruth RTP. Gus an obraich na sìoltachain sin, feumaidh iad puing a chuir gu rud seisean RTP, a dh’ fhaodas sruth de bhlocaichean dàta a thionndadh gu sruth de phasgan RTP no an taobh eile a dhèanamh. Leis nach eil cruth dàta a-staigh an t-sruthadair mheadhanan a’ freagairt ri cruth dàta a’ phacaid RTP, mus gluais thu an dàta gu MS_RTP_SEND, feumaidh tu criathrag encoder a chleachdadh a dh’ atharraicheas sampallan de chomharran claisneachd 16-bit gu ochd-bit air an còdachadh a rèir an u-lagh (mu-law). Air an taobh faighinn, bidh an sìoltachan decoder a ’coileanadh a’ ghnìomh eile.

Gu h-ìosal tha teacsa a ’phrògraim a chuireas an gnìomh an sgeama a chithear san fhigear (na # samhlaidhean mus deach na stiùiridhean a thoirt a-steach a thoirt air falbh, na dìochuimhnich an toirt a-steach):

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

Bidh sinn a 'cruinneachadh agus a' ruith. Bidh am prògram ag obair mar a bha san eisimpleir roimhe, ach thèid an dàta a ghluasad tro shruth RTP.

Anns an ath artaigil roinnidh sinn am prògram seo ann an dà thagradh neo-eisimeileach - cuidhteas agus inneal-sgaoilidh agus cuiridh sinn air bhog iad ann an diofar chrìochan. Aig an aon àm, ionnsaichidh sinn mar a nì sinn sgrùdadh air pacaidean RTP a’ cleachdadh prògram TShark.

Source: www.habr.com

Cuir beachd ann