د Mediastreamer2 VoIP انجن سپړنه. 6 برخه

د مقالې مواد زما څخه اخیستل شوي دي زین چینل.

د RTP جریان له لارې د آډیو سیګنال لیږدول

د Mediastreamer2 VoIP انجن سپړنه. 6 برخه

په اخر کې مقالې موږ د ټون جنراتور او د ټون کشف کونکي څخه د ریموټ کنټرول سرکټ راټول کړی چې په ورته برنامه کې کار کوي. پدې مقاله کې به موږ زده کړو چې څنګه د RTP پروتوکول کارول (RFC 3550 - RTP: د ریښتیني وخت غوښتنلیکونو لپاره د ترانسپورت پروتوکول) د ایترنیټ شبکې له لارې د آډیو سیګنال ترلاسه کولو / لیږدولو لپاره.

RTP پروتوکول (د ریښتیني وخت پروتوکول) ژباړه د ریښتیني وخت پروتوکول معنی لري ، دا د آډیو ، ویډیو ، ډیټا ، هر هغه څه چې په ریښتیني وخت کې لیږد ته اړتیا لري لیږدولو لپاره کارول کیږي. راځئ چې د مثال په توګه یو آډیو سیګنال واخلو. د پروتوکول انعطاف داسې دی چې دا تاسو ته اجازه درکوي د مخکې ټاکل شوي کیفیت سره آډیو سیګنال لیږد کړئ.

لیږد د UDP پاکټونو په کارولو سره ترسره کیږي ، پدې معنی چې د لیږد پرمهال د پیکټ ضایع د منلو وړ دی. هر کڅوړه د ځانګړي RTP سرلیک او د لیږدول شوي سیګنال ډیټا بلاک لري. سرلیک په تصادفي ډول ټاکل شوی سیګنال سرچینه پیژندونکی لري ، د لیږد شوي سیګنال ډول په اړه معلومات ، او د ځانګړي کڅوړې ترتیب شمیره لري ترڅو پاکټونه د کوډ کولو پرمهال په سم ترتیب تنظیم شي ، پرته لدې چې د کوم ترتیب لخوا تحویل شوي وي. شبکه سرلیک کولی شي اضافي معلومات هم ولري، تش په نامه تمدید، کوم چې سرلیک ته اجازه ورکوي چې د ځانګړي غوښتنلیک دندې کې د کارولو لپاره تطبیق شي.

د ډیټا بلاک د کڅوړې تادیه لري. د مینځپانګې داخلي تنظیم د بار ډول پورې اړه لري ، دا د مونو سیګنال نمونې کیدی شي ، د سټیریو سیګنال ، د ویډیو عکس لاین ، او داسې نور.

د بار ډول د اوه بټ نمبر لخوا ښودل شوی. سپارښتنه RFC3551 (د لږترلږه کنټرول سره د آډیو او ویډیو کنفرانسونو لپاره د RTP پروفایل) د بار ډیری ډولونه رامینځته کوي؛ اړونده جدول د بار ډولونو توضیحات او د کوډونو معنی وړاندې کوي چې له مخې یې ډیزاین شوي. ځینې ​​کوډونه د هر ډول بار سره په کلکه تړلي ندي؛ دوی د خپل سري بار ټاکلو لپاره کارول کیدی شي.

د ډیټا بلاک اندازه پورته د اعظمي پیکټ اندازې پورې محدوده ده چې پرته له قطع کولو (MTU پیرامیټر) په ورکړل شوي شبکه کې لیږدول کیدی شي. په عموم کې، دا د 1500 بایټ څخه ډیر نه دی. پدې توګه ، په هره ثانیه کې د لیږدول شوي ډیټا مقدار زیاتولو لپاره ، تاسو کولی شئ د پیکټ اندازه تر یو ټاکلي نقطې پورې لوړه کړئ ، او بیا تاسو اړتیا لرئ د پاکټونو لیږلو فریکوینسي ډیر کړئ. په میډیا سټیمر کې ، دا د تنظیم کولو وړ ترتیب دی. د ډیفالټ له مخې دا 50 Hz دی، i.e. په هره ثانیه کې 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-bit آډیو سیګنال نمونې په اتو بټ کوډ شوي کې بدلوي. u-law (mu-law). د ترلاسه کولو اړخ کې، د کوډ کونکي فلټر مخالف فعالیت ترسره کوي.

لاندې د برنامه متن دی چې په شکل کې ښودل شوي سکیم پلي کوي (# سمبولونه مخکې لدې چې د شاملولو لارښوونو لرې شوي وي ، مه هیروئ چې پکې شامل کړئ):

/* Файл 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 کڅوړې تحلیل کړو.

سرچینه: www.habr.com

Add a comment