{"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\/sl\/blog\/administrirovanie\/izuchaem-voip-dvizhok-mediastreamer2-chast-11","title":{"rendered":"Prou\u010dujemo VoIP motor Mediastreamer2. Deo 11","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Materijal u \u010dlanku preuzet je sa mog <noindex><a rel=\"nofollow\" href=\"https:\/\/zen.yandex.ru\/profile\/editor\/id\/5e3f8e0751f5346faab4fc7a\">zen kanala<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Prou\u010dujemo VoIP motor Mediastreamer2. Deo 11\" src=\"\/wp-content\/uploads\/2020\/04\/b66fab43eb45c626c50f0383dcfa7cca.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Mehanizam prenosa podataka<\/p>\n<p><\/p>\n<ul>\n<li>Blok podataka dblk_t<\/li>\n<li>Poruka mblk_t<\/li>\n<li>Funkcije rada sa porukama mblk_t<\/li>\n<li>Red queue_t<\/li>\n<li>Funkcije rada sa redovima queue_t<\/li>\n<li>Povezivanje filtara<\/li>\n<li>Signala ta\u010dka dijagrama obrade podataka<\/li>\n<li>Zakulisna aktivnost tikera<\/li>\n<li>Bafer (MSBufferizer)<\/li>\n<li>Funkcije rada sa MSBufferizer<\/li>\n<\/ul>\n<p><\/p>\n<p>V prej\u0161njem <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/497932\/\">\u010dlanku<\/a><\/noindex> Razvili smo svoj vlastiti filtar. Ovaj \u010dlanak \u0107emo posvetiti ure\u0111aju unutra\u0161njeg mehanizma prenosa podataka izme\u0111u filtara mediastreamera. To \u0107e nam omogu\u0107iti da kasnije pi\u0161emo slo\u017eene filtre uz manje truda.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2 id=\"mehanizm-peremescheniya-dannyh\">Mehanizam prenosa podataka<\/h2>\n<p><\/p>\n<p>Prenos podataka u mediastreameru vr\u0161i se pomo\u0107u redova opisanih strukturom <em>queue_t<\/em>. Kroz redove se prenose sekvence poruka tipa <em>mblk_t<\/em>, koje same po sebi ne sadr\u017ee podatke signala, ve\u0107 samo reference na prethodnu, slede\u0107u poruku i na blok podataka. Pored toga, \u017eelim posebno naglasiti da postoji jo\u0161 jedan pokazatelj za referenciranje poruka istog tipa, \u0161to omogu\u0107ava organizovanje jednostruko povezanih lista poruka. Grupu poruka ujedinjenih takvim putem naziva\u0107emo tuplom. Tako, svaka stavka u redu mo\u017ee biti pojedina\u010dna poruka <em>mblk_t<\/em>, ili mo\u017ee biti i glava tupla poruka <em>mblk_t<\/em>. Svaka poruka tupla mo\u017ee imati svoj podra\u010dun blok podataka. Za\u0161to su tuple potrebne, razgovara\u0107emo malo kasnije.<\/p>\n<p><\/p>\n<p>Kot je bilo omenjeno zgoraj, sporo\u010dilo samo po sebi ne vsebuje bloka podatkov, temve\u010d le kazalec na obmo\u010dje pomnilnika, kjer se shranjuje blok. V tem delu celotna slika delovanja medijskega predvajalnika spominja na skladi\u0161\u010de vrat iz risanke \"Korporacija po\u0161asti\", kjer se vrata (povezave na podatke \u2014 sobe) z nebrzdno hitrostjo premikajo po vise\u010dih trakovi, medtem ko same sobe ostajajo nepremi\u010dne. <\/p>\n<p><\/p>\n<p>Sada, kre\u0107u\u0107i se kroz hijerarhiju od dna ka vrhu, detaljno \u0107emo razmotriti navedene entitete mehanizma prenosa podataka u mediastreameru.<\/p>\n<p><\/p>\n<h3 id=\"blok--dannyh-dblk_t\">Blok podataka <em>dblk_t<\/em><\/h3>\n<p><\/p>\n<p>Blok podataka se sastoji od zaglavlja i bafera podataka. Zaglavlje je opisano slede\u0107om strukturom,<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">typedef struct datab\n{\nunsigned char *db_base; \/\/ Pokaziva\u010d na po\u010detak bafera podataka.\nunsigned char *db_lim;  \/\/ Pokaziva\u010d na kraj bafera podataka.\nvoid (*db_freefn)(void*); \/\/ Funkcija za osloba\u0111anje memorije pri brisanju bloka.\nint db_ref; \/\/ Broja\u010d referenci.\n} dblk_t;<\/code><\/pre>\n<p><\/p>\n<p>Polja strukture vsebujejo kazalce na za\u010detek in konec pomnilnika, funkcijo za brisanje podatkovnega pomnilnika. Zadnji element v glavi <em>db_ref<\/em> \u2014 \u0161tevec sklicev, ko dose\u017ee ni\u010d, to slu\u017ei kot signal za brisanje tega bloka iz pomnilnika. \u010ce je blok podatkov ustvarjen s funkcijo <em>datab_alloc() <\/em>, bo podatkovni pomnilnik razmestjen v pomnilniku takoj za glavo. V vseh drugih primerih je pomnilnik lahko lo\u010deno. V podatkovnem pomnilniku bodo shranjeni signali ali drugi podatki, ki jih \u017eelimo obdelati s filtri.<\/p>\n<p><\/p>\n<p>Nov primer podatkovnega bloka se ustvari s pomo\u010djo funkcije:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">dblk_t *datab_alloc(int size);<\/code><\/pre>\n<p><\/p>\n<p>Kot vhodni parameter ji je predana velikost podatkov, ki jih bo shranjeval blok. Pomnilnik se dodeli ve\u010d, da se na za\u010detku dodeljenega pomnilnika postavi glava \u2014 struktura <em>datab<\/em>. Vendar pa pri uporabi drugih funkcij to ni vedno tako, v nekaterih primerih je lahko podatkovni pomnilnik lo\u010den od glave podatkovnega bloka. Polja strukture so pri ustvarjanju nastavljena tako, da njeno polje <em>db_base<\/em> ka\u017ee na za\u010detek podatkovnega podro\u010dja, medtem ko <em>db_lim<\/em> ka\u017ee na njen konec. \u0160tevec sklicev <em>db_ref<\/em> se nastavi na enoto. Kazalec funkcije za \u010di\u0161\u010denje podatkov se nastavi na ni\u010d.<\/p>\n<p><\/p>\n<h3 id=\"soobschenie-mblk_t\">Sporo\u010dilo <em>mblk_t<\/em><\/h3>\n<p><\/p>\n<p>Kot omenjeno, elementi vrste imajo tip <em>mblk_t,<\/em> je definiran tako:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">typedef struct msgb\n{\n  struct msgb *b_prev;   \/\/ Kazalec na prej\u0161nji element seznama.\n  struct msgb *b_next;   \/\/ Kazalec na naslednji element seznama.\n  struct msgb *b_cont;   \/\/ Kazalec za dodajanje drugih sporo\u010dil k sporo\u010dilu, za ustvarjanje paketa sporo\u010dil.\n  struct datab *b_datap; \/\/ Kazalec na strukturo podatkovnega bloka.\n  unsigned char *b_rptr; \/\/ Kazalec na za\u010detek podatkovnega podro\u010dja za branje podatkov iz pomnilnika b_datap.\n  unsigned char *b_wptr; \/\/ Kazalec na za\u010detek podatkovnega podro\u010dja za pisanje podatkov v pomnilnik b_datap.\n  uint32_t reserved1;    \/\/ Rezervirano polje1, medijski streamer tja postavi upravno informacijo. \n  uint32_t reserved2;    \/\/ Rezervirano polje2, medijski streamer tja postavi upravno informacijo.\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> na za\u010detku vsebuje kazalce <em>b_prev<\/em>, <em>b_next<\/em>, ki so potrebni za organizacijo dvostranskega seznama (ki je vrsta <em>queue_t<\/em>). <\/p>\n<p><\/p>\n<p>Nato sledi kazalec <em>b_cont<\/em>, ki se uporablja le, ko sporo\u010dilo vstopi v tupl. Za zadnje sporo\u010dilo v tuplu ostane ta kazalec ni\u010d. <\/p>\n<p><\/p>\n<p>Nato vidimo kazalec na blok podatkov <em>b_datap<\/em>, zaradi katerega sporo\u010dilo sploh obstaja. Za njim sledijo kazalci na obmo\u010dje znotraj podatkovnega bloka. Polje <em>b_rptr<\/em> kazalec ozna\u010duje mesto, s katerega se bodo brali podatki iz predpomnilnika. Polje <em>b_wptr<\/em> ozna\u010duje mesto, s katerega se bodo izvajale zapise v predpomnilnik. <\/p>\n<p><\/p>\n<p>Preostala polja so rezervirana in niso povezana z delovanjem mehanizma prenosa podatkov.<\/p>\n<p><\/p>\n<p>Spodaj je prikazano posamezno sporo\u010dilo z imenom <em>m1<\/em> in podatkovnim blokom <em>d1<\/em>.<br \/>\n<img decoding=\"async\" alt=\"Prou\u010dujemo VoIP motor Mediastreamer2. Deo 11\" src=\"\/wp-content\/uploads\/2020\/04\/e6a726b13491832258c1228f03bde802.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nNa naslednji sliki je prikazan tupl iz treh sporo\u010dil <em>m1<\/em>, <em>m1_1<\/em>, <em>m1_2<\/em>.<br \/>\n<img decoding=\"async\" alt=\"Prou\u010dujemo VoIP motor Mediastreamer2. Deo 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\">Funkcije za delo s sporo\u010dili <em>mblk_t<\/em><\/h3>\n<p><\/p>\n<p>Novo sporo\u010dilo <em>mblk_t<\/em> ustvari funkcija:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">mblk_t *allocb(int size, int pri); <\/code><\/pre>\n<p><\/p>\n<p>ta alocira novo sporo\u010dilo v pomnilniku <em>mblk_t<\/em> s podatkovnim blokom dolo\u010dene velikosti <em>size<\/em>, drugi argument \u2014 <em>pri<\/em> se v obravnavani razli\u010dici knji\u017enice ne uporablja. Ostati mora ni\u010delno. Med delovanjem funkcije bo pomnilnik dodeljen za strukturo novega sporo\u010dila in klicana bo funkcija <em>mblk_init()<\/em>, ki bo vse polja ustvarjene instance strukture nastavila na ni\u010d in nato, s pomo\u010djo prej omenjenega, <em>datab_alloc()<\/em>, ustvarila podatkovni predpomnilnik. Nato bo izvedena nastavitev polj v strukturi: <\/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>Na izhodu dobimo novo sporo\u010dilo z inicializiranimi polji in praznim podatkovnim predpomnilnikom. Da dodamo podatke v sporo\u010dilo, je treba te kopirati v predpomnilnik podatkovnega bloka:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">memcpy(msg-&gt;b_rptr, data, size);<\/code><\/pre>\n<p><\/p>\n<p>kjer <em>data<\/em> je kazalec na vir podatkov, medtem ko <em>size<\/em> je njihova velikost.<br \/>\nNato je treba posodobiti kazalec na zapisno mesto, da ponovno ka\u017ee na za\u010detek prostega obmo\u010dja v predpomnilniku:<\/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>\u010ce je potrebno ustvariti sporo\u010dilo iz \u017ee obstoje\u010dega predpomnilnika, brez kopiranja, se za to uporabi funkcija:<\/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>Funkcija po ustvarjanju sporo\u010dila in strukture podatkovnega bloka nastavi njene kazalce na podatke na naslovu <em>buf<\/em>. T.j. v tem primeru podatkovni predpomnilnik ni name\u0161\u010den za polji glave podatkovnega bloka, kot je bilo pri ustvarjanju podatkovnega bloka s funkcijo. <em>datab_alloc()<\/em>\u041f\u0440\u0435\u0434\u0430\u043d\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0431\u0443\u0444\u0435\u0440 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043e\u0441\u0442\u0430\u043d\u0435\u0442\u0441\u044f \u043d\u0430 \u043c\u0435\u0441\u0442\u0435, \u043d\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u043c\u0443 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0443 \u0431\u043b\u043e\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445, \u0430 \u0442\u043e\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043a \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044e.<\/p>\n<p><\/p>\n<p>\u041a \u043e\u0434\u043d\u043e\u043c\u0443 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044e <em>mblk_t<\/em> \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u044b \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u043b\u043e\u043a\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439:<\/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 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0431\u043b\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445;<br \/>\n<em>data<\/em> \u2014 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0431\u043b\u043e\u043a, \u043a\u043e\u043f\u0438\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430 \u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435;<br \/>\n<em>size<\/em> \u2014 \u0440\u0430\u0437\u043c\u0435\u0440 \u0434\u0430\u043d\u043d\u044b\u0445;<br \/>\n<em>pad<\/em> \u2014 \u0444\u043b\u0430\u0433 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0440\u0430\u0437\u043c\u0435\u0440 \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u043c\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0432\u044b\u0440\u043e\u0432\u043d\u0435\u043d \u043f\u043e \u0433\u0440\u0430\u043d\u0438\u0446\u0435 4 \u0431\u0430\u0439\u0442 (\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e \u043d\u0443\u043b\u044f\u043c\u0438). <\/p>\n<p><\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432 \u0438\u043c\u0435\u044e\u0449\u0435\u043c\u0441\u044f \u0431\u0443\u0444\u0435\u0440\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043c\u0435\u0441\u0442\u0430, \u0442\u043e \u043d\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u044b \u0437\u0430 \u0443\u0436\u0435 \u0438\u043c\u0435\u044e\u0449\u0438\u043c\u0438\u0441\u044f \u0442\u0430\u043c \u0434\u0430\u043d\u043d\u044b\u043c\u0438. \u0415\u0441\u043b\u0438 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430 \u0432 \u0431\u0443\u0444\u0435\u0440\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043c\u0435\u043d\u044c\u0448\u0435 \u0447\u0435\u043c <em>size<\/em>, \u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u044b\u043c \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c \u0431\u0443\u0444\u0435\u0440\u0430, \u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u043f\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 \u0435\u0433\u043e \u0431\u0443\u0444\u0435\u0440. \u042d\u0442\u043e \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0435\u0442\u0441\u044f \u0441 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f <em>b_cont<\/em>. \u0412 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u0440\u0442\u0435\u0436. <\/p>\n<p><\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432 \u043a\u043e\u0440\u0442\u0435\u0436 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0431\u043b\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445, \u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e:<\/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>\u043e\u043d\u0430 \u043d\u0430\u0439\u0434\u0435\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u043a\u043e\u0440\u0442\u0435\u0436\u0435 (\u0443 \u043d\u0435\u0433\u043e <em>b_cont<\/em> \u0431\u0443\u0434\u0435\u0442 \u043d\u0443\u043b\u0435\u0432\u044b\u043c) \u0438 \u0432\u044b\u0437\u043e\u0432\u0435\u0442 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044e <em>appendb()<\/em>.<\/p>\n<p><\/p>\n<p>\u0423\u0437\u043d\u0430\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0438 \u0438\u043b\u0438 \u043a\u043e\u0440\u0442\u0435\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u0438:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">int msgdsize(const mblk_t *mp);<\/code><\/pre>\n<p><\/p>\n<p>\u043e\u043d\u0430 \u043f\u0440\u043e\u0431\u0435\u0436\u0438\u0442\u0441\u044f \u043f\u043e \u0432\u0441\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u043c \u043a\u043e\u0440\u0442\u0435\u0436\u0430 \u0438 \u0432\u0435\u0440\u043d\u0435\u0442 \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0431\u0443\u0444\u0435\u0440\u0430\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u044d\u0442\u0438\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439. \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u0430\u043a:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\"> mp-&gt;b_wptr - mp-&gt;b_rptr<\/code><\/pre>\n<p><\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0434\u0432\u0430 \u043a\u043e\u0440\u0442\u0435\u0436\u0430 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f:<\/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>\u043e\u043d\u0430 \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u043a\u043e\u0440\u0442\u0435\u0436 <em>newm<\/em> \u0432 \u043a\u043e\u043d\u0435\u0446 \u043a\u043e\u0440\u0442\u0435\u0436\u0430 <em>mp<\/em> \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0432\u0448\u0435\u0433\u043e\u0441\u044f \u043a\u043e\u0440\u0442\u0435\u0436\u0430.<\/p>\n<p><\/p>\n<p>\u041f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u043a\u043e\u0440\u0442\u0435\u0436 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u0432 \u043e\u0434\u043d\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441 \u0435\u0434\u0438\u043d\u044b\u043c \u0431\u043b\u043e\u043a\u043e\u043c \u0434\u0430\u043d\u043d\u044b\u0445, \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void msgpullup(mblk_t *mp,int len);<\/code><\/pre>\n<p><\/p>\n<p>\u0435\u0441\u043b\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 <em>len<\/em> \u0440\u0430\u0432\u0435\u043d -1, \u0442\u043e \u0440\u0430\u0437\u043c\u0435\u0440 \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u043c\u043e\u0433\u043e \u0431\u0443\u0444\u0435\u0440\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438. \u0415\u0441\u043b\u0438 <em>len<\/em> \u010ce je \u0161tevilo pozitivno, bo ustvarjen predpomnilnik te velikosti, v katerega bodo kopirani podatki tupla. \u010ce se predpomnilnik napolni, se kopiranje prekine. Prvo sporo\u010dilo tupla bo prejelo predpomnilnik nove velikosti s kopiranimi podatki. Ostala sporo\u010dila bodo izbrisana, spomin pa vrnjen v kup.<\/p>\n<p><\/p>\n<p>Ob izbrisu strukture <em>mblk_t<\/em> se upo\u0161teva \u0161tevec referenc podatkovnega bloka, \u010de ob klicu <em>freeb()<\/em> dose\u017ee ni\u010d, se predpomnilnik podatkov izbri\u0161e skupaj z instanco <em>mblk_t<\/em>, na katero ka\u017ee.<\/p>\n<p><\/p>\n<p>Inicializacija polj novega sporo\u010dila:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void mblk_init(mblk_t *mp);<\/code><\/pre>\n<p><\/p>\n<p>Dodajanje \u0161e enega niza podatkov v sporo\u010dilo: <\/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>\u010ce novi podatki ne ustrezajo prostornini prostega prostora v predpomnilniku sporo\u010dila, se sporo\u010dilu prilo\u017ei lo\u010deno ustvarjeno sporo\u010dilo s potrebnim velikostnim predpomnilnikom (v prvem sporo\u010dilu se nastavi kazalec na dodano sporo\u010dilo) in sporo\u010dilo se spremeni v tuple.<\/p>\n<p><\/p>\n<p>Dodajanje niza podatkov v 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>Funkcija klicanje appendb() izvede v zanki.<\/p>\n<p><\/p>\n<p>Zdru\u017eevanje dveh tuple v eno:<\/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>Sporo\u010dilo <em>newm<\/em> bo pripeto na <em>mp<\/em>.<\/p>\n<p><\/p>\n<p>Ustvarjanje kopije posameznega sporo\u010dila:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">mblk_t *copyb(const mblk_t *mp);<\/code><\/pre>\n<p><\/p>\n<p>Popolno kopiranje tupla z vsemi podatkovnimi bloki:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">mblk_t *copymsg(const mblk_t *mp);<\/code><\/pre>\n<p><\/p>\n<p>Elementi tupla se kopirajo s funkcijo <em>copyb()<\/em>.<\/p>\n<p><\/p>\n<p>Ustvarjanje lahke kopije sporo\u010dila. <em>mblk_t<\/em>Pri tem se podatkovni blok ne kopira, temve\u010d se pove\u010da \u0161tevec njegovih referenc. <em>db_ref<\/em>:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">mblk_t *dupb(mblk_t *mp);<\/code><\/pre>\n<p><\/p>\n<p>Ustvarjanje lahke kopije tupla. Podatkovni bloki se ne kopirajo, le njihovi \u0161tevci referenc se pove\u010dajo. <em>db_ref<\/em>:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">mblk_t *dupmsg(mblk_t* m);<\/code><\/pre>\n<p><\/p>\n<p>Zlepljenje vseh sporo\u010dil tupla v eno sporo\u010dilo:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void msgpullup(mblk_t *mp,size_t len);<\/code><\/pre>\n<p><\/p>\n<p>\u010ce je argument <em>len<\/em> enak -1, se velikost dodeljenega predpomnilnika dolo\u010di samodejno.<\/p>\n<p><\/p>\n<p>Izbris sporo\u010dila, tupla:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void freemsg(mblk_t *mp);<\/code><\/pre>\n<p><\/p>\n<p>\u0160tevec referenc podatkovnega bloka se zmanj\u0161a za enoto. \u010ce ob tem dose\u017ee ni\u010d, se tudi podatkovni blok izbri\u0161e.<\/p>\n<p><\/p>\n<p>\u0160tetje skupne prostornine podatkov v sporo\u010dilu ali tuple.<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">size_t msgdsize(const mblk_t *mp);<\/code><\/pre>\n<p><\/p>\n<p>Pridobitev sporo\u010dila iz repa vrste:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">mblk_t *ms_queue_peek_last (q);<\/code><\/pre>\n<p><\/p>\n<p>Kopiranje vsebine rezerviranih polj enega sporo\u010dila v drugo sporo\u010dilo (v teh poljih so v resnici zastavice, ki jih uporablja medijski stre\u017enik):<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">mblk_meta_copy(const mblk_t *source, mblk *dest);<\/code><\/pre>\n<p><\/p>\n<h3 id=\"ochered-queue_t\">Vrsta <em>queue_t<\/em><\/h3>\n<p><\/p>\n<p>Queuing messages in the media streamer is implemented as a circular doubly linked list. Each list element contains a pointer to a data block with signal readings. This means that only the pointers to the data blocks move in the queue, while the actual data remains stationary. In other words, only the references to them are moved.<br \/>\nThe structure describing the queue <em>queue_t<\/em>, is shown below:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">typedef struct _queue\n{\n   mblk_t _q_stopper; \/* \"Prazni\" element vrste, ne ka\u017ee na podatke, uporablja se samo za upravljanje vrste. Pri inicializaciji vrste (qinit()) so njegovi kazalci nastavljeni tako, da ka\u017eejo nanj samega. *\/\n   int q_mcount;        \/\/ \u0160tevilo elementov v vrsti.\n} queue_t;<\/code><\/pre>\n<p><\/p>\n<p>The structure contains the field \u2014 a pointer <em>_q_stopper<\/em> of type *mblk_t, which points to the first element (message) in the queue. The second field of the structure is a counter of messages that are in the queue.<br \/>\nThe image below shows the queue named q1, containing 4 messages m1, m2, m3, m4.<br \/>\n<img decoding=\"async\" alt=\"Prou\u010dujemo VoIP motor Mediastreamer2. Deo 11\" src=\"\/wp-content\/uploads\/2020\/04\/07fc043861edf15e5eb40e49c8ec5e3e.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nThe next image shows the queue named q1, containing 4 messages m1, m2, m3, m4. The message m2 is the head of the tuple, to which two more messages m2_1 and m2_2 are linked.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Prou\u010dujemo VoIP motor Mediastreamer2. Deo 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\">Funkcije rada sa redovima queue_t<\/h3>\n<p><\/p>\n<p>Initialization of the queue:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void qinit(queue_t *q);<\/code><\/pre>\n<p><\/p>\n<p>Field <em>_q_stopper<\/em> (naprej ga bomo imenovali \"stopper\") se inicializira s funkcijo <em>mblk_init()<\/em>, its pointer to the previous element and the next element are set to point to itself. The element counter of the queue is reset to zero.<\/p>\n<p><\/p>\n<p>Adding a new element (message):<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void putq(queue_t *q, mblk_t *m);<\/code><\/pre>\n<p><\/p>\n<p>The new element <em>m<\/em> is added to the end of the list, the pointers of the element are set so that the stopper becomes the next element for it, and it becomes the previous element for the stopper. The element counter of the queue is incremented.<\/p>\n<p><\/p>\n<p>Extracting an element from the queue:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">mblk_t * getq(queue_t *q); <\/code><\/pre>\n<p><\/p>\n<p>the message that is after the stopper is extracted, the element counter is decremented. If there are no elements in the queue other than the stopper, 0 is returned.<\/p>\n<p><\/p>\n<p>Inserting a message into the queue:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void insq(queue_t *q, mblk_t *emp, mblk_t *mp); <\/code><\/pre>\n<p><\/p>\n<p>Element <em>mp<\/em> is inserted before the element <em>emp<\/em>. \u0415\u0441\u043b\u0438 <em>emp<\/em>=0, then the message is added to the tail of the queue.<\/p>\n<p><\/p>\n<p>Extracting a message from the head of the queue:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void remq(queue_t *q, mblk_t *mp); <\/code><\/pre>\n<p><\/p>\n<p>The element counter is decremented.<\/p>\n<p><\/p>\n<p>Reading the pointer to the first element in the queue:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">mblk_t * peekq(queue_t *q); <\/code><\/pre>\n<p><\/p>\n<p>Removing all elements from the queue while deleting the actual elements:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void flushq(queue_t *q, int how);<\/code><\/pre>\n<p><\/p>\n<p>Argument <em>how<\/em> ni se uporablja. \u0160tevilo elementov v \u010dakalni vrsti se nastavi na ni\u010d.<\/p>\n<p><\/p>\n<p>Makar za branje kazalca na zadnji element \u010dakalne vrste:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">mblk_t * qlast(queue_t *q);<\/code><\/pre>\n<p><\/p>\n<p>Pri delu z sporo\u010dilnimi \u010dakalnimi vrstami je treba upo\u0161tevati, da ob klicu <em>ms_queue_put(q, m)<\/em> z ni\u010delnim kazalcem na sporo\u010dilo, funkcija zaide v neskon\u010dno zanko. Va\u0161 program se bo ustavil. Podobno se obna\u0161a <em>ms_queue_next(q, m)<\/em>.<\/p>\n<p><\/p>\n<h3 id=\"soedinenie-filtrov\">Povezivanje filtara<\/h3>\n<p><\/p>\n<p>Navr\u017eena vrsta se uporablja za prenos sporo\u010dil od enega filtra do drugega ali od enega do ve\u010d filtrov. Filtri in njihovo povezovanje med seboj tvorijo usmerjeno grafiko. Vhod ali izhod filtra bomo imenovali skupni izraz \"pin\". Za opis vrstnega reda povezav med filtri se v medijskem predvajalniku uporablja pojem \"signalna to\u010dka\". Signalna to\u010dka je struktura <em>_MSCPoint<\/em>, ki vsebuje kazalec na filter in \u0161tevilko enega od njegovih pinov, s tem opisuje povezavo enega od vhodov ali izhodov filtra. <\/p>\n<p><\/p>\n<h4 id=\"signalnaya-tochka-grafa-obrabotki-dannyh\">Signala ta\u010dka dijagrama obrade podataka<\/h4>\n<p><\/p>\n<pre><code class=\"cpp\">typedef struct _MSCPoint{\nstruct _MSFilter *filter; \/\/ Kazalec na filter medijskega stre\u017enika.\nint pin;                        \/\/ \u0160tevilka enega od vhodov ali izhodov filtra, tj. pin.\n} MSCPoint;\n<\/code><\/pre>\n<p><\/p>\n<p>Pini filtrov so o\u0161tevil\u010deni, pri \u010demer se za\u010dne \u0161tetje z ni\u010d. <\/p>\n<p><\/p>\n<p>Povezava dveh pinov prek sporo\u010dilne \u010dakalne vrste je opisana s strukturo <em>_MSQueue<\/em>, ki vsebuje sporo\u010dilno \u010dakalno vrsto in kazalce na dve signalni to\u010dki, ki jih povezuje:<\/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>To strukturo bomo imenovali signalna povezava. Vsak filter medijskega stre\u017enika vsebuje tabelo vhodnih povezav in tabelo izhodnih povezav (<em>MSQueue<\/em>). Velikost tabel se nastavi ob ustvarjanju filtra, kar smo \u017ee storili s pomo\u010djo izvoznega spremenljivke tipa <em>MSFilterDesc<\/em>, ko smo razvijali na\u0161 lasten filter. Spodaj je prikazana struktura, ki opisuje vsak filter v medijskem stre\u017eniku, <em>MSFilter<\/em>:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">\nstruct _MSFilter{\n    MSFilterDesc *desc;    \n    \/* Pointer to the filter descriptor. *\/\n    \/* Protected attributes, they cannot be shifted or removed as this would disrupt plugin operation. *\/\n    ms_mutex_t lock;      \/* Semaphore. *\/\n    MSQueue **inputs;     \/* Table of input links. *\/\n    MSQueue **outputs;    \/* Table of output links. *\/\n    struct _MSFactory *factory; \/* Pointer to the factory that created this filter instance. *\/\n    void *padding;              \/* Not used, will be utilized if protected fields are added. *\/\n    void *data;                 \/* Pointer to an arbitrary structure for storing the filter's internal state data and intermediate computations. *\/\n    struct _MSTicker *ticker;   \/* Pointer to the ticker object, which must not be null when the process() function is called. *\/\n    \/* private attributes, they can be moved and changed at any time *\/\n    MSList *notify_callbacks; \/* List of callbacks used for handling filter events. *\/\n    uint32_t last_tick;       \/* The number of the last tick when the process() call was executed. *\/\n    MSFilterStats *stats;     \/* Filter operation statistics. *\/\n    int postponed_task; \/* Number of postponed tasks. Some filters may delay data processing (the process() call) for several ticks. *\/\n    bool_t seen;  \/* A flag used by the ticker to indicate that this filter instance has already been serviced in the current tick. *\/\n};\ntypedef struct _MSFilter MSFilter;\n<\/code><\/pre>\n<p><\/p>\n<p>After connecting the filters in our C program according to our design (but without connecting the ticker), we have thus created a directed graph, where the nodes are instances of the structure <em>MSFilter<\/em>, and the edges are instances of links <em>MSQueue<\/em>. <\/p>\n<p><\/p>\n<h3 id=\"zakulisnaya-deyatelnost-tikera\">Zakulisna aktivnost tikera<\/h3>\n<p><\/p>\n<p>When I told you that the ticker is a filter that outputs ticks, it wasn't the whole truth about it. The ticker is an object that triggers function executions on a timed basis <em>process()<\/em> vseh filtrov sheme (grafa), s katerimi je povezan. Ko v C programu pove\u017eemo tiker s filtrom grafa, poka\u017eemo tikru graf, kjer ga bo od tega trenutka vodil, dokler ga ne odklopimo. Po povezavi tiker za\u010dne raziskovati graf, ki mu je zaupano, in sestavlja seznam filtrov, ki vanj vstopajo. Da ne bi \"pre\u0161tel\" istega filtra dvakrat, ozna\u010duje odkrite filtre, tako da v njih nastavi zastavico <em>seen<\/em>. The search is conducted through the link tables that each filter has. <\/p>\n<p><\/p>\n<p>Med svojemu uvodnem izletu po grafu ticker preveri, ali je med filtri vsaj en, ki deluje kot vir podatkovnih blokov. \u010ce taki filtri ne obstajajo, se graf \u0161teje za napa\u010dnega in ticker nujno zaklju\u010di delo.<\/p>\n<p><\/p>\n<p>\u010ce se je graf izkazal za \"pravilen\", se za vsak najdeni filter za inicializacijo pokli\u010de funkcija <em>preprocess()<\/em>. Ko pride \u010das za naslednji cikel obdelave (privzeto vsakih 10 milisekund), ticker pokli\u010de funkcijo <em>process()<\/em> za vse prej najdene vire filtriranja, nato pa tudi za ostale filtre na seznamu. \u010ce filter ima vhodne povezave, se zagon funkcije <em>process()<\/em> se ponavlja, dokler vrste vhodnih povezav niso prazne. Po tem preide na naslednji filter na seznamu in \"predvaja\" njegovo vsebino, dokler se vhodne povezave ne osvobodijo sporo\u010dil. Tiker prehaja od filtra do filtra, dokler se seznam ne kon\u010da. Na tem mestu obdelava takta kon\u010da. <\/p>\n<p><\/p>\n<p>Zdaj se vrnimo k naborom in pogovorimo se o tem, zakaj je bila v medijskem pretvorniku dodana taka entiteta. Na splo\u0161no se prostornina podatkov, potrebna algoritmu, ki deluje znotraj filtra, ne ujema in ni deljiva z velikostjo podatkovnih buferjev, ki prihajajo na vhodu. Na primer, pi\u0161emo filter, ki izvaja hitro Fourierjevo transformacijo, ki po definiciji lahko obdela le bloke podatkov, katerih velikost je enaka potencam dvojke. Naj bo to 512 vzorcev. \u010ce podatki izvirajo iz telefonskega kanala, bo podatkovni bufer vsakega sporo\u010dila na vhodu prinesel po 160 vzorcev signala. Obstaja sku\u0161njava, da ne vzamemo podatkov z vhodu, dokler ne pride do potrebne koli\u010dine podatkov. A v tem primeru pride do kolizije s tickerjem, ki bo neuspe\u0161no posku\u0161al preklopiti filter, dokler se vhodna povezava ne izprazni. Prej smo to pravilo ozna\u010dili kot tretji princip delovanja filtra. V skladu s tem na\u010delom mora funkcija process() filtra pobrati vse podatke iz vhodnih \u010dakalnih vrst.<\/p>\n<p><\/p>\n<p>Poleg tega ni mogo\u010de prevzeti le 512 podatkovnih to\u010dk, saj jih je mogo\u010de prevzeti le v celotnih blokih, tj. filtrirati bo potrebno 640 podatkovnih to\u010dk in uporabiti 512 od njih, preostanek pa do zbiranja nove serije podatkov. Tako mora na\u0161 filter, poleg svojega glavnega dela, zagotavljati tudi pomo\u017ene naloge za medsebojno shranjevanje vhodnih podatkov. Razvijalci medijskega pretvornika so za re\u0161evanje te skupne naloge razvili poseben objekt - MSBufferizer (buffer), ki to nalogo re\u0161uje s pomo\u010djo tuplov. <\/p>\n<p><\/p>\n<h3 id=\"buferizator-msbufferizer\">Bafer (MSBufferizer)<\/h3>\n<p><\/p>\n<p>To je objekt, ki bo shranjeval vhodne podatke znotraj filtra in jih za\u010del oddajati v obdelavo, takoj ko bo koli\u010dina informacij zadostna za izvajanje filtra. Medtem ko buffer kopi\u010dijo podatke, bo filter deloval v praznem na\u010dinu, brez porabe ra\u010dunalni\u0161ke mo\u010di procesorja. Toda takoj ko funkcija branja iz bufferja vrne vrednost, ki ni ni\u010d, funkcija process() filtra za\u010dne prevzemati in obdelovati podatke iz bufferja v obrokih ustrezne velikosti, dokler ne zmanjka.<br \/>\nNepotrebni podatki ostajajo v bufferju kot prvi element tupla, ki mu sledijo naslednji bloki vhodnih podatkov. <\/p>\n<p><\/p>\n<p>Struktura, ki opisuje buffer: <\/p>\n<p><\/p>\n<pre><code class=\"cpp\">struct _MSBufferizer{\nqueue_t q; \/* \u010cakalna vrsta sporo\u010dil. *\/\nint size; \/* Skupna velikost podatkov, ki so trenutno v bufferju. *\/\n};\ntypedef struct _MSBufferizer MSBufferizer;<\/code><\/pre>\n<p><\/p>\n<h3 id=\"funkcii-raboty-s-msbufferizer\">Funkcije rada sa MSBufferizer<\/h3>\n<p><\/p>\n<p>Ustvarjanje novega primera bufferja:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">MSBufferizer * ms_bufferizer_new(void);<\/code><\/pre>\n<p><\/p>\n<p>Dodeli se pomnilnik, inicializira se v <em>ms_bufferizer_init()<\/em> in vrne se kazalec.<\/p>\n<p><\/p>\n<p>Funkcija inicializacije:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void ms_bufferizer_init(MSBufferizer *obj); <\/code><\/pre>\n<p><\/p>\n<p>Inicializira se \u010dakalna vrsta <em>q<\/em>, polje <em>size<\/em> se nastavi na ni\u010d.<\/p>\n<p><\/p>\n<p>Dodajanje sporo\u010dila:<\/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>Sporo\u010dilo m se doda v \u010dakalno vrsto. Izra\u010dunana velikost podatkovnih blokov se doda k <em>size<\/em>.<\/p>\n<p><\/p>\n<p>Preklop bufferja vseh sporo\u010dil \u010dakalne vrste podatkovne povezave <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>Prenos sporo\u010dil iz povezave <em>q<\/em> v buffer se izvede s pomo\u010djo funkcije <em>ms_bufferizer_put()<\/em>.<\/p>\n<p><\/p>\n<p>Branje iz bufferja:<\/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>\u010ce je velikost shranjenih podatkov v bufferju manj\u0161a od zahtevane (<em>datalen<\/em>), to funkcija vrne ni\u010dlo, kopiranje podatkov v data se ne izvede. V nasprotnem primeru se podatki zaporedno kopirajo iz tuple, ki so v predpomnilniku. Po kopiranju se tuple odstrani in spomin se osvobodi. Kopiranje se zaklju\u010di, ko je skopiranih datalen bajtov. \u010ce se prostor kon\u010da sredi podatkovnega bloka, se v tem sporo\u010dilu podatkovni blok skraj\u0161a na preostali nekopirani del. Pri naslednjem klicu se kopiranje nadaljuje od te to\u010dke.<\/p>\n<p><\/p>\n<p>Preberite koli\u010dino podatkov, ki so trenutno na voljo v predpomnilniku:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">int ms_bufferizer_get_avail(MSBufferizer *obj); <\/code><\/pre>\n<p><\/p>\n<p>Vrne polje <em>size<\/em> predpomnilnika.<\/p>\n<p><\/p>\n<p>Prekrivanje dela podatkov, ki so v predpomnilniku:<\/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>Dolo\u010deno \u0161tevilo bajtov podatkov se izvle\u010de in prelo\u017ei. Prelo\u017eeni so najstarej\u0161i podatki.<\/p>\n<p><\/p>\n<p>Odstranitev vseh sporo\u010dil, ki so v predpomnilniku:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void ms_bufferizer_flush(MSBufferizer *obj); <\/code><\/pre>\n<p><\/p>\n<p>\u0160tevec podatkov se ponastavi na ni\u010d.<\/p>\n<p><\/p>\n<p>Odstranitev vseh sporo\u010dil, ki so v predpomnilniku:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void ms_bufferizer_uninit(MSBufferizer *obj); <\/code><\/pre>\n<p><\/p>\n<p>Ponastavitev \u0161tevca se ne izvede.<\/p>\n<p><\/p>\n<p>Odstranitev predpomnilnika in osvoboditev spomina:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">void ms_bufferizer_destroy(MSBufferizer *obj);  <\/code><\/pre>\n<p><\/p>\n<p>Primeri uporabe predpomnilnika so na voljo v izvorni kodi ve\u010d filtrov medijskega pretakalnika. Na primer pri filtru MS_L16_ENC, ki izvaja preureditev bajtov v vzorcih iz omre\u017enega reda v red gostitelja:<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>V naslednjem \u010dlanku bomo obravnavali vpra\u0161anje ocene obremenitve na tickerju in na\u010dine za obvladovanje prekomerne ra\u010dunalni\u0161ke obremenitve v medijskem pretakalniku.<\/p>\n<p>Izvor: <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.5 - 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\/sl\/blog\/administrirovanie\/izuchaem-voip-dvizhok-mediastreamer2-chast-11\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.5\" \/>\n\t\t<meta property=\"og:locale\" content=\"sl_SI\" \/>\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\/sl\/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\udd47Spreminjanje VoIP motorja Mediastreamer2. Del 11 | ProHoster","description":"Vsebina \u010dlanka je bila vzeta z mojega zen-kanala.","canonical_url":"https:\/\/prohoster.info\/sl\/blog\/administrirovanie\/izuchaem-voip-dvizhok-mediastreamer2-chast-11","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sl_SI","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\/sl\/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\/sl\/wp-json\/wp\/v2\/posts\/79540","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/comments?post=79540"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/posts\/79540\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/media\/79541"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/media?parent=79540"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/categories?post=79540"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/tags?post=79540"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}