Uurime VoIP-mootorit Mediastreamer2. Osa 11

Artikli sisu on pärit minu zen-kanalist.

Uurime VoIP-mootorit Mediastreamer2. Osa 11

Andmete liikumismehhanism

  • Andmeplokk dblk_t
  • Sõnum mblk_t
  • Sõnumitega töötamise funktsioonid mblk_t
  • Järjekord queue_t
  • Järjekordadega töötamise funktsioonid queue_t
  • Filtrite ühendamine
  • Andmete töötlemise graafi signaalpunkt
  • Tickere tagumine tegevus
  • Vahemälu (MSBufferizer)
  • MSBufferizeri töötamise funktsioonid

Eelmises osas artiklis Oleme välja töötanud oma filtri. Selles artiklis pühendame tähelepanu andmete liikumismehhanismi sisesele ehitusele, mis toimub meediastreameri filtrite vahel. See võimaldab tulevikus kirjutada keerukamaid filtreid väiksema vaevaga.

Andmete liikumismehhanism

Andmete liikumine meediastreameris toimub kirjeldatud struktuuri kaudu queue_t. Andmete liikumine toimub sõnumite jada kaudu, mille tüüp on mblk_t, mis ei sisalda enda sees signaali andmeid, vaid ainult lingid eelmise, järgmise sõnumi ja andmeploki peale. Lisaks tahan rõhutada, et on olemas ka väli, mis viitab sama tüüpi sõnumile, mis võimaldab korraldada sõnumite ühekordset loetelu. Sõnumite rühma, mida ühendab see loetelu, nimetame kimpuks. Seega võib iga järjekorra element olla kas üksik sõnum mblk_t, või kimpude pea mblk_t. Igal kimpude sõnumil võib olla oma andmeplokk. Miks on kimbud vajalikud, arutame hiljem.

Nagu eespool mainitud, ei sisalda sõnum ise andmeplokki, vaid sisaldab ainult näidikut mälupiirkonnas, kus andmeplokk asub. Selles osas sarnaneb meediastreameri toimimise üldine pilt Disney animatsiooniga "Koletiste ettevõte", kus uksed (andmete lingid — ruumid) liiguvad hullumeelse kiiruseni üles riputatud konveierite kaudu, samas kui ruumid ise jäävad paigale.

Nüüd, liikumine alt ülesse, vaatame üksikasjalikult meediastreameris andmete edastamise mehhanismi elemente.

Andmeplokk dblk_t

Andmeplokk koosneb päisest ja andmevahemikust. Pealkiri on kirjeldatud järgmise struktuuriga:

typedef struct datab
{
unsigned char *db_base; // Näidik andmevahemiku algusele.
unsigned char *db_lim;  // Näidik andmevahemiku lõpule.
void (*db_freefn)(void*); // Mälua vabastamise funktsioon ploki eemaldamisel.
int db_ref; // Viidete loendur.
} dblk_t;

Struktuuri väljad sisaldavad näidikuid andmevahemiku algusele, lõppu, andmevahemiku vabastamisefunktsiooni. Viimane element pealkirjas db_ref — viidete loendur, ja kui see jõuab nulli, on see signaal andmeploki eemaldamiseks mälust. Kui andmeplokk loodi funktsiooni datab_alloc() , siis paigutatakse andmevahemik mällu vahetult pärast pealkirja. Kõigil muudel juhtudel võib andmevahemik paikneda kuskil eraldi. Andmevahemikus asuvad signaali näidud või muud andmed, mida soovime filtritega töödelda.

Uus andmeploki eksemplar luuakse järgnevaga:

dblk_t *datab_alloc(int size);

Sellele antakse sisendparameetrina andmete suurus, mida plokk hoiustab. Mälu eraldatakse rohkem, et alguses eraldatud mälus asetada pealkiri — struktuur datab. Kuid teiste funktsioonide puhul ei toimu see alati, mõningatel juhtudel võib andmevahemik asuda eraldi andmeplokist. Struktuuri väljad luuakse selliselt, et selle väli db_base osutaks andmevahemiku algusele ja db_lim lõpule. Viidete loendur db_ref seatakse ühte. Andmete puhastamise näidik seatakse nullile.

