Binciko injin Mediastreamer2 VoIP. Kashi na 6

An ɗauko kayan labarin daga nawa zen channel.

Ana isar da siginar sauti ta rafin RTP

Binciko injin Mediastreamer2 VoIP. Kashi na 6

A karshe labarin Mun harhada da'ira mai sarrafa nesa daga na'urar samar da sautin sauti da na'urar gano sautin da ke aiki a cikin wannan shirin. A cikin wannan labarin za mu koyi yadda ake amfani da yarjejeniyar RTP (RFC 3550 - RTP: Yarjejeniyar Sufuri don Aikace-aikacen Lokaci na Gaskiya) don karɓar / watsa siginar sauti akan hanyar sadarwar Ethernet.

RTP yarjejeniya (Real Time Protocol) Fassara yana nufin ƙa'idar lokaci-lokaci, ana amfani da ita don watsa sauti, bidiyo, bayanai, duk abin da ke buƙatar watsawa a cikin ainihin lokaci. Bari mu ɗauki siginar sauti a matsayin misali. Sassaucin ƙa'idar shine ta yadda zata baka damar watsa siginar sauti tare da ƙayyadaddun inganci.

Ana aiwatar da watsawa ta amfani da fakitin UDP, wanda ke nufin cewa asarar fakitin abin karɓa ne sosai yayin watsawa. Kowane fakiti ya ƙunshi kan na musamman na RTP da toshe bayanai na siginar da aka watsa. Taken yana ƙunshe da maɓallin gano siginar da aka zaɓa ba da gangan, bayani game da nau'in siginar da ake watsawa, da lambar jeri na fakiti na musamman domin a iya tsara fakitin cikin tsari daidai lokacin yanke hukunci, ba tare da la'akari da tsarin da aka isar da su ba. hanyar sadarwa. Har ila yau, rubutun yana iya ƙunsar ƙarin bayani, abin da ake kira tsawo, wanda ke ba da damar daidaita rubutun don amfani a cikin takamaiman aikin aikace-aikacen.

Toshe bayanan yana ƙunshe da nauyin fakitin. Ƙungiyar ciki na abun ciki ya dogara da nau'in kaya, yana iya zama samfurori na siginar mono, sitiriyo sitiriyo, layin hoton bidiyo, da dai sauransu.

Ana nuna nau'in kaya ta lamba bakwai-bit. Bayani na RFC3551Bayanan martaba na RTP don Audio da taron Bidiyo tare da Karamin Sarrafa) ya kafa nau'ikan kaya da yawa; tebur mai dacewa yana ba da bayanin nau'ikan kaya da ma'anar lambobin da aka tsara su. Wasu lambobi ba a ɗaure su da kowane nau'in kaya ba; ana iya amfani da su don zayyana kaya na sabani.

Girman toshe bayanai yana iyakance a sama ta matsakaicin girman fakiti wanda za'a iya watsawa akan hanyar sadarwar da aka bayar ba tare da rabuwa ba (MTU parameter). Gabaɗaya, wannan bai wuce 1500 bytes ba. Don haka, don ƙara adadin bayanan da ake watsawa a cikin daƙiƙa guda, zaku iya ƙara girman fakiti har zuwa wani matsayi, sannan kuna buƙatar ƙara yawan fakitin aikawa. A cikin kafofin watsa labarai streamer, wannan saitin daidaitacce ne. Ta hanyar tsoho shine 50 Hz, i.e. fakiti 50 a sakan daya. Za mu kira jerin fakitin RTP da aka watsa da rafin RTP.

Don fara watsa bayanai tsakanin tushen da mai karɓa, ya isa cewa mai watsawa ya san adireshin IP na mai karɓar da lambar tashar tashar da yake amfani da shi don karɓa. Wadancan. ba tare da wani tsari na farko ba, tushen ya fara watsa bayanai, kuma mai karɓa, bi da bi, yana shirye don karɓa da sarrafa su nan da nan. Bisa ga ma'auni, lambar tashar da aka yi amfani da ita don aikawa ko karɓar rafin RTP dole ne ta kasance daidai.

A cikin yanayin da ba za a iya sanin adireshin mai karɓa ba tukuna, ana amfani da sabar sabar inda masu karɓa suka bar adireshinsu, kuma mai watsawa na iya buƙace shi ta hanyar yin nuni ga wani suna na musamman na mai karɓar.

A lokuta da ba a san ingancin tashar sadarwa ko kuma ƙarfin mai karɓa ba, ana shirya tashar amsawa ta hanyar da mai karɓa zai iya sanar da mai watsawa game da damarsa, adadin fakitin da ya ɓace, da dai sauransu. Wannan tashar tana amfani da ka'idar RTCP. An bayyana tsarin fakitin da ake watsawa a cikin wannan tashar a cikin RFC 3605. Dan kadan ana watsa bayanai akan wannan tashar, 200..300 bytes a sakan daya, don haka gaba ɗaya, kasancewarsa ba ta da nauyi. Lambar tashar da aka aika fakitin RTCP zuwa gare ta dole ne ta kasance mara kyau kuma wacce ta fi lambar tashar tashar da rafin RTP ke fitowa. A cikin misalinmu, ba za mu yi amfani da wannan tashar ba, tunda iyawar mai karɓa da tashoshi a fili ya wuce bukatunmu, har zuwa yanzu.

A cikin shirin namu, za a raba da’irar watsa bayanai, sabanin misalin da ya gabata, zuwa kashi biyu: hanyar watsawa da hanyar karba. Ga kowane bangare za mu yi namu tushen agogo, kamar yadda aka nuna a hoton take.

Za a gudanar da sadarwa ta hanya ɗaya a tsakanin su ta amfani da ka'idar RTP. A cikin wannan misali, ba ma buƙatar hanyar sadarwa ta waje, tun da duka mai watsawa da mai karɓa za su kasance a kan kwamfuta ɗaya - fakitin za su yi tafiya a ciki.

Don kafa rafin RTP, mai watsa shirye-shiryen watsa labarai yana amfani da filtata biyu: MS_RTP_SEND da MS_RTP_RECV. Na farko yana watsa na biyu kuma yana karɓar rafin RTP. Domin waɗannan masu tacewa suyi aiki, suna buƙatar ƙaddamar da ma'ana zuwa abu na zaman RTP, wanda zai iya ko dai ya canza rafi na tubalan bayanai zuwa rafi na fakitin RTP ko yin akasin haka. Tunda tsarin bayanan cikin gida na mai rafi mai ratsawa bai yi daidai da tsarin bayanan fakitin RTP ba, kafin canja wurin bayanai zuwa MS_RTP_SEND, kuna buƙatar amfani da tacewa mai ɓoyewa wanda ke juyar da samfuran siginar sauti 16-bit zuwa XNUMX-bit da aka rufaffen bisa ga u-law (mu-law). A gefen karɓa, tace mai ƙaddamarwa yana yin kishiyar aikin.

Da ke ƙasa akwai rubutun shirin wanda ke aiwatar da makircin da aka nuna a cikin adadi (alamomin # kafin a cire umarnin, kar a manta ku haɗa su):

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

Muna tattarawa da gudu. Shirin zai yi aiki kamar misalin da ya gabata, amma za a watsa bayanan ta hanyar rafi na RTP.

A cikin kasida ta gaba za mu raba wannan shirin zuwa aikace-aikace masu zaman kansu guda biyu - na'ura mai karɓa da na'urar watsawa da ƙaddamar da su a cikin tashoshi daban-daban. A lokaci guda, za mu koyi yadda ake nazarin fakitin RTP ta amfani da shirin TShark.

source: www.habr.com

Add a comment