Ke ʻimi nei i ka ʻenekini Mediastreamer2 VoIP. Mahele 9

Lawe ʻia ka mea o ka ʻatikala mai kaʻu zen channel.

Intercom duplex

Ke ʻimi nei i ka ʻenekini Mediastreamer2 VoIP. Mahele 9

I ka hope loa 'ōlelo ua hoʻolaha ʻia kahi intercom duplex, a ma kēia e hana mākou.

Hōʻike ʻia ke kiʻikuhi ma ke poʻo inoa. Hoʻokumu ke kaulahao haʻahaʻa o nā kānana i ke ala hoʻouna, e hoʻomaka ana mai ke kāleka kani. Hāʻawi ia i nā hōʻailona hōʻailona mai ka microphone. Ma ka maʻamau, loaʻa kēia ma kahi o 8000 mau mea hoʻohālike i kekona. ʻO ka hohonu o ka ʻikepili i hoʻohana ʻia e nā kānana leo streamer media he 16 bits (ʻaʻole koʻikoʻi kēia; inā makemake ʻoe, hiki iā ʻoe ke kākau i nā kānana e hana me ka hohonu iki. Hoʻopili ʻia ka ʻikepili i nā poloka o 160 mau laʻana. No laila, he 320 bytes ka nui o kēlā me kēia poloka. A laila, hānai mākou i ka ʻikepili i ka hoʻokomo ʻana o ka generator, i ka wā i hoʻopau ʻia ai, he "transparent" i ka ʻikepili. Ua hoʻohui au iā ia inā e luhi ʻoe i ke kamaʻilio ʻana i ka microphone i ka wā debugging - hiki iā ʻoe ke hoʻohana i ka generator e "pana" i ke ala me kahi hōʻailona leo.

Ma hope o ka mīkini hana, hele ka hōʻailona i ka encoder, nāna e hoʻololi i kā mākou 16-bit samples e like me ke kānāwai µ (G.711 standard) i ʻewalu-bit. Ma ka puka o ka encoder, ua loaʻa iā mākou kahi poloka ʻikepili i ka hapalua o ka nui. Ma keʻano laulā, hiki iā mākou ke hoʻouna i ka ʻikepili me ka ʻole o ke kaomi ʻana inā ʻaʻole pono mākou e mālama i ke kaʻa. Eia nō naʻe he mea pono ke hoʻohana ʻana i kahi encoder, no ka mea hiki iā Wireshark ke hana hou i ka leo mai kahi kahawai RTP wale nō ke hoʻopili ʻia e like me ka µ-law a i ʻole a-law.

Ma hope o ka encoder, hoʻounaʻia nā'āpana māmā o kaʻikepili i ka kānana rtpsend, e hoʻokomo iā lākou i loko o kahi pahu RTP, e hoʻonoho i nā hae e pono ai a hāʻawi iā lākou i ka media streamer no ka hoʻounaʻana ma luna o ka pūnaewele ma keʻano o ka UDP packet.

Hoʻokumu ke kaulahao luna o nā kānana i ke ala e loaʻa ai; ʻO nā ʻeke RTP i loaʻa e ka media streamer mai ka pūnaewele e komo i ka kānana rtprecv, ma ka hopena o lākou e ʻike ʻia ma ke ʻano o nā poloka data, kēlā me kēia mea e pili ana i hoʻokahi ʻeke i loaʻa. Aia i loko o ka poloka ka ʻikepili uku; ma ka ʻatikala mua i hōʻike ʻia lākou i ka ʻōmaʻomaʻo i ke kiʻi.

A laila, hoʻouna ʻia nā poloka i ka kānana decoder, kahi e hoʻohuli ai i nā ʻāpana hoʻokahi-byte i loko o ia mau mea i linear, 16-bit. Hiki ke hana ʻia e nā kānana streamer media. I kā mākou hihia, hoʻouna wale mākou iā lākou i ke kāleka kani no ka pāʻani ʻana ma nā leo o kāu headset.

I kēia manawa e neʻe kākou i ka hoʻokō polokalamu. No ka hana ʻana i kēia, e hoʻohui mākou i nā faila a me nā faila transmitter a mākou i hoʻokaʻawale ai ma mua. Ma mua o kēia, ua hoʻohana mākou i nā hoʻonohonoho paʻa no nā awa a me nā ʻōlelo, akā i kēia manawa pono mākou i ka papahana e hiki ke hoʻohana i nā hoʻonohonoho a mākou i kuhikuhi ai i ka hoʻomaka. No ka hana ʻana i kēia, e hoʻohui mākou i ka hana no ka hoʻoponopono ʻana i nā manaʻo laina kauoha. Ma hope e hiki iā mākou ke hoʻonohonoho i ka IP address a me ke awa o ka intercom a mākou e makemake ai e hoʻokumu i kahi pilina.

ʻO ka mea mua, e hoʻohui i kahi hoʻolālā i ka papahana e mālama i kāna mau hoʻonohonoho:

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

typedef struct _app_vars app_vars;

E haʻi ka papahana i kahi ʻano o kēia ʻano i kapa ʻia he vars.
Ma hope aʻe, e hoʻohui i kahi hana e parse i nā manaʻo laina kauoha:

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

I ka hopena o ka parsing, e hoʻokomo ʻia nā ʻōlelo hoʻopaʻapaʻa laina kauoha ma nā kahua o ka hoʻolālā vars. ʻO ka hana nui o ka noi e hōʻiliʻili i ka hoʻouna ʻana a me ka loaʻa ʻana o nā ala mai nā kānana; ma hope o ka hoʻopili ʻana i ka ticker, e hoʻoneʻe ʻia ka mana i kahi loop palena ʻole, inā i hoʻonohonoho ʻia ka frequency generator i non-zero, e hoʻomaka hou i ka generator hōʻike. hana me ka hooki ole.

Pono ka mīkini hana i kēia mau hoʻomaka hou ʻana ma muli o kāna hoʻolālā; no kekahi kumu ʻaʻole hiki iā ia ke hana i kahi hōʻailona ʻoi aku ma mua o 16 kekona. Pono e hoʻomaopopo ʻia ua kuhikuhi ʻia kona lōʻihi e kahi helu 32-bit.

E like me kēia ka papahana holoʻokoʻa:

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

E houluulu kakou. A laila hiki ke holo ka polokalamu ma nā kamepiula ʻelua. A i ʻole ma kekahi, e like me kaʻu e hana ai i kēia manawa. Hoʻomaka mākou iā TShark me kēia mau manaʻo:

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

Inā hōʻike wale ke kahua hoʻomaka i ka console i kahi leka e pili ana i ka hoʻomaka ʻana o ka hopu ʻana, a laila he hōʻailona maikaʻi kēia - ʻo ia ka mea ʻaʻole i noho ʻia kā mākou awa e nā papahana ʻē aʻe. Ma kahi pahu ʻē aʻe, hoʻomaka mākou i kahi papahana e hoʻohālikelike i kahi intercom "mamao" ma ke kuhikuhi ʻana i kēia helu port:

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

E like me ka ʻike ʻia mai ka kikokikona o ka papahana, ʻo ka helu IP paʻamau ʻo 127.0.0.1 (local loopback).

Ma kahi pahu ʻē aʻe, hoʻomaka mākou i kahi lua o ka papahana, e hoʻohālikelike ana i kahi hāmeʻa kūloko. Hoʻohana mākou i kahi hoʻopaʻapaʻa ʻē aʻe e hiki ai i ka mīkini hoʻāʻo i kūkulu ʻia e hana:

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

I kēia manawa, pono e hoʻomaka nā ʻeke i hoʻouna ʻia i ka hāmeʻa "mamao" i ka console me TShark, a e lohe ʻia kahi leo hoʻomau mai ka leo kamepiula.

Inā hana nā mea a pau e like me ka mea i kākau ʻia, a laila hoʻomaka mākou i ke kope ʻelua o ka papahana, akā me ka ʻole o ke kī a me ka hoʻopaʻapaʻa "-gen 440". E hoʻokani ʻoe i ka hana o ka generator. Ma hope o kēia, hiki iā ʻoe ke hana i ka walaʻau i loko o ka microphone; pono ʻoe e lohe i ke kani kūpono ma ka leo a i ʻole nā ​​​​headheads. Hiki paha ke hoʻohauʻoli iā ia iho; e hoʻemi i ka leo leo a e nalowale ka hopena.

Inā holo ʻoe iā ia ma nā kamepiula ʻelua a ʻaʻole i huikau e pili ana i nā helu IP, a laila ke kali nei ka hopena like iā ʻoe - ʻelua ala ʻelua kamaʻilio leo leo kikohoʻe.

Ma ka ʻatikala aʻe e aʻo mākou pehea e kākau ai i kā mākou mau kānana ponoʻī - nā plugins, mahalo i kēia mākaukau e hiki ai iā ʻoe ke hoʻohana i ka streamer media ʻaʻole wale no ka leo a me ke wikiō, akā ma kekahi wahi kikoʻī.

Source: www.habr.com

Pākuʻi i ka manaʻo hoʻopuka