Teade mblk_t

Nagu juba öeldud, on järjekorra elemendid tüüpi mblk_t, mille definirime järgmiselt:

typedef struct msgb
{
  struct msgb *b_prev;   // Näidik eelmisele loendi elemendile.
  struct msgb *b_next;   // Näidik järgmisele loendi elemendile.
  struct msgb *b_cont;   // Näidik teiste sõnumite lisamisest sõnumile, kimpude loomiseks.
  struct datab *b_datap; // Näidik andmeploki struktuurile.
  unsigned char *b_rptr; // Näidik andmevahemiku algusele b_datap andmete lugemiseks.
  unsigned char *b_wptr; // Näidik andmevahemiku algusele b_datap andmete kirjutamiseks.
  uint32_t reserved1;    // Reserveeritud väli1, meediastreamer paneb sinna teenindusteabe.
  uint32_t reserved2;    // Reserveeritud väli2, meediastreamer paneb sinna teenindusteabe.
  #if defined(ORTP_TIMESTAMP)
  struct timeval timestamp;
  #endif
  ortp_recv_addr_t recv_addr;
} mblk_t;

Struktuur mblk_t alguses sisaldab näidikud b_prev, b_next, mis on vajalikud kahekordse loendi korraldamiseks (millega on järjekord queue_t).

Seejärel on näidik b_cont, mis kasutatakse ainult siis, kui sõnum kuulub kimpude. Viimase sõnumi puhul kimpude jääb see näidik nulliks.

Edasi näeme näidiku andmeploki b_datap, mille, mille jaoks sõnum eksisteerib. Selle järel on näidikud andmebloki sisemisele andmepuhvrile. Väli b_rptr osutab kohale, kust andmeid loetakse puhvrisse. Väli b_wptr osutab kohale, kust andmeid kirjutatakse puhvrisse.

Ülejäänud väljad on teenindava iseloomuga ja ei seondu andmete edastamise mehhanismiga.

Allpool on näidatud ühekordne sõnum nimega m1 ja andmeblokk d1.
Uurime VoIP-mootorit Mediastreamer2. Osa 11
Järgmises joonises on kujutatud kolme sõnumi kopleksi m1, m1_1, m1_2.
Uurime VoIP-mootorit Mediastreamer2. Osa 11

Sõnumitega töötamise funktsioonid mblk_t

Uue sõnumi mblk_t loob funktsioon:

mblk_t *allocb(int size, int pri); 

see eraldab mälus uue sõnumi mblk_t näidatud suurusega andmebloki. sizeTeine argument — pri ei kasutata arutatava versiooni raamatukogus. See peaks jääma nulliks. Funktsiooni töös eraldatakse mälu uue sõnumi struktuuri jaoks ja kutsutakse välja funktsioon mblk_init(), mis nullib loodud struktuuri kõik väljad ja seejärel, eelnevalt mainitud, loob andmepuhvri. Seejärel seadistatakse struktuuri väljad: datab_alloc()mp->b_datap=datab; mp->b_rptr=mp->b_wptr=datab->db_base; mp->b_next=mp->b_prev=mp->b_cont=NULL;

Saame välja uue sõnumi alginitseeritud väljadega ja tühja andmepuvriga. Andmete lisamiseks sõnumisse tuleb need kopeerida andmebloki puhvrisse:

memcpy(msg->b_rptr, data, size);

— näitaja andmeallikale, ja

kus data — nende suurus. size järel tuleb uuendada kirjutamiskoha näitajat, et see näitaks jälle vaba ala algusesse puhvrisse:
msg->b_wptr = msg->b_wptr + size

Kui on vajalik luua sõnum juba olemasolevast puhvrist, ilma kopeerimiseta, siis kasutatakse selleks funktsiooni:

mblk_t *esballoc(uint8_t *buf, int size, int pri, void (*freefn)(void*));

Funktsioon pärast sõnumi ja andmeploki struktuuri loomist seadistab andmete näitajad aadressile 

