Verken die Mediastreamer2 VoIP-enjin. Deel 11

Die materiaal van die artikel is geneem uit my zen-kanaal.

Verken die Mediastreamer2 VoIP-enjin. Deel 11

Databewegingsmeganisme

  • Datablok dblk_t
  • Boodskap mblk_t
  • Funksies om met boodskappe te werk mblk_t
  • Tou tou tou_t
  • Funksies om met toue te werk queue_t
  • Koppel filters
  • Seinpunt van dataverwerkingsgrafiek
  • Agter die skerms aktiwiteite van die tikker
  • Bufferizer (MSBufferizer)
  • Funksies om met MSBufferizer te werk

In die laaste Artikel ons het ons eie filter ontwikkel. Hierdie artikel sal fokus op die interne meganisme om data tussen mediastroomfilters te verskuif. Dit sal jou in staat stel om in die toekoms gesofistikeerde filters met minder moeite te skryf.

Databewegingsmeganisme

Databeweging in die mediastreamer word uitgevoer met behulp van toue wat deur die struktuur beskryf word tou_t. Strings boodskappe soos mblk_t, wat self nie seindata bevat nie, maar slegs na die vorige, volgende boodskap en na die datablok skakel. Daarbenewens wil ek veral beklemtoon dat daar ook 'n veld is vir 'n skakel na 'n boodskap van dieselfde tipe, wat jou toelaat om 'n enkelgeskakelde lys boodskappe te organiseer. Ons sal 'n groep boodskappe wat deur so 'n lys verenig word, 'n tupel noem. Dus, enige element van die tou kan 'n enkele boodskap wees mblk_t, en miskien die hoof van 'n boodskap-tupel mblk_t. Elke tupelboodskap kan sy eie saaldatablok hê. Ons sal 'n bietjie later bespreek waarom tupels nodig is.

Soos hierbo genoem, bevat die boodskap self nie 'n blok data nie; in plaas daarvan bevat dit slegs 'n wyser na die geheue area waar die blok gestoor word. In hierdie deel herinner die geheelbeeld van die mediastreamer se werk aan die deurpakhuis in die spotprent "Monsters, Inc.," waar deure (skakels na data - kamers) teen 'n waansinnige spoed langs oorhoofse vervoerbande beweeg, terwyl die kamers self roerloos bly.

Nou, beweeg langs die hiërargie van onder na bo, laat ons die gelyste entiteite van die data-oordragmeganisme in die mediastreamer in detail oorweeg.

Data blok dblk_t

Die datablok bestaan ​​uit 'n kopskrif en 'n databuffer. Die kop word beskryf deur die volgende struktuur,

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

Die velde van die struktuur bevat wysers na die begin van die buffer, die einde van die buffer en die funksie om die databuffer uit te vee. Laaste element in kop db_ref — verwysingsteller, as dit nul bereik, dien dit as 'n sein om hierdie blok uit die geheue te skrap. As die datablok deur die funksie geskep is data_alloc() , dan sal die databuffer onmiddellik na die kopskrif in die geheue geplaas word. In alle ander gevalle kan die buffer iewers apart geleë wees. Die databuffer sal seinmonsters of ander data bevat wat ons met filters wil verwerk.

'n Nuwe instansie van 'n datablok word geskep met die funksie:

dblk_t *datab_alloc(int size);

As 'n invoerparameter word die grootte gegee van die data wat die blok sal stoor. Meer geheue word toegeken om 'n kop - struktuur - aan die begin van die toegekende geheue te plaas datab. Maar wanneer ander funksies gebruik word, gebeur dit nie altyd nie; in sommige gevalle kan die databuffer apart van die datablokopskrif geleë wees. Wanneer 'n struktuur geskep word, word die velde so gekonfigureer dat sy veld db_basis het na die begin van die data area gewys, en db_lim tot sy einde. Skakeltelling db_ref is op een gestel. Die data clear funksie wyser is op nul gestel.

Boodskap mblk_t

Soos genoem, is tou-elemente van tipe mblk_t, dit word soos volg gedefinieer:

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 bevat aanwysings aan die begin b_vorige, b_volgende, wat nodig is om 'n dubbelgekoppelde lys te organiseer (wat 'n tou is tou_t).

Dan kom die wyser b_vervolg, wat slegs gebruik word wanneer die boodskap deel van 'n tupel is. Vir die laaste boodskap in die tupel, bly hierdie wyser nul.

Volgende sien ons 'n wyser na 'n datablok b_datap, waarvoor die boodskap bestaan. Dit word gevolg deur wysers na die area binne die blokdatabuffer. Veld b_rptr spesifiseer die ligging vanwaar data van die buffer gelees sal word. Veld b_wptr dui die ligging aan waarvandaan skryf na die buffer uitgevoer sal word.

Die oorblywende velde is van 'n diensaard en hou nie verband met die werking van die data-oordragmeganisme nie.

Hieronder is 'n enkele boodskap met die naam m1 en datablok d1.
Verken die Mediastreamer2 VoIP-enjin. Deel 11
Die volgende figuur toon 'n tupel van drie boodskappe m1, m1_1, m1_2.
Verken die Mediastreamer2 VoIP-enjin. Deel 11

Boodskapfunksies mblk_t

'n Nuwe boodskap mblk_t geskep deur die funksie:

mblk_t *allocb(int size, int pri); 

sy plaas 'n nuwe boodskap in die geheue mblk_t met 'n datablok van die gespesifiseerde grootte grootte, tweede argument - pri nie in hierdie weergawe van die biblioteek gebruik nie. Dit moet nul bly. Tydens die werking van die funksie sal geheue vir die struktuur van die nuwe boodskap toegewys word en die funksie sal opgeroep word mblk_init(), wat alle velde van die geskepde instansie van die struktuur sal herstel en dan, met behulp van die bogenoemde data_alloc(), sal 'n databuffer skep. Daarna sal die velde in die struktuur gekonfigureer word:

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

By die uitset ontvang ons 'n nuwe boodskap met geïnisialiseerde velde en 'n leë databuffer. Om data by 'n boodskap te voeg, moet jy dit na die datablokbuffer kopieer:

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

waar data is 'n wyser na die databron, en grootte - hul grootte.
dan moet jy die wyser na die skryfpunt bywerk sodat dit weer na die begin van die vrye area in die buffer wys:

msg->b_wptr = msg->b_wptr + size

As jy 'n boodskap van 'n bestaande buffer moet skep, sonder om te kopieer, gebruik dan die funksie:

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

Die funksie, nadat die boodskap en die struktuur van die datablok geskep is, sal sy wysers na die data by die adres opstel buff. Dié. in hierdie geval is die databuffer nie na die kopvelde van die datablok geleë nie, soos die geval was wanneer 'n datablok met die funksie geskep is data_alloc(). Die buffer met data wat na die funksie oorgedra word, sal bly waar dit was, maar met behulp van wysers sal dit aan die nuutgeskepte kop van die datablok geheg word, en dit, dienooreenkomstig, aan die boodskap.

Aan een boodskap mblk_t Verskeie datablokke kan opeenvolgend aaneengeskakel word. Dit word gedoen deur die funksie:

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

mp — 'n boodskap waarby nog 'n datablok gevoeg sal word;
data — wyser na die blok, waarvan 'n kopie by die boodskap gevoeg sal word;
grootte - data grootte;
pad - 'n vlag dat die grootte van die toegekende geheue langs 'n 4-grepe-grens in lyn moet wees (opvulling sal met nulle gedoen word).

As daar genoeg spasie in die bestaande boodskapdatabuffer is, sal die nuwe data agter die data wat reeds daar is geplak word. As daar minder vrye spasie in die boodskapdatabuffer is as grootte, dan word 'n nuwe boodskap geskep met 'n voldoende buffergrootte en die data word na sy buffer gekopieer. Dit is 'n nuwe boodskap, gekoppel aan die oorspronklike een deur 'n wyser te gebruik b_vervolg. In hierdie geval verander die boodskap in 'n tupel.

As jy nog 'n blok data by die tupel moet voeg, moet jy die funksie gebruik:

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

sy sal die laaste boodskap in die tupel vind (hy het b_vervolg sal nul wees) en sal die funksie vir hierdie boodskap oproep appendb().

Jy kan die grootte van data in 'n boodskap of tupel uitvind deur die funksie te gebruik:

int msgdsize(const mblk_t *mp);

dit sal deur al die boodskappe in die tupel loop en die totale hoeveelheid data in die databuffers van daardie boodskappe terugstuur. Vir elke boodskap word die hoeveelheid data soos volg bereken:

 mp->b_wptr - mp->b_rptr

Om twee tupels te kombineer, gebruik die funksie:

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

sy voeg die tupel by nuut na die stert van die tupel mp en gee 'n wyser terug na die laaste boodskap van die resulterende tupel.

Indien nodig, kan 'n tupel omskep word in een boodskap met 'n enkele blok data; dit word gedoen deur die funksie:

void msgpullup(mblk_t *mp,int len);

as argument len is -1, dan word die grootte van die toegekende buffer outomaties bepaal. As len 'n positiewe getal is, sal 'n buffer van hierdie grootte geskep word en die tupelboodskapdata sal daarin gekopieer word. As die buffer opraak, sal kopiëring daar stop. Die eerste boodskap van die tupel sal 'n nuwe grootte buffer met die gekopieerde data ontvang. Die oorblywende boodskappe sal uitgevee word en die geheue sal na die hoop teruggekeer word.

Wanneer 'n struktuur uitvee mblk_t die verwysingtelling van die datablok word in ag geneem indien, wanneer gebel word freeb() dit blyk nul te wees, dan word die databuffer saam met die instansie uitgevee mblk_t, wat daarop dui.

Inisialiseer die velde van 'n nuwe boodskap:

void mblk_init(mblk_t *mp);

Voeg nog 'n stukkie data by die boodskap:

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

As die nuwe data nie in die vrye spasie van die boodskapdatabuffer pas nie, word 'n afsonderlik geskepte boodskap met 'n buffer van die vereiste grootte aan die boodskap geheg ('n wyser na die bygevoegde boodskap word in die eerste boodskap gestel) en die boodskap verander in 'n tupel.

Voeg 'n stukkie data by 'n tupel:

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

Die funksie roep appendb() in 'n lus.

Kombineer twee tupels in een:

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

Boodskap nuut sal geheg word aan mp.

Maak 'n afskrif van 'n enkele boodskap:

mblk_t *copyb(const mblk_t *mp);

Voltooi kopiëring van 'n tupel met alle datablokke:

mblk_t *copymsg(const mblk_t *mp);

Die elemente van die tupel word deur die funksie gekopieer copyb().

Skep 'n maklike kopie van 'n boodskap mblk_t. In hierdie geval word die datablok nie gekopieer nie, maar sy verwysingsteller word verhoog db_ref:

mblk_t *dupb(mblk_t *mp);

Maak 'n liggewigkopie van 'n tupel. Datablokke word nie gekopieer nie, slegs hul verwysingstellers word verhoog db_ref:

mblk_t *dupmsg(mblk_t* m);

Plak alle boodskappe van 'n tupel in een boodskap:

void msgpullup(mblk_t *mp,size_t len);

As die argument len is -1, dan word die grootte van die toegekende buffer outomaties bepaal.

Vee 'n boodskap uit, tuple:

void freemsg(mblk_t *mp);

Die datablok se verwysingtelling word met een verminder. As dit nul bereik, word die datablok ook uitgevee.

Berekening van die totale hoeveelheid data in 'n boodskap of tupel.

size_t msgdsize(const mblk_t *mp);

Haal 'n boodskap van die stert van die tou af:

mblk_t *ms_queue_peek_last (q);

Kopieer die inhoud van die gereserveerde velde van een boodskap na 'n ander boodskap (in werklikheid bevat hierdie velde vlae wat deur die mediastreamer gebruik word):

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

draai tou_t

Die boodskapwaglys in die mediastreamer word geïmplementeer as 'n omsendbrief, dubbelgekoppelde lys. Elke lyselement bevat 'n wyser na 'n datablok met seinmonsters. Dit blyk dat slegs wysers na die datablok om die beurt beweeg, terwyl die data self roerloos bly. Dié. slegs skakels na hulle word geskuif.
Struktuur wat die tou beskryf tou_t, onderstaande:

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

Die struktuur bevat 'n veld - 'n wyser _q_stopper tik *mblk_t, dit wys na die eerste element (boodskap) in die tou. Die tweede veld van die struktuur is die teller van boodskappe in die tou.
Die figuur hieronder toon 'n tou genaamd q1 wat 4 boodskappe m1, m2, m3, m4 bevat.
Verken die Mediastreamer2 VoIP-enjin. Deel 11
Die volgende figuur toon 'n tou genaamd q1 wat 4 boodskappe m1,m2,m3,m4 bevat. Boodskap m2 is die kop van 'n tupel wat nog twee boodskappe m2_1 en m2_2 bevat.

Verken die Mediastreamer2 VoIP-enjin. Deel 11

Funksies om met toue te werk queue_t

Inisialisasie van tou:

void qinit(queue_t *q);

Veld _q_stopper (hierna sal ons dit “stopper” noem) word geïnisialiseer deur die funksie mblk_init(), sy vorige element en volgende element wyser word aangepas om na homself te wys. Die tou-elementteller word na nul teruggestel.

Voeg 'n nuwe element by (boodskappe):

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

Nuwe element m aan die einde van die lys gevoeg word, word die elementwysers so aangepas dat die prop die volgende element daarvoor word, en dit word die vorige element vir die stop. Die tou-elementteller word verhoog.

Haal 'n element uit die tou:

mblk_t * getq(queue_t *q); 

Die boodskap wat kom nadat die stop is herwin, en die element teller word verlaag. As daar geen elemente in die tou is nie, behalwe die stop, dan word 0 teruggestuur.

Voeg 'n boodskap in 'n tou in:

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

element mp voor die element ingevoeg OBP. indien OBP=0, dan word die boodskap by die stert van die tou gevoeg.

Haal tans 'n boodskap van die hoof van die tou af:

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

Die elementteller word verlaag.

Lees 'n wyser na die eerste element in die tou:

mblk_t * peekq(queue_t *q); 

Verwyder alle elemente uit die tou terwyl die elemente self uitvee:

void flushq(queue_t *q, int how);

argument hoe nie gebruik nie. Die tou-elementteller is op nul gestel.

Makro vir die lees van 'n wyser na die laaste element van die tou:

mblk_t * qlast(queue_t *q);

Wanneer jy met boodskaprye werk, wees bewus daarvan dat wanneer jy bel ms_queue_put(q, m) met 'n nulwyser na die boodskap, loop die funksie. Jou program sal vries. tree soortgelyk op ms_queue_next(q, m).

Koppel filters

Die tou hierbo beskryf word gebruik om boodskappe van een filter na 'n ander of van een na verskeie filters deur te gee. Filters en hul verbindings vorm 'n gerigte grafiek. Die toevoer of uitset van die filter sal die algemene woord "pen" genoem word. Om die volgorde waarin filters aan mekaar gekoppel is, te beskryf, gebruik die mediastreamer die konsep van 'n "seinpunt". Seinpunt is struktuur _MSCPoint, wat 'n wyser na die filter en die nommer van een van sy penne bevat; dienooreenkomstig beskryf dit die verbinding van een van die insette of uitsette van die filter.

Seinpunt van dataverwerkingsgrafiek

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

Filterpennetjies is genommer vanaf nul.

Die verbinding van twee penne deur 'n boodskap tou word beskryf deur die struktuur _MSWou, wat 'n boodskap-tou en wysers bevat na die twee seinpunte wat dit verbind:

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

Ons sal hierdie struktuur 'n seinskakel noem. Elke mediastroomfilter bevat 'n tabel van invoerskakels en 'n tabel van uitvoerskakels (MSWou). Die grootte van tabelle word gestel wanneer 'n filter geskep word; ons het dit reeds gedoen met 'n uitgevoerde veranderlike van tipe MSFilterDesc, toe ons ons eie filter ontwikkel het. Hieronder is 'n struktuur wat enige filter in 'n mediastreamer beskryf, 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;

Nadat ons die filters in die C-program in ooreenstemming met ons plan gekoppel het (maar nie die tikker gekoppel het nie), het ons daardeur 'n gerigte grafiek geskep, waarvan die nodusse gevalle van die struktuur is MSFilter, en rande is gevalle van skakels MSWou.

Agter die skerms aktiwiteite van die tikker

Toe ek jou vertel dat die tikker 'n filter vir die bron van bosluise is, was dit nie die volle waarheid daaroor nie. 'n Tikker is 'n voorwerp wat funksies op die klok laat loop proses() alle filters van die stroombaan (grafiek) waaraan dit gekoppel is. Wanneer ons 'n tikker aan 'n grafiekfilter in 'n C-program koppel, wys ons die tikker die grafiek wat dit van nou af sal beheer totdat ons dit afskakel. Nadat dit gekoppel is, begin die tikker die grafiek wat aan sy sorg toevertrou is, ondersoek en 'n lys filters saamstel wat dit insluit. Om nie dieselfde filter twee keer te "tel" nie, merk dit die bespeurde filters deur 'n merkblokkie daarin te plaas gesien. Die soektog word uitgevoer met behulp van die skakeltabelle wat elke filter het.

Tydens sy inleidende toer van die grafiek kyk die tikker of daar onder die filters ten minste een is wat as 'n bron van datablokke dien. As daar geen is nie, word die grafiek as verkeerd beskou en die tikker val neer.

As die grafiek "korrek" blyk te wees vir elke gevind filter, word die funksie vir inisialisering geroep voorverwerk(). Sodra die oomblik vir die volgende verwerkingsiklus aanbreek (elke 10 millisekondes by verstek), roep die tikker die funksie proses() vir alle voorheen gevind bronfilters, en dan vir die oorblywende filters in die lys. As die filter invoerskakels het, voer dan die funksie uit proses() herhaal totdat die invoerskakelrye leeg is. Hierna beweeg dit na die volgende filter in die lys en "scroll" dit totdat die invoerskakels vry is van boodskappe. Die tikker beweeg van filter na filter totdat die lys eindig. Dit voltooi die verwerking van die siklus.

Nou sal ons terugkeer na tuples en praat oor hoekom so 'n entiteit by die mediastreamer gevoeg is. Oor die algemeen val die hoeveelheid data wat deur die algoritme wat binne die filter werk, nie saam nie en is nie 'n veelvoud van die grootte van die databuffers wat by die invoer ontvang word nie. Ons skryf byvoorbeeld 'n filter wat 'n vinnige Fourier-transformasie uitvoer, wat per definisie slegs datablokke kan verwerk waarvan die grootte 'n krag van twee is. Laat dit 512 tellings wees. As die data deur 'n telefoonkanaal gegenereer word, sal die databuffer van elke boodskap by die inset vir ons 160 seinmonsters bring. Dit is aanloklik om nie data van die invoer in te samel totdat die vereiste hoeveelheid data daar is nie. Maar in hierdie geval sal 'n botsing met die tikker plaasvind, wat onsuksesvol sal probeer om die filter te blaai totdat die invoerskakel leeg is. Voorheen het ons hierdie reël as die derde beginsel van die filter aangewys. Volgens hierdie beginsel moet die filter se proses()-funksie alle data van die invoerrye neem.

Daarbenewens sal dit nie moontlik wees om slegs 512 monsters uit die insette te neem nie, aangesien jy slegs hele blokke kan neem, d.w.s. die filter sal 640 monsters moet neem en 512 daarvan moet gebruik, die res voordat 'n nuwe gedeelte data versamel word. Dus moet ons filter, benewens sy hoofwerk, hulpaksies verskaf vir intermediêre berging van insetdata. Die ontwikkelaars van die mediastreamer en oplossing vir hierdie algemene probleem het 'n spesiale voorwerp ontwikkel - MSBufferizer (buffer), wat hierdie probleem oplos deur tuples te gebruik.

Bufferizer (MSBufferizer)

Dit is 'n voorwerp wat insetdata binne die filter sal opgaar en dit sal begin indien vir verwerking sodra die hoeveelheid inligting voldoende is om die filteralgoritme te laat loop. Terwyl die buffer data ophoop, sal die filter in ledige modus werk sonder om die verwerkingskrag van die verwerker te gebruik. Maar sodra die leesfunksie van die buffer 'n ander waarde as nul terugstuur, begin die proses()-funksie van die filter om data van die buffer in te neem en te verwerk in gedeeltes van die vereiste grootte, totdat dit uitgeput is.
Data wat nog nie benodig word nie, bly in die buffer as die eerste element van die tupel, waaraan daaropvolgende blokke insetdata geheg word.

Die struktuur wat die buffer beskryf:

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

Funksies om met MSBufferizer te werk

Skep 'n nuwe buffer-instansie:

MSBufferizer * ms_bufferizer_new(void);

Geheue word toegewys, geïnisialiseer in ms_bufferizer_init() en 'n wyser word teruggestuur.

Inisialisering funksie:

void ms_bufferizer_init(MSBufferizer *obj); 

Die tou is besig om te inisialiseer q, veld grootte is op nul gestel.

Voeg 'n boodskap by:

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

Boodskap m word by die tou gevoeg. Die berekende grootte van datablokke word bygevoeg grootte.

Die oordrag van alle boodskappe vanaf die skakeldata-ry na die buffer q:

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

Die oordrag van boodskappe vanaf 'n skakel q in die buffer word uitgevoer met behulp van die funksie ms_bufferizer_put().

Lees vanaf die buffer:

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

As die grootte van die data wat in die buffer opgehoop is, kleiner is as die versoekte een (datalen), dan gee die funksie nul terug, data word nie na data gekopieer nie. Andersins word opeenvolgende kopiëring van data van tupels wat in die buffer geleë is, uitgevoer. Na kopiëring word die tupel uitgevee en die geheue is vrygestel. Kopiëring eindig op die oomblik wanneer data-grepe gekopieer word. As spasie in die middel van 'n datablok opraak, sal die datablok in hierdie boodskap verminder word tot die oorblywende ongekopieerde deel. Die volgende keer as jy bel, sal kopiëring vanaf hierdie punt voortgaan.

Lees die hoeveelheid data wat tans in die buffer beskikbaar is:

int ms_bufferizer_get_avail(MSBufferizer *obj); 

Gee die veld terug grootte buffer.

Gooi deel van die data in die buffer weg:

void ms_bufferizer_skip_bytes(MSBufferizer *obj, int bytes);

Die gespesifiseerde aantal grepe data word herwin en weggegooi. Die oudste data word weggegooi.

Vee alle boodskappe in die buffer uit:

void ms_bufferizer_flush(MSBufferizer *obj); 

Die datateller word na nul teruggestel.

Vee alle boodskappe in die buffer uit:

void ms_bufferizer_uninit(MSBufferizer *obj); 

Die teller is nie teruggestel nie.

Verwyder die buffer en maak geheue vry:

void ms_bufferizer_destroy(MSBufferizer *obj);  

Voorbeelde van die gebruik van die buffer kan gevind word in die bronkode van verskeie media streamer filters. Byvoorbeeld, in die MS_L16_ENC-filter, wat die grepe in die monsters van die netwerkorde na die gasheerorde herrangskik: l16.c

In die volgende artikel sal ons kyk na die kwessie van tikkerladingskatting en hoe om oormatige rekenaarlading in die mediastreamer te hanteer.

Bron: will.com

Voeg 'n opmerking