Mikaroka ny motera Mediastreamer2 VoIP. Fizarana 9

Ny fitaovan'ny lahatsoratra dia nalaina avy amin'ny ahy fantsona zen.

Duplex intercom

Mikaroka ny motera Mediastreamer2 VoIP. Fizarana 9

Amin'ny farany lahatsoratra Nisy intercom duplex nambara, ary amin'ity iray ity dia hanao izany izahay.

Ny kisary dia aseho amin'ny sarin'ny lohateny. Ny rojo sivana ambany dia mamorona ny lalan'ny fifindrana, izay manomboka amin'ny karatra fanamafisam-peo. Izy io dia manome santionany famantarana avy amin'ny mikrΓ΄. Amin'ny alΓ lan'ny default, izany dia mitranga amin'ny tahan'ny santionany 8000 isan-tsegondra. Ny halalin'ny angon-drakitra ampiasain'ny sivana audio streamer dia 16 bits (tsy zava-dehibe izany, raha tianao dia azonao atao ny manoratra sivana izay hiasa amin'ny halalin'ny kely kokoa). Ny angon-drakitra dia navondrona ho blocs misy santionany 160. Noho izany, ny bloc tsirairay dia 320 bytes ny habeny. Manaraka, mamahana ny angon-drakitra amin'ny fampidirana ny mpamokatra, izay, rehefa tapaka, dia "mangarahara" amin'ny data. Nampiako izany raha toa ka reraky ny miresaka amin'ny mikrΓ΄ ianao mandritra ny debugging - azonao atao ny mampiasa ny gropy mba "hitifitra" ny lalana miaraka amin'ny mari-pamantarana feo.

Aorian'ny famokarana, ny famantarana dia mankany amin'ny encoder, izay mamadika ny santionany 16-bit araka ny lalΓ na Β΅ (G.711 standard) ho lasa valo-bit. Amin'ny fivoahan'ny encoder dia efa manana sakana angon-drakitra ny antsasaky ny habeny. Amin'ny ankapobeny, afaka mamindra angona tsy misy famoretana isika raha tsy mila mitsitsy fifamoivoizana. Fa eto dia ilaina ny mampiasa encoder, satria Wireshark dia afaka mamerina feo avy amin'ny RTP stream raha tsy rehefa voatsindry araka ny Β΅-lalΓ na na a-lalΓ na.

Aorian'ny encoder dia alefa any amin'ny sivana rtpsend ireo sakana maivana kokoa, izay hametraka azy ireo ao anaty fonosana RTP, mametraka ny saina ilaina ary manome azy ireo amin'ny streamer media ho an'ny fampitana amin'ny tambajotra amin'ny endrika fonosana UDP.

Ny rojo sivana ambony dia mamorona ny lalana fandraisana; Ny fonosana RTP noraisin'ny media streamer avy amin'ny tambajotra dia miditra amin'ny sivana rtprecv, amin'ny famoahana azy ireo amin'ny endrika sakana data, izay mifanaraka amin'ny fonosana iray voaray. Ny sakana dia tsy misy afa-tsy angon-drakitra momba ny karama; tao amin'ny lahatsoratra teo aloha dia naseho tamin'ny maitso izy ireo tamin'ny sary.

Avy eo dia alefa any amin'ny sivana decoder ireo sakana, izay mamadika ireo santionany tokana misy ao aminy ho lasa tsipika, 16-bit. Izay efa azo karakarain'ny sivana streamer media. Amin'ny tranga misy anay, alefanay any amin'ny karatra fanamafisam-peo fotsiny izy ireo mba hamerenana amin'ny fanamafisam-peo amin'ny headset.

Andeha isika hiroso amin'ny fampiharana rindrambaiko. Mba hanaovana izany, dia hanambatra ny fisie mpandray sy mpandefa izay nosarahanay taloha. Talohan'izay dia nampiasa rindrankajy raikitra ho an'ny seranan-tsambo sy adiresy izahay, fa ankehitriny dia mila ny programa izahay mba hahafahana mampiasa ny toe-javatra voafaritra amin'ny fanombohana. Mba hanaovana izany, dia hanampy fampiasa amin'ny fanodinana ny tohan-kevitra andalana baiko. Aorian'izay dia ho afaka hametraka ny adiresy IP sy ny seranan-tsambon'ny intercom izay tiantsika hanorina fifandraisana.

Voalohany, andeha isika hanampy rafitra iray amin'ny programa izay hitahiry ny firafiny:

struct _app_vars
{
  int  local_port;              /* Π›ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ ΠΏΠΎΡ€Ρ‚. */
  int  remote_port;             /* ΠŸΠΎΡ€Ρ‚ ΠΏΠ΅Ρ€Π΅Π³ΠΎΠ²ΠΎΡ€Π½ΠΎΠ³ΠΎ устройства Π½Π° ΡƒΠ΄Π°Π»Π΅Π½Π½ΠΎΠΌ ΠΊΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€Π΅. */
  char remote_addr[128];        /* IP-адрСс ΡƒΠ΄Π°Π»Π΅Π½Π½ΠΎΠ³ΠΎ ΠΊΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€Π°. */
  MSDtmfGenCustomTone dtmf_cfg; /* Настройки тСстового сигнала Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€Π°. */
};

typedef struct _app_vars app_vars;

Ny programa dia hanambara rafitra iray amin'ity karazana antsoina hoe vars.
Manaraka, ndao ampio asa iray handinihana ny arguments command line:

/* Ѐункция прСобразования Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠ² ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строки Π²
* настройки ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹. */
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]);
        }
    }
}

Vokatry ny famakafakana dia hapetraka ao amin'ny sahan'ny firafitry ny vars ny tohan-kevitra andalana baiko. Ny tena anjara asan'ny fampiharana dia ny hanangona ny fampitana sy ny fandraisana lalana avy amin'ny sivana; aorian'ny fampifandraisana ny ticker, ny fanaraha-maso dia hafindra amin'ny loop tsy manam-petra izay, raha toa ka napetraka amin'ny tsy aotra ny fatran'ny mpamokatra, dia hamerina indray ny mpamokatra fitsapana ka miasa tsy miato.

Ny mpamokatra dia mila ireo famerenana ireo noho ny famolavolana azy; noho ny antony tsy ahafahany mamoaka famantarana maharitra mihoatra ny 16 segondra. Tsara homarihina fa ny faharetany dia voafaritra amin'ny isa 32-bit.

Ny fandaharana manontolo dia ho toy izao:

/* Π€Π°ΠΉΠ» 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);
    }
}

Andao hanangona. Avy eo dia azo atao amin'ny ordinatera roa ny programa. Na amin'ny iray, toy ny hataoko izao. Manomboka TShark miaraka amin'ireto hevitra manaraka ireto izahay:

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

Raha ny sahan'ny fanombohana ao amin'ny console ihany no mampiseho hafatra momba ny fanombohan'ny fisamborana, dia famantarana tsara izany - midika izany fa ny seranan-tsambontsika dia azo inoana fa tsy misy programa hafa. Ao amin'ny terminal iray hafa, dia manomboka programa iray izahay izay hanahaka ny intercom "lavitra" amin'ny alΓ lan'ny famaritana ity laharana seranana ity:

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

Araka ny hita amin'ny lahatsoratry ny programa, ny adiresy IP default dia 127.0.0.1 (loopback eo an-toerana).

Any amin'ny terminal iray hafa, dia manomboka ohatra faharoa amin'ny programa izahay, izay mamolavola fitaovana eo an-toerana. Mampiasa tohan-kevitra fanampiny izahay izay ahafahan'ny mpamokatra fitsapana naorina:

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

Amin'izao fotoana izao, ny fonosana ampitaina mankany amin'ny fitaovana "lavitra" dia tokony hanomboka hikoropaka ao amin'ny console miaraka amin'ny TShark, ary hisy feo mitohy ho re avy amin'ny mpandahateny solosaina.

Raha toa ka nitranga araka ny voasoratra ny zava-drehetra, dia averinay indray ny kopia faharoa amin'ny programa, fa tsy misy ny fanalahidy sy ny tohan-kevitra "-gen 440". Hilalao ny andraikitry ny mpamokatra ianao izao. Aorian'izany dia afaka manao tabataba amin'ny mikrΓ΄ ianao; tokony handre ny feo mifanaraka amin'izany ianao amin'ny fanamafisam-peo na headphone. Mety hitranga mihitsy aza ny fientanam-po amin'ny acoustic; ampidino ny haavon'ny mpandahateny dia hanjavona ny vokany.

Raha mihazakazaka amin'ny solosaina roa ianao ary tsy very hevitra momba ny adiresy IP, dia ny vokatra mitovy ihany no miandry anao - fifandraisana feo nomerika roa.

Ao amin'ny lahatsoratra manaraka dia hianarantsika ny fomba fanoratana ny sivana manokana - plugins, noho io fahaiza-manao io dia ho afaka hampiasa ny streamer amin'ny haino aman-jery ianao tsy ho an'ny feo sy horonan-tsary, fa amin'ny faritra hafa manokana.

Source: www.habr.com

Add a comment