buf . St. sel juhul andmepuvr ei asu andmeploki päise väljade taga, nagu see oli andmeploki loomisel funktsiooni abil. Funktsioonile edastatud andmepuvr jääb sinna, kus see oli, kuid näitajate kaudu suunatakse see just loodud andmeploki päisele, ja see vastavalt sõnumile. datab_alloc()Ühele sõnumile

võivad järjestikku kinnituda mitu andmeplokki. See toimub funktsiooni abil: mblk_t mblk_t * appendb(mblk_t *mp, const char *data, int size, bool_t pad);

mp 

— sõnum, millele lisatakse veel üks andmeplokk; — näitaja plokile, mille koopia lisatakse sõnumisse;
data — andmete suurus;
size pad
— lipp, et eraldatava mälu suurus peaks olema joondatud 4-baidise piiri järgi (täiendamine toimub nullidega). Kui antud sõnumi andmepuvrisse on piisavalt ruumi, siis uued andmed kinnitatakse seal juba olemasolevate andmete taha. Kui sõnumi andmepuvrisse on ruumi vähem kui

, luuakse uus sõnum piisava suurusega puhvri jaoks ja andmed kopeeritakse selle puhvri sisse. See uus sõnum kinnitatakse algsele läbi näitaja size. Sel juhul muutub sõnum kopleksiks. b_contKui kopleksile on vaja lisada veel üks andmeplokk, siis tuleb kasutada funktsiooni:

void msgappend(mblk_t *mp, const char *data, int size, bool_t pad);

see otsib kopleksi viimast sõnumit (sel on

oleb null) ja kutsub sellele sõnumile välja funktsiooni b_cont appendb() Andmete suuruse määramine sõnumis või kopleksis toimub funktsiooni abil:.

int msgdsize(const mblk_t *mp);

see läbib kõik kopleksi sõnumid ja tagastab nende sõnumite andmepuvirite kogusumma. Iga sõnumi andmete maht arvutatakse järgmiselt:

mp->b_wptr - mp->b_rptr

 Kahte kopleksi ühendamiseks kasutatakse funktsiooni:

mblk_t *concatb(mblk_t *mp, mblk_t *newm);

see lisab kopleksi

newm kopleksi lõppu ja tagastab näitaja saadud kopleksi viimasele sõnumile. — sõnum, millele lisatakse veel üks andmeplokk; Vajadusel võib kopleksi muuta üheks sõnumiks, millel on ainus andmeplokk, milleks on funktsioon:

void msgpullup(mblk_t *mp,int len);

kui argument

on -1, siis määratakse andmepuhvri suurus automaatselt. Kui len on positiivne number, siis luuakse selle suurusega puhvri ja kopeeritakse kopleksi sõnumite andmed. Kui puhv tasuta lõpeb, siis kopeerimine peatub. Kopleksi esimene sõnum saab uue suurusega puhvri kopeeritud andmetega. Ülejäänud sõnumid kaovad ja mälu tagastatakse kuhja. len Struktuuri eemaldamisel

arvestatakse andmeploki viidete arvu, kui selle väärtus on väljundite kutsumise ajal mblk_t freeb() on null, siis eemaldatakse andmepuhver koos struktuuriga, mis sellele viitab. Uue sõnumi väljade alginitseerimine: mblk_tvoid mblk_init(mblk_t *mp);

Andmete lisamine sõnumisse veel ühe portion:

void mblk_init(mblk_t *mp);

Sõnumile lisatakse veel üks andmeosa:

mblk_t * appendb(mblk_t *mp, const char *data, size_t size, bool_t pad);

Kui uued andmed ei mahu teate andmebufferisse, siis lisatakse teatele eraldi loodud sõnum, millel on vajalik suurus. (esimeses sõnumis seadistatakse näitaja lisatud sõnumile) sõnum muutub tupiks.

Andmepartiis tupisse lisamine:

void msgappend(mblk_t *mp, const char *data, size_t size, bool_t pad); 

Funktsioon kutsub appendb() välja tsüklis.

Kahe tupiku ühendamine üheks:

see lisab kopleksi

Teade kopleksi lõppu lisatakse — sõnum, millele lisatakse veel üks andmeplokk;.

Ühe sõnumi koopia loomine:

mblk_t *copyb(const mblk_t *mp);

