{"id":79540,"date":"2020-04-28T07:42:01","date_gmt":"2020-04-28T05:42:01","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/izuchaem-voip-dvizhok-mediastreamer2-chast-11"},"modified":"2020-04-28T07:42:01","modified_gmt":"2020-04-28T05:42:01","slug":"izuchaem-voip-dvizhok-mediastreamer2-chast-11","status":"publish","type":"post","link":"https:\/\/prohoster.info\/sq\/blog\/administrirovanie\/izuchaem-voip-dvizhok-mediastreamer2-chast-11","title":{"rendered":"Studimi i motorit VoIP Mediastreamer2. Pjesa 11","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Materiali i artikullit \u00ebsht\u00eb marr\u00eb nga kanali im <noindex><a rel=\"nofollow\" href=\"https:\/\/zen.yandex.ru\/profile\/editor\/id\/5e3f8e0751f5346faab4fc7a\">zen<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Studimi i motorit VoIP Mediastreamer2. Pjesa 11\" src=\"\/wp-content\/uploads\/2020\/04\/b66fab43eb45c626c50f0383dcfa7cca.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Mekanizmi i transferit t\u00eb t\u00eb dh\u00ebnave<\/p>\n<p><\/p>\n<ul>\n<li>Blloku i t\u00eb dh\u00ebnave dblk_t<\/li>\n<li>Mesazhi mblk_t<\/li>\n<li>Funksionet p\u00ebr menaxhimin e mesazheve mblk_t<\/li>\n<li>Rrjeti queue_t<\/li>\n<li>Funksionet p\u00ebr menaxhimin e rrjeteve queue_t<\/li>\n<li>Lidhja e filtrave<\/li>\n<li>Pika e sinjalizimit n\u00eb grafikun e p\u00ebrpunimit t\u00eb t\u00eb dh\u00ebnave<\/li>\n<li>Aktiviteti i prapasken\u00ebs i ticker-it<\/li>\n<li>Bufferizuesi (MSBufferizer)<\/li>\n<li>Funksionet p\u00ebr menaxhimin e MSBufferizer<\/li>\n<\/ul>\n<p><\/p>\n<p>N\u00eb t\u00eb kaluar\u00ebn <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/497932\/\">artikullin<\/a><\/noindex> Ne kemi zhvilluar filtrin ton\u00eb. Ky artikull do t'i kushtohet mekanizmit t\u00eb brendsh\u00ebm t\u00eb transferit t\u00eb t\u00eb dh\u00ebnave midis filtrave t\u00eb mediastream-it. Kjo do t\u00eb lejoj\u00eb krijimin e filtrave m\u00eb t\u00eb sofistikuar me m\u00eb pak p\u00ebrpjekje.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2 id=\"mehanizm-peremescheniya-dannyh\">Mekanizmi i transferit t\u00eb t\u00eb dh\u00ebnave<\/h2>\n<p><\/p>\n<p>Transferimi i t\u00eb dh\u00ebnave n\u00eb mediastream realizohet p\u00ebrmes rrjeteve t\u00eb p\u00ebrshkruara nga struktura <em>queue_t<\/em>. P\u00ebrmes rrjeteve kalojn\u00eb seri mesazhesh t\u00eb tipit <em>mblk_t<\/em>, t\u00eb cilat vet\u00eb nuk p\u00ebrmbajn\u00eb t\u00eb dh\u00ebna sinjali, por vet\u00ebm referencia p\u00ebr mesazhin e m\u00ebparsh\u00ebm, at\u00eb t\u00eb ardhsh\u00ebm dhe bllokun e t\u00eb dh\u00ebnave. P\u00ebr m\u00eb tep\u00ebr, d\u00ebshiroj t\u00eb theksoj se ka nj\u00eb fush\u00eb p\u00ebr referenc\u00eb n\u00eb nj\u00eb mesazh t\u00eb nj\u00ebjt\u00eb, e cila lejon organizimin e nj\u00eb liste t\u00eb lidhur nga mesazhet. Grupin e mesazheve t\u00eb bashkuara k\u00ebshtu, do ta quajm\u00eb tuple. Pra, \u00e7do element i rrjetit mund t\u00eb jet\u00eb nj\u00eb mesazh i vet\u00ebm <em>mblk_t<\/em>, ose mund t\u00eb jet\u00eb kryefjala e nj\u00eb tuple mesazhesh <em>mblk_t<\/em>. \u00c7do mesazh n\u00eb tuple mund t\u00eb ket\u00eb bllokun e tij t\u00eb dh\u00ebnave n\u00ebn mbik\u00ebqyrje. Pse na duhen tuple, do ta diskutojm\u00eb pak m\u00eb von\u00eb.<\/p>\n<p><\/p>\n<p>Si e p\u00ebrmendur m\u00eb sip\u00ebr, mesazhi vetvetiu nuk p\u00ebrmban nj\u00eb bllok t\u00eb dh\u00ebnash, p\u00ebrkundrazi, ai p\u00ebrmban vet\u00ebm nj\u00eb tregues p\u00ebr zon\u00ebn e memories ku ruhet blloku. N\u00eb k\u00ebt\u00eb pjes\u00eb, pamja e p\u00ebrgjithshme e pun\u00ebs s\u00eb mediastreamerit i ngjan nj\u00eb depoje derash n\u00eb animacionin \"Korporata e Monstrave\", ku derat (t\u00eb dh\u00ebnat - dhomat) l\u00ebvizin me shpejt\u00ebsi t\u00eb \u00e7mendur n\u00ebp\u00ebr konveyor\u00eb t\u00eb varur, nd\u00ebrkoh\u00eb q\u00eb vet\u00eb dhomat mbeten t\u00eb pal\u00ebvizshme. <\/p>\n<p><\/p>\n<p>Tani, duke u l\u00ebvizur n\u00eb hierarki nga posht\u00eb lart, le t\u00eb shqyrtojm\u00eb n\u00eb detaje entitetet e listuara t\u00eb mekanizmit t\u00eb transferit t\u00eb t\u00eb dh\u00ebnave n\u00eb mediastream.<\/p>\n<p><\/p>\n<h3 id=\"blok--dannyh-dblk_t\">Blloku i t\u00eb dh\u00ebnave <em>dblk_t<\/em><\/h3>\n<p><\/p>\n<p>Blloku i t\u00eb dh\u00ebnave p\u00ebrb\u00ebhet nga nj\u00eb krye dhe nj\u00eb buffer t\u00eb dh\u00ebnash. Krye i p\u00ebrshkruar nga struktura e m\u00ebposhtme,<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">typedef struct datab\n{\nunsigned char *db_base; \/\/ Tregues p\u00ebr fillimin e buffer t\u00eb dh\u00ebnash.\nunsigned char *db_lim;  \/\/ Tregues p\u00ebr fundin e buffer t\u00eb dh\u00ebnash.\nvoid (*db_freefn)(void*); \/\/ Funksioni p\u00ebr lirimin e memories kur fshihet blloku.\nint db_ref; \/\/ Num\u00ebruesi i referencave.\n} dblk_t;<\/code><\/pre>\n<p><\/p>\n<p>Fushat e struktur\u00ebs p\u00ebrmbajn\u00eb tregues p\u00ebr fillimin e bufferit, fundin e bufferit, funksionin e fshirjes t\u00eb bufferit t\u00eb dh\u00ebnash. Elementi i fundit n\u00eb krye <em>db_ref<\/em> \u2014 num\u00ebruesi i referencave, n\u00ebse arrin zero, sinjalizon fshirjen e k\u00ebtij blloku nga memoria. N\u00ebse blloku i t\u00eb dh\u00ebnave \u00ebsht\u00eb krijuar nga funksioni <em>datab_alloc() <\/em>, at\u00ebher\u00eb bufferi i t\u00eb dh\u00ebnave do t\u00eb vendoset n\u00eb memorie menj\u00ebher\u00eb pas krye-s\u00eb. N\u00eb t\u00eb gjitha rastet e tjera, bufferi mund t\u00eb ndodhet diku tjet\u00ebr. N\u00eb bufferin e t\u00eb dh\u00ebnave do t\u00eb ruhen t\u00eb dh\u00ebnat e sinjalit ose t\u00eb tjera t\u00eb dh\u00ebna q\u00eb d\u00ebshirojm\u00eb t\u00eb p\u00ebrpunojm\u00eb me filtrat.<\/p>\n<p><\/p>\n<p>Nj\u00eb instanc\u00eb e re e bllokut t\u00eb t\u00eb dh\u00ebnave krijohet me funksionin:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">dblk_t *datab_alloc(int size);<\/code><\/pre>\n<p><\/p>\n<p>Si paramet\u00ebr hyr\u00ebs kalon madh\u00ebsia e t\u00eb dh\u00ebnave q\u00eb do t\u00eb mbahen nga blloku. Memoria e ndan m\u00eb shum\u00eb p\u00ebr t\u00eb vendosur n\u00eb fillim t\u00eb memories t\u00eb dedikuar krye-n\u00eb \u2014 struktur\u00ebn <em>datab<\/em>. Por n\u00eb p\u00ebrdorimin e funksioneve t\u00eb tjera, kjo nuk ndodh gjithmon\u00eb, n\u00eb disa raste bufferi i t\u00eb dh\u00ebnave mund t\u00eb ndodhet ve\u00e7mas nga krye-i i bllokut t\u00eb t\u00eb dh\u00ebnave. Fushat e struktur\u00ebs, kur krijohen, rregullohen n\u00eb m\u00ebnyr\u00eb q\u00eb fusha e saj <em>db_base<\/em> tregues q\u00eb t\u00eb jet\u00eb n\u00eb fillim t\u00eb zon\u00ebs s\u00eb t\u00eb dh\u00ebnave, dhe <em>db_lim<\/em> n\u00eb fundin e saj. Num\u00ebruesi i referencave <em>db_ref<\/em> vendoset n\u00eb nj\u00eb.<\/p>\n<p><\/p>\n<h3 id=\"soobschenie-mblk_t\">Mesazhi <em>mblk_t<\/em><\/h3>\n<p><\/p>\n<p>Si\u00e7 u tha, elementet e rrjetit kan\u00eb tipin <em>mblk_t,<\/em> i cili \u00ebsht\u00eb p\u00ebrcaktuar si m\u00ebposht\u00eb:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">typedef struct msgb\n{\n  struct msgb *b_prev;   \/\/ Tregues p\u00ebr elementin e m\u00ebparsh\u00ebm t\u00eb list\u00ebs.\n  struct msgb *b_next;   \/\/ Tregues p\u00ebr elementin e ardhsh\u00ebm t\u00eb list\u00ebs.\n  struct msgb *b_cont;   \/\/ Tregues p\u00ebr ngjitjen e mesazheve t\u00eb tjera n\u00eb mesazh, p\u00ebr krijimin e tuple mesazhesh.\n  struct datab *b_datap; \/\/ Tregues p\u00ebr struktur\u00ebn e bllokut t\u00eb t\u00eb dh\u00ebnave.\n  unsigned char *b_rptr; \/\/ Tregues p\u00ebr fillimin e zon\u00ebs s\u00eb t\u00eb dh\u00ebnave p\u00ebr t\u00eb lexuar t\u00eb dh\u00ebnat nga bufferi b_datap.\n  unsigned char *b_wptr; \/\/ Tregues p\u00ebr fillimin e zon\u00ebs s\u00eb t\u00eb dh\u00ebnave p\u00ebr t\u00eb shkruar t\u00eb dh\u00ebnat n\u00eb bufferin b_datap.\n  uint32_t reserved1;    \/\/ Fush\u00eb e rezervuar1, mediastream-i e vendos aty informacion sh\u00ebrbimi.\n  uint32_t reserved2;    \/\/ Fush\u00eb e rezervuar2, mediastream-i e vendos aty informacion sh\u00ebrbimi.\n  #if defined(ORTP_TIMESTAMP)\n  struct timeval timestamp;\n  #endif\n  ortp_recv_addr_t recv_addr;\n} mblk_t;<\/code><\/pre>\n<p><\/p>\n<p>Struktura <em>mblk_t<\/em> n\u00eb fillim ka treguesit <em>b_prev<\/em>, <em>b_next,<\/em>t\u00eb cil\u00ebt jan\u00eb t\u00eb nevojsh\u00ebm p\u00ebr organizimin e nj\u00eb liste dyfishe (e cila \u00ebsht\u00eb rrjeti <em>queue_t<\/em>). <\/p>\n<p><\/p>\n<p>Pastaj vjen treguesi <em>b_cont,<\/em>i cili p\u00ebrdoret vet\u00ebm kur mesazhi hyn n\u00eb tuple. P\u00ebr mesazhin e fundit n\u00eb tuple, ky tregues mbetet zero. <\/p>\n<p><\/p>\n<p>M\u00eb pas shohim treguesin p\u00ebr bllokun e t\u00eb dh\u00ebnave <em>b_datap<\/em>, p\u00ebr t\u00eb cilin ekziston mesazhi. Pas tij vijn\u00eb treguesit n\u00eb zon\u00ebn brenda buffer-it t\u00eb t\u00eb dh\u00ebnave t\u00eb bllokut. Fusha <em>b_rptr<\/em> tregon vendin nga i cili do t\u00eb lexohen t\u00eb dh\u00ebnat nga buffer-i. Fusha <em>b_wptr<\/em> tregon vendin nga i cili do t\u00eb kryhet shkruajta n\u00eb buffer. <\/p>\n<p><\/p>\n<p>Fushat e mbetura kan\u00eb karakter t\u00eb ndihm\u00ebs dhe nuk lidhen me funksionin e mekanizmit t\u00eb transmetimit t\u00eb t\u00eb dh\u00ebnave.<\/p>\n<p><\/p>\n<p>M\u00eb posht\u00eb ilustrohet nj\u00eb mesazh i vet\u00ebm me emrin <em>m1<\/em> dhe blloku i t\u00eb dh\u00ebnave <em>d1<\/em>.<br \/>\n<img decoding=\"async\" alt=\"Studimi i motorit VoIP Mediastreamer2. Pjesa 11\" src=\"\/wp-content\/uploads\/2020\/04\/e6a726b13491832258c1228f03bde802.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nN\u00eb figur\u00ebn n\u00eb vazhdim \u00ebsht\u00eb paraqitur nj\u00eb tuple prej tre mesazhesh <em>m1<\/em>, <em>m1_1<\/em>, <em>m1_2<\/em>.<br \/>\n<img decoding=\"async\" alt=\"Studimi i motorit VoIP Mediastreamer2. Pjesa 11\" src=\"\/wp-content\/uploads\/2020\/04\/9613feefe9684b9551cd98115faa9a08.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<h3 id=\"funkcii-raboty-s-soobscheniyami--mblk_t\">Funksionet q\u00eb lidhen me mesazhet <em>mblk_t<\/em><\/h3>\n<p><\/p>\n<p>Mesazhi i ri <em>mblk_t<\/em> krijohet nga funksioni:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">mblk_t *allocb(int size, int pri); <\/code><\/pre>\n<p><\/p>\n<p>ai alokon n\u00eb memorie nj\u00eb mesazh t\u00eb ri <em>mblk_t<\/em> m\u00eb bllok t\u00eb dh\u00ebnash t\u00eb caktuar. <em>size<\/em>, argumenti i dyt\u00eb \u2014 <em>pri<\/em> nuk p\u00ebrdoret n\u00eb versionin q\u00eb po shqyrtohet t\u00eb bibliotek\u00ebs. Ai duhet t\u00eb mbetet zero. N\u00eb procesin e funksionit do t\u00eb alokohet memorie p\u00ebr struktur\u00ebn e mesazhit t\u00eb ri dhe do t\u00eb thirret funksioni <em>mblk_init()<\/em>, i cili do t\u00eb zeroj\u00eb t\u00eb gjitha fushat e instanc\u00ebs s\u00eb krijuar t\u00eb struktur\u00ebs dhe pastaj, me an\u00eb t\u00eb t\u00eb p\u00ebrmendur\u00ebs m\u00eb lart, <em>datab_alloc()<\/em>, do t\u00eb krijoj\u00eb buffer-in e t\u00eb dh\u00ebnave. Pas k\u00ebsaj do t\u00eb b\u00ebhet konfigurimi i fushave n\u00eb struktur\u00eb: <\/p>\n<p><\/p>\n<pre><code class=\"cpp\">mp-&gt;b_datap=datab;\nmp-&gt;b_rptr=mp-&gt;b_wptr=datab-&gt;db_base;\nmp-&gt;b_next=mp-&gt;b_prev=mp-&gt;b_cont=NULL;<\/code><\/pre>\n<p><\/p>\n<p>N\u00eb dalje marrim nj\u00eb mesazh t\u00eb ri me fushat e inicializuara dhe buffer-in e t\u00eb dh\u00ebnave bosh. P\u00ebr t\u00eb shtuar t\u00eb dh\u00ebna n\u00eb mesazh, duhet t\u00eb kryhet kopjimi n\u00eb buffer-in e bllokut t\u00eb t\u00eb dh\u00ebnave:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">memcpy(msg-&gt;b_rptr, data, size);<\/code><\/pre>\n<p><\/p>\n<p>ku <em>data<\/em> \u2014 treguesi n\u00eb burimin e t\u00eb dh\u00ebnave, dhe <em>size<\/em> \u2014 madh\u00ebsia e tyre.<br \/>\nPastaj duhet t\u00eb p\u00ebrdit\u00ebsohet treguesi te pika e shkruajtes, n\u00eb m\u00ebnyr\u00eb q\u00eb p\u00ebrs\u00ebri t\u00eb tregoj\u00eb p\u00ebr fillimin e zon\u00ebs s\u00eb lir\u00eb n\u00eb buffer:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">msg-&gt;b_wptr = msg-&gt;b_wptr + size<\/code><\/pre>\n<p><\/p>\n<p>N\u00ebse k\u00ebrkohet t\u00eb krijojm\u00eb nj\u00eb mesazh nga nj\u00eb buffer ekzistues, pa kopjim, at\u00ebher\u00eb p\u00ebr k\u00ebt\u00eb p\u00ebrdoret funksioni:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">mblk_t *esballoc(uint8_t *buf, int size, int pri, void (*freefn)(void*)); <\/code><\/pre>\n<p><\/p>\n<p>Funksioni pas krijimit t\u00eb mesazhit dhe struktur\u00ebs s\u00eb bllokut t\u00eb t\u00eb dh\u00ebnave, do t\u00eb konfiguroj\u00eb treguesit e tij p\u00ebr t\u00eb dh\u00ebna n\u00eb adres\u00ebn <em>buf<\/em>. Pra, n\u00eb k\u00ebt\u00eb rast buffer-in e t\u00eb dh\u00ebnave nuk ndodhet pas fushave t\u00eb titullit t\u00eb bllokut t\u00eb t\u00eb dh\u00ebnave, si\u00e7 ishte kur u krijua blloku i t\u00eb dh\u00ebnave nga funksioni <em>datab_alloc()<\/em>. Buffer-i i t\u00eb dh\u00ebnave i kaluar funksionit do t\u00eb mbetet atje ku ishte, por me an\u00eb t\u00eb treguesve do t\u00eb lidhet me titullin e sapokrijuar t\u00eb bllokut t\u00eb t\u00eb dh\u00ebnave, dhe ai p\u00ebrkat\u00ebsisht me mesazhin.<\/p>\n<p><\/p>\n<p>Nj\u00eb mesazhi <em>mblk_t<\/em> mundu t\u00eb lidhen disa blloqe t\u00eb dh\u00ebnash radhazi. Kjo b\u00ebhet me funksionin:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">mblk_t * appendb(mblk_t *mp, const char *data, int size, bool_t pad); <\/code><\/pre>\n<p><\/p>\n<p><em>mp<\/em> \u2014 mesazhi n\u00eb t\u00eb cilin do t\u00eb shtohet nj\u00eb bllok i ri t\u00eb dh\u00ebnash;<br \/>\n<em>data<\/em> \u2014 treguesi n\u00eb bllokun, kopja e t\u00eb cilit do t\u00eb shtohet n\u00eb mesazh;<br \/>\n<em>size<\/em> \u2014 madh\u00ebsia e t\u00eb dh\u00ebnave;<br \/>\n<em>pad<\/em> \u2014 flamuri q\u00eb tregon se madh\u00ebsia e memories e alokuar duhet t\u00eb jet\u00eb e p\u00ebrputhshme me kufirin 4 byte (plot\u00ebsimi do t\u00eb kryhet me zeros). <\/p>\n<p><\/p>\n<p>N\u00ebse n\u00eb buffer-in ekzistues t\u00eb mesazhit ka mjaft vend, data e re do t\u00eb lidhet pas t\u00eb dh\u00ebnave atje q\u00eb jan\u00eb tashm\u00eb. N\u00ebse nuk ka mjaft vend n\u00eb buffer-in e t\u00eb dh\u00ebnave t\u00eb mesazhit <em>size<\/em>, at\u00ebher\u00eb krijohet nj\u00eb mesazh i ri, me nj\u00eb buffer t\u00eb mjaftuesh\u00ebm dhe t\u00eb dh\u00ebnat kopjohen n\u00eb buffer-in e tij. Ky mesazh i ri do t\u00eb lidhet me origjinalin me an\u00eb t\u00eb treguesit <em>b_cont,<\/em>. N\u00eb k\u00ebt\u00eb rast mesazhi shnd\u00ebrrohet n\u00eb nj\u00eb tuple. <\/p>\n<p><\/p>\n<p>N\u00ebse n\u00eb tuple k\u00ebrkohet t\u00eb shtohet nj\u00eb bllok i ri t\u00eb dh\u00ebnash, at\u00ebher\u00eb duhet t\u00eb p\u00ebrdoret funksioni:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void msgappend(mblk_t *mp, const char *data, int size, bool_t pad);<\/code><\/pre>\n<p><\/p>\n<p>ai do t\u00eb gjej\u00eb mesazhin e fundit n\u00eb tuple (ai <em>b_cont,<\/em> do t\u00eb ket\u00eb zero) dhe do t\u00eb th\u00ebrras\u00eb p\u00ebr k\u00ebt\u00eb mesazh funksionin <em>appendb()<\/em>.<\/p>\n<p><\/p>\n<p>P\u00ebr t\u00eb ditur madh\u00ebsin\u00eb e t\u00eb dh\u00ebnave n\u00eb mesazh ose tuple mund t\u00eb p\u00ebrdoret funksioni:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">int msgdsize(const mblk_t *mp);<\/code><\/pre>\n<p><\/p>\n<p>ai do t\u00eb kaloj\u00eb n\u00ebp\u00ebr t\u00eb gjitha mesazhet e tuple dhe do t\u00eb kthej\u00eb numrin total t\u00eb t\u00eb dh\u00ebnave n\u00eb buffer-at e k\u00ebtyre mesazheve. P\u00ebr \u00e7do mesazh numri i t\u00eb dh\u00ebnave llogaritet k\u00ebshtu:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\"> mp-&gt;b_wptr - mp-&gt;b_rptr<\/code><\/pre>\n<p><\/p>\n<p>P\u00ebr t\u00eb bashkuar dy tuple aplikohet funksioni:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">mblk_t *concatb(mblk_t *mp, mblk_t *newm);<\/code><\/pre>\n<p><\/p>\n<p>ai lidhet tuple <em>newm<\/em> n\u00eb fund t\u00eb tuple <em>mp<\/em> dhe kthen treguesin n\u00eb mesazhin e fundit t\u00eb tuple t\u00eb krijuar.<\/p>\n<p><\/p>\n<p>N\u00ebse \u00ebsht\u00eb e nevojshme, tuple mund t\u00eb shnd\u00ebrrohet n\u00eb nj\u00eb mesazh t\u00eb vetme me nj\u00eb bllok t\u00eb vet\u00ebm t\u00eb dh\u00ebnash, kjo b\u00ebhet me funksionin:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void msgpullup(mblk_t *mp,int len);<\/code><\/pre>\n<p><\/p>\n<p>n\u00ebse argumenti <em>len<\/em> \u00ebsht\u00eb i barabart\u00eb me -1, at\u00ebher\u00eb madh\u00ebsia e buffer-it t\u00eb alokuar p\u00ebrcaktohet automatikisht. N\u00ebse <em>len<\/em> \u00ebsht\u00eb nj\u00eb num\u00ebr pozitiv, at\u00ebher\u00eb do t\u00eb krijohet nj\u00eb buffer i k\u00ebtij madh\u00ebsie dhe n\u00eb t\u00eb do t\u00eb kopjohen t\u00eb dh\u00ebnat e mesazheve t\u00eb tuple. N\u00ebse buffer-i p\u00ebrfundon, at\u00ebher\u00eb kopjimi do t\u00eb nd\u00ebrpritet k\u00ebtu. Mesazhi i par\u00eb i tuple do t\u00eb marr\u00eb nj\u00eb buffer t\u00eb madh\u00ebsis\u00eb s\u00eb re me t\u00eb dh\u00ebna t\u00eb kopjuara. Mesazhet e tjera do t\u00eb fshihen dhe memoria do t\u2019i kthehet grumbullit.<\/p>\n<p><\/p>\n<p>N\u00eb heqjen e struktur\u00ebs <em>mblk_t<\/em> merret parasysh numri i referencave t\u00eb bllokut t\u00eb t\u00eb dh\u00ebnave, n\u00ebse gjat\u00eb thirrjes <em>freeb()<\/em> ai rezulton t\u00eb jet\u00eb zero, at\u00ebher\u00eb buffer-i i t\u00eb dh\u00ebnave hiqet s\u00eb bashku me instanc\u00ebn <em>mblk_t<\/em>q\u00eb e tregon at\u00eb.<\/p>\n<p><\/p>\n<p>Inicializimi i fushave t\u00eb mesazhit t\u00eb ri:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void mblk_init(mblk_t *mp);<\/code><\/pre>\n<p><\/p>\n<p>Shtimi n\u00eb mesazh nj\u00eb sasie t\u00eb re t\u00eb t\u00eb dh\u00ebnave: <\/p>\n<p><\/p>\n<pre><code class=\"cpp\">mblk_t * appendb(mblk_t *mp, const char *data, size_t size, bool_t pad);<\/code><\/pre>\n<p><\/p>\n<p>N\u00ebse t\u00eb dh\u00ebnat e reja nuk p\u00ebrshtaten n\u00eb hap\u00ebsir\u00ebn e lir\u00eb t\u00eb buffers, do t'i bashk\u00eblidhet mesazhit nj\u00eb mesazh i krijuar ve\u00e7mas me bufferin e nevojsh\u00ebm (n\u00eb mesazhin e par\u00eb vendoset nj\u00eb tregues drejt mesazhit t\u00eb shtuar) mesazhi shnd\u00ebrrohet n\u00eb nj\u00eb tuple.<\/p>\n<p><\/p>\n<p>Shtimi i nj\u00eb porcioni t\u00eb dh\u00ebnash n\u00eb tuple:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void msgappend(mblk_t *mp, const char *data, size_t size, bool_t pad); <\/code><\/pre>\n<p><\/p>\n<p>Funksioni th\u00ebrret appendb() n\u00eb nj\u00eb cik\u00ebl.<\/p>\n<p><\/p>\n<p>P\u00ebrbashkimi i dy tuple n\u00eb nj\u00eb:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">mblk_t *concatb(mblk_t *mp, mblk_t *newm);<\/code><\/pre>\n<p><\/p>\n<p>Mesazhi <em>newm<\/em> do t\u00eb bashk\u00eblidhet me <em>mp<\/em>.<\/p>\n<p><\/p>\n<p>Krijimi i nj\u00eb kopjeje t\u00eb nj\u00eb mesazhi:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">mblk_t *copyb(const mblk_t *mp);<\/code><\/pre>\n<p><\/p>\n<p>Kopjimi i plot\u00eb i tuple me t\u00eb gjitha blloqet e t\u00eb dh\u00ebnave:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">mblk_t *copymsg(const mblk_t *mp);<\/code><\/pre>\n<p><\/p>\n<p>Elementet e tuple n\u00eb k\u00ebt\u00eb m\u00ebnyr\u00eb kopjohen nga funksioni <em>copyb()<\/em>.<\/p>\n<p><\/p>\n<p>Krijimi i nj\u00eb kopje t\u00eb leht\u00eb t\u00eb mesazhit. N\u00eb k\u00ebt\u00eb rast, blloku i t\u00eb dh\u00ebnave nuk kopjohet, por numri i referencave t\u00eb tij rritet <em>mblk_t<\/em>mblk_t *dupb(mblk_t *mp); <em>db_ref<\/em>:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">Krijimi i nj\u00eb kopjeje t\u00eb leht\u00eb t\u00eb tuple. Blloqet e t\u00eb dh\u00ebnave nuk kopjohen, vet\u00ebm numrat e referencave rriten<\/code><\/pre>\n<p><\/p>\n<p>mblk_t *dupmsg(mblk_t* m); <em>db_ref<\/em>:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">Bashkimi i t\u00eb gjitha mesazheve t\u00eb tuple n\u00eb nj\u00eb mesazh:<\/code><\/pre>\n<p><\/p>\n<p>void msgpullup(mblk_t *mp, size_t len);<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">N\u00ebse argumenti<\/code><\/pre>\n<p><\/p>\n<p>\u00ebsht\u00eb i barabart\u00eb me -1, at\u00ebher\u00eb madh\u00ebsia e bufferit t\u00eb rezervuar p\u00ebrcaktohet automatikisht. <em>len<\/em> Kastrimi i mesazhit, tuple:<\/p>\n<p><\/p>\n<p>void freemsg(mblk_t *mp);<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">Numri i referencave t\u00eb bllokut t\u00eb t\u00eb dh\u00ebnave zvog\u00eblohet me nj\u00eb. N\u00ebse arrin zero, at\u00ebher\u00eb blloku i t\u00eb dh\u00ebnave gjithashtu fshihet.<\/code><\/pre>\n<p><\/p>\n<p>Num\u00ebrimi i volumit total t\u00eb t\u00eb dh\u00ebnave n\u00eb mesazh ose tuple.<\/p>\n<p><\/p>\n<p>size_t msgdsize(const mblk_t *mp);<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">Nxjerrja e mesazhit nga bishti i radh\u00ebs:<\/code><\/pre>\n<p><\/p>\n<p>mblk_t *ms_queue_peek_last (q);<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">Kopjimi i p\u00ebrmbajtjes s\u00eb fushave t\u00eb rezervuara t\u00eb nj\u00eb mesazhi n\u00eb nj\u00eb mesazh tjet\u00ebr (n\u00eb t\u00eb v\u00ebrtet\u00eb n\u00eb k\u00ebto fusha ndodhen flamujt q\u00eb p\u00ebrdoren nga media streameri):<\/code><\/pre>\n<p><\/p>\n<p>mblk_meta_copy(const mblk_t *source, mblk *dest);<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">Radh\u00ebt e mesazheve n\u00eb media streamer jan\u00eb t\u00eb implementuara si nj\u00eb list\u00eb dyfishe cirkulluese. \u00c7do element i list\u00ebs p\u00ebrmban nj\u00eb tregues drejtp\u00ebrdrejt n\u00eb bllokun e t\u00eb dh\u00ebnave me matjet e sinjalit. K\u00ebshtu, n\u00eb radh\u00eb l\u00ebvizin vet\u00ebm treguesit n\u00eb bllokun e t\u00eb dh\u00ebnave, nd\u00ebrsa vet\u00eb t\u00eb dh\u00ebnat mbeten t\u00eb pal\u00ebvizshme. Pra, l\u00ebvizin vet\u00ebm referencat p\u00ebr to.<\/code><\/pre>\n<p><\/p>\n<h3 id=\"ochered-queue_t\">Radhitja <em>queue_t<\/em><\/h3>\n<p><\/p>\n<p>Struktura q\u00eb p\u00ebrshkruan radh\u00ebn<br \/>\n, tregohet m\u00eb posht\u00eb: <em>queue_t<\/em>typedef struct _queue\n{\n   mblk_t _q_stopper; \/* \"Element i zbraz\u00ebt\" i radh\u00ebs, nuk tregon n\u00eb t\u00eb dh\u00ebna, p\u00ebrdoret vet\u00ebm p\u00ebr menaxhimin e radh\u00ebs. Gjat\u00eb inicializimit t\u00eb radh\u00ebs (qinit()) treguesit e tij konfigurohen q\u00eb t\u00eb tregojn\u00eb p\u00ebr veten e tij. *\/\n   int q_mcount;        \/\/ Numri i elementeve n\u00eb radh\u00eb.\n} queue_t;<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">typedef struct _queue\n{\n   mblk_t _q_stopper; \/* \"Elementi bos\" i radh\u00ebs, nuk tregon p\u00ebr t\u00eb dh\u00ebna, p\u00ebrdoret vet\u00ebm p\u00ebr menaxhimin e radh\u00ebs. Gjat\u00eb inicializimit t\u00eb radh\u00ebs (qinit()), treguesit e tij rregullohen q\u00eb t\u00eb tregojn\u00eb p\u00ebr vetveten. *\/\n   int q_mcount;        \/\/ Numri i elementeve n\u00eb radh\u00eb.\n} queue_t;<\/code><\/pre>\n<p><\/p>\n<p>_q_stopper <em>n\u00eb tipin *mblk_t, ai tregon n\u00eb elementin e par\u00eb (mesazhin) n\u00eb radh\u00eb. Fusha e dyt\u00eb e struktur\u00ebs \u00ebsht\u00eb numri i mesazheve q\u00eb ndodhen n\u00eb radh\u00eb.<\/em> N\u00eb figur\u00ebn m\u00eb posht\u00eb tregohet radh\u00eb c me emrin q1, q\u00eb p\u00ebrmban 4 mesazhe m1, m2, m3, m4.<br \/>\nN\u00eb figur\u00ebn tjet\u00ebr tregohet radh\u00eb c me emrin q1, q\u00eb p\u00ebrmban 4 mesazhe m1, m2, m3, m4. Mesazhi m2 \u00ebsht\u00eb koka e tuple, n\u00eb t\u00eb cil\u00ebn lidhen edhe dy mesazhe m2_1 dhe m2_2.<br \/>\n<img decoding=\"async\" alt=\"Studimi i motorit VoIP Mediastreamer2. Pjesa 11\" src=\"\/wp-content\/uploads\/2020\/04\/07fc043861edf15e5eb40e49c8ec5e3e.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nInicializimi i radh\u00ebs:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Studimi i motorit VoIP Mediastreamer2. Pjesa 11\" src=\"\/wp-content\/uploads\/2020\/04\/8fa7667f3690674a2ee321b4a6c39e1d.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<h3 id=\"funkcii-raboty-s-ocheredyami-queue_t\">Funksionet p\u00ebr menaxhimin e rrjeteve queue_t<\/h3>\n<p><\/p>\n<p>void qinit(queue_t *q);<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">(m\u00eb tej do ta quajm\u00eb \"stoper\") inicializohet nga funksioni<\/code><\/pre>\n<p><\/p>\n<p>Fusha <em>n\u00eb tipin *mblk_t, ai tregon n\u00eb elementin e par\u00eb (mesazhin) n\u00eb radh\u00eb. Fusha e dyt\u00eb e struktur\u00ebs \u00ebsht\u00eb numri i mesazheve q\u00eb ndodhen n\u00eb radh\u00eb.<\/em> (duke e quajtur at\u00eb \"stopar\") inicializohet nga funksioni <em>mblk_init()<\/em>Shtimi i nj\u00eb elementi t\u00eb ri (mesazhit):<\/p>\n<p><\/p>\n<p>void putq(queue_t *q, mblk_t *m);<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">Elementi i ri<\/code><\/pre>\n<p><\/p>\n<p>shtohet n\u00eb fund t\u00eb list\u00ebs, treguesit e elementit konfigurohen q\u00eb stopper t\u00eb b\u00ebhet elementi i ardhsh\u00ebm p\u00ebr t\u00eb, dhe ai p\u00ebr stopperin e m\u00ebparsh\u00ebm. Numri i elementeve t\u00eb radh\u00ebs rritet. <em>m<\/em> Nxjerrja e nj\u00eb elementi nga radh\u00eb:<\/p>\n<p><\/p>\n<p>mblk_t * getq(queue_t *q);<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">nxjerret ai mesazh q\u00eb ndodhet pas stopperit, numri i elementeve zvog\u00eblohet. N\u00ebse n\u00eb radh\u00eb, p\u00ebrve\u00e7 stoperit, nuk ka elemente, at\u00ebher\u00eb kthehet 0. <\/code><\/pre>\n<p><\/p>\n<p>Shtimi i mesazhit n\u00eb radh\u00eb:<\/p>\n<p><\/p>\n<p>void insq(queue_t *q, mblk_t *emp, mblk_t *mp);<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">shtohet para elementit <\/code><\/pre>\n<p><\/p>\n<p>Element <em>mp<\/em> emp <em>=0, at\u00ebher\u00eb mesazhi shtohet n\u00eb fund t\u00eb radh\u00ebs.<\/em>. N\u00ebse <em>=0, at\u00ebher\u00eb mesazhi shtohet n\u00eb fund t\u00eb radh\u00ebs.<\/em>Nxjerrja e mesazhit nga koka e radh\u00ebs:<\/p>\n<p><\/p>\n<p>void remq(queue_t *q, mblk_t *mp);<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">Numri i elementeve zvog\u00eblohet. <\/code><\/pre>\n<p><\/p>\n<p>Leximi i treguesit t\u00eb elementit t\u00eb par\u00eb n\u00eb radh\u00eb:<\/p>\n<p><\/p>\n<p>mblk_t * peekq(queue_t *q);<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">Fshirja e t\u00eb gjith\u00eb elementeve nga radha me fshirjen e vet\u00eb elementeve: <\/code><\/pre>\n<p><\/p>\n<p>void flushq(queue_t *q, int how);<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">si<\/code><\/pre>\n<p><\/p>\n<p>Argumenti <em>nuk p\u00ebrdoret. Numri i elementeve t\u00eb radh\u00ebs vendoset n\u00eb zero.<\/em> Makro p\u00ebr leximin e treguesit n\u00eb elementin e fundit t\u00eb radh\u00ebs:<\/p>\n<p><\/p>\n<p>mblk_t * qlast(queue_t *q);<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">Gjat\u00eb pun\u00ebs me radh\u00ebt e mesazheve duhet t\u00eb kemi parasysh se gjat\u00eb thirrjes<\/code><\/pre>\n<p><\/p>\n<p>ms_queue_put(q, m) <em>me nj\u00eb tregues null n\u00eb mesazh, funksioni do t\u00eb ngulfatet. Programi juaj do t\u00eb ngec\u00eb. Nj\u00eblloj sillet edhe<\/em> ms_queue_next(q, m) <em>ms_queue_next(q, m)<\/em>.<\/p>\n<p><\/p>\n<h3 id=\"soedinenie-filtrov\">Lidhja e filtrave<\/h3>\n<p><\/p>\n<p>Radh\u00ebt e p\u00ebrshkruara m\u00eb sip\u00ebr p\u00ebrdoren p\u00ebr t\u00eb kaluar mesazhe nga nj\u00eb filtrues te tjetri ose nga nj\u00eb deri n\u00eb disa filtrues. Filtruesit dhe lidhjet e tyre formojn\u00eb nj\u00eb grafik t\u00eb orientuar. Hyrja ose dalja e filtruesit do ta quajm\u00eb me fjal\u00ebn e gjer\u00eb \"pin\". P\u00ebr t\u00eb p\u00ebrshkruar rendin e lidhjeve midis filtruesve, mediastreameri p\u00ebrdor konceptin \"pik\u00eb sinjali\". Pik\u00eb sinjali \u00ebsht\u00eb nj\u00eb struktur\u00eb <em>_MSCPoint<\/em>, e cila p\u00ebrmban nj\u00eb tregues n\u00eb filt\u00ebr dhe numrin e nj\u00ebrit prej pins, p\u00ebrkat\u00ebsisht ajo p\u00ebrshkruan lidhjen e nj\u00ebrit prej hyrjeve ose daljeve t\u00eb filtrit. <\/p>\n<p><\/p>\n<h4 id=\"signalnaya-tochka-grafa-obrabotki-dannyh\">Pika e sinjalizimit n\u00eb grafikun e p\u00ebrpunimit t\u00eb t\u00eb dh\u00ebnave<\/h4>\n<p><\/p>\n<pre><code class=\"cpp\">typedef struct _MSCPoint{\nstruct _MSFilter *filter; \/\/ Treguesi n\u00eb filt\u00ebrin e mediastreamer.\nint pin;                        \/\/ Numri i nj\u00ebrit prej hyrjeve ose daljeve t\u00eb filtrit, dmth. pin.\n} MSCPoint;\n<\/code><\/pre>\n<p><\/p>\n<p>Pin e filtrave num\u00ebrohen duke filluar nga zero. <\/p>\n<p><\/p>\n<p>Lidhja midis dy pins me radh\u00ebn e mesazheve p\u00ebrshkruhet nga struktura <em>_MSQueue<\/em>, e cila p\u00ebrmban nj\u00eb radh\u00eb mesazhesh dhe tregues n\u00eb dy pika sinjali, t\u00eb cilat ajo i lidh:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">typedef struct _MSQueue\n{\nqueue_t q;\nMSCPoint prev;\nMSCPoint next;\n}MSQueue;\n<\/code><\/pre>\n<p><\/p>\n<p>Do ta quajm\u00eb k\u00ebt\u00eb struktur\u00eb si lidhjen e sinjalit. \u00c7do filt\u00ebr i mediastreamer, p\u00ebrmban nj\u00eb tabel\u00eb lidhjesh hyr\u00ebse dhe nj\u00eb tabel\u00eb lidhjesh dal\u00ebse (<em>MSQueue<\/em>). Madh\u00ebsia e tabelave p\u00ebrcaktohet kur krijohet filtri, ne tashm\u00eb kemi b\u00ebr\u00eb k\u00ebt\u00eb me ndihm\u00ebn e nj\u00eb variabli t\u00eb eksportuar t\u00eb tipit <em>MSFilterDesc<\/em>, kur po zhvillonim filtrin ton\u00eb. M\u00eb posht\u00eb \u00ebsht\u00eb e paraqitur struktura q\u00eb p\u00ebrshkruan \u00e7do filt\u00ebr n\u00eb mediastreamer, <em>MSFilter<\/em>:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">\nstruct _MSFilter{\n    MSFilterDesc *desc;    \/* Treguesi n\u00eb deshkruesin e filtrit. *\/\n    \/* Atributet e mbrojtura, nuk mund t\u00eb l\u00ebvizen apo hiqen ndryshe do t\u00eb d\u00ebmtohet funksionimi me pluginet. *\/\n    ms_mutex_t lock;      \/* Semafori. *\/\n    MSQueue **inputs;     \/* Tabela e lidhjeve hyr\u00ebse. *\/\n    MSQueue **outputs;    \/* Tabela e lidhjeve dal\u00ebse. *\/\n    struct _MSFactory *factory; \/* Treguesi n\u00eb fabrik\u00ebn q\u00eb krijoi k\u00ebt\u00eb instanc\u00eb filtri. *\/\n    void *padding;              \/* Nuk p\u00ebrdoret, do t\u00eb aktivizohet n\u00ebse shtohen fusha t\u00eb mbrojtura. *\/\n    void *data;                 \/* Treguesi n\u00eb nj\u00eb struktur\u00eb t\u00eb rast\u00ebsishme p\u00ebr ruajtjen e t\u00eb dh\u00ebnave t\u00eb gjendjes s\u00eb brendshme t\u00eb filtrit dhe llogaritjeve nd\u00ebrmjet\u00ebse. *\/\n    struct _MSTicker *ticker;   \/* Treguesi n\u00eb objektin ticker, i cili nuk duhet t\u00eb jet\u00eb zero kur thirret funksioni process(). *\/\n    \/* Atributet private, ato mund t\u00eb l\u00ebvizen dhe ndryshohen n\u00eb \u00e7do koh\u00eb *\/\n    MSList *notify_callbacks; \/* Lista e thirrjeve kthyes, q\u00eb p\u00ebrdoren p\u00ebr t\u00eb trajtuar ngjarjet e filtrit. *\/\n    uint32_t last_tick;       \/* Numri i ciklit t\u00eb fundit, kur \u00ebsht\u00eb kryer thirrja process(). *\/ \n    MSFilterStats *stats;     \/* Statistika e pun\u00ebs s\u00eb filtrit.*\/\n    int postponed_task; \/*Numri i detyrave t\u00eb shtyra. Disa filtra mund t\u00eb shtyjn\u00eb p\u00ebrpunimin e t\u00eb dh\u00ebnave (thirjen e process()) p\u00ebr disa cikle.*\/\n    bool_t seen;  \/* Flaqi, q\u00eb p\u00ebrdoret nga ticker, p\u00ebr t\u00eb sh\u00ebnuar se ky instanc\u00eb filtri e ka sh\u00ebrbyer tashm\u00eb n\u00eb k\u00ebt\u00eb cik\u00ebl.*\/\n};\ntypedef struct _MSFilter MSFilter;\n<\/code><\/pre>\n<p><\/p>\n<p>Pas lidhjes s\u00eb filtrave n\u00eb programin C sipas konceptit ton\u00eb (por pa lidhur ticker-in), ne k\u00ebshtu krijuam nj\u00eb grafik t\u00eb drejtuar, ku nodet jan\u00eb instancat e struktur\u00ebs <em>MSFilter<\/em>, nd\u00ebrsa skajor\u00ebt jan\u00eb instancat e lidhjeve <em>MSQueue<\/em>. <\/p>\n<p><\/p>\n<h3 id=\"zakulisnaya-deyatelnost-tikera\">Aktiviteti i prapasken\u00ebs i ticker-it<\/h3>\n<p><\/p>\n<p>Kur ju thash\u00eb se ticker \u00ebsht\u00eb nj\u00eb filt\u00ebr burimi i cikleve, nuk ishte e v\u00ebrteta e plot\u00eb p\u00ebr t\u00eb. Ticker \u00ebsht\u00eb nj\u00eb objekt q\u00eb p\u00ebr \u00e7do cik\u00ebl ekzekuton funksionet <em>process()<\/em> e t\u00eb gjith\u00eb filtruesve t\u00eb skem\u00ebs (grafit) t\u00eb cilit iu bashkua. Kur ne n\u00eb programin C lidhim nj\u00eb ticker me filtrin e grafit, ne i tregojm\u00eb tickers grafikun q\u00eb nga ky moment do t\u00eb menaxhoj\u00eb, derisa ta \u00e7lirojm\u00eb. Pas lidhjes, ticker fillon t\u00eb shqyrtoj\u00eb grafikun e besuar, duke p\u00ebrpiluar nj\u00eb list\u00eb t\u00eb filtruesve q\u00eb p\u00ebrfshihen n\u00eb t\u00eb. P\u00ebr t\u00eb mos \"num\u00ebruar\" t\u00eb nj\u00ebjtin filtrues dy her\u00eb, ai i sh\u00ebnon filtruesit e zbuluar, duke vendosur nj\u00eb flamur n\u00eb to. <em>seen<\/em>. K\u00ebrkimi zhvillohet n\u00ebp\u00ebr tabelat e lidhjeve q\u00eb ka \u00e7do filt\u00ebr. <\/p>\n<p><\/p>\n<p>Gjat\u00eb excursioneve t\u00eb tij informative n\u00ebp\u00ebr grafik, ticker kontrollon n\u00ebse ka ndonj\u00eb filt\u00ebr q\u00eb luan rolin e burimit t\u00eb blok\u00ebve t\u00eb t\u00eb dh\u00ebnave. N\u00ebse nuk gjenden t\u00eb till\u00eb, grafiku shpallet i gabuar dhe ticker p\u00ebrfundon pun\u00ebn n\u00eb m\u00ebnyr\u00eb emergjente.<\/p>\n<p><\/p>\n<p>N\u00ebse grafiku rezulton t\u00eb jet\u00eb \"i sakt\u00eb\", p\u00ebr \u00e7do filtrues t\u00eb gjetur, funksioni p\u00ebr inicializim thirret <em>preprocess()<\/em>. Sa her\u00eb q\u00eb arrin momenti p\u00ebr ciklin tjet\u00ebr t\u00eb p\u00ebrpunimit (me default \u00e7do 10 milisekonda), ticker th\u00ebrret funksionin <em>process()<\/em> p\u00ebr t\u00eb gjith\u00eb filtrat burim\u00eb t\u00eb gjetur m\u00eb par\u00eb dhe m\u00eb pas edhe p\u00ebr filtrat e tjer\u00eb t\u00eb list\u00ebs. N\u00ebse filt\u00ebr ka lidhje hyr\u00ebse, at\u00ebher\u00eb aktivizimi i funksionit <em>process()<\/em> p\u00ebr t\u00eb vazhduar derisa radh\u00ebt e lidhjeve hyr\u00ebse t\u00eb shkarkohen. Pas k\u00ebsaj, ai kalon te filtruesi tjet\u00ebr i list\u00ebs dhe \"rrokulliset\" deri n\u00eb \u00e7lirimin e lidhjeve hyr\u00ebse nga mesazhet. Ticker kalon nga filtruesi n\u00eb filtrues derisa t\u00eb p\u00ebrfundoj\u00eb lista. N\u00eb k\u00ebt\u00eb pik\u00eb, p\u00ebrpunimi i ciklit p\u00ebrfundon. <\/p>\n<p><\/p>\n<p>Tani, ne do t\u00eb kthehemi tek tuples dhe do t\u00eb flasim p\u00ebr arsyen pse nj\u00eb struktur\u00eb e till\u00eb u shtua n\u00eb mediastreamer. N\u00eb p\u00ebrgjith\u00ebsi, sasia e t\u00eb dh\u00ebnave t\u00eb nevojshme p\u00ebr algoritmin q\u00eb funksionon brenda filtrit nuk p\u00ebrputhet dhe nuk \u00ebsht\u00eb shum\u00ebfish i madh\u00ebsis\u00eb s\u00eb bufereve t\u00eb t\u00eb dh\u00ebnave q\u00eb po vijn\u00eb. P\u00ebr shembull, ne shkruajm\u00eb nj\u00eb filtr\u00eb q\u00eb b\u00ebn nj\u00eb transformim t\u00eb shpejt\u00eb t\u00eb Fourier-it, i cili sipas definicionit mund t\u00eb p\u00ebrpunoj\u00eb vet\u00ebm blloqe t\u00eb t\u00eb dh\u00ebnave, ku madh\u00ebsia \u00ebsht\u00eb nj\u00eb fuqi e dyshes. Le t\u00eb jet\u00eb kjo 512 pika. N\u00ebse t\u00eb dh\u00ebnat gjenerohen nga nj\u00eb kanal telefonik, buffering i \u00e7do mesazhi n\u00eb hyrje do t\u00eb na sjell\u00eb 160 pika sinjali. Ekziston nj\u00eb tundim p\u00ebr t\u00eb mos marr\u00eb t\u00eb dh\u00ebna nga hyrja derisa t\u00eb ket\u00eb sasi t\u00eb nevojshme t\u00eb t\u00eb dh\u00ebnave. Por n\u00eb k\u00ebt\u00eb rast do t\u00eb shfaqej nj\u00eb konflikt me ticker-in, i cili do t\u00eb p\u00ebrpiqej pa sukses t\u00eb rrotullonte filtrin deri sa t\u00eb zbrazte linj\u00ebn e hyrjes. M\u00eb par\u00eb e kemi quajtur k\u00ebt\u00eb rregull si parimi i tret\u00eb i funksionimit t\u00eb filtrit. Sipas k\u00ebtij parimi, funksioni process() i filtrit duhet t\u00eb marr\u00eb t\u00eb gjitha t\u00eb dh\u00ebnat nga radh\u00ebt hyr\u00ebse.<\/p>\n<p><\/p>\n<p>P\u00ebrve\u00e7 k\u00ebsaj, nga hyrja nuk mund t\u00eb merren vet\u00ebm 512 pika, pasi q\u00eb mund t\u00eb merren vet\u00ebm blloqe t\u00eb plota, pra, filtrit do t\u2019i duhet t\u00eb marr\u00eb 640 pika dhe duke p\u00ebrdorur 512 nga ato, derisa t\u00eb akumuloj\u00eb sasin\u00eb e re t\u00eb t\u00eb dh\u00ebnave. N\u00eb k\u00ebt\u00eb m\u00ebnyr\u00eb, filtrat tan\u00eb, p\u00ebrve\u00e7 funksionit t\u00eb tij kryesor, duhet t\u00eb siguroj\u00eb veprime ndihm\u00ebse p\u00ebr ruajtjen e p\u00ebrkohshme t\u00eb t\u00eb dh\u00ebnave n\u00eb hyrje. Zhvilluesit e mediastreamer-it p\u00ebr zgjidhjen e k\u00ebsaj problemi t\u00eb p\u00ebrgjithsh\u00ebm kan\u00eb zhvilluar nj\u00eb objekt t\u00eb ve\u00e7ant\u00eb - MSBufferizer (bufferizer), i cili zgjidh k\u00ebt\u00eb problem duke p\u00ebrdorur tuples. <\/p>\n<p><\/p>\n<h3 id=\"buferizator-msbufferizer\">Bufferizuesi (MSBufferizer)<\/h3>\n<p><\/p>\n<p>Ky \u00ebsht\u00eb nj\u00eb objekt q\u00eb do t\u00eb akumuloj\u00eb t\u00eb dh\u00ebnat hyr\u00ebse brenda filtrit dhe do t\u00eb filloj\u00eb t'i jap\u00eb ato p\u00ebr p\u00ebrpunim, sapo sasia e informacionit t\u00eb jet\u00eb e mjaftueshme p\u00ebr t\u00eb realizuar algoritmin e filtrit. Nd\u00ebrsa bufferizatori akumulohet t\u00eb dh\u00ebna, filtri do t\u00eb punoj\u00eb n\u00eb modin bosh, pa shpenzuar kapacitetin llogarit\u00ebs t\u00eb procesorit. Por sapo funksioni i leximit nga bufferizatori t\u00eb kthej\u00eb nj\u00eb vler\u00eb t\u00eb ndryshme nga zero, funksioni process() i filtrit fillon t\u00eb marr\u00eb dhe t\u00eb p\u00ebrpunoj\u00eb t\u00eb dh\u00ebnat nga bufferizatori n\u00eb sasi t\u00eb nevojshme, deri n\u00eb p\u00ebrfundimin e tyre.<br \/>\nT\u00eb dh\u00ebnat e pa k\u00ebrkuara mbeten n\u00eb bufferizator si elementi i par\u00eb i tuples, i cili lidhet me blloqet e ardhshme t\u00eb t\u00eb dh\u00ebnave hyr\u00ebse. <\/p>\n<p><\/p>\n<p>Struktura q\u00eb p\u00ebrshkruan bufferizatorin: <\/p>\n<p><\/p>\n<pre><code class=\"cpp\">struct _MSBufferizer{\nqueue_t q; \/* Radh\u00ebt e mesazheve. *\/\nint size; \/* Sasia totale e t\u00eb dh\u00ebnave q\u00eb ndodhen n\u00eb bufferizator n\u00eb k\u00ebt\u00eb moment. *\/\n};\ntypedef struct _MSBufferizer MSBufferizer;<\/code><\/pre>\n<p><\/p>\n<h3 id=\"funkcii-raboty-s-msbufferizer\">Funksionet p\u00ebr menaxhimin e MSBufferizer<\/h3>\n<p><\/p>\n<p>Krijimi i nj\u00eb ekzemplar t\u00eb ri t\u00eb bufferizatorit:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">MSBufferizer * ms_bufferizer_new(void);<\/code><\/pre>\n<p><\/p>\n<p>Memoria ndahet, inicializohet n\u00eb <em>ms_bufferizer_init()<\/em> dhe kthehet treguesi.<\/p>\n<p><\/p>\n<p>Funksioni i inicializimit:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void ms_bufferizer_init(MSBufferizer *obj); <\/code><\/pre>\n<p><\/p>\n<p>Inicializohet radh\u00ebt <em>q<\/em>, fush\u00eb <em>size<\/em> vendoset n\u00eb zero.<\/p>\n<p><\/p>\n<p>Shtimi i nj\u00eb mesazhi:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void ms_bufferizer_put(MSBufferizer *obj, mblk_t *m); <\/code><\/pre>\n<p><\/p>\n<p>Mesazhi m shtohet n\u00eb radh\u00eb. Madh\u00ebsia e llogaritur e bllokut t\u00eb t\u00eb dh\u00ebnave shtohet n\u00eb <em>size<\/em>.<\/p>\n<p><\/p>\n<p>Transferta n\u00eb bufferizator e t\u00eb gjitha mesazheve nga radh\u00ebt e t\u00eb dh\u00ebnave t\u00eb lidhjes <em>q<\/em>:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void ms_bufferizer_put_from_queue(MSBufferizer *obj, MSQueue *q);   <\/code><\/pre>\n<p><\/p>\n<p>Transferimi i mesazheve nga lidhja <em>q<\/em> n\u00eb bufferizator b\u00ebhet me funksionin <em>ms_bufferizer_put()<\/em>.<\/p>\n<p><\/p>\n<p>Leximi nga bufferizatori:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">int ms_bufferizer_read(MSBufferizer *obj, uint8_t *data, int datalen); <\/code><\/pre>\n<p><\/p>\n<p>N\u00ebse madh\u00ebsia e t\u00eb dh\u00ebnave t\u00eb akumuluara n\u00eb bufferizator \u00ebsht\u00eb m\u00eb e vog\u00ebl se e k\u00ebrkuara (<em>datalen<\/em>), funksioni kthen zero, kopjimi i t\u00eb dh\u00ebnave n\u00eb data nuk kryhet. N\u00eb rastin e tjet\u00ebr kryhet kopjimi i rendit t\u00eb t\u00eb dh\u00ebnave nga tuples q\u00eb ndodhen n\u00eb bufferizator. Pas kopjimit, tuple fshihet dhe memoria lirohet. Kopjimi p\u00ebrfundon kur t\u00eb jen\u00eb kopjuar datalen byte. N\u00ebse vendi mbaron n\u00eb mes t\u00eb nj\u00eb blloku t\u00eb t\u00eb dh\u00ebnave, at\u00ebher\u00eb n\u00eb k\u00ebt\u00eb mesazh, blloku i t\u00eb dh\u00ebnave do t\u00eb shkurtohet deri n\u00eb pjes\u00ebn e mbetur q\u00eb nuk \u00ebsht\u00eb kopjuar. N\u00eb thirrjen e ardhshme, kopjimi do t\u00eb vazhdoj\u00eb nga ky vend.<\/p>\n<p><\/p>\n<p>Leximi i sasis\u00eb s\u00eb t\u00eb dh\u00ebnave q\u00eb jan\u00eb n\u00eb dispozicion n\u00eb k\u00ebt\u00eb moment n\u00eb bufferizator:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">int ms_bufferizer_get_avail(MSBufferizer *obj); <\/code><\/pre>\n<p><\/p>\n<p>Kthen fush\u00ebn <em>size<\/em> bufferizatorit.<\/p>\n<p><\/p>\n<p>Hedhja e nj\u00eb pjese t\u00eb t\u00eb dh\u00ebnave q\u00eb ndodhen n\u00eb bufferizator:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void ms_bufferizer_skip_bytes(MSBufferizer *obj, int bytes);<\/code><\/pre>\n<p><\/p>\n<p>Sasia e specifikuar e byte t\u00eb dh\u00ebnave shkurtohet dhe hidhet. Hidh\u00ebn t\u00eb dh\u00ebnat m\u00eb t\u00eb vjetra.<\/p>\n<p><\/p>\n<p>Fshirja e t\u00eb gjitha mesazheve n\u00eb bufferizator:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void ms_bufferizer_flush(MSBufferizer *obj); <\/code><\/pre>\n<p><\/p>\n<p>Numri i t\u00eb dh\u00ebnave rikthehet n\u00eb zero.<\/p>\n<p><\/p>\n<p>Fshirja e t\u00eb gjitha mesazheve n\u00eb bufferizator:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void ms_bufferizer_uninit(MSBufferizer *obj); <\/code><\/pre>\n<p><\/p>\n<p>Zeroimi i numrit nuk kryhet.<\/p>\n<p><\/p>\n<p>Fshirja e bufferizatorit dhe lirimi i memories:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void ms_bufferizer_destroy(MSBufferizer *obj);  <\/code><\/pre>\n<p><\/p>\n<p>Shembujt e p\u00ebrdorimit t\u00eb bufferizatorit mund t\u00eb gjenden n\u00eb kodin burimor t\u00eb disa filtrave n\u00eb mediastreamer. P\u00ebr shembull, n\u00eb filtrin MS_L16_ENC, i cili kryen ri-renditjen e byte-ve n\u00eb pik\u00eb nga rendi rrjetor n\u00eb rendin e hostit:<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/BelledonneCommunications\/mediastreamer2\/blob\/1a9e8dec369a65ed10db975f5b77b92dc999b096\/src\/audiofilters\/l16.c\"> l16.c<\/a><\/noindex><\/p>\n<p><\/p>\n<p>N\u00eb artikullin e ardhsh\u00ebm, ne do t\u00eb shqyrtojm\u00eb \u00e7\u00ebshtjen e vler\u00ebsimit t\u00eb ngarkes\u00ebs n\u00eb ticker dhe m\u00ebnyrat p\u00ebr t\u00eb p\u00ebrballuar ngarkes\u00ebn e tepruar t\u00eb llogaritjeve n\u00eb mediastreamer.<\/p>\n<p>Burimi: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/499010\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u0437\u044f\u0442 \u0441 \u043c\u043e\u0435\u0433\u043e \u0434\u0437\u0435\u043d-\u043a\u0430\u043d\u0430\u043b\u0430. \u041c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0411\u043b\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445 dblk_t \u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 mblk_t \u0424\u0443\u043d\u043a\u0446\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u043c\u0438 mblk_t \u041e\u0447\u0435\u0440\u0435\u0434\u044c queue_t \u0424\u0443\u043d\u043a\u0446\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043e\u0447\u0435\u0440\u0435\u0434\u044f\u043c\u0438 queue_t \u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432 \u0421\u0438\u0433\u043d\u0430\u043b\u044c\u043d\u0430\u044f \u0442\u043e\u0447\u043a\u0430 \u0433\u0440\u0430\u0444\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0417\u0430\u043a\u0443\u043b\u0438\u0441\u043d\u0430\u044f \u0434\u0435\u044f\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0442\u0438\u043a\u0435\u0440\u0430 \u0411\u0443\u0444\u0435\u0440\u0438\u0437\u0430\u0442\u043e\u0440 (MSBufferizer) \u0424\u0443\u043d\u043a\u0446\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 MSBufferizer \u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0441\u0432\u043e\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0444\u0438\u043b\u044c\u0442\u0440. \u042d\u0442\u0443 \u0441\u0442\u0430\u0442\u044c\u044e \u043c\u044b \u043f\u043e\u0441\u0432\u0435\u0442\u0438\u043c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0443 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":79541,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-79540","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u0437\u044f\u0442 \u0441 \u043c\u043e\u0435\u0433\u043e \u0434\u0437\u0435\u043d-\u043a\u0430\u043d\u0430\u043b\u0430.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/sq\/blog\/administrirovanie\/izuchaem-voip-dvizhok-mediastreamer2-chast-11\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"sq_AL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0418\u0437\u0443\u0447\u0430\u0435\u043c VoIP-\u0434\u0432\u0438\u0436\u043e\u043a Mediastreamer2. \u0427\u0430\u0441\u0442\u044c 11 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u0437\u044f\u0442 \u0441 \u043c\u043e\u0435\u0433\u043e \u0434\u0437\u0435\u043d-\u043a\u0430\u043d\u0430\u043b\u0430.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/sq\/blog\/administrirovanie\/izuchaem-voip-dvizhok-mediastreamer2-chast-11\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-04-28T05:42:01+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-04-28T05:42:01+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Po studiojm\u00eb motorin VoIP Mediastreamer2. Pjesa 11 | ProHoster","description":"Materiali i artikullit \u00ebsht\u00eb marr\u00eb nga kanali im n\u00eb Dzen.","canonical_url":"https:\/\/prohoster.info\/sq\/blog\/administrirovanie\/izuchaem-voip-dvizhok-mediastreamer2-chast-11","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sq_AL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0418\u0437\u0443\u0447\u0430\u0435\u043c VoIP-\u0434\u0432\u0438\u0436\u043e\u043a Mediastreamer2. \u0427\u0430\u0441\u0442\u044c 11 | ProHoster","og:description":"\u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u0437\u044f\u0442 \u0441 \u043c\u043e\u0435\u0433\u043e \u0434\u0437\u0435\u043d-\u043a\u0430\u043d\u0430\u043b\u0430.","og:url":"https:\/\/prohoster.info\/sq\/blog\/administrirovanie\/izuchaem-voip-dvizhok-mediastreamer2-chast-11","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-04-28T05:42:01+00:00","article:modified_time":"2020-04-28T05:42:01+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"79540","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 12:40:33","updated":"2022-10-06 16:26:59","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/posts\/79540","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/comments?post=79540"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/posts\/79540\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/media\/79541"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/media?parent=79540"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/categories?post=79540"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/tags?post=79540"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}