Mediastreamer2 VoIP-mootori uurimine. 11. osa

Artikli materjal on võetud minu zen kanal.

Mediastreamer2 VoIP-mootori uurimine. 11. osa

Andmete liikumise mehhanism

  • Andmeplokk dblk_t
  • Sõnum mblk_t
  • Funktsioonid sõnumitega töötamiseks mblk_t
  • Järjekord järjekord_t
  • Funktsioonid järjekordadega töötamiseks queue_t
  • Filtrite ühendamine
  • Andmetöötlusgraafiku signaalpunkt
  • Tickeri telgitagune tegevus
  • Puhver (MSBufferizer)
  • Funktsioonid MSBufferizeriga töötamiseks

Viimases siit oleme välja töötanud oma filtri. See artikkel keskendub sisemisele mehhanismile andmete teisaldamiseks meediumivoofiltrite vahel. See võimaldab teil edaspidi väiksema vaevaga kirjutada keerukaid filtreid.

Andmete liikumise mehhanism

Andmete liikumine meediumivoodris toimub struktuuriga kirjeldatud järjekordade abil järjekord_t. Sõnumite jada nagu mblk_t, mis ise signaaliandmeid ei sisalda, vaid lingivad ainult eelmisele, järgmisele sõnumile ja andmeplokile. Lisaks tahan eriti rõhutada, et on olemas ka sama tüüpi sõnumi lingi väli, mis võimaldab korraldada üksikult lingitud kirjade loendit. Nimetame sellise loendiga ühendatud sõnumite rühma korteežiks. Seega võib järjekorra mis tahes element olla üks sõnum mblk_tja võib-olla ka sõnumikorpuse pea mblk_t. Igal korteeži teatel võib olla oma palatiandmete plokk. Miks kortereid vaja on, arutame veidi hiljem.

Nagu eespool mainitud, ei sisalda sõnum ise andmeplokki, selle asemel sisaldab see ainult osutit mälualale, kus plokk on salvestatud. Selles osas meenutab meediastriimija töö üldpilt multikas “Monsters, Inc.” ukseladu, kus uksed (lingid andmetele – ruumid) liiguvad meeletu kiirusega mööda õhukonveiereid, ruumid ise aga liikumatuks jääda.

Nüüd, liikudes mööda hierarhiat alt üles, kaalume üksikasjalikult meediumistriimi andmeedastusmehhanismi loetletud üksusi.

Andmeplokk dblk_t

Andmeplokk koosneb päisest ja andmepuhvrist. Päist kirjeldab järgmine struktuur,

typedef struct datab
{
unsigned char *db_base; // Указатель на начало буфер данных.
unsigned char *db_lim;  // Указатель на конец буфер данных.
void (*db_freefn)(void*); // Функция освобождения памяти при удалении блока.
int db_ref; // Счетчик ссылок.
} dblk_t;

Struktuuri väljad sisaldavad viiteid puhvri algusele, puhvri lõpule ja andmepuhvri kustutamise funktsioonile. Päise viimane element db_ref — võrdlusloendur, kui see jõuab nullini, on see signaal selle ploki mälust kustutamiseks. Kui andmeploki lõi funktsioon datab_alloc() , siis paigutatakse andmepuhver mällu kohe pärast päist. Kõigil muudel juhtudel võib puhver asuda kuskil eraldi. Andmepuhver sisaldab signaalinäidiseid või muid andmeid, mida soovime filtritega töödelda.

Andmeploki uus eksemplar luuakse funktsiooni abil:

dblk_t *datab_alloc(int size);

Sisendparameetrina antakse sellele andmete suurus, mida plokk salvestab. Rohkem mälu eraldatakse selleks, et paigutada eraldatud mälu algusesse päis - struktuur andmeb. Kuid teiste funktsioonide kasutamisel seda alati ei juhtu, mõnel juhul võib andmepuhver asuda andmeploki päisest eraldi. Struktuuri loomisel konfigureeritakse väljad nii, et selle väli db_base osutas andmeala algusesse ja db_lim selle lõpuni. Linkide arv db_ref on seatud ühele. Andmete kustutamise funktsiooni kursor on seatud nullile.

Sõnum mblk_t

Nagu öeldud, on järjekorra elemendid tüüpi mblk_t, see on määratletud järgmiselt:

typedef struct msgb
{
  struct msgb *b_prev;   // Указатель на предыдущий элемент списка.
  struct msgb *b_next;   // Указатель на следующий элемент списка.
  struct msgb *b_cont;   // Указатель для подклейки к сообщению других сообщений, для создания кортежа сообщений.
  struct datab *b_datap; // Указатель на структуру блока данных.
  unsigned char *b_rptr; // Указатель на начало области данных для чтения данных буфера b_datap.
  unsigned char *b_wptr; // Указатель на начало области данных для записи данных буфера b_datap.
  uint32_t reserved1;    // Зарезервированное поле1, медиастример помещает туда служебную информацию. 
  uint32_t reserved2;    // Зарезервированное поле2, медиастример помещает туда служебную информацию.
  #if defined(ORTP_TIMESTAMP)
  struct timeval timestamp;
  #endif
  ortp_recv_addr_t recv_addr;
} mblk_t;

Struktuur mblk_t sisaldab viiteid alguses b_eelmine, b_next, mis on vajalikud topeltlingitud loendi (mis on järjekord järjekord_t).

Siis tuleb osuti b_cont, mida kasutatakse ainult siis, kui sõnum on korteeži osa. Korpuse viimase kirja puhul jääb see osuti nulliks.

Järgmisena näeme kursorit andmeplokile b_datap, mille jaoks sõnum on olemas. Sellele järgnevad osutid ploki andmepuhvris olevale alale. Väli b_rptr määrab asukoha, kust puhvrist andmeid loetakse. Väli b_wptr näitab asukohta, kust puhvrisse kirjutatakse.

Ülejäänud väljad on teenuse iseloomuga ega ole seotud andmeedastusmehhanismi toimimisega.

Allpool on üks teade nimega m1 ja andmeplokk d1.
Mediastreamer2 VoIP-mootori uurimine. 11. osa
Järgmisel joonisel on kujutatud kolmest sõnumist koosnev rida m1, m1_1, m1_2.
Mediastreamer2 VoIP-mootori uurimine. 11. osa

Sõnumside funktsioonid mblk_t

Uus sõnum mblk_t loodud funktsiooniga:

mblk_t *allocb(int size, int pri); 

ta paneb mällu uue sõnumi mblk_t määratud suurusega andmeplokiga suurus, teine ​​argument - pre selles teegi versioonis ei kasutata. See peaks jääma nulliks. Funktsiooni töötamise ajal eraldatakse mälu uue sõnumi struktuuri jaoks ja funktsioon kutsutakse välja mblk_init(), mis lähtestab kõik loodud struktuuri eksemplari väljad ja seejärel ülalnimetatu abil datab_alloc(), loob andmepuhvri. Pärast seda konfigureeritakse struktuuri väljad:

mp->b_datap=datab;
mp->b_rptr=mp->b_wptr=datab->db_base;
mp->b_next=mp->b_prev=mp->b_cont=NULL;

Väljundis saame uue teate initsialiseeritud väljade ja tühja andmepuhvriga. Sõnumile andmete lisamiseks peate selle kopeerima andmeploki puhvrisse:

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

kus andmed on osutaja andmeallikale ja suurus - nende suurus.
siis peate värskendama kursorit kirjutuspunktile nii, et see osutaks uuesti puhvris oleva vaba ala algusesse:

msg->b_wptr = msg->b_wptr + size

Kui teil on vaja luua sõnum olemasolevast puhvrist ilma kopeerimiseta, kasutage funktsiooni:

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

Funktsioon seadistab pärast sõnumi ja andmeploki struktuuri loomist oma viidad aadressil olevatele andmetele buff. Need. sel juhul ei asu andmepuhver andmeploki päiseväljade järel, nagu juhtus funktsiooniga andmeploki loomisel datab_alloc(). Funktsioonile edastatud andmetega puhver jääb sinna, kus ta oli, kuid osutite abil kinnitatakse see andmeploki vastloodud päisesse ja see vastavalt ka sõnumile.

Ühele sõnumile mblk_t Mitu andmeplokki saab järjestikku ühendada. Seda teeb funktsioon:

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

mp — teade, millele lisatakse veel üks andmeplokk;
andmed — kursor plokile, mille koopia lisatakse sõnumile;
suurus — andmete suurus;
pad — lipp, et eraldatud mälu suurus peab olema joondatud piki 4-baidist piiri (polster tehakse nullidega).

Kui olemasolevas sõnumiandmete puhvris on piisavalt ruumi, kleebitakse uued andmed juba seal olevate andmete taha. Kui sõnumi andmepuhvris on vähem vaba ruumi kui suurus, siis luuakse piisava puhvriga uus sõnum ja andmed kopeeritakse selle puhvrisse. See on uus sõnum, mis on kursori abil lingitud algse sõnumiga b_cont. Sel juhul muutub sõnum korteežiks.

