ဆောင်းပါး၏ အကြောင်းအရာကို ကျွန်ုပ်ထံမှ ယူပါသည်။
နောက်ဆုံး၌
ကျွန်ုပ်တို့သည် ပလပ်အင်တစ်ခုကို တီထွင်နေပါသည်။
အခြားပရိုဂရမ်များစွာတွင်ကဲ့သို့ မီဒီယာထုတ်လွှင့်သူရှိ ပလပ်အင်များကို မီဒီယာထုတ်လွှင့်သူကိုယ်တိုင် ပြန်လည်ပေါင်းစပ်ရန် မလိုအပ်ဘဲ လုပ်ဆောင်နိုင်စွမ်းကို ချဲ့ထွင်ရန်အတွက် အသုံးပြုပါသည်။
သင့်ပရိုဂရမ်ရှိ plugin ကိုအသုံးပြုရန်၊ သင်အသုံးပြုသည်။ ပါဝင် plugin header file ပါ၀င်ရမည်။ ပရိုဂရမ်၏ကိုယ်ထည်တွင်၊ လုပ်ဆောင်ချက် y ကိုအသုံးပြုသည်။ ms_filter_register() စစ်ထုတ်မှုအသစ်တစ်ခုကို မှတ်ပုံတင်ပါ။ ပုံမှန်အားဖြင့်၊ သင်၏ပရိုဂရမ်နှင့် ပလပ်အင်ရင်းမြစ်ကို အပလီကေးရှင်းတစ်ခုတွင် စုစည်းပြီး စုစည်းထားရမည်ဖြစ်သည်။
အခု plugin တစ်ခုရေးဖို့လှည့်ကြည့်ရအောင်။ media streamer filters နှင့် plugins များအားလုံးသည် ၎င်းတို့၏ အရေးအသားတွင် ဘုံ canon တစ်ခုအတိုင်း လုပ်ဆောင်ပြီး သင်လေ့လာလိုသော နောက် filter ၏ ဖွဲ့စည်းပုံကို နားလည်ရန် ပိုမိုလွယ်ကူစေသည်။ ထို့ကြောင့်၊ ထပ်မံ၍ အကြောင်းအရာများ မများပြားစေရန်၊ ကျွန်ုပ်သည် plugins filters များကို ခေါ်ပါမည်။
ကျွန်ုပ်တို့သည် NASH_FILTR ဟုခေါ်သော စစ်ထုတ်မှုအသစ်တစ်ခုကို ဖန်တီးလိုသည်ဆိုပါစို့။ ၎င်းသည် ရိုးရှင်းသော အရာတစ်ခုကို လုပ်ဆောင်လိမ့်မည် - ၎င်း၏ တစ်ခုတည်းသော ထည့်သွင်းမှုမှ ပိတ်ဆို့မှုများကို လက်ခံပြီး ၎င်း၏ အထွက်ငါးခုသို့ ပေးပို့ပါ။ ပေးထားသည့် အတိုင်းအတာတစ်ခုအောက်ရှိ အချက်ပြအဆင့်တစ်ခုအောက်ရှိ အတုံးငါးခုထက်ပိုပါက ၎င်းကိုဖြတ်သွားကာ ၎င်းကိုဖြတ်ကျော်သည့်အဆင့်ထက် အချက်ပြအဆင့်ထက် ငါးတုံးကျော်သွားပါက ၎င်းသည် ဖြစ်ရပ်တစ်ခုကိုလည်း ထုတ်ပေးမည်ဖြစ်သည်။
စစ်ထုတ်သည့်နည်းလမ်းကို အသုံးပြု၍ အဆင့်သတ်မှတ်မည်ဖြစ်သည်။ ဒုတိယနှင့် တတိယနည်းလမ်းများသည် ထွက်ပေါက်များသို့ ပိတ်ဆို့ခြင်းများကို ခွင့်ပြု/တားမြစ်ပေးမည်ဖြစ်သည်။
စလိုက်ကြစို့။ Filter ရေးတဲ့အခါမှာ header file တစ်ခုနဲ့ စတင်ရပါမယ်။ ပထမစာကြောင်းများတွင် ၎င်းသည် ဖိုင်ကို ထည့်သွင်းသင့်သည်။ msfilter.hMS_FILTER_METHOD မက်ခရိုကို အသုံးပြု၍ စစ်ထုတ်မှုအသစ်၏ နည်းလမ်းများကို ကြေညာပါ (ရှိပါက)၊ စစ်ထုတ်မှုမှ ထုတ်ပေးသည့် အဖြစ်အပျက်များကို ကြေညာပါ (ရှိပါက) နှင့် အမျိုးအစား၏ တင်ပို့ထားသော ဖွဲ့စည်းပုံကို ကြေညာပါ။ MSFilterDesc filter parameters ၏ဖော်ပြချက်နှင့်အတူ
/* Файл nash_filter.h, описывает фильтр-разветвитель и нойзгейт. */
#ifndef myfilter_h
#define myfilter_h
/* Подключаем заголовочный файл с перечислением фильтров медиастримера. */
#include <mediastreamer2/msticker.h>
/*
Задаем числовой идентификатор нового типа фильтра. Это число не должно
совпадать ни с одним из других типов. В медиастримере в файле allfilters.h
есть соответствующее перечисление enum MSFilterId. К сожалению, непонятно
как определить максимальное занятое значение, кроме как заглянуть в этот
файл. Но мы возьмем в качестве id для нашего фильтра заведомо большее
значение: 4000. Будем полагать, что разработчики добавляя новые фильтры, не
скоро доберутся до этого номера.
*/
#define NASH_FILTER_ID 4000
/*
Определяем методы нашего фильтра. Вторым параметром макроса должен
порядковый номер метода, число от 0. Третий параметр это тип аргумента
метода, указатель на который будет передаваться методу при вызове. У методов
аргументов может и не быть, как показано ниже.
*/
#define NASH_FILTER_SET_TRESHOLD MS_FILTER_METHOD(NASH_FILTER_ID , 0, float)
#define NASH_FILTER_TUNE_OFF MS_FILTER_METHOD_NO_ARG(NASH_FILTER_ID ,1)
#define NASH_FILTER_TUNE_ON MS_FILTER_METHOD_NO_ARG(NASH_FILTER_ID ,2)
/* Теперь определяем структуру, которая будет передаваться вместе с событием. */
struct _NASHFilterEvent
{
/* Это поле, которое будет выполнять роль флага,
0 - появились нули, 1 - появился сигнал.*/
char state;
/* Время, когда произошло событие. */
uint64_t time;
};
typedef struct _NASHFilterEvent NASHFilterEvent;
/* Определяем событие для нашего фильтра. */
#define NASH_FILTER_EVENT MS_FILTER_EVENT(MS_RTP_RECV_ID, 0, NASHFilterEvent)
/* Определяем экспортируемую переменную, которая будет
хранить характеристики для данного типа фильтров. */
extern MSFilterDesc nash_filter_desc;
#endif /* myfilter_h */
ယခု သင်သည် အရင်းအမြစ်ဖိုင်သို့ ဆက်သွားနိုင်သည်။ မှတ်ချက်များဖြင့် စစ်ထုတ်ခြင်းအတွက် အရင်းအမြစ်ကုဒ်ကို အောက်တွင် ပြထားသည်။ စစ်ထုတ်ခြင်းနည်းလမ်းများနှင့် လိုအပ်သော စစ်ထုတ်ခြင်းလုပ်ဆောင်ချက်များကို ဤနေရာတွင် သတ်မှတ်ထားပါသည်။ ထို့နောက် ပို့ကုန်ဖွဲ့စည်းပုံတွင် နည်းလမ်းများနှင့် လုပ်ဆောင်ချက်များကို ရည်ညွှန်းချက်များကို သတ်မှတ်ထားသော အစီအစဥ်အတိုင်း ထားရှိမည်ဖြစ်သည်။ ကျွန်ုပ်တို့၏_filter_desc. ဒေတာလုပ်ဆောင်ခြင်းလုပ်ငန်းအသွားအလာတွင် ဤအမျိုးအစား၏ "ထည့်သွင်းခြင်း" စစ်ထုတ်ရန် မီဒီယာထုတ်လွှင့်သူမှ အသုံးပြုသည်။
/* Файл nash_filter.с, описывает фильтр-разветвитель и нойзгейт. */
#include "nash_filter.h"
#include <math.h>
#define NASH_FILTER_NOUTPUTS 5
/* Определяем структуру, которая хранит внутреннее состояние фильтра. */
typedef struct _nash_filterData
{
bool_t disable_out; /* Разрешение передачи блоков на выход. */
int last_state; /* Текущее состояние переключателя. */
char zero_count; /* Счетчик нулевых блоков. */
char lag; /* Количество блоков для принятия решения нойзгейтом. */
char n_count; /* Счетчик НЕнулевых блоков. */
float skz_level; /* Среднеквадратическое значение сигнала внутри
блока, при котором фильтр будет пропускать сигнал. Одновременно это порог
срабатывания, по которому будет формироваться событие. */
} nash_filterData;
/*----------------------------------------------------------*/
/* Обязательная функция инициализации. */
static void nash_filter_init(MSFilter *f)
{
nash_filterData *d=ms_new0(nash_filterData, 1);
d->lag=5;
f->data=d;
}
/*----------------------------------------------------------*/
/* Обязательная функция финализации работы фильтра,
освобождается память. */
static void nash_filter_uninit(MSFilter *f)
{
ms_free(f->data);
}
/*----------------------------------------------------------*/
/* Определяем образцовый массив с нулями, заведомо
большего размера чем блок. */
char zero_array[1024]={0};
/* Определяем событие фильтра. */
NASHFilterEvent event;
/*----------------------------------------------------------*/
/* Функция отправки события. */
static void send_event(MSFilter *f, int state)
{
nash_filterData *d =( nash_filterData* ) f->data;
d->last_state = state;
/* Устанавливаем время возникновения события,
от момента первого тика. Время в миллисекундах. */
event.time=f -> ticker -> time;
event.state=state;
ms_filter_notify(f, NASH_FILTER_EVENT, &event);
}
/*----------------------------------------------------------*/
/* Функция вычисляет среднеквадратическое (эффективное) значение сигнала внутри
блока. */
static float calc_skz(nash_filterData *d, int16_t *signal, int numsamples)
{
int i;
float acc = 0;
for (i=0; i<numsamples; i++)
{
int s=signal[i];
acc = acc + s * s;
}
float skz = (float)sqrt(acc / numsamples);
return skz;
}
/*----------------------------------------------------------*/
/* Обязательная функция основного цикла фильтра,
вызывается с каждым тиком. */
static void nash_filter_process(MSFilter *f)
{
nash_filterData *d=(nash_filterData*)f->data;
/* Указатель на входное сообщение содержащее блок данных. */
mblk_t *im;
int i;
int state;
/* Вычитываем сообщения из входной очереди
до полного её опустошения. */
while((im=ms_queue_get(f->inputs[0]))!=NULL)
{
/* Если выходы запрещены, то просто удаляем входное сообщение. */
if ( d -> disable_out)
{
freemsg(im);
continue;
}
/* Измеряем уровень сигнала и принимаем решение об отправке сигнала. */
float skz = calc_skz(d, (int16_t*)im->b_rptr, msgdsize(im));
state = (skz > d->skz_level) ? 1 : 0;
if (state)
{
d->n_count++;
d->zero_count = 0;
}
else
{
d->n_count = 0;
d->zero_count++;
}
if (((d->zero_count > d->lag) || (d->n_count > d->lag))
&& (d->last_state != state)) send_event(f, state);
/* Приступаем к копированию входного сообщения и раскладке по выходам. Но
* только по тем, к которым подключена нагрузка. Оригинальное сообщение
* уйдет на выход с индексом 0, а его копии попадут на остальные
* выходы. */
int output_count = 0;
mblk_t *outm; /* Указатель на сообщение с выходным блоком данных. */
for(i=0; i < f->desc->noutputs; i++)
{
if (f->outputs[i]!=NULL)
{
if (output_count == 0)
{
outm = im;
}
else
{
/* Создаем легкую копию сообщения. */
outm = dupmsg(im);
}
/* Помещаем копию или оригинал входного сообщения на очередной
* выход фильтра. */
ms_queue_put(f->outputs[i], outm);
output_count++;
}
}
}
}
/*----------------------------------------------------------*/
/* Функция-обработчик вызова метода NASH_FILTER_SET_LAG. */
static int nash_filter_set_treshold(MSFilter *f, void *arg)
{
nash_filterData *d=(nash_filterData*)f->data;
d->skz_level=*(float*)arg;
return 0;
}
/*----------------------------------------------------------*/
/* Функция-обработчик вызова метода NASH_FILTER_TUNE_OFF. */
static int nash_filter_tune_off(MSFilter *f, void *arg)
{
nash_filterData *d=(nash_filterData*)f->data;
d->disable_out=TRUE;
return 0;
}
/*----------------------------------------------------------*/
/* Функция-обработчик вызова метода NASH_FILTER_TUNE_ON. */
static int nash_filter_tune_on(MSFilter *f, void *arg)
{
nash_filterData *d=(nash_filterData*)f->data;
d->disable_out=FALSE;
return 0;
}
/*----------------------------------------------------------*/
/* Заполняем таблицу методов фильтра, сколько методов
мы определили в заголовочном файле столько ненулевых
строк. */
static MSFilterMethod nash_filter_methods[]={
{ NASH_FILTER_SET_TRESHOLD, nash_filter_set_treshold },
{ NASH_FILTER_TUNE_OFF, nash_filter_tune_off },
{ NASH_FILTER_TUNE_ON, nash_filter_tune_on },
{ 0 , NULL } /* Маркер конца таблицы. */
};
/*----------------------------------------------------------*/
/* Описание фильтра для медиастримера. */
MSFilterDesc nash_filter_desc=
{
NASH_FILTER_ID,
"NASH_FILTER",
"A filter with noise gate that reads from input and copy to it's five outputs.",
MS_FILTER_OTHER,
NULL,
1,
NASH_FILTER_NOUTPUTS,
nash_filter_init,
NULL,
nash_filter_process,
NULL,
nash_filter_uninit,
nash_filter_methods
};
MS_FILTER_DESC_EXPORT(nash_filter_desc)
ယခု၊ မနှောင့်နှေးဘဲ၊ အစောပိုင်းက ကျွန်ုပ်တို့ပြုလုပ်ခဲ့သော အင်တာကွန်တွင် ကျွန်ုပ်တို့၏ filter ကိုသုံးကြပါစို့။ ခေါင်းစဉ်ပုံတွင် ပြုပြင်ထားသော အင်တာကွန်တစ်ခု၏ ပုံကြမ်းကို ပြထားသည်။
ကျွန်ုပ်တို့၏ လက်လုပ်ဇကာများကို အထူးတောက်ပသောပုံစံဖြင့် ပုံဖော်လိုပါသည်။ ထို့ကြောင့်၊ သင်သည် ကျွန်ုပ်တို့၏ filter ကို ပုံကြမ်းတွင် ချက်ချင်းတွေ့လိမ့်မည်။
input signal ကို wav ဖိုင်သို့ရေးပေးသည့် circuit တွင် filter-recorer ကိုထည့်ထားသည်။ စီစဉ်ထားသည့်အတိုင်း၊ ကျွန်ုပ်တို့၏ filter သည် သင့်အား ဖိုင်ထဲသို့ စကားပြောဆိုမှုတွင် ခေတ္တရပ်နားခြင်းများကို ရှောင်ရှားနိုင်စေမည်ဖြစ်သည်။ ထို့ကြောင့်၎င်း၏အရွယ်အစားကိုလျှော့ချ။
ဆောင်းပါးအစတွင်၊ ကျွန်ုပ်တို့သည် filter ၏ algorithm ကိုဖော်ပြခဲ့သည်။ ပင်မအပလီကေးရှင်းသည် ၎င်းထုတ်လုပ်သည့်ဖြစ်ရပ်များကို ကိုင်တွယ်သည်။ ဖြစ်ရပ်တွင် "0" အလံပါရှိပါက၊ လက်ခံဆောင်ရွက်ပေးသူ အပလီကေးရှင်းသည် မှတ်တမ်းတင်ခြင်းကို ခေတ္တရပ်ပါမည်။ “1” အလံပါသည့် ဖြစ်ရပ်တစ်ခု ရောက်ရှိလာသည်နှင့် တပြိုင်နက် မှတ်တမ်းတင်မှု ပြန်လည်စတင်သည်။
နောက်ထပ် command line argument နှစ်ခုကို ယခင်အရာများသို့ ထည့်ထားသည်- --ng
၊ filter တံခါးခုံအဆင့်နှင့် သတ်မှတ်ပေးသော၊ --rec
ဟုခေါ်သော ဖိုင်တစ်ခုသို့ စတင်ရေးသားသည်။ record.wav.
/* Файл mstest9.c Имитатор переговорного устройства c регистратором и
* нойзгейтом. */
#include <mediastreamer2/mssndcard.h>
#include <mediastreamer2/dtmfgen.h>
#include <mediastreamer2/msrtp.h>
#include <mediastreamer2/msfilerec.h>
/* Подключаем наш фильтр. */
#include "nash_filter.h"
/* Подключаем файл общих функций. */
#include "mstest_common.c"
/*----------------------------------------------------------*/
struct _app_vars
{
int local_port; /* Локальный порт. */
int remote_port; /* Порт переговорного устройства на удаленном компьютере. */
char remote_addr[128]; /* IP-адрес удаленного компьютера. */
MSDtmfGenCustomTone dtmf_cfg; /* Настройки тестового сигнала генератора. */
MSFilter* recorder; /* Указатель на фильтр регистратор. */
bool_t file_is_open; /* Флаг того, что файл для записи открыт. */
/* Порог, при котором прекращается запись принимаемого сигнала в файл. */
float treshold;
bool_t en_rec; /*Включить запись в файл.*/
};
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");
printf("--ng Noise gate treshold level from 0. to 1.0n");
printf("--rec record to file 'record.wav'.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]);
}
if (!strcmp(argv[i], "--ng"))
{
v -> dtmf_cfg.frequencies[0] = atoi(argv[i+1]);
printf("noise gate treshold: %fn", v -> treshold);
}
if (!strcmp(argv[i], "--rec"))
{
v -> en_rec = TRUE;
printf("enable recording: %in", v -> en_rec);
}
}
}
/*----------------------------------------------------------*/
/* Функция обратного вызова, она будет вызвана фильтром, как только он
* заметит, что наступила тишина или наоборот тишина сменилась звуками. */
static void change_detected_cb(void *data, MSFilter *f, unsigned int event_id,
NASHFilterEvent *ev)
{
app_vars *vars = (app_vars*) data;
/* Если запись не была разрешена, то выходим. */
if (! vars -> en_rec) return;
if (ev -> state)
{
/* Возобновляем запись. */
if(!vars->file_is_open)
{
ms_filter_call_method(vars->recorder, MS_FILE_REC_OPEN, "record.wav");
vars->file_is_open = 1;
}
ms_filter_call_method(vars->recorder, MS_FILE_REC_START, 0);
printf("Recording...n");
}
else
{
/* Приостанавливаем запись. */
ms_filter_call_method(vars->recorder, MS_FILE_REC_STOP, 0);
printf("Pause...n");
}
}
/*----------------------------------------------------------*/
int main(int argc, char *argv[])
{
/* Устанавливаем настройки по умолчанию. */
app_vars vars={5004, 7010, "127.0.0.1", {0}, 0, 0, 0.01, 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");
//MS_FILE_REC_ID
/* Регистрируем наш фильтр. */
ms_filter_register(&nash_filter_desc);
MSFilter *nash = ms_filter_new(NASH_FILTER_ID);
/* Создаем фильтр звуковой карты. */
MSFilter *snd_card_write = ms_snd_card_create_writer(snd_card);
/* Создаем фильтр регистратора. */
MSFilter *recorder=ms_filter_new(MS_FILE_REC_ID);
vars.recorder = recorder;
/* Соединяем фильтры приёмного тракта. */
ms_filter_link(rtprecv, 0, decoder, 0);
ms_filter_link(decoder, 0, nash, 0);
ms_filter_link(nash, 0, snd_card_write, 0);
ms_filter_link(nash, 1, recorder, 0);
/* Подключаем к фильтру функцию обратного вызова, и передаем ей в
* качестве пользовательских данных указатель на структуру с настройками
* программы, в которой среди прочих есть указать на фильтр
* регистратора. */
ms_filter_set_notify_callback(nash,
(MSFilterNotifyFunc)change_detected_cb, &vars);
ms_filter_call_method(nash,NASH_FILTER_SET_TRESHOLD, &vars.treshold);
/* Создаем источник тактов - тикер. */
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;
}
/* Организуем цикл перезапуска генератора. */
printf("Press ENTER to exit.n ");
char c=getchar();
while(c != 'n')
{
if(vars.dtmf_cfg.frequencies[0])
{
/* Включаем звуковой генератор. */
ms_filter_call_method(dtmfgen, MS_DTMF_GEN_PLAY_CUSTOM,
(void*)&vars.dtmf_cfg);
}
char c=getchar();
printf("--n");
}
if (vars.en_rec ) ms_filter_call_method(recorder, MS_FILE_REC_CLOSE, 0);
}
ဖိုင်များထည့်၍ စာကြည့်တိုက်ကို အသုံးပြုခဲ့ခြင်းကြောင့် သင်္ချာcompilation အတွက် command line သည် ပိုမိုရှုပ်ထွေးလာပြီး ဤပုံအတိုင်းဖြစ်သည်-
$ gcc mstest9.c nash_filter.c -o mstest9 `pkg-config mediastreamer --libs --cflags` -lm
အပလီကေးရှင်းကို တည်ဆောက်ပြီးနောက်၊ အောက်ဖော်ပြပါ အကြောင်းပြချက်များဖြင့် ပထမကွန်ပျူတာပေါ်တွင် ၎င်းကို run ပါ။
$ ./mstest9 --lport 7010 --port 8010 --addr <тут адрес второго компьютера> --rec
ဒုတိယကွန်ပြူတာတွင် အောက်ပါဆက်တင်များဖြင့် ကျွန်ုပ်တို့ စတင်လုပ်ဆောင်သည်-
$ ./mstest9 --lport 8010 --port 7010 --addr <тут адрес первого компьютера>
အဲဒီနောက်မှာတော့ ပထမကွန်ပြူတာက သင်ပြောသမျှကို ဒုတိယ မိုက်ခရိုဖုန်းမှာ မှတ်တမ်းတင်ဖို့ စတင်ပါလိမ့်မယ်။ ဒီနေရာမှာ “စကားလုံး၊မှတ်တမ်းတင်နေသည်..."။ သင် အသံတိတ်သွားသည်နှင့် တပြိုင်နက် အသံသွင်းခြင်းကို ခေတ္တရပ်ပါမည်"ခေတ္တရပ်နားသည်…"သင်သည် တံခါးခုံအဆင့်ကို စမ်းသပ်ရန် လိုအပ်နိုင်သည်။
ဤဆောင်းပါးတွင် Filter များရေးသားနည်းကို လေ့လာခဲ့သည်။ သင်သတိပြုမိသည့်အတိုင်း၊ nash_filter_process() လုပ်ဆောင်ချက်သည် ဒေတာပိတ်ဆို့မှုများဖြင့် ကိုင်တွယ်ဖြေရှင်းမှုများကို လုပ်ဆောင်သည်။ ဥပမာသည် ပညာပေးဖြစ်သောကြောင့်၊ ဒေတာဘလောက်များကို ကိုင်တွယ်ရန်အတွက် မီဒီယာထုတ်လွှင့်သူ၏ အနိမ့်ဆုံးစွမ်းရည်ကို အသုံးပြုခဲ့သည်။
နောက်တစ်ခု
source: www.habr.com