ויס׀א֞ךשן די Mediastreamer2 ווא֞י׀֌ מא־טא־׹. טייל 6

דעך מאַטעךיאַל ׀ון דעם אַךטיקל איז גענומען ׀ון מיין זען קאַנאַל.

טךאַנסמיטינג אַ אַודיא֞ סיגנאַל דו׹ך RTP טייַך

ויס׀א֞ךשן די Mediastreamer2 ווא֞י׀֌ מא־טא־׹. טייל 6

אין דעך ׀אַךגאַנגענהייט אַךטיקל מי׹ הא־בן ׀אךזאמלט אַ ווייַט קא־נט׹א־ל קךייַז ׀ון אַ טא־ן גענעךאַטא֞ך און אַ טא־ן דעטעקטא֞ך ווא֞ס אַךבעטן אין דעך זעלביקעך ׀֌ךא֞גךאַם. אין דעם אַךטיקל מי׹ וועלן לעךנען ווי שו נושן די RTP ׀֌ךא֞טא֞קא֞ל (RFC 3550 - RTP: א טךאַנס׀֌א֞ךט ׀֌ךא֞טא֞קא֞ל ׀ֿאַך ׀אַקטיש-שייט אַ׀֌לאַקיישאַנז) ׀ֿאַך ךיסיווינג / טךאַנסמיטינג אַ אַודיא֞ סיגנאַל איבעך אַן עטהעךנעט × ×¢×¥.

RTP ׀֌ךא֞טא֞קא֞ל (׀אַקטיש שייט ׀֌ךא֞טא֞קא֞ל) איבעךגעזע׊ט מיטל ׀אַקטיש-שייט ׀֌ךא֞טא֞קא֞ל, עס איז געני׊ט שו אַךיבעך׀יךן אַודיא֞, ווידעא, דאַטן, אַלץ ווא֞ס ךיקווייעךז טךאַנסמיסיע אין ׀אַקטיש שייט. זאל ס נעמען אַן אַודיא֞ סיגנאַל ווי אַ בייַש׀֌יל. די בייגיקייט ׀ון דעם ׀֌ךא֞טא֞קא֞ל איז אַזוי אַז עס אַלאַוז אי׹ שו אַךיבעך׀יךן אַ אַודיא֞ סיגנאַל מיט אַ ׀֌ךידיטעךמינד קוואַליטעט.

די טךאַנסמיסיע איז דוךכגעקא֞כט מיט UDP ׀֌אַקיץ, ווא֞ס מיטל אַז ׀֌אַקאַט א֞נוועך איז גאַנץ ׀֌אַסיק בעשאַס טךאַנסמיסיע. יעדעך ׀֌אַקאַט כ֌ולל אַ ס׀֌ע׊יעל RTP כעדעך און אַ דאַטן בלא־ק ׀ון די טךאַנסמיטטעד סיגנאַל. דעך כעדעך כ֌ולל אַ ךאַנדאַמלי אויסגעקליבן סיגנאַל מקו׹ אידענטי׀י׊יךן, אינ׀ֿא֞ךמאַ׊יע וועגן דעם טי׀֌ ׀ון סיגנאַל טךאַנסמיטטעד, און אַ יינשיק ׀֌אַקאַט סיקוואַנס נומעך אַזוי אַז די ׀֌אַקיץ קענען זיין עךיינדזשד אין די ׹יכטיק סדך ווען דיקא־ודינג, ךאַגאַךדלאַס ׀ון די סדך אין ווא֞ס זיי זענען איבעךגעגעבן דו׹ך די כעדעך. × ×¢×¥. דעך כעדעך קען אויך אַנטהאַלטן נא־ך אינ׀ֿא֞ךמאַ׊יע, די אַזוי געךו׀ענע ׀אַךלענגעךונג, ווא֞ס אַלאַוז די כעדעך שו זיין ׊וגע׀אסט שו נושן אין אַ ס׀֌ע׊י׀יש אַ׀֌לאַקיישאַן אַךבעט.

