د Mediastreamer2 VoIP انجن سپړنه. 9 برخه

د مقالې مواد زما څخه اخیستل شوي دي زین چینل.

ډوپلیکس انټرکام

د Mediastreamer2 VoIP انجن سپړنه. 9 برخه

په اخر کې مقالې یو ډوپلیکس انټرکام اعلان شو ، او پدې کې به موږ دا جوړ کړو.

ډیاګرام د سرلیک په شکل کې ښودل شوی. د فلټرونو ښکته زنځیر د لیږد لاره جوړوي، کوم چې د غږ کارت څخه پیل کیږي. دا د مایکروفون څخه سیګنال نمونې چمتو کوي. د ډیفالټ په واسطه، دا په هره ثانیه کې د 8000 نمونو په کچه واقع کیږي. د ډیټا بټ ژوروالی چې د میډیا سټیمر آډیو فلټرونه کاروي 16 بټونه دي (دا مهم ندي؛ که تاسو وغواړئ ، تاسو کولی شئ فلټرونه ولیکئ چې د لوړې بټ ژوروالي سره به کار وکړي). معلومات د 160 نمونو بلاکونو کې ګروپ شوي. په دې توګه، هر بلاک په اندازه کې 320 بایټ دی. بیا، موږ ډاټا د جنراتور ان پټ ته تغذیه کوو، کوم چې کله چې بند شي، ډاټا ته "شفاف" وي. ما دا اضافه کړه په هغه صورت کې چې تاسو د ډیبګ کولو پرمهال مایکروفون کې له خبرو کولو ستړي شوي یاست - تاسو کولی شئ جنریټر وکاروئ ترڅو د ټون سیګنال سره لاره "شوټ" کړئ.

د جنراتور څخه وروسته، سیګنال انکوډر ته ځي، کوم چې زموږ د 16-bit نمونې د µ-قانون (G.711 معیار) سره سم په اتو بټ کې بدلوي. د کوډر په محصول کې، موږ دمخه د ډیټا بلاک نیم اندازه لرو. په عموم کې، موږ کولی شو د کمپریشن پرته ډاټا انتقال کړو که چیرې موږ د ټرافیک خوندي کولو ته اړتیا نلرو. مګر دلته د انکوډر کارول ګټور دي ، ځکه چې ویرشارک کولی شي د RTP جریان څخه آډیو بیا تولید کړي کله چې دا د µ-قانون یا a-قانون سره سم فشار شوی وي.

د کوډر وروسته، د ډیټا روښانه بلاکونه د rtpsend فلټر ته لیږل کیږي، کوم چې به یې د RTP پاکټ کې واچوي، اړین بیرغونه تنظیم کړي او د UDP پاکټ په بڼه د شبکې له لارې د لیږد لپاره میډیا سټیمر ته ورکړي.

د فلټرونو پورتنۍ سلسله د ترلاسه کولو لاره جوړوي؛ د شبکې څخه د میډیا سټیمر لخوا ترلاسه شوي RTP پاکټونه د rtprecv فلټر ته ننوځي، چې په پایله کې دوی د ډیټا بلاکس په بڼه ښکاري، چې هر یو یې د ترلاسه شوي پاکټ سره مطابقت لري. په بلاک کې یوازې د پایلوډ ډیټا شتون لري؛ په تیرو مقاله کې دوی په شنه رنګ کې ښودل شوي.

بیا ، بلاکونه د ډیکوډر فلټر ته لیږل کیږي ، کوم چې په دوی کې موجود واحد بایټ نمونې په خطي ، 16-بټ کې بدلوي. کوم چې دمخه د میډیا سټیمر فلټرونو لخوا پروسس کیدی شي. زموږ په قضیه کې ، موږ دوی په ساده ډول ستاسو د هیډسیټ سپیکرو کې د پلی بیک لپاره غږ کارت ته لیږو.

اوس راځئ چې د سافټویر پلي کولو ته لاړ شو. د دې کولو لپاره، موږ به د رسیدونکي او لیږدونکي فایلونه یوځای کړو چې مخکې مو جلا کړي. مخکې له دې، موږ د بندرونو او پتې لپاره ثابت ترتیبات کاروو، مګر اوس موږ پروګرام ته اړتیا لرو ترڅو د هغه ترتیباتو کارولو وړتیا ولرو چې موږ یې په پیل کې مشخص کوو. د دې کولو لپاره، موږ به د کمانډ لاین دلیلونو پروسس کولو لپاره فعالیت اضافه کړو. له هغې وروسته به موږ وکولی شو د انټرکام IP پته او بندر تنظیم کړو چې موږ ورسره اړیکه رامینځته کول غواړو.

لومړی، راځئ چې پروګرام ته یو جوړښت اضافه کړو چې دا به یې تنظیمات ذخیره کړي:

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

typedef struct _app_vars app_vars;

برنامه به د دې ډول جوړښت اعلان کړي چې vars نومیږي.
بیا ، راځئ چې د کمانډ لاین دلیلونو تحلیل کولو لپاره فنکشن اضافه کړو:

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

د پارس کولو په پایله کې، د کمانډ لاین دلیلونه به د vars جوړښت په برخو کې ځای په ځای شي. د غوښتنلیک اصلي دنده به د فلټرونو څخه د لیږد او ترلاسه کولو لارې راټولول وي؛ د ټیکر سره وصل کیدو وروسته ، کنټرول به لامحدود لوپ ته لیږدول کیږي چې که چیرې د جنراتور فریکوینسي غیر صفر ته ټاکل شوې وي ، نو د ازموینې جنراتور به بیا پیل کړي. دا پرته له ځنډه کار کوي.

جنراتور به د دې ډیزاین له امله دې بیا پیلونو ته اړتیا ولري؛ د ځینې دلیلونو لپاره دا نشي کولی سیګنال تولید کړي چې له 16 ثانیو څخه ډیر دوام وکړي. دا باید په یاد ولرئ چې د هغې موده د 32-bit شمیرې لخوا مشخص شوې.

ټول پروګرام به داسې ښکاري:

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

راځئ چې تالیف وکړو. بیا برنامه په دوه کمپیوټرونو کې پرمخ وړل کیدی شي. یا په یوه کې، لکه څنګه چې زه به اوس وکړم. موږ د لاندې دلیلونو سره TShark پیل کوو:

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

که په کنسول کې د لانچ ساحه یوازې د نیولو پیل په اړه پیغام ښکاره کړي، نو دا یو ښه نښه ده - دا پدې مانا ده چې زموږ بندر ډیری احتمال د نورو برنامو لخوا نیول شوی نه دی. په بل ټرمینل کې، موږ د برنامه بیلګه پیل کوو چې د دې پورټ نمبر په ټاکلو سره به د "ریموټ" انټرکام تقلید وکړي:

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

لکه څنګه چې د پروګرام متن څخه لیدل کیدی شي، د ډیفالټ IP پته 127.0.0.1 (سیمه ایز لوپ بیک) دی.

په بل ټرمینل کې، موږ د برنامه دویمه بیلګه پیل کوو، کوم چې د محلي وسیله سمول کوي. موږ یو اضافي دلیل کاروو چې د جوړ شوي ټیسټ جنریټر کار کولو ته اجازه ورکوي:

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

پدې شیبه کې ، د "ریموټ" وسیلې ته لیږدول شوي پاکټونه باید د TShark سره کنسول کې فلش پیل شي ، او د کمپیوټر سپیکر څخه به دوامداره ټون اوریدل کیږي.

که هرڅه د لیکلو په څیر پیښ شوي وي، نو موږ د پروګرام دویمه کاپي بیا پیل کوو، مګر پرته له کیلي او دلیل "—gen 440". تاسو به اوس د جنراتور رول ولوبوي. له دې وروسته، تاسو کولی شئ په مایکروفون کې شور جوړ کړئ؛ تاسو باید په سپیکر یا هیډفونونو کې ورته غږ واورئ. د اکوسټیک ځان هڅونه حتی پیښ کیدی شي؛ د سپیکر حجم کم کړئ او اغیز به ورک شي.

که تاسو دا په دوه کمپیوټرونو کې چلولی او د IP پتې په اړه مغشوش نه یاست ، نو ورته پایله به تاسو ته په تمه وي - دوه طرفه ډیجیټل کیفیت غږ مواصلات.

په راتلونکې مقاله کې به موږ زده کړو چې څنګه خپل فلټرونه - پلگ انونه ولیکئ، د دې مهارت څخه مننه تاسو به وکولی شئ د میډیا سټیمر نه یوازې د آډیو او ویډیو لپاره ، بلکه په ځینو نورو ځانګړو برخو کې هم وکاروئ.

سرچینه: www.habr.com

Add a comment