Ny fitaovan'ny lahatsoratra dia nalaina avy amin'ny ahy .
Duplex intercom

Amin'ny farany 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 -xRaha 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 7010Araka 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 440Amin'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