די דאַטן בלא־ק כ֌ולל די ׀֌יילא֞וד ׀ון די ׀֌אַקאַט. די ינעךלעך א֞ךגאַניזאַ׊יע ׀ון ​​אינהאַלט דע׀֌ענדס אויף דעם טי׀֌ ׀ון מאַסע, עס קענען זיין סאַמ׀֌אַלז ׀ון אַ מא־נא־ סיגנאַל, אַ סטעךיא֞ו סיגנאַל, אַ ווידעא בילד שוךה, עטק.

די מאַסע טי׀֌ איז ינדאַקייטיד דו׹ך אַ זיבן-ביסל נומעך. ךעקא֞מענדאַ׊יע RFC3551 (RTP ׀֌ךא֞׀יל ׀ֿאַך אַודיא֞ און ווידעא קאַנ׀ךאַנסאַז מיט מינימאַל קא־נט׹א־ל) יסטאַבלישיז עטלעכע טיי׀֌ס ׀ון מאַסע; די קא֞ךאַס׀֌אַנדינג טיש גיט אַ באַשךייַבונג ׀ון די טיי׀֌ס ׀ון מאַסע און די טייַטש ׀ון די קא־ודז דו׹ך ווא֞ס זיי זענען דעזיגנייטיד. עטלעכע קא־ודז זענען נישט שטךענג טייד שו קיין טי׀֌ ׀ון מאַסע; זיי קענען זיין געני׊ט שו דעזיגנייט אַ אַךביטךאַךיש מאַסע.

די גךייס ׀ון אַ דאַטן בלא־ק איז לימיטעד אויבן דו׹ך די מאַקסימום ׀֌אַקאַט גךייס ווא֞ס קענען זיין טךאַנסמיטטעד אויף אַ געגעבן × ×¢×¥ א־ן סעגמאַנטיישאַן (MTU ׀֌אַךאַמעטעך). אין אַלגעמיין, דא֞ס איז ניט מעך ווי 1500 ביטעס. אזוי, אין סדך שו ׀אַךגךעסעךן די סומע ׀ון ​​דאַטן טךאַנסמיטטעד ׀֌עך סעקונדע, אי׹ קענען ׀אַךגךעסעךן די ׀֌אַקאַט גךייס אַךויף שו אַ זיכעך ׀ונט, און דעמא֞לט אי׹ דאַך׀ֿן שו ׀אַךגךעסעךן די א֞׀טקייַט ׀ון שיקן ׀֌אַקיץ. אין אַ מידיאַ סטךימעך, דא֞ס איז אַ קאַנ׀יגיעךאַבאַל באַשטעטיקן. דו׹ך ׀עליקייַט עס איז 50 הז, ד"ה. 50 ׀֌אַקיץ ׀֌עך סעקונדע. מי׹ וועלן ךו׀ן די סיקוואַנס ׀ון טךאַנסמיטטעד ךט׀֌ ׀֌אַקיץ אַ ךט׀֌ טייַך.

שו א־נהייבן טךאַנסמיטינג דאַטן ׊ווישן די מקו׹ און די ו׀נעמעך, עס איז גענוג אַז די טךאַנסמיטעך ווייסט די IP אַדךעס ׀ון די ו׀נעמעך און די ׀֌א֞ךט נומעך ווא֞ס עך נישט ׀ֿאַך ךיסיווינג. יענע. א־ן קיין ׀֌ךילימאַנעךי ׀֌ךא֞וסידזשעךז, דעך מקו׹ הייבט שו יבעךשיקן דאַטן, און דעך ו׀נעמעך, אין קעך, איז ג׹ייט שו מיד באַקומען און ׀֌ךא֞׊עס עס. לויט דעך נא֞ךמאַל, די ׀֌א֞ךט נומעך געני׊ט שו אַךיבעך׀יךן א֞דעך באַקומען אַ RTP טייַך מוזן זיין גלייַך.

אין סיטואַטיא֞נס ווו עס איז אוממעגלעך שו וויסן די ו׀נעמעך ס אַדךעס אין שטייַגן, סעךוועךס זענען געני׊ט ווו ךיסיוועךז לא־זן זייעך אַדךעס, און די טךאַנסמיטעך קענען בעטן עס דו׹ך ךי׀עךינג שו עטלעכע יינשיק נא֞מען ׀ון די ו׀נעמעך.

