Ṣiṣawari ẹrọ Mediastreamer2 VoIP. Apa 6

Awọn ohun elo ti awọn article ti wa ni ya lati mi zen ikanni.

Gbigbe ifihan ohun afetigbọ nipasẹ ṣiṣan RTP

Ṣiṣawari ẹrọ Mediastreamer2 VoIP. Apa 6

Ni ikẹhin article A ti ṣajọpọ iṣakoso isakoṣo latọna jijin lati inu olupilẹṣẹ ohun orin ati aṣawari ohun orin ti o ṣiṣẹ laarin eto kanna. Ninu nkan yii a yoo kọ bi a ṣe le lo ilana RTP (RFC 3550 - RTP: Ilana Gbigbe fun Awọn ohun elo Akoko-gidi) fun gbigba/gbigba ifihan agbara ohun lori nẹtiwọki Ethernet kan.

Ilana RTP (Real Time Ilana) Itumọ tumọ si ilana akoko gidi, o lo lati gbe ohun, fidio, data, ohun gbogbo ti o nilo gbigbe ni akoko gidi. Jẹ ki a gba ifihan agbara ohun bi apẹẹrẹ. Irọrun ti Ilana jẹ iru eyiti o gba ọ laaye lati tan ifihan agbara ohun pẹlu didara ti a ti pinnu tẹlẹ.

Gbigbe naa ni a ṣe ni lilo awọn apo-iwe UDP, eyiti o tumọ si pe pipadanu apo jẹ itẹwọgba lakoko gbigbe. Paketi kọọkan ni akọsori RTP pataki kan ati bulọọki data ti ifihan agbara ti a firanṣẹ. Akọsori naa ni idanimọ orisun ifihan agbara ti a yan laileto, alaye nipa iru ifihan agbara ti o tan kaakiri, ati nọmba ọkọọkan soso kan ki awọn apo-iwe le wa ni idayatọ ni ọna ti o pe nigba iyipada, laibikita aṣẹ ti wọn ti fi jiṣẹ nipasẹ nẹtiwọki. Akọsori tun le ni alaye afikun ninu, eyiti a pe ni itẹsiwaju, eyiti o fun laaye akọsori lati ṣe atunṣe fun lilo ninu iṣẹ-ṣiṣe ohun elo kan pato.

Àkọsílẹ data naa ni fifuye isanwo ti apo-iwe naa. Eto inu ti akoonu da lori iru fifuye, o le jẹ awọn apẹẹrẹ ti ifihan monomono, ifihan sitẹrio, laini aworan fidio, ati bẹbẹ lọ.

Awọn fifuye iru ti wa ni itọkasi nipa a meje-bit nọmba. Iṣeduro RFC3551 (Profaili RTP fun Ohun ati Awọn apejọ fidio pẹlu Iṣakoso Iwọnba) ṣe agbekalẹ ọpọlọpọ awọn iru ẹru; tabili ti o baamu pese apejuwe awọn iru ẹru ati itumọ ti awọn koodu nipasẹ eyiti a yan wọn. Diẹ ninu awọn koodu ko ni asopọ muna si eyikeyi iru ẹru; wọn le ṣee lo lati ṣe apẹrẹ ẹru lainidii.

Iwọn bulọọki data ni opin loke nipasẹ iwọn apo ti o pọju ti o le tan kaakiri lori nẹtiwọọki ti a fun laisi ipin (parameter MTU). Ni gbogbogbo, eyi ko ju 1500 baiti lọ. Nitorinaa, lati le mu iye data ti o tan kaakiri fun iṣẹju kan, o le mu iwọn apo pọ si aaye kan, lẹhinna o yoo nilo lati mu igbohunsafẹfẹ ti awọn apo-iwe ranṣẹ. Ninu ṣiṣan media, eyi jẹ eto atunto. Nipa aiyipada o jẹ 50 Hz, i.e. Awọn apo-iwe 50 fun iṣẹju-aaya. A yoo pe ọkọọkan ti awọn apo-iwe RTP ti a firanṣẹ ni ṣiṣan RTP.

Lati bẹrẹ gbigbe data laarin orisun ati olugba, o to pe atagba naa mọ adiresi IP ti olugba ati nọmba ibudo ti o nlo fun gbigba. Awon. laisi awọn ilana alakoko eyikeyi, orisun bẹrẹ lati atagba data, ati olugba, ni ọna, ti ṣetan lati gba lẹsẹkẹsẹ ati ṣe ilana rẹ. Gẹgẹbi boṣewa, nọmba ibudo ti a lo lati tan kaakiri tabi gba ṣiṣan RTP gbọdọ jẹ paapaa.

Ni awọn ipo nibiti ko ṣee ṣe lati mọ adirẹsi olugba tẹlẹ, awọn olupin ni a lo nibiti awọn olugba ti fi adirẹsi wọn silẹ, ati pe atagba le beere rẹ nipa tọka si orukọ alailẹgbẹ ti olugba.

Ni awọn ọran nibiti didara ikanni ibaraẹnisọrọ tabi awọn agbara ti olugba ko jẹ aimọ, ikanni esi ti ṣeto nipasẹ eyiti olugba le sọ fun atagba nipa awọn agbara rẹ, nọmba awọn idii ti o padanu, ati bẹbẹ lọ. Ikanni yii nlo ilana RTCP. Awọn ọna kika ti awọn apo-iwe ti a gbejade ni ikanni yii jẹ asọye ni RFC 3605. Ni ibatan diẹ data ti wa ni gbigbe lori ikanni yii, 200..300 awọn baiti fun iṣẹju kan, nitorinaa ni gbogbogbo, wiwa rẹ kii ṣe ẹru. Nọmba ibudo ti awọn apo-iwe RTCP ti firanṣẹ gbọdọ jẹ aiṣedeede ati ọkan ti o tobi ju nọmba ibudo lati eyiti ṣiṣan RTP ti wa. Ninu apẹẹrẹ wa, a kii yoo lo ikanni yii, nitori awọn agbara ti olugba ati ikanni o han gbangba kọja awọn iwulo wa, niwọntunwọnsi.

Ninu eto wa, Circuit gbigbe data, ko dabi apẹẹrẹ ti tẹlẹ, yoo pin si awọn ẹya meji: ọna gbigbe ati ọna gbigba. Fun apakan kọọkan a yoo ṣe orisun aago tiwa, bi a ṣe han ninu aworan akọle.

Ibaraẹnisọrọ ọna kan laarin wọn yoo ṣee ṣe nipa lilo ilana RTP. Ni apẹẹrẹ yii, a ko nilo nẹtiwọọki ita, nitori mejeeji atagba ati olugba yoo wa lori kọnputa kanna - awọn apo-iwe yoo rin irin-ajo inu rẹ.

Lati fi idi ṣiṣan RTP kan mulẹ, ṣiṣan media nlo awọn asẹ meji: MS_RTP_SEND ati MS_RTP_RECV. Ni igba akọkọ ti atagba awọn keji ati ki o gba awọn RTP san. Ni ibere fun awọn asẹ wọnyi lati ṣiṣẹ, wọn nilo lati gbe itọka kan si nkan igba RTP kan, eyiti o le ṣe iyipada ṣiṣan ti awọn bulọọki data sinu ṣiṣan ti awọn apo-iwe RTP tabi ṣe idakeji. Niwọn igba ti ọna kika data inu ti ṣiṣan media ko baamu ọna kika data ti apo RTP, ṣaaju gbigbe data si MS_RTP_SEND, o nilo lati lo àlẹmọ koodu kan ti o yi awọn apẹẹrẹ ifihan ohun afetigbọ ohun 16-bit pada si koodu mẹjọ-bit ni ibamu si u-ofin (mu-ofin). Ni ẹgbẹ gbigba, àlẹmọ decoder ṣe iṣẹ idakeji.

Ni isalẹ ni ọrọ ti eto ti o ṣe imuse ero ti o han ninu eeya (awọn aami # ṣaaju ki o to yọkuro awọn ilana pẹlu, maṣe gbagbe lati ṣafikun wọn):

/* Файл 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 ṣe akopọ ati ṣiṣe. Eto naa yoo ṣiṣẹ bi ninu apẹẹrẹ ti tẹlẹ, ṣugbọn data naa yoo tan kaakiri nipasẹ ṣiṣan RTP kan.

Ninu nkan ti o tẹle a yoo pin eto yii si awọn ohun elo ominira meji - olugba ati atagba kan ati ṣe ifilọlẹ wọn ni awọn ebute oriṣiriṣi. Ni akoko kanna, a yoo kọ ẹkọ bi o ṣe le ṣe itupalẹ awọn apo-iwe RTP nipa lilo eto TShark.

orisun: www.habr.com

Fi ọrọìwòye kun