Kui teil on vaja korteeži lisada veel üks andmeplokk, peate kasutama funktsiooni:

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

ta leiab kataloogist viimase sõnumi (tal on b_cont on null) ja kutsub selle sõnumi funktsiooni appendb().

Sõnumis või korpuses olevate andmete suuruse saate teada funktsiooni abil:

int msgdsize(const mblk_t *mp);

see vaatab läbi kõik korteeži sõnumid ja tagastab nende sõnumite andmepuhvrites olevate andmete kogumahu. Iga sõnumi jaoks arvutatakse andmemaht järgmiselt:

 mp->b_wptr - mp->b_rptr

Kahe korteeži ühendamiseks kasutage funktsiooni:

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

ta lisab korteeži uusm korteeži sabale mp ja tagastab kursori tulemuseks oleva korteeži viimasele sõnumile.

Vajadusel saab korteeži muuta üheks sõnumiks ühe andmeplokiga, seda teeb funktsioon:

void msgpullup(mblk_t *mp,int len);

kui argument len on -1, siis määratakse eraldatud puhvri suurus automaatselt. Kui len on positiivne arv, luuakse sellise suurusega puhver ja sinna kopeeritakse sõnumite andmed. Kui puhver saab otsa, siis kopeerimine peatub. Korpuse esimene sõnum saab uue suurusega puhvri koos kopeeritud andmetega. Ülejäänud sõnumid kustutatakse ja mälu tagastatakse hunnikusse.

Struktuuri kustutamisel mblk_t andmeploki viiteloendust võetakse arvesse, kui helistamisel freeb() see osutub nulliks, siis kustutatakse andmepuhver koos eksemplariga mblk_t, mis sellele viitab.

Uue sõnumi väljade lähtestamine:

void mblk_init(mblk_t *mp);

Sõnumile teise andmeosa lisamine:

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

Kui uued andmed ei mahu sõnumi andmepuhvri vabasse ruumi, siis lisatakse kirjale eraldi koostatud sõnum koos vajaliku suurusega puhvriga (esimesse sõnumisse seatakse kursor lisatud sõnumile) ja sõnum muutub korteežiks.

Andmeosa lisamine korteisse:

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

Funktsioon kutsub appendb() tsüklina.

Kahe korteeži ühendamine üheks:

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

Sõnum uusm külge kinnitatakse mp.

Ühest sõnumist koopia tegemine:

mblk_t *copyb(const mblk_t *mp);

Korpuse täielik kopeerimine kõigi andmeplokkidega:

mblk_t *copymsg(const mblk_t *mp);

Korteri elemendid kopeerib funktsioon copyb().

Looge sõnumist lihtne koopia mblk_t. Sel juhul andmeplokki ei kopeerita, vaid suurendatakse selle võrdlusloendurit db_ref:

mblk_t *dupb(mblk_t *mp);

Korpuse kerge koopia tegemine. Andmeplokke ei kopeerita, ainult nende viiteloendureid suurendatakse db_ref:

mblk_t *dupmsg(mblk_t* m);

Korpuse kõigi kirjade liimimine üheks sõnumiks:

void msgpullup(mblk_t *mp,size_t len);

Kui argument len on -1, siis määratakse eraldatud puhvri suurus automaatselt.

Sõnumi kustutamine, korp:

void freemsg(mblk_t *mp);

Andmeploki võrdlusarvu vähendatakse ühe võrra. Kui see jõuab nullini, kustutatakse ka andmeplokk.

Sõnumi või korteeži andmete koguhulga arvutamine.

size_t msgdsize(const mblk_t *mp);

Sõnumi toomine järjekorra lõpust:

mblk_t *ms_queue_peek_last (q);

Ühe sõnumi reserveeritud väljade sisu kopeerimine teise sõnumisse (tegelikult sisaldavad need väljad lippe, mida meediavooder kasutab):

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

Pöörake järjekord_t

Sõnumijärjekord meediumivooderdis on realiseeritud ringikujulise topeltlingitud loendina. Iga loendi element sisaldab osutit signaalinäidistega andmeplokile. Selgub, et kordamööda liiguvad ainult osutid andmeplokile, samas kui andmed ise jäävad liikumatuks. Need. teisaldatakse ainult nende linke.
Järjekorda kirjeldav struktuur järjekord_t, näidatud allpool:

typedef struct _queue
{
   mblk_t _q_stopper; /* "Холостой" элемент очереди, не указывает на данные, используется только для управления очередью. При инициализации очереди (qinit()) его указатели настраиваются так, чтобы они указывали на него самого. */
   int q_mcount;        // Количество элементов в очереди.
} queue_t;

Struktuur sisaldab välja – osutit _q_stopper tippige *mblk_t, osutab see järjekorra esimesele elemendile (sõnumile). Struktuuri teine ​​väli on järjekorras olevate sõnumite loendur.
Alloleval joonisel on kujutatud järjekorda nimega q1, mis sisaldab 4 teadet m1, m2, m3, m4.
Mediastreamer2 VoIP-mootori uurimine. 11. osa
Järgmisel joonisel on kujutatud järjekorda nimega q1, mis sisaldab 4 sõnumit m1,m2,m3,m4. Sõnum m2 on korteeži pea, mis sisaldab veel kahte sõnumit m2_1 ja m2_2.

Mediastreamer2 VoIP-mootori uurimine. 11. osa

Funktsioonid järjekordadega töötamiseks queue_t

Järje lähtestamine:

void qinit(queue_t *q);

Väli _q_stopper (edaspidi nimetame seda "korkiks") lähtestab funktsioon mblk_init(), selle eelmist elementi ja järgmise elemendi osutit kohandatakse nii, et see osutab iseendale. Järjekorraelementide loendur lähtestatakse nullile.

Uue elemendi (sõnumite) lisamine:

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

Uus element m Lisatakse loendi lõppu, kohandatakse elementide viiteid nii, et stopper saab selle järgmiseks elemendiks ja sellest saab stopperi eelmine element. Järjekorraelementide loendurit suurendatakse.

Elemendi toomine järjekorrast:

mblk_t * getq(queue_t *q); 

Sõnum, mis saabub pärast stopperit, otsitakse ja elementide loendurit vähendatakse. Kui järjekorras pole elemente peale stopperi, tagastatakse 0.

Sõnumi lisamine järjekorda:

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

Element mp sisestatud enne elementi emp. Kui emp=0, siis lisatakse teade järjekorra saba.

Sõnumi toomine järjekorra peast:

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

Elementide loendurit vähendatakse.

Kursori lugemine järjekorra esimesele elemendile:

mblk_t * peekq(queue_t *q); 

Kõigi elementide eemaldamine järjekorrast elementide endi kustutamise ajal:

void flushq(queue_t *q, int how);

argument kuidas pole kasutatud. Järjekorraelementide loendur on seatud nullile.

Makro kursori lugemiseks järjekorra viimasele elemendile:

mblk_t * qlast(queue_t *q);

Sõnumijärjekordadega töötades arvestage sellega, et helistades ms_queue_put(q, m) nullkursoriga sõnumile loob funktsioon silmuseid. Teie programm hangub. käitub sarnaselt ms_queue_next(q, m).

Filtrite ühendamine

Ülalkirjeldatud järjekorda kasutatakse sõnumite edastamiseks ühest filtrist teise või ühest filtrist mitmele. Filtrid ja nende ühendused moodustavad suunatud graafiku. Filtri sisendit või väljundit nimetatakse üldsõnaks “pin”. Filtrite üksteisega ühendamise järjekorra kirjeldamiseks kasutab meediumistriimer mõistet "signaalpunkt". Signaalpunkt on struktuur _MSCPoint, mis sisaldab kursorit filtrile ja selle ühe tihvti numbrit; vastavalt kirjeldab see filtri ühe sisendi või väljundi ühendamist.

Andmetöötlusgraafiku signaalpunkt

typedef struct _MSCPoint{
struct _MSFilter *filter; // Указатель на фильтр медиастримера.
int pin;                        // Номер одного из входов или выходов фильтра, т.е. пин.
} MSCPoint;

Filtri tihvtid on nummerdatud alates nullist.

Kahe kontakti ühendamist sõnumijärjekorraga kirjeldab struktuur _MSQueue, mis sisaldab sõnumijärjekorda ja viiteid kahele signaalipunktile, mida see ühendab:

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

Nimetame seda struktuuri signaalilingiks. Iga meedia voogedastusfilter sisaldab sisendlinkide tabelit ja väljundlinkide tabelit (MSQueue). Tabelite suurus määratakse filtri loomisel, oleme seda juba teinud eksporditud tüüpi muutuja abil MSFilterDesc, kui töötasime välja oma filtri. Allpool on struktuur, mis kirjeldab mis tahes filtrit meediumivooge, MSFilter:


struct _MSFilter{
    MSFilterDesc *desc;    /* Указатель на дескриптор фильтра. */
    /* Защищенные атрибуты, их нельзя сдвигать или убирать иначе будет нарушена работа с плагинами. */
    ms_mutex_t lock;      /* Семафор. */
    MSQueue **inputs;     /* Таблица входных линков. */
    MSQueue **outputs;    /* Таблица выходных линков. */
    struct _MSFactory *factory; /* Указатель на фабрику, которая создала данный экземпляр фильтра. */
    void *padding;              /* Не используется, будет задействован если добавятся защищенные поля. */
    void *data;                 /* Указатель на произвольную структуру для хранения данных внутреннего состояния фильтра и промежуточных вычислений. */
    struct _MSTicker *ticker;   /* Указатель на объект тикера, который не должен быть нулевым когда вызывается функция process(). */
    /*private attributes, they can be moved and changed at any time*/
    MSList *notify_callbacks; /* Список обратных вызовов, используемых для обработки событий фильтра. */
    uint32_t last_tick;       /* Номер последнего такта, когда выполнялся вызов process(). */ 
    MSFilterStats *stats;     /* Статистика работы фильтра.*/
    int postponed_task; /*Количество отложенных задач. Некоторые фильтры могут откладывать обработку данных (вызов process()) на несколько тактов.*/
    bool_t seen;  /* Флаг, который использует тикер, чтобы помечать что этот экземпляр фильтра он уже обслужил на данном такте.*/
};
typedef struct _MSFilter MSFilter;

Pärast seda, kui ühendasime programmis C filtrid vastavalt oma plaanile (kuid ei ühendanud tickerit), lõime sellega suunatud graafiku, mille sõlmed on struktuuri eksemplarid MSFilterja servad on linkide näited MSQueue.

Tickeri telgitagune tegevus

Kui ma ütlesin teile, et ticker on puukide allika filter, ei olnud see selle kohta kogu tõde. Tiker on objekt, mis käivitab kella funktsioone protsess () kõik selle ahela (graafiku) filtrid, millega see on ühendatud. Kui ühendame tickeri C-programmis graafikufiltriga, näitame tickerile graafikut, mida ta juhib edaspidi kuni selle väljalülitamiseni. Pärast ühendamist hakkab ticker uurima tema hoolde usaldatud graafikut, koostades seda sisaldavate filtrite loendi. Et sama filtrit kaks korda mitte "loendaks", märgib see tuvastatud filtrid, lisades nendesse märkeruudu nähtud. Otsing toimub iga filtri linkitabelite abil.

Graafiku sissejuhatava ringkäigu ajal kontrollib ticker, kas filtrite hulgas on vähemalt üks, mis toimib andmeplokkide allikana. Kui neid pole, loetakse graafik valeks ja ticker jookseb kokku.

Kui graafik osutub “õigeks”, kutsutakse iga leitud filtri puhul funktsioon lähtestamiseks eeltöötlus (). Niipea kui saabub hetk järgmiseks töötlemistsükliks (vaikimisi iga 10 millisekundi järel), kutsub ticker funktsiooni protsess () kõigi varem leitud allikafiltrite jaoks ja seejärel loendis ülejäänud filtrite jaoks. Kui filtril on sisendlingid, käivitage funktsioon protsess () kordub, kuni sisendlingi järjekorrad on tühjad. Pärast seda liigub see loendis järgmise filtri juurde ja “kerib” seda seni, kuni sisendlingid on sõnumitest vabad. Ticker liigub filtrilt filtrile kuni loendi lõpuni. See lõpetab tsükli töötlemise.

Nüüd pöördume tagasi korteeži juurde ja räägime, miks selline olem meediavoodrisse lisati. Üldjuhul ei lange filtri sees töötava algoritmi poolt nõutav andmemaht kokku ega ole sisendis vastuvõetud andmepuhvrite suuruse kordne. Näiteks kirjutame filtri, mis teostab kiire Fourier' teisenduse, mis definitsiooni järgi suudab töödelda ainult andmeplokke, mille suurus on kahe astme võrra. Olgu see siis 512. Kui andmed genereeritakse telefonikanali kaudu, siis iga sõnumi andmepuhver sisendis toob meile 160 signaali näidist. On ahvatlev mitte koguda sisendist andmeid enne, kui vajalik kogus andmeid on käes. Kuid sel juhul toimub kokkupõrge tickeriga, mis proovib edutult filtrit kerida, kuni sisendlink on tühi. Varem määrasime selle reegli filtri kolmandaks põhimõtteks. Selle põhimõtte kohaselt peab filtri protsess() funktsioon võtma kõik andmed sisendjärjekordadest.

Lisaks ei saa sisendist võtta ainult 512 proovi, kuna saate võtta ainult terveid plokke, st. filter peab võtma 640 proovi ja kasutama neist 512, ülejäänu enne uue andmeosa kogumist. Seega peab meie filter lisaks oma põhitööle pakkuma abitoiminguid sisendandmete vahepealseks salvestamiseks. Meediumistriimi ja selle üldise probleemi lahenduse arendajad on välja töötanud spetsiaalse objekti - MSBufferizer (puhver), mis lahendab selle probleemi kortereid kasutades.

Puhver (MSBufferizer)

See on objekt, mis kogub filtrisse sisendandmeid ja hakkab neid töötlemiseks saatma niipea, kui teabe hulk on filtrialgoritmi käivitamiseks piisav. Kui puhver andmeid kogub, töötab filter jõuderežiimis, ilma protsessori töötlemisvõimsust kasutamata. Kuid niipea, kui puhvri lugemisfunktsioon tagastab nullist erineva väärtuse, hakkab filtri funktsioon protsess () võtma ja töötlema puhvrist andmeid vajaliku suurusega osadena, kuni see on ammendatud.
Andmed, mida veel ei nõuta, jäävad puhvrisse korteeži esimese elemendina, millele on lisatud järgnevad sisendandmete plokid.

Puhvrit kirjeldav struktuur:

struct _MSBufferizer{
queue_t q; /* Очередь сообщений. */
int size; /* Суммарный размер данных находящихся в буферизаторе в данный момент. */
};
typedef struct _MSBufferizer MSBufferizer;

Funktsioonid MSBufferizeriga töötamiseks

Uue puhvri eksemplari loomine:

MSBufferizer * ms_bufferizer_new(void);

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

Initsialiseerimisfunktsioon:

void ms_bufferizer_init(MSBufferizer *obj); 

Järjekord initsialiseeritakse q, väli suurus on seatud nulli.

Sõnumi lisamine:

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

Sõnum m lisatakse järjekorda. Lisatakse andmeplokkide arvutatud suurus suurus.

Kõigi sõnumite edastamine lingi andmejärjekorrast puhvrisse q:

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

Sõnumite edastamine lingilt q puhvris teostatakse funktsiooni abil ms_bufferizer_put().

Puhvrist lugemine:

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

Kui puhvrisse kogutud andmete maht on väiksem kui nõutud (datalen), tagastab funktsioon nulli, andmeid andmetesse ei kopeerita. Vastasel juhul kopeeritakse andmed järjestikku puhvris asuvatest korteežidest. Pärast kopeerimist korteež kustutatakse ja mälu vabastatakse. Kopeerimine lõpeb hetkel, kui andmebaidid on kopeeritud. Kui andmeploki keskel saab ruum otsa, siis selles teates taandatakse andmeplokk allesjäänud kopeerimata osale. Järgmine kord, kui helistate, kopeerimine jätkub sellest hetkest.

Praegu puhvris saadaolevate andmete hulga lugemine:

int ms_bufferizer_get_avail(MSBufferizer *obj); 

Tagastab välja suurus puhver.

Osa puhvris olevatest andmetest loobumine:

void ms_bufferizer_skip_bytes(MSBufferizer *obj, int bytes);

Määratud arv baite andmeid otsitakse ja visatakse ära. Vanimad andmed visatakse ära.

Kõigi puhvris olevate sõnumite kustutamine:

void ms_bufferizer_flush(MSBufferizer *obj); 

Andmeloendur nullitakse.

Kõigi puhvris olevate sõnumite kustutamine:

void ms_bufferizer_uninit(MSBufferizer *obj); 

Loendurit ei nullita.

Puhvri eemaldamine ja mälu vabastamine:

void ms_bufferizer_destroy(MSBufferizer *obj);  

Näiteid puhvri kasutamise kohta leiate mitme meedia voogedastusfiltri lähtekoodist. Näiteks filtris MS_L16_ENC, mis korraldab proovide baidid ümber võrgujärjekorrast hostijärjekorrasse: l16.c

Järgmises artiklis käsitleme tickeri koormuse hindamise küsimust ja viise, kuidas võidelda meediumistriimi liigse arvutuskoormusega.

Allikas: www.habr.com

Lisa kommentaar