אין קאַסעס ווו די קוואַליטעט ׀ון די קא֞מוניקאַ׊יע קאַנאַל א֞דעך די קיי׀֌אַבילאַטיז ׀ון די ו׀נעמעך זענען אומבאַקאַנט, אַ באַמעךקונגען קאַנאַל איז א֞ךגאַניזיךט דו׹ך ווא֞ס די ו׀נעמעך קענען מיטטיילן די טךאַנסמיטעך וועגן זייַן קיי׀֌אַבילאַטיז, די נומעך ׀ון ׀֌אַקיץ עס מיסט, אאז"ו ו. דעך קאַנאַל נישט די RTCP ׀֌ךא֞טא֞קא֞ל. דעך ׀ֿא֞ךמאַט ׀ון ׀֌אַקיץ טךאַנסמיטטעד אין דעם קאַנאַל איז די׀יינד אין RFC 3605. לע׀יעךעך קליין דאַטן זענען טךאַנסמיטטעד איבעך דעם קאַנאַל, 200..300 ביטעס ׀֌עך סעקונדע, אַזוי אין אַלגעמיין, זייַן בייַזייַן איז נישט בעךדאַנסאַם. די ׀֌א֞ךט נומעך שו ווא֞ס RTCP ׀֌אַקיץ זענען געשיקט מוזן זיין מא֞דנע און איינעך גךעסעך ווי די ׀֌א֞ךט נומעך ׀ון ווא֞ס די RTP טייַך קומט. אין אונדזעך בייַש׀֌יל, מי׹ וועלן נישט נושן דעם קאַנאַל, ווייַל די קיי׀֌אַבילאַטיז ׀ון די ו׀נעמעך און קאַנאַל דא־ך יקסיד אונדזעך, אַזוי ווייַט באַשיידן, דאַךף.

אין אונדזעך ׀֌ךא֞גךאַם, די דאַטן טךאַנסמיסיע קךייַז, ניט ענלעך דעם ׀ךיעךדיקן בייַש׀֌יל, וועט זיין ׊עטיילט אין שוויי טיילן: אַ טךאַנסמיטינג וועג און אַ ךיסיווינג וועג. ׀ֿאַך יעדעך טייל מי׹ וועלן מאַכן אונדזעך אייגענע זייגעך מקו׹, ווי געוויזן אין די טיטל בילד.

איין-וועג קא֞מוניקאַ׊יע ׊ווישן זיי וועט זיין דוךכגעקא֞כט מיט די RTP ׀֌ךא֞טא֞קא֞ל. אין דעם בייַש׀֌יל, מי׹ טא־ן ניט דאַך׀ֿן אַ ׀ונדךויסנדיק × ×¢×¥, ווייַל ביידע די טךאַנסמיטעך און די ו׀נעמעך וועט זיין ליגן אויף דעך זעלביקעך קא֞מ׀֌יוטעך - די ׀֌אַקיץ וועט אַךומ׀א֞ךן ין עס.

שו ׀אַךלייגן אַ RTP טייַך, די מידיאַ סטךימעך נישט שוויי ׀ילטעךס: MS_RTP_SEND און MS_RTP_RECV. דעך עךשטעך טךאַנסמיטט די ךגע און נעמט די RTP טייַך. כ֌די די ׀ילטעךס זא־ל אַךבעטן, זיי דאַך׀ֿן שו ׀א֞ךן אַ טייַטל שו אַ RTP סעסיע ×›×™×™×€×¢×¥, ווא֞ס קענען א֞דעך געך אַ טייַך ׀ון דאַטן בלאַקס אין אַ טייַך ׀ון RTP ׀֌אַקיץ א֞דעך טא־ן די ׀אַךקעךט. זינט די ינעךלעך דאַטן ׀ֿא֞ךמאַט ׀ון די מעדיע סטךימעך שטימען נישט מיט די דאַטן ׀ֿא֞ךמאַט ׀ון די RTP ׀֌אַקאַט, איידעך טךאַנס׀עךינג די דאַטן שו MS_RTP_SEND, אי׹ דאַך׀ֿן שו נושן אַ ענקא֞דעך ׀ילטעך ווא֞ס קאַנוועךץ 16-ביסל אַודיא֞ סיגנאַל סאַמ׀֌אַלז אין אַכט-ביסל ענקא֞ודיד לויט ו-געזעץ (מו-געזעץ). אויף די ךיסיווינג זייַט, די דיקא֞ודעך ׀ילטעך ׀֌עך׀א֞ךמז די ׀אַךקעךט ׀ונק׊יע.

ונטעך איז דעך טעקסט ׀ון די ׀֌ךא֞גךאַם ווא֞ס ימ׀֌לאַמאַנץ די סכעמע געוויזן אין די ׀יגוך (די # סימבא֞לס איידעך די ינקלודז דייךעקטיווז זענען אַוועקגענומען, טא־ן ניט ׀אַךגעסן שו אַךייַננעמען זיי):

/* Ѐайл mstest6.c ИЌОтатПр пульта управлеМОя О прОеЌМОка. */
#include <mediastreamer2/msfilter.h>
#include <mediastreamer2/msticker.h>
#include <mediastreamer2/dtmfgen.h>
#include <mediastreamer2/mssndcard.h>
#include <mediastreamer2/msvolume.h>
#include <mediastreamer2/mstonedetector.h>
#include <mediastreamer2/msrtp.h>
#include <ortp/rtpsession.h>
#include <ortp/payloadtype.h>
/* ППЎключаеЌ загПлПвПчМый файл с фуМкцОяЌО управлеМОя сПбытОяЌО
* ЌеЎОастрОЌера.*/
include <mediastreamer2/mseventqueue.h>
#define PCMU 0
/* ЀуМкцОя ПбратМПгП вызПва, ПМа буЎет вызваМа фОльтрПЌ, как тПлькП ПМ
ПбМаружОт сПвпаЎеМОе характерОстОк вхПЎМПгП сОгМала с заЎаММыЌО. */
static void tone_detected_cb(void *data, MSFilter *f, unsigned int event_id,
MSToneDetectorEvent *ev)
{
printf("ПрОМята кПЌаМЎа: %sn", ev->tone_name);
}
/*----------------------------------------------------------------------------*/
/* ЀуМкцОя регОстрацОО тОпПв пПлезМых МагрузПк. */
void register_payloads(void)
{
/*РегОстрОруеЌ тОпы МагрузПк в таблОце прПфОлей. ППзЎМее, пП ОМЎексу
взятПЌу Оз загПлПвка RTP-пакета Оз этПй таблОцы буЎут Озвлекаться
параЌетры МагрузкО, МеПбхПЎОЌые Ўля ЎекПЎОрПваМОя ЎаММых пакета. */
rtp_profile_set_payload (&av_profile, PCMU, &payload_type_pcm8000);
}
/*----------------------------------------------------------------------------*/
/* Эта фуМкцОя сПзЎаМа Оз фуМкцОО create_duplex_rtpsession() в audiostream.c
ЌеЎОастрОЌера2. */
static RtpSession *
create_rtpsession (int loc_rtp_port, int loc_rtcp_port,
bool_t ipv6, RtpSessionMode mode)
{
RtpSession *rtpr;
rtpr = rtp_session_new ((int) mode);
rtp_session_set_scheduling_mode (rtpr, 0);
rtp_session_set_blocking_mode (rtpr, 0);
rtp_session_enable_adaptive_jitter_compensation (rtpr, TRUE);
rtp_session_set_symmetric_rtp (rtpr, TRUE);
rtp_session_set_local_addr (rtpr, ipv6 ? "::" : "0.0.0.0", loc_rtp_port,
loc_rtcp_port);
rtp_session_signal_connect (rtpr, "timestamp_jump",
(RtpCallback) rtp_session_resync, 0);
rtp_session_signal_connect (rtpr, "ssrc_changed",
(RtpCallback) rtp_session_resync, 0);
rtp_session_set_ssrc_changed_threshold (rtpr, 0);
rtp_session_set_send_payload_type(rtpr, PCMU);
/* ПП уЌПлчаМОю выключаеЌ RTCP-сессОю, так как Маш пульт Ме буЎет ОспПльзПвать её. */
rtp_session_enable_rtcp (rtpr, FALSE);
return rtpr;
}
/*----------------------------------------------------------------------------*/
int main()
{
ms_init();
/* СПзЎаеЌ экзеЌпляры фОльтрПв. */
MSFilter *voidsource = ms_filter_new(MS_VOID_SOURCE_ID);
MSFilter *dtmfgen = ms_filter_new(MS_DTMF_GEN_ID);
MSFilter *volume = ms_filter_new(MS_VOLUME_ID);
MSSndCard *card_playback =
ms_snd_card_manager_get_default_card(ms_snd_card_manager_get());
MSFilter *snd_card_write = ms_snd_card_create_writer(card_playback);
MSFilter *detector = ms_filter_new(MS_TONE_DETECTOR_ID);
/* ОчОщаеЌ ЌассОв МахПЎящОйся вМутрО ЎетектПра тПМПв, ПМ ПпОсывает
* ПсПбые прОЌеты разыскОваеЌых сОгМалПв.*/
ms_filter_call_method(detector, MS_TONE_DETECTOR_CLEAR_SCANS, 0);
/* ППЎключаеЌ к фОльтру фуМкцОю ПбратМПгП вызПва. */
ms_filter_set_notify_callback(detector,
(MSFilterNotifyFunc)tone_detected_cb, NULL);
/* СПзЎаеЌ ЌассОв, кажЎый элеЌеМт кПтПрПгП ПпОсывает характерОстОку
* ПЎМПгП Оз тПМПв, кПтПрый требуется ПбМаружОвать: ТекстПвПе ОЌя
* ЎаММПгП элеЌеМта, частПта в герцах, ЎлОтельМПсть в ЌОллОсекуМЎах,
* ЌОМОЌальМый урПвеМь ПтМПсОтельМП 0,775В. */
MSToneDetectorDef scan[6]=
{
{"V+",440, 100, 0.1}, /* КПЌаМЎа "УвелОчОть грПЌкПсть". */
{"V-",540, 100, 0.1}, /* КПЌаМЎа "УЌеМьшОть грПЌкПсть". */
{"C+",640, 100, 0.1}, /* КПЌаМЎа "УвелОчОть МПЌер каМала". */
{"C-",740, 100, 0.1}, /* КПЌаМЎа "УЌеМьшОть МПЌер каМала". */
{"ON",840, 100, 0.1}, /* КПЌаМЎа "ВключОть телевОзПр". */
{"OFF", 940, 100, 0.1}/* КПЌаМЎа "ВыключОть телевОзПр". */
};
/* ПереЎаеЌ "прОЌеты" сОгМалПв ЎетектПр тПМПв. */
int i;
for (i = 0; i < 6; i++)
{
ms_filter_call_method(detector, MS_TONE_DETECTOR_ADD_SCAN,
&scan[i]);
}
/* СПзЎаеЌ фОльтры кПЎера О ЎекПЎера */
MSFilter *encoder = ms_filter_create_encoder("PCMU");
MSFilter *decoder=ms_filter_create_decoder("PCMU");
/* РегОстрОруеЌ тОпы МагрузкО. */
register_payloads();
/* СПзЎаеЌ RTP-сессОю переЎатчОка. */
RtpSession *tx_rtp_session = create_rtpsession (8010, 8011, FALSE, RTP_SESSION_SENDONLY);
rtp_session_set_remote_addr_and_port(tx_rtp_session,"127.0.0.1", 7010, 7011);
rtp_session_set_send_payload_type(tx_rtp_session, PCMU);
MSFilter *rtpsend = ms_filter_new(MS_RTP_SEND_ID);
ms_filter_call_method(rtpsend, MS_RTP_SEND_SET_SESSION, tx_rtp_session);
/* СПзЎаеЌ RTP-сессОю прОеЌМОка. */
MSFilter *rtprecv = ms_filter_new(MS_RTP_RECV_ID);
RtpSession *rx_rtp_session = create_rtpsession (7010, 7011, FALSE, RTP_SESSION_RECVONLY);
ms_filter_call_method(rtprecv, MS_RTP_RECV_SET_SESSION, rx_rtp_session);
/* СПзЎаеЌ ОстПчМОкО тактПв - тОкеры. */
MSTicker *ticker_tx = ms_ticker_new();
MSTicker *ticker_rx = ms_ticker_new();
/* СПеЎОМяеЌ фОльтры переЎатчОка. */
ms_filter_link(voidsource, 0, dtmfgen, 0);
ms_filter_link(dtmfgen, 0, volume, 0);
ms_filter_link(volume, 0, encoder, 0);
ms_filter_link(encoder, 0, rtpsend, 0);
/* СПеЎОМяеЌ фОльтры прОёЌМОка. */
ms_filter_link(rtprecv, 0, decoder, 0);
ms_filter_link(decoder, 0, detector, 0);
ms_filter_link(detector, 0, snd_card_write, 0);
/* ППЎключаеЌ ОстПчМОк тактПв. */
ms_ticker_attach(ticker_tx, voidsource);
ms_ticker_attach(ticker_rx, rtprecv);
/* НастраОваеЌ структуру, управляющую выхПЎМыЌ сОгМалПЌ геМератПра. */
MSDtmfGenCustomTone dtmf_cfg;
dtmf_cfg.tone_name[0] = 0;
dtmf_cfg.duration = 1000;
dtmf_cfg.frequencies[0] = 440;
/* БуЎеЌ геМерОрПвать ПЎОМ тПМ, частПту втПрПгП тПМа устаМПвОЌ в 0. */
dtmf_cfg.frequencies[1] = 0;
dtmf_cfg.amplitude = 1.0;
dtmf_cfg.interval = 0.;
dtmf_cfg.repeat_count = 0.;
/* ОргаМОзуеЌ цОкл скаМОрПваМОя Мажатых клавОш. ВвПЎ Муля завершает
* цОкл О рабПту прПграЌЌы. */
char key='9';
printf("НажЌОте клавОшу кПЌаМЎы, затеЌ ввПЎ.n"
"Для завершеМОя прПграЌЌы ввеЎОте 0.n");
while(key != '0')
{
key = getchar();
if ((key >= 49) && (key <= 54))
{
printf("ОтправлеМа кПЌаМЎа: %cn", key);
/* УстаМавлОваеЌ частПту геМератПра в сППтветствОО с
* кПЎПЌ МажатПй клавОшО. */
dtmf_cfg.frequencies[0] = 440 + 100*(key-49);
/* ВключаеЌ звукПвПй геМератПр c ПбМПвлеММПй частПтПй. */
ms_filter_call_method(dtmfgen, MS_DTMF_GEN_PLAY_CUSTOM,
(void*)&dtmf_cfg);
}
/* УклаЎываеЌ треЎ в спячку Ма 20Ќс, чтПбы ЎругОе треЎы
* прОлПжеМОя пПлучОлО вреЌя Ма рабПту. */
ms_usleep(20000);
}
}

מי׹ ׊ונוי׀נעמען און לוי׀ן. דעך ׀֌ךא֞גךאַם וועט אַךבעטן ווי אין די ׀ךיעךדיקע בייַש׀֌יל, א֞בעך די דאַטן וועט זיין טךאַנסמיטטעד דו׹ך אַ RTP טייַך.

אין דעך ווייַטעך אַךטיקל מי׹ וועלן טיילן דעם ׀֌ךא֞גךאַם אין שוויי ׀ךייַ אַ׀֌לאַקיישאַנז - אַ ו׀נעמעך און אַ טךאַנסמיטעך און קאַטעך זיי אין ׀אַךשידענע טעךמינאַלס. אין דעך זעלביקעך שייט, מי׹ וועלן לעךנען ווי שו אַנאַלייז RTP ׀֌אַקיץ נישן די TShark ׀֌ךא֞גךאַם.

מקו׹: www.habr.com

לייגן אַ באַמעךקונג