Kuongorora iyo Mediastreamer2 VoIP injini. Chikamu 9

Zvinyorwa zvechinyorwa zvakatorwa kubva kwangu zen channel.

Duplex intercom

Kuongorora iyo Mediastreamer2 VoIP injini. Chikamu 9

Pakupedzisira chinyorwa duplex intercom yakaziviswa, uye mune ino tichaigadzira.

Dhiagiramu inoratidzwa mumufananidzo wemusoro. Iyo yepasi cheni yemasefa inoumba nzira yekutapurirana, iyo inotanga kubva pakadhi rezwi. Inopa sampuli dzechiratidzo kubva kumakrofoni. Nekutadza, izvi zvinoitika pamwero we8000 samples pasekondi. Iyo data bit kudzika iyo media streamer odhiyo mafirita anoshandisa 16 bits (izvi hazvina kukosha; kana uchida, unogona kunyora mafirita anozoshanda nehupamhi hwepamusoro). Iyo data yakakamurwa kuita mabhuroko e160 samples. Saka, chivharo chimwe nechimwe chine 320 bytes muhukuru. Zvadaro, tinodyisa data kune kuiswa kwejenereta, iyo, kana yakadzimwa, "inooneka" kune data. Ndakaiwedzera kana ukaneta nekutaura mumakrofoni panguva yekugadzirisa - unogona kushandisa jenareta "kupfura" nzira nechiratidzo chetoni.

Mushure mejenareta, chiratidzo chinoenda kune encoder, iyo inoshandura yedu 16-bit samples maererano neµ-law (G.711 standard) kuita masere-bit. Pakubuda kweiyo encoder, isu tatova nedata block hafu yehukuru. Kazhinji, tinogona kufambisa data pasina kudzvanywa kana isu tisingade kuchengetedza traffic. Asi pano zvinobatsira kushandisa encoder, sezvo Wireshark ichikwanisa kuburitsa odhiyo kubva kuRTP rukova chete kana yamanikidzwa zvinoenderana neµ-mutemo kana-mutemo.

Mushure meiyo encoder, iwo akareruka mabhuraki e data anotumirwa kune rtpsend sefa, iyo inovaisa muRTP packet, isa mireza inodiwa uye uvape kune midhiya streamer yekufambisa pamusoro petiweki nenzira yeUDP packet.

Iyo yepamusoro cheni yemafirita inoumba nzira yekugamuchira; RTP mapaketi anogamuchirwa ne media streamer kubva kunetiweki anopinda rtprecv sefa, pakubuda kwaanoonekwa muchimiro che data blocks, imwe neimwe inoenderana neyakagamuchirwa pakiti. Iyo block ine chete payload data; mune yapfuura chinyorwa ivo vakaratidzwa mugirinhi mumufananidzo.

Tevere, zvidhinha zvinotumirwa kune decoder sefa, iyo inoshandura ma-single-byte samples arimo kuita mutsara, 16-bit iwo. Iyo inogona kutogadziriswa ne media streamer mafirita. Kwatiri isu, isu tinongovatumira kune kadhi rekurira kuti vatambe pane vatauri vemusoro wako.

Iye zvino ngatiendererei kukushandisa software. Kuti tiite izvi, isu tinosanganisa anogamuchira uye anotapurirana mafaera atakaparadzanisa kare. Izvi zvisati zvaitika, takashandisa zvigadziro zvakagadziriswa zvezvikepe nemakero, asi ikozvino tinoda purogiramu kuti tikwanise kushandisa zvigadziridzo zvatinotsanangura pakutanga. Kuti tiite izvi, isu taizowedzera kushanda kwekugadzirisa mitsetse yemirairo mitsetse. Mushure mezvo tichakwanisa kuseta IP kero uye chiteshi cheintercom chatinoda kumisikidza chinongedzo.

Kutanga, ngatiwedzerei chimiro kuchirongwa chinozochengeta marongero ayo:

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

typedef struct _app_vars app_vars;

Iyo purogiramu ichazivisa chimiro chemhando iyi inonzi vars.
Tevere, ngati wedzera basa kusiyanisa mitsetse yemirairo mitsetse:

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

Nekuda kwekupatsanurwa, mutsara wemirairo nharo uchaiswa muminda yevars chimiro. Basa guru rechishandiso richave rekuunganidza nzira dzekufambisa uye dzekugamuchira kubva kune mafirita; mushure mekubatanidza ticker, kutonga kunoendeswa kune isingaperi loop iyo, kana jenareta frequency yakaiswa kune isiri zero, ichatangazve jenareta rekuyedza kuti inoshanda pasina kumira.

Jenareta inozoda idzi restarts nekuda kwekugadzirwa kwayo; nekuda kwechimwe chikonzero haigone kuburitsa chiratidzo chinogara kupfuura masekonzi gumi nematanhatu. Zvinofanira kucherechedzwa kuti nguva yaro inotsanangurwa nenhamba ye16-bit.

Iyo yose purogiramu ichaita seizvi:

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

Ngatiunganidzei. Zvadaro purogiramu inogona kushandiswa pamakombiyuta maviri. Kana pane imwe, sezvandichaita zvino. Isu tinotangisa TShark nemakakatanwa anotevera:

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

Kana iyo yekutanga nzvimbo mukoni inongoratidza meseji nezve kutanga kubatwa, saka ichi chiratidzo chakanaka - zvinoreva kuti chiteshi chedu chingangove chisina kugarwa nezvimwe zvirongwa. Mune imwe terminal, tinotangisa chiitiko chechirongwa chinozotevedzera "kure" intercom nekutsanangura iyi nhamba yechiteshi:

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

Sezvinogona kuonekwa kubva mumagwaro epurogiramu, kero ye IP yakagara iri 127.0.0.1 (local loopback).

Mune imwe terminal, isu tinotangisa yechipiri chiitiko chechirongwa, chinoteedzera mudziyo wemuno. Isu tinoshandisa imwe nharo inobvumira yakavakirwa-mukati bvunzo jenareta kushanda:

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

Panguva ino, mapaketi anofambiswa akananga kune "kure" mudziyo anofanirwa kutanga kupenya mukoni ine TShark, uye inoenderera toni inonzwika kubva kumutauri wekombuta.

Kana zvinhu zvose zvikaitika sezvakanyorwa, saka tinotangazve kopi yechipiri yepurogiramu, asi pasina kiyi uye nharo "-gen 440". Iwe zvino uchatamba basa rejenareta. Mushure meizvi, unogona kuita ruzha mumaikorofoni; iwe unofanirwa kunzwa ruzha rwunoenderana mutauri kana mahedhifoni. Acoustic self-excitation inogona kutoitika; dzikisa inzwi remutauri uye mhedzisiro yacho inopera.

Kana iwe wakamhanyisa pamakomputa maviri uye ukasavhiringika nezve IP kero, ipapo mhedzisiro yakafanana yakakumirira - nzira mbiri dzedhijitari yemhando yekutaura.

Muchinyorwa chinotevera tichadzidza manyorero edu ega mafirita - plugins, nekuda kwehunyanzvi uhu iwe uchakwanisa kushandisa media streamer kwete chete yekuteerera uye vhidhiyo, asiwo mune imwe nzvimbo chaiyo.

Source: www.habr.com

Voeg