Terve tupiku koopia koos kõigi andmeblokidega:

mblk_t *copymsg(const mblk_t *mp);

Tupiku elemendid kopeeritakse funktsiooni copyb().

Kerge sõnumi koopia loomine mblk_t. Samal ajal andmeplokki ei kopeerita, vaid selle viidete arvu suurendatakse. db_ref:

mblk_t *dupb(mblk_t *mp);

Kerge tupiku koopia loomine. Andmeblokke ei kopeerita, ainult nende viidete arvu suurendatakse. db_ref:

mblk_t *dupmsg(mblk_t* m);

Kõikide tupiku sõnumite liitmine üheks sõnumiks:

void msgpullup(mblk_t *mp,size_t len);

Kui argumendi len väärtus on -1, siis määratakse eraldatud bufferi suurus automaatselt.

Sõnumi, tupiku eemaldamine:

void freemsg(mblk_t *mp);

Andmeploki viidete arv väheneb ühe võrra. Kui see saavutab nulli, siis eemaldatakse ka andmeplokk.

Teate või tupiku andmete kogumahu arvestamine.

size_t msgdsize(const mblk_t *mp);

Sõnumi väljavõtmine järjekorra sabast:

mblk_t *ms_queue_peek_last (q);

Teise sõnumi reservitud väljade sisu kopeerimine teise sõnumisse (tõepoolest sisaldavad need väljad märke, mida meediavoog kasutab):

mblk_meta_copy(const mblk_t *source, mblk *dest);

Järjekord queue_t

Meediavoogude sõnumite järjekord on rakendatud kui ringikujuline kahekordne lingitud loend. Iga loendi element sisaldab viidatud andmeplokki signaali näitudega. Seega liiguvad järjekorras vaid viidatud andmeplokid, samas kui tegelikud andmed jäävad liikumatuks. Ehkki liigutatakse ainult nende viiteid.
Järjekorra struktureerimine queue_t, nagu näidatud allpool:

typedef struct _queue
{
   mblk_t _q_stopper; /* "Tühi" järjekorraelement, ei viita andmetele, kasutatakse ainult järjekorra haldamiseks. Järjekorra initsialiseerimisel (qinit()) seadistatakse selle viidatud nii, et nad viitavad sellele endale. */
   int q_mcount;        // elementide arvu järjekorras.
} queue_t;

Struktuur sisaldab välja - viidatud _q_stopper tüüpi *mblk_t, see viitab esimesele elemendile (sõnum) järjekorras. Teine välja struktuuris on sõnumite arv järjekorras.
Alloleval joonisel on järjekord nimega q1, mis sisaldab 4 sõnumit m1,m2, m3, m4.
Uurime VoIP-mootorit Mediastreamer2. Osa 11
Järgmine joonis näitab järjekorda nimega q1, mis sisaldab 4 sõnumit m1,m2, m3, m4. Sõnum m2 on tupiku pea, kuhu viivad veel kaks sõnumit m2_1 ja m2_2.

Uurime VoIP-mootorit Mediastreamer2. Osa 11

Järjekordadega töötamise funktsioonid queue_t

Järjekorra initsialiseerimine:

void qinit(queue_t *q);

Väli _q_stopper (edasi nimetame seda "stööriks") initsialiseeritakse funktsiooniga mblk_init(), mille eelmine element ja järgmine element seadistatakse nii, et nad viitavad iseendale. Järjekorra elementide arvu loendit nullitakse.

Uue elementi (sõnumi) lisamine:

void putq(queue_t *q, mblk_t *m);

Uus element m lisatakse loendi lõppu, elemendi näitajad seadistatakse nii, et stopp muutub selle järgmiseks elemendiks ja tema eelmine element on stopp. Järjekorra elementide arvu suurendatakse.

Elemendi välja tõmbamine järjekorrast:

mblk_t * getq(queue_t *q); 

välja tõmmatakse see sõnum, mis on stoppist järgmisel kohal, elemendi loendit vähendatakse. Kui järjekorras pole muud elemente peale stoppi, siis tagastatakse 0.

Sõnumi järjekorras sisestamine:

void insq(queue_t *q, mblk_t *emp, mblk_t *mp); 

Element — sõnum, millele lisatakse veel üks andmeplokk; sisestatakse elemendi emp. Kui emp=0, siis sõnum lisatakse järjekorra sabasse.

Sõnumi eemaldamine järjekorra peast:

void remq(queue_t *q, mblk_t *mp); 

Elemendi loendit vähendatakse.

Viidatud esimese elemendi lugemine järjekorras:

mblk_t * peekq(queue_t *q); 

Kõikide elementide eemaldamine järjekorrast koos elementide enda eemaldamisega:

void flushq(queue_t *q, int how);

Argument how ei kasutata. Järjekorra elementide arvu seadistatakse nulli.

Makro viidatud viimase järjekorra elemendi lugemiseks:

mblk_t * qlast(queue_t *q);

Teatestrateegiate tööpiirkondadega tuleb arvestada, et ms_queue_put(q, m) nullse näitajaga sõnumile kutse tsükeldub. Teie programm hangub. Sarnaselt käitub ms_queue_next(q, m).

Filtrite ühendamine

Ülaltoodud järjekorda kasutatakse sõnumite edastamiseks ühest filtrist teise või ühest mitmele filtrile. Filtrid ja nende ühendused loovad suunatud graafi. Filtri sisenemist või väljundit nimetame üldiselt "pin-ks". Filtrite omavahelise ühendamise järjekorra kirjeldamiseks kasutatakse meediastrateegis mõistet "signaalpunkt". Signaalpunkt on struktuur _MSCPoint, mis sisaldab viidatud filtrit ja ühe selle pin-i numbrit, kirjeldades seega ühendust ühe filtri sisendi või väljundi vahel.

Andmete töötlemise graafi signaalpunkt

typedef struct _MSCPoint{
struct _MSFilter *filter; // Viit filteri meediastrateegis.
int pin;                        // Ühe filtrisisendi või -väljundi number, s.t. pin.
} MSCPoint;

Filtrite pinnad nummerdatakse alates nullist.

Kahte pin-i sõnumite järjekorraga ühendust kirjeldab struktuur _MSQueue, mis sisaldab sõnumite järjekorda ja viiteid kahe signaalpunkti vahel, mida see ühendab:

typedef struct _MSQueue
{
queue_t q;
MSCPoint prev;
MSCPoint next;
}MSQueue;

Kutsume seda struktuuri signaallinkiks. Igal meediastrateegifiltril on sisend- ja väljundlinkide tabelid (MSQueue). Tabelite suurus määratakse filtri loomisel, mida me juba tegime eksportimise abil, kasutades muutujat tüübi MSFilterDesc, kui arendasime oma filtrit. Allpool on näidatud struktuur, mis kirjeldab kõiki filtreid meediastrateegis, MSFilter:


struct _MSFilter{
    MSFilterDesc *desc;    /* Viit filtri descriptor-ile. */
    /* Kaitstud atribuudid, neid ei tohi nihutada või eemaldada, muidu rikutakse pluginatega töötamist. */
    ms_mutex_t lock;      /* Semafor. */
    MSQueue **inputs;     /* Sisendlinkide tabel. */
    MSQueue **outputs;    /* Väljundlinkide tabel. */
    struct _MSFactory *factory; /* Viit tehasele, mis lõi antud filtrieksampli. */
    void *padding;              /* Ei kasutata, kasutatakse ära, kui kaitstud väljad on lisatud. */
    void *data;                 /* Viit suvalisele struktuurile filtri sisemise oleku ja vaheandmete salvestamiseks. */
    struct _MSTicker *ticker;   /* Viit ticker-erille, mis ei tohi olla null, kui kutsutakse funktsiooni process(). */
    /* eraatribuudid, neid saab viia ja muuta igal ajal */
    MSList *notify_callbacks; /* Tagasikutsumiste loend, mida kasutatakse filtri sündmuste töötlemiseks. */
    uint32_t last_tick;       /* Viimane tehke number, kui viidi läbi process() kutse. */ 
    MSFilterStats *stats;     /* Filtri tööstatistika. */
    int postponed_task; /* Edasilükatud ülesannete arv. Mõned filtrid võivad edasilükata andmete töötlemist (process() kutse) mitme taktiga. */
    bool_t seen;  /* Lipp, mida ticker kasutab selleks, et tähistada, et antud filtri eksemplar on juba teenindatud antud taktiga. */
};
typedef struct _MSFilter MSFilter;

Pärast seda, kui oleme C-programmis filtrid vastavalt meie kavandile kokku ühendanud (aga tickerit ei ühendanud), oleme loonud suunatud graafi, mille sõlmed on struktuuri eksemplarid MSFilter, ning servad on linkide eksemplarid. MSQueue.

Tickere tagumine tegevus

Kui ütlesin teile, et ticker on taktiallikas, siis see ei olnud kogu tõde tema kohta. Ticker on objekt, mis käitada kõiki filtreid protsesside (graafik) käivitavat funktsiooni process() koosneva kõikide filtreid, millega ta on ühendatud. Kui me C-programmis ühendame tickeri graafi filtri, näitame tickerile graafi, mida ta juhtima hakkab, kuni me ta välja lülitame. Pärast ühendamist hakkab ticker vaatama talle antud graafi, koostades loetelu filtritest, mis selles on. Et mitte "loenda" sama filtrit kaks korda, märgib ta avastatud filtrid, määrates neile märgi seen. Otsing toimub iga filtri linkide tabelite kaudu.

Oma sissejuhatava ekskursiooni ajal graafis kontrollib ticker, kas filtrite seas on vähemalt üks, mis täidab andmeplokkide allika rolli. Kui selliseid ei leita, loetakse graaf vale ja ticker lõpetab hädaolukorraga oma töö.

Kui graaf on "õige", kutsutakse iga leitud filtri jaoks initsialiseerimise funktsioon preprocess(). Niipea kui saabub aeg järgmise töötlemise taktiks (vaikimisi iga 10 millisekundi järel), kutsub ticker välja funktsiooni process() kõigi eelnevalt leitud allikafiltrite jaoks ja seejärel ka ülejäänud filtrile loendis. Kui filtril on sisendlinke, siis invokeeritakse funktsiooni process() korduvalt seni, kuni sisendlinkide järjekorrad on tühjaks saanud. Pärast seda liigub ta järgmise filtri juurde loendis ja "käitab" seda, kuni sisendlinkidelt sõnumid vabanevad. Ticker liigub filtrist filtrisse seni, kuni loend lõpeb. Sellega töötlemine takt on lõpetatud.

Nüüd naaseme tuplede juurde ja räägime, miks selline entiteet on lisatud mediastreamerisse. Üldiselt on andmemaht, mida algoritm, mis töötab filtri sees, vajab, erinev ega ole suhtega ning ei ole kordne sisenemise andmebufferite suurusega. Näiteks, kui kirjutame filtri, mis teostab kiiret Fourier' muundamist, siis see võib töödelda ainult andmeplokke, mille suurus on 2 astmes. Olgu see 512 näidist. Kui andmed genereeritakse telefonikanali kaudu, siis sisenemise igas sõnumis andmebuffer toob meile 160 näidist signaalist. On kiusatus mitte võtta andmeid sisenemisest, kuni seal on vajalik hulk andmeid. Kuid sel juhul tekib konflikt ticker'iga, mis püüab filtri tühjaks ajada. Varem märkasime seda reeglit filtrite kolmanda tööprintsiibina. Selle printsiibi kohaselt peab filtri process() funktsioon võtma kõik andmed sisenemise järjekordadest.

Lisaks ei saa sisenemisest võtta lihtsalt 512 näidist, kuna andmeid saab võtta ainult täistehnikas, st filter peab võtma 640 näidist ja kasutama neist 512, jättes ülejäänud uute andmepakkide kogunemiseks. Seega peab meie filter, lisaks oma peamisele tööle, tagama abifunktsioonid sisenemise andmete vahepealseks säilitamiseks. Mediastreameri arendajad lahendasid selle üldise ülesande jaoks spetsiaalse objekti – MSBufferizer (vahebuffer), mis lahendab selle ülesande tuplede abil.

Vahemälu (MSBufferizer)

See on objekt, mis hakkab akumuleerima sisenemise andmeid filtri sees ja hakkab edastama neid töötlemiseks, kui teabe hulk on piisav filtri algoritmi käivitamiseks. Kui vahebuffer kogub andmeid, töötab filter tühja režiimis, raiskamata protsessori arvutusvõimet. Kuid niipea, kui lugemine vahebufferist tagastab väärtuse, mis pole null, hakkab filtri process() funktsioon võtma ja töötlema vahebufferist andmeid vajalikus suuruses kuni nende lõpuni.
Kasuta käsitletud andmed jäävad vahebufferisse kui esimene element tuple'ist, millele liituvad järgmised sisenemisandmete plokid.

Struktuur, mis kirjeldab vahebufferit:

struct _MSBufferizer{
queue_t q; /* Sõnumite järjekord. */
int size; /* Vahebufferis olevate andmete kogus hetkel. */
};
typedef struct _MSBufferizer MSBufferizer;

MSBufferizeri töötamise funktsioonid

Uue vahebufferi eksemplari loomine:

MSBufferizer * ms_bufferizer_new(void);

Mälu eraldatakse, initsialiseeritakse ms_bufferizer_init() ja tagastatakse viide.

Initsialiseerimise funktsioon:

void ms_bufferizer_init(MSBufferizer *obj); 

Initsialiseeritakse järjekord q, väli size seatakse nulliks.

Sõnumi lisamine:

void ms_bufferizer_put(MSBufferizer *obj, mblk_t *m); 

Sõnum m lisatakse järjekorda. Arvutatud andmeplokkide suurus liidetakse size.

Tõlge vahebufferisse kõigist sõnumitest, mis on andmejärjekorras q:

void ms_bufferizer_put_from_queue(MSBufferizer *obj, MSQueue *q);   

Sõnumite edasiviimine andmejärjekorrast q vahebufferisse toimub funktsiooni kaudu ms_bufferizer_put().

Lugemine vahebufferist:

int ms_bufferizer_read(MSBufferizer *obj, uint8_t *data, int datalen); 

Kui kogus vahebufferis olevatest andmetest on väiksem kui nõutud (datalen), tagastab funktsioon nulli, andmete kopeerimine data'i ei toimu. Vastupidisel juhul toimub järjestikune andmete kopeerimine vahebufferis olevatest tuple'idest. Pärast kopeerimist tuple eemaldatakse ja mälu vabastatakse. Kopeerimine lõppeb hetkel, kui kopeeritakse datalen baitide suurus. Kui koht lõpeb andmeploki keskel, siis.antud sõnumis vähendatakse andmeploki suurust allesjäänud kopeerimata osale. Järgmise kutsumise korral jätkub kopeerimine sealt.

Andmete lugemine, mis on hetkel vahebufferis saadaval:

int ms_bufferizer_get_avail(MSBufferizer *obj); 

Tagastab vahebufferi. size Andmete osa ignoreerimine, mis asub vahebufferis:

void ms_bufferizer_skip_bytes(MSBufferizer *obj, int bytes);

Määratud andmebaite kogus eemaldatakse ja kõrvaldatakse. Eemaldatakse vanimad andmed.

Kõigi vahebufferis olevate sõnumite eemaldamine:

void ms_bufferizer_flush(MSBufferizer *obj);

Andmete loendurit nullitakse. 

void ms_bufferizer_uninit(MSBufferizer *obj);

void ms_bufferizer_flush(MSBufferizer *obj);

Loenduri nullimine ei toimu. 

Vahebufferi eemaldamine ja mälukaartide vabastamine:

void ms_bufferizer_destroy(MSBufferizer *obj);

Näiteid vahebufferi kasutamisest võib leida mitme mediastreameri filtri allikakoodist. Näiteks filter MS_L16_ENC, mis teostab baitide aubristikul järgset ümberpaigutust, saates neid võrgukorra kätte:  

l16.c l16.c

Järgmises artiklis käsitleme koormuse hindamist tikkeril ja viise üleliigse arvutuskoormuse vähendamiseks meediastreameris.

Allikas: habr.com

Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster