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

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

Ile oloke meji intercom

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

Ni ikẹhin article intercom duplex ti kede, ati ninu eyi a yoo ṣe.

Aworan naa han ninu eeya akọle. Ẹwọn kekere ti awọn asẹ jẹ ọna gbigbe, eyiti o bẹrẹ lati kaadi ohun. O pese awọn ayẹwo ifihan agbara lati gbohungbohun. Nipa aiyipada, eyi waye ni iwọn awọn ayẹwo 8000 fun iṣẹju kan. Ijinle bit data ti awọn asẹ ohun afetigbọ media ṣiṣan lo jẹ awọn iwọn 16 (eyi ko ṣe pataki; ti o ba fẹ, o le kọ awọn asẹ ti yoo ṣiṣẹ pẹlu ijinle bit ti o ga julọ). Awọn data ti wa ni akojọpọ si awọn bulọọki ti awọn ayẹwo 160. Nitorinaa, bulọọki kọọkan jẹ 320 baiti ni iwọn. Nigbamii ti, a jẹun data naa si titẹ sii ti monomono, eyiti, nigbati o ba wa ni pipa, jẹ "sihin" si data naa. Mo ṣafikun rẹ ti o ba rẹwẹsi lati sọrọ sinu gbohungbohun lakoko ti n ṣatunṣe aṣiṣe - o le lo monomono lati “tu” ọna pẹlu ifihan ohun orin kan.

Lẹhin olupilẹṣẹ, ifihan agbara naa lọ si koodu koodu, eyiti o yi awọn ayẹwo 16-bit wa pada ni ibamu si ofin µ-ofin (ọṣewọn G.711) si awọn iwọn mẹjọ-mẹjọ. Ni abajade ti kooduopo, a ti ni dina data kan idaji iwọn. Ni gbogbogbo, a le atagba data laisi funmorawon ti a ko ba nilo lati fi ijabọ pamọ. Ṣugbọn nibi o wulo lati lo koodu koodu kan, nitori Wireshark le ṣe ẹda ohun lati inu ṣiṣan RTP nikan nigbati o ba wa ni fisinuirindigbindigbin ni ibamu si µ-ofin tabi a-ofin.

Lẹhin kooduopo, awọn bulọọki fẹẹrẹfẹ ti data ni a firanṣẹ si àlẹmọ rtpsend, eyiti yoo fi wọn sinu apo RTP kan, ṣeto awọn asia to wulo ati fun wọn si ṣiṣan media fun gbigbe lori nẹtiwọọki ni irisi apo UDP kan.

Ẹwọn oke ti awọn asẹ jẹ ọna gbigba; Awọn apo-iwe RTP ti o gba nipasẹ ṣiṣan media lati inu nẹtiwọọki tẹ àlẹmọ rtprecv, ni iṣelọpọ eyiti wọn han ni irisi awọn bulọọki data, ọkọọkan eyiti o baamu si apo-iwe kan ti o gba. Bulọọki naa ni data isanwo isanwo nikan; ninu nkan iṣaaju wọn fihan ni alawọ ewe ninu apejuwe naa.

Nigbamii ti, awọn bulọọki naa ni a fi ranṣẹ si àlẹmọ decoder, eyiti o yi awọn ayẹwo-baiti kan ti o wa ninu wọn pada si laini, awọn 16-bit. Eyi ti o le ti ni ilọsiwaju tẹlẹ nipasẹ awọn asẹ ṣiṣan media. Ninu ọran wa, a kan fi wọn ranṣẹ si kaadi ohun fun ṣiṣiṣẹsẹhin lori awọn agbohunsoke ti agbekọri rẹ.

Bayi jẹ ki a lọ si imuse software. Lati ṣe eyi, a yoo darapọ olugba ati awọn faili atagba ti a yapa tẹlẹ. Ṣaaju eyi, a lo awọn eto ti o wa titi fun awọn ebute oko oju omi ati awọn adirẹsi, ṣugbọn nisisiyi a nilo eto naa lati ni anfani lati lo awọn eto ti a pato ni ibẹrẹ. Lati ṣe eyi, a yoo ṣafikun iṣẹ ṣiṣe fun ṣiṣe awọn ariyanjiyan laini aṣẹ. Lẹhin eyi a yoo ni anfani lati ṣeto adiresi IP ati ibudo ti intercom pẹlu eyiti a fẹ fi idi asopọ kan mulẹ.

Ni akọkọ, jẹ ki a ṣafikun eto kan si eto ti yoo tọju awọn eto rẹ:

struct _app_vars
{
  int  local_port;              /* Локальный порт. */
  int  remote_port;             /* Порт переговорного устройства на удаленном компьютере. */
  char remote_addr[128];        /* IP-адрес удаленного компьютера. */
  MSDtmfGenCustomTone dtmf_cfg; /* Настройки тестового сигнала генератора. */
};

typedef struct _app_vars app_vars;

Eto naa yoo kede eto iru ti a pe ni vars.
Nigbamii, jẹ ki a ṣafikun iṣẹ kan lati ṣe itupalẹ awọn ariyanjiyan laini aṣẹ:

/* Функция преобразования аргументов командной строки в
* настройки программы. */
void  scan_args(int argc, char *argv[], app_vars *v)
{
    char i;
    for (i=0; i<argc; i++)
    {
        if (!strcmp(argv[i], "--help"))
        {
            char *p=argv[0]; p=p + 2;
            printf("  %s walkie talkienn", p);
            printf("--help      List of options.n");
            printf("--version   Version of application.n");
            printf("--addr      Remote abonent IP address string.n");
            printf("--port      Remote abonent port number.n");
            printf("--lport     Local port number.n");
            printf("--gen       Generator frequency.n");
            exit(0);
        }

        if (!strcmp(argv[i], "--version"))
        {
            printf("0.1n");
            exit(0);
        }

        if (!strcmp(argv[i], "--addr"))
        {
            strncpy(v->remote_addr, argv[i+1], 16);
            v->remote_addr[16]=0;
            printf("remote addr: %sn", v->remote_addr);
        }

        if (!strcmp(argv[i], "--port"))
        {
            v->remote_port=atoi(argv[i+1]);
            printf("remote port: %in", v->remote_port);
        }

        if (!strcmp(argv[i], "--lport"))
        {
            v->local_port=atoi(argv[i+1]);
            printf("local port : %in", v->local_port);
        }

        if (!strcmp(argv[i], "--gen"))
        {
            v -> dtmf_cfg.frequencies[0] = atoi(argv[i+1]);
                printf("gen freq : %in", v -> dtmf_cfg.frequencies[0]);
        }
    }
}

Bi abajade ti itupalẹ, awọn ariyanjiyan laini aṣẹ yoo gbe si awọn aaye ti eto vars. Iṣẹ akọkọ ti ohun elo yoo jẹ lati gba gbigbe ati gbigba awọn ọna lati awọn asẹ; lẹhin sisopọ ami-ami, iṣakoso yoo gbe lọ si lupu ailopin eyiti, ti o ba ṣeto igbohunsafẹfẹ monomono si ti kii ṣe odo, yoo tun bẹrẹ olupilẹṣẹ idanwo naa ki o ṣiṣẹ lai duro.

Olupilẹṣẹ yoo nilo awọn atunbere wọnyi nitori apẹrẹ rẹ; fun idi kan ko le gbe ifihan kan ti o pẹ diẹ sii ju awọn aaya 16 lọ. O yẹ ki o ṣe akiyesi pe iye akoko rẹ jẹ pato nipasẹ nọmba 32-bit kan.

Gbogbo eto yoo dabi eyi:

/* Файл mstest8.c Имитатор переговорного устройства. */

#include <mediastreamer2/mssndcard.h>
#include <mediastreamer2/dtmfgen.h>
#include <mediastreamer2/msrtp.h>

/* Подключаем файл общих функций. */
#include "mstest_common.c"

/*----------------------------------------------------------*/
struct _app_vars
{
    int  local_port;              /* Локальный порт. */
    int  remote_port;             /* Порт переговорного устройства на удаленном компьютере. */
    char remote_addr[128];        /* IP-адрес удаленного компьютера. */
    MSDtmfGenCustomTone dtmf_cfg; /* Настройки тестового сигнала генератора. */
};

typedef struct _app_vars app_vars;

/*----------------------------------------------------------*/
/* Создаем дуплексную RTP-сессию. */
RtpSession* create_duplex_rtp_session(app_vars v)
{
    RtpSession *session = create_rtpsession (v.local_port, v.local_port + 1, FALSE, RTP_SESSION_SENDRECV);
    rtp_session_set_remote_addr_and_port(session, v.remote_addr, v.remote_port, v.remote_port + 1);
    rtp_session_set_send_payload_type(session, PCMU);
    return session;
}

/*----------------------------------------------------------*/
/* Функция преобразования аргументов командной строки в
* настройки программы. */
void  scan_args(int argc, char *argv[], app_vars *v)
{
    char i;
    for (i=0; i<argc; i++)
    {
        if (!strcmp(argv[i], "--help"))
        {
            char *p=argv[0]; p=p + 2;
            printf("  %s walkie talkienn", p);
            printf("--help      List of options.n");
            printf("--version   Version of application.n");
            printf("--addr      Remote abonent IP address string.n");
            printf("--port      Remote abonent port number.n");
            printf("--lport     Local port number.n");
            printf("--gen       Generator frequency.n");
            exit(0);
        }

        if (!strcmp(argv[i], "--version"))
        {
            printf("0.1n");
            exit(0);
        }

        if (!strcmp(argv[i], "--addr"))
        {
            strncpy(v->remote_addr, argv[i+1], 16);
            v->remote_addr[16]=0;
            printf("remote addr: %sn", v->remote_addr);
        }

        if (!strcmp(argv[i], "--port"))
        {
            v->remote_port=atoi(argv[i+1]);
            printf("remote port: %in", v->remote_port);
        }

        if (!strcmp(argv[i], "--lport"))
        {
            v->local_port=atoi(argv[i+1]);
            printf("local port : %in", v->local_port);
        }

        if (!strcmp(argv[i], "--gen"))
        {
            v -> dtmf_cfg.frequencies[0] = atoi(argv[i+1]);
                printf("gen freq : %in", v -> dtmf_cfg.frequencies[0]);
        }
    }
}

/*----------------------------------------------------------*/
int main(int argc, char *argv[])
{
    /* Устанавливаем настройки по умолчанию. */
    app_vars vars={5004, 7010, "127.0.0.1", {0}};

    /* Устанавливаем настройки настройки программы в
     * соответствии с аргументами командной строки. */
    scan_args(argc, argv, &vars);

    ms_init();

    /* Создаем экземпляры фильтров передающего тракта. */
    MSSndCard *snd_card =
        ms_snd_card_manager_get_default_card(ms_snd_card_manager_get());
    MSFilter *snd_card_read = ms_snd_card_create_reader(snd_card);
    MSFilter *dtmfgen = ms_filter_new(MS_DTMF_GEN_ID);
    MSFilter *rtpsend = ms_filter_new(MS_RTP_SEND_ID);

    /* Создаем фильтр кодера. */
    MSFilter *encoder = ms_filter_create_encoder("PCMU");

    /* Регистрируем типы нагрузки. */
    register_payloads();

    /* Создаем дуплексную RTP-сессию. */
    RtpSession* rtp_session= create_duplex_rtp_session(vars);
    ms_filter_call_method(rtpsend, MS_RTP_SEND_SET_SESSION, rtp_session);

    /* Соединяем фильтры передатчика. */
    ms_filter_link(snd_card_read, 0, dtmfgen, 0);
    ms_filter_link(dtmfgen, 0, encoder, 0);
    ms_filter_link(encoder, 0, rtpsend, 0);

    /* Создаем фильтры приемного тракта. */
    MSFilter *rtprecv = ms_filter_new(MS_RTP_RECV_ID);
    ms_filter_call_method(rtprecv, MS_RTP_RECV_SET_SESSION, rtp_session);

    /* Создаем фильтр декодера, */
    MSFilter *decoder=ms_filter_create_decoder("PCMU");

    /* Создаем фильтр звуковой карты. */
    MSFilter *snd_card_write = ms_snd_card_create_writer(snd_card);

    /* Соединяем фильтры приёмного тракта. */
    ms_filter_link(rtprecv, 0, decoder, 0);
    ms_filter_link(decoder, 0,  snd_card_write, 0);

    /* Создаем источник тактов - тикер. */
    MSTicker *ticker = ms_ticker_new();

    /* Подключаем источник тактов. */
    ms_ticker_attach(ticker, snd_card_read);
    ms_ticker_attach(ticker, rtprecv);

    /* Если настройка частоты генератора отлична от нуля, то запускаем генератор. */   
    if (vars.dtmf_cfg.frequencies[0])
    {
        /* Настраиваем структуру, управляющую выходным сигналом генератора. */
        vars.dtmf_cfg.duration = 10000;
        vars.dtmf_cfg.amplitude = 1.0;
    }

    /* Организуем цикл перезапуска генератора. */
    while(TRUE)
    {
        if(vars.dtmf_cfg.frequencies[0])
        {
            /* Включаем звуковой генератор. */
            ms_filter_call_method(dtmfgen, MS_DTMF_GEN_PLAY_CUSTOM,
                    (void*)&vars.dtmf_cfg);
        }
        /* Укладываем тред в спячку на 20мс, чтобы другие треды
         * приложения получили время на работу. */
        ms_usleep(20000);
    }
}

Jẹ ki a ṣe akopọ. Lẹhinna eto naa le ṣiṣẹ lori awọn kọnputa meji. Tabi lori ọkan, bi Emi yoo ṣe ni bayi. A ṣe ifilọlẹ TShark pẹlu awọn ariyanjiyan wọnyi:

$ sudo tshark -i lo -f "udp dst port 7010" -P -V -O RTP -o rtp.heuristic_rtp:TRUE -x

Ti aaye ifilọlẹ ninu console nikan ṣafihan ifiranṣẹ kan nipa ibẹrẹ gbigba, lẹhinna eyi jẹ ami ti o dara - o tumọ si pe ibudo wa ko ṣee gba nipasẹ awọn eto miiran. Ni ebute miiran, a ṣe ifilọlẹ apẹẹrẹ eto kan ti yoo ṣe afiwe intercom “latọna” nipa sisọ nọmba ibudo yii pato:

$ ./mstest8 --port 9010 --lport 7010

Gẹgẹbi a ti le rii lati ọrọ eto, adiresi IP aiyipada jẹ 127.0.0.1 (loopback agbegbe).

Ni ebute miiran, a ṣe ifilọlẹ apẹẹrẹ keji ti eto naa, eyiti o ṣe adaṣe ẹrọ agbegbe kan. A lo afikun ariyanjiyan ti o fun laaye olupilẹṣẹ idanwo inu lati ṣiṣẹ:

$ ./mstest8  --port 7010 --lport 9010 --gen 440

Ni akoko yii, awọn apo-iwe ti o tan kaakiri si ẹrọ “latọna jijin” yẹ ki o bẹrẹ lati filasi ninu console pẹlu TShark, ati pe ohun orin lilọsiwaju yoo gbọ lati ọdọ agbọrọsọ kọnputa.

Ti ohun gbogbo ba ṣẹlẹ bi a ti kọ, lẹhinna a tun bẹrẹ ẹda keji ti eto naa, ṣugbọn laisi bọtini ati ariyanjiyan “—gen 440”. O yoo bayi mu awọn ipa ti monomono. Lẹhin eyi, o le ṣe ariwo sinu gbohungbohun; o yẹ ki o gbọ ohun ti o baamu ninu agbọrọsọ tabi agbekọri. Idunnu ara-ẹni Acoustic le paapaa waye; fi iwọn didun agbọrọsọ silẹ ati pe ipa naa yoo parẹ.

Ti o ba ṣiṣẹ lori awọn kọnputa meji ati pe ko ni idamu nipa awọn adirẹsi IP, lẹhinna abajade kanna n duro de ọ - ibaraẹnisọrọ ohun didara oni-nọmba meji-ọna.

Ninu nkan ti o tẹle a yoo kọ bi a ṣe le kọ awọn asẹ tiwa - awọn afikun, o ṣeun si ọgbọn yii iwọ yoo ni anfani lati lo ṣiṣan media kii ṣe fun ohun ati fidio nikan, ṣugbọn tun ni agbegbe kan pato miiran.

orisun: www.habr.com

Fi ọrọìwòye kun