Sahaminta mashiinka Mediastreamer2 VoIP. Qaybta 9

Nuxurka maqaalku waxa aan ka soo qaatay kanaalka zen.

Duplex intercom

Sahaminta mashiinka Mediastreamer2 VoIP. Qaybta 9

Waagii hore maqaal intercom-ka duplex ayaa lagu dhawaaqay, middan ayaanu ku samayn doonaa.

Jaantuska waxa lagu muujiyay shaxanka cinwaanka. Silsiladda hoose ee filtarrada ayaa qaabeeya jidka gudbinta, kaas oo ka bilaabma kaadhka codka. Waxay bixisaa muunado signal ka makarafoonka. Sida caadiga ah, tani waxay ku dhacdaa qiyaasta 8000 oo muunado ilbiriqsikii. Qoto dheer ee xogta ee miirayaasha maqalka streamer ay isticmaalaan waa 16 bits (tani muhiim maaha; haddii aad rabto, waxaad qori kartaa filtarrada la shaqeyn doona qoto dheer oo sare). Xogta waxa loo qaybiyay baloogyo 160 muunado ah. Sidaa darteed, baloog kasta wuxuu cabbirkiisu yahay 320 bytes. Marka xigta, waxaan ku quudineynaa xogta soo-gelinta koronto-dhaliyaha, kaas oo, marka la damiyo, waa "caddaan" xogta. Waxaan ku daray haddii ay dhacdo inaad ku daashid inaad ku hadasho makarafoonka inta lagu jiro khaladaadka - waxaad isticmaali kartaa koronto-dhaliye si aad u "toogto" waddada adoo wata calaamad dhawaaq.

Koronto-dhaliye ka bacdi, signalku waxa uu tagayaa encoder-ka, kaas oo u beddela muunadyadayada 16-bit sida uu qabo sharciga μ-law (G.711 standard) una beddela kuwa siddeed-bit ah. Marka la soo saaro cod-bixiyaha, waxaanu hore u haysanay xog xannibaysa cabbirka kala badh. Guud ahaan, waxaan gudbin karnaa xogta iyada oo aan la xakameynin haddii aanaan u baahnayn inaan badbaadino taraafikada. Laakiin halkan waa faa'iido leh in la isticmaalo cod-bixiyaha, maadaama Wireshark ay dib u soo saari karto maqalka qulqulka RTP kaliya marka la cadaadiyo si waafaqsan sharciga µ-law ama a-law.

Codeeyaha ka dib, xogta khafiifka ah ee xogta waxaa loo diraa filtarka rtpsend, kaas oo ku ridi doona xirmo RTP ah, dejin doona calamada lagama maarmaanka ah oo siin doona qulqulka warbaahinta si loogu gudbiyo shabakada qaab xirmo UDP ah.

Silsiladda sare ee filtarrada ayaa qaabeeya dariiqa qaabilaadda; Xirmooyinka RTP ee ay ka helaan streamer-ka shabakadda waxay galaan shaandhada rtprecv, marka la soo saaro kuwaas oo u muuqda qaab blocks xogta, mid kasta oo ka mid ah wuxuu u dhigmaa mid la helay. Balooggu waxa uu ka kooban yahay oo kaliya xogta culeyska; Maqaalkii hore waxaa lagu muujiyay cagaar sawirka.

Marka xigta, baloogyada waxaa loo diraa filter-ka-dejiyaha, kaas oo u beddelaya muunadaha hal-byte ee ku jira iyaga oo u beddelaya kuwa toosan, 16-bit. Kaas oo mar hore lagu farsamayn karo filtarrada streamer media. Xaaladeena, waxaan si fudud ugu direynaa kaadhka codka si ay dib ugu soo celiyaan sameecadaha dhegahaaga.

Hadda aan u gudubno hirgelinta software. Si tan loo sameeyo, waxaan isku dari doonaa aqbalaha iyo gudbinta faylalka aan horay u kala soocnay. Taas ka hor, waxaan u isticmaalnay goobo go'an oo loogu talagalay dekedaha iyo cinwaannada, laakiin hadda waxaan u baahanahay barnaamijka si uu u awoodo inuu isticmaalo goobaha aan ku qeexnay bilowga. Si tan loo sameeyo, waxaan ku dari doonaa shaqeynta habaynta xujooyinka khadka taliska. Taas ka dib waxaan awoodi doonaa inaan dejino cinwaanka IP-ga iyo dekedda intercom-ka ee aan rabno inaan xiriir la sameyno.

Marka hore, aan ku darno qaab dhismeedka barnaamijka oo kaydin doona dejintiisa:

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

typedef struct _app_vars app_vars;

Barnaamijku wuxuu ku dhawaaqi doonaa qaab-dhismeedka noocaan ah ee loo yaqaan vars.
Marka xigta, aan ku darno shaqo si aan u kala saarno xujooyinka khadka taliska:

/* Функция преобразования аргументов командной строки в
* настройки программы. */
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]);
        }
    }
}

Natiijooyinka kala-soocidda, doodaha khadka taliska waxaa lagu dhejin doonaa goobaha qaab dhismeedka vars. Shaqada ugu weyn ee arjigu waxay noqon doontaa in la ururiyo gudbinta iyo helitaanka waddooyinka filtarrada; ka dib marka la isku xidho calaamadeeyaha, xakamaynta waxaa loo wareejin doonaa wareeg aan dhammaad lahayn, kaas oo, haddii inta jeer ee koronto-dhaliyaha loo dejiyay mid aan eber ahayn, wuxuu dib u bilaabi doonaa koronto dhaliyaha tijaabada si markaa iyada oo aan joojinayn ayay shaqaysaa.

Koronto-dhaliye wuxuu u baahan doonaa dib-u-kicinta naqshadiisa awgeed; sababo jira awgeed ma soo saari karo calaamad soconaysa in ka badan 16 ilbiriqsi. Waa in la ogaadaa in muddada ay ku qeexan tahay lambar 32-bit ah.

Barnaamijka oo dhami wuxuu u ekaan doonaa sidan:

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

Aan soo ururinno. Markaa barnaamijka waxa lagu shaqayn karaa laba kombayuutar. Ama mid, sida aan hadda samayn doono. Waxaan ku bilownay TShark doodaha soo socda:

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

Haddii goobta furitaanka ee konsole kaliya ay soo bandhigto fariin ku saabsan bilawga qabashada, markaa tani waa calaamad wanaagsan - waxay la macno tahay dekeddeenu waxay u badan tahay inaysan ku jirin barnaamijyada kale. Terminal kale, waxaanu ku bilaabaynaa tusaale barnaamij kaas oo u ekaan doona intercom-ka “fog” anaga oo tilmaamaya nambarkan dekeda:

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

Sida laga arki karo qoraalka barnaamijka, cinwaanka IP-ga caadiga ah waa 127.0.0.1 (loopback maxalli ah).

Terminal kale, waxaan bilaabeynaa barnaamijka labaad ee barnaamijka, kaas oo u dhigma qalab maxalli ah. Waxaan isticmaalnaa dood dheeri ah oo u oggolaanaysa koronto-dhaliyaha tijaabada ku dhex jira inuu shaqeeyo:

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

Waqtigan xaadirka ah, xirmooyinka loo gudbiyo aaladda "remote" waa inay bilaabaan inay ku dhex dhalaaliyaan console-ka TShark, cod joogto ah ayaa laga maqli doonaa ku hadla kombayutarka.

Haddii wax waliba u dhaceen sida qoran, ka dibna waxaan dib u bilaabaynaa nuqulka labaad ee barnaamijka, laakiin iyada oo aan furaha iyo doodaha "- Gen 440". Hadda waxaad ciyaari doontaa doorka koronto-dhaliye. Taas ka dib, waxaad samayn kartaa buuqa makarafoonka; waa inaad maqashaa codka u dhigma ee ku hadlaaya ama taleefoonnada gacanta. Is kicinta acoustic ayaa laga yaabaa inay xitaa dhacdo; hoos u dhig mugga hadlaya saameyntuna way baabi'i doontaa.

Haddii aad ku orday laba kombiyuutar oo aadan ku wareerin cinwaanada IP-ga, markaa isla natiijada ayaa ku sugaysa - isgaarsiinta codka tayada leh ee laba-dhinac ah.

Maqaalka soo socda waxaan ku baran doonaa sida loo qoro filtarrada noo gaar ah - plugins, mahad xirfad this aad awoodi doontaa inaad isticmaasho streamer warbaahinta ma aha oo kaliya audio iyo video, laakiin sidoo kale qaar ka mid ah meelaha kale oo gaar ah.

Source: www.habr.com

Add a comment