Istraživanje Mediastreamer2 VoIP motora. Dio 11

Materijal članka je preuzet sa mog zen kanal.

Istraživanje Mediastreamer2 VoIP motora. Dio 11

Mehanizam kretanja podataka

  • Blok podataka dblk_t
  • Poruka mblk_t
  • Funkcije za rad sa porukama mblk_t
  • Red čekanja queue_t
  • Funkcije za rad sa redovima queue_t
  • Povezivanje filtera
  • Signalna tačka grafa obrade podataka
  • Aktivnosti iza kulisa
  • Bufferizer (MSBufferizer)
  • Funkcije za rad sa MSBufferizer-om

U poslednjem članak razvili smo sopstveni filter. Ovaj članak će se fokusirati na interni mehanizam za premještanje podataka između filtera medijskih strimera. Ovo će vam omogućiti da u budućnosti pišete sofisticirane filtere uz manje napora.

Mehanizam kretanja podataka

Kretanje podataka u media streameru se izvodi pomoću redova opisanih strukturom queue_t. Nizovi poruka poput mblk_t, koji sami po sebi ne sadrže signalne podatke, već samo povezuju na prethodnu, sljedeću poruku i na blok podataka. Pored toga, želim posebno da naglasim da postoji i polje za vezu ka poruci istog tipa, što vam omogućava da organizujete pojedinačno povezanu listu poruka. Grupu poruka ujedinjenih takvom listom nazvaćemo torkom. Dakle, bilo koji element reda može biti jedna poruka mblk_t, a možda i glava torke poruke mblk_t. Svaka poruka torke može imati svoj vlastiti blok podataka odjeljenja. Razgovaraćemo o tome zašto su tuple potrebne nešto kasnije.

Kao što je već spomenuto, sama poruka ne sadrži blok podataka; umjesto toga, sadrži samo pokazivač na memorijsku oblast u kojoj je blok pohranjen. U ovom dijelu cjelokupna slika rada medijskog streamera podsjeća na vrata magacina u crtiću “Monsters, Inc.”, gdje se vrata (linkovi na podatke – sobe) kreću sumanutom brzinom duž nadzemnih transportera, a same prostorije ostati nepomičan.

Sada, krećući se po hijerarhiji od dna prema vrhu, razmotrimo detaljno navedene entitete mehanizma za prijenos podataka u medijskom streameru.

Blok podataka dblk_t

Blok podataka sastoji se od zaglavlja i bafera podataka. Zaglavlje je opisano sljedećom strukturom,

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

Polja strukture sadrže pokazivače na početak bafera, kraj bafera i funkciju za brisanje bafera podataka. Zadnji element u zaglavlju db_ref — referentni brojač, ako dostigne nulu, to služi kao signal za brisanje ovog bloka iz memorije. Ako je blok podataka kreirala funkcija datab_alloc() , tada će bafer podataka biti smješten u memoriju odmah nakon zaglavlja. U svim ostalim slučajevima, bafer se može locirati negdje odvojeno. Bafer podataka će sadržavati uzorke signala ili druge podatke koje želimo obraditi filterima.

Nova instanca bloka podataka kreira se pomoću funkcije:

dblk_t *datab_alloc(int size);

Kao ulazni parametar daje se veličina podataka koje će blok pohraniti. Više memorije se dodjeljuje kako bi se zaglavlje - struktura - postavilo na početak dodijeljene memorije datab. Ali kada se koriste druge funkcije, to se ne događa uvijek; u nekim slučajevima, bafer podataka može biti lociran odvojeno od zaglavlja bloka podataka. Prilikom kreiranja strukture, polja se konfigurišu tako da njeno polje db_base pokazao na početak područja podataka, i db_lim do svog kraja. Broj linkova db_ref je postavljeno na jedan. Pokazivač funkcije brisanja podataka postavljen je na nulu.

Poruka mblk_t

Kao što je navedeno, elementi reda su tipa mblk_t, definira se na sljedeći način:

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;

struktura mblk_t sadrži pokazivače na početku b_prev, b_next, koji su neophodni za organiziranje dvostruko povezane liste (koja je red queue_t).

Zatim dolazi pokazivač b_cont, koji se koristi samo kada je poruka dio tuple. Za posljednju poruku u tuple, ovaj pokazivač ostaje null.

Zatim vidimo pokazivač na blok podataka b_datap, za koji poruka postoji. Nakon njega slijede pokazivači na područje unutar međuspremnika podataka bloka. Polje b_rptr specificira lokaciju sa koje će se čitati podaci iz bafera. Polje b_wptr označava lokaciju sa koje će se izvršiti upisivanje u međuspremnik.

Preostala polja su uslužne prirode i ne odnose se na rad mehanizma za prijenos podataka.

Ispod je jedna poruka sa imenom m1 i blok podataka d1.
Istraživanje Mediastreamer2 VoIP motora. Dio 11
Sljedeća slika prikazuje torku od tri poruke m1, m1_1, m1_2.
Istraživanje Mediastreamer2 VoIP motora. Dio 11

Funkcije razmjene poruka mblk_t

Nova poruka mblk_t kreirana od strane funkcije:

mblk_t *allocb(int size, int pri); 

ona stavlja novu poruku u memoriju mblk_t sa blokom podataka određene veličine veličina, drugi argument - pri ne koristi se u ovoj verziji biblioteke. Trebao bi ostati nula. Tokom rada funkcije, memorija će biti dodijeljena za strukturu nove poruke i funkcija će biti pozvana mblk_init(), koji će resetirati sva polja kreirane instance strukture i zatim, koristeći gore navedeno datab_alloc(), će kreirati bafer podataka. Nakon čega će se konfigurirati polja u strukturi:

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

Na izlazu dobijamo novu poruku sa inicijalizovanim poljima i praznim baferom podataka. Da biste dodali podatke u poruku, morate ih kopirati u bafer bloka podataka:

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

gdje podaci je pokazivač na izvor podataka, i veličina - njihovu veličinu.
tada morate ažurirati pokazivač na tačku pisanja tako da ponovo pokazuje na početak slobodnog područja u međuspremniku:

msg->b_wptr = msg->b_wptr + size

Ako trebate kreirati poruku iz postojećeg bafera, bez kopiranja, tada koristite funkciju:

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

Funkcija će, nakon kreiranja poruke i strukture bloka podataka, konfigurirati svoje pokazivače na podatke na adresi buff. One. u ovom slučaju, bafer podataka se ne nalazi iza polja zaglavlja bloka podataka, kao što je bio slučaj kada se kreira blok podataka sa funkcijom datab_alloc(). Bafer sa podacima prosleđenim funkciji ostaće tamo gde je i bio, ali će uz pomoć pokazivača biti prikačen na novostvoreno zaglavlje bloka podataka, a to, shodno tome, i na poruku.

Na jednu poruku mblk_t Nekoliko blokova podataka može biti povezano uzastopno. To radi funkcija:

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

mp — poruka kojoj će se dodati još jedan blok podataka;
podaci — pokazivač na blok čija će kopija biti dodata poruci;
veličina — veličina podataka;
pad — oznaka da veličina dodijeljene memorije mora biti poravnata duž granice od 4 bajta (dodavanje će se vršiti nulama).

Ako ima dovoljno prostora u postojećem baferu podataka poruke, tada će novi podaci biti zalijepljeni iza podataka koji su već tamo. Ako ima manje slobodnog prostora u međuspremniku podataka poruke od veličina, tada se kreira nova poruka sa dovoljnom veličinom bafera i podaci se kopiraju u njen bafer. Ovo je nova poruka, povezana s originalnom pomoću pokazivača b_cont. U ovom slučaju, poruka se pretvara u tuple.

Ako trebate dodati još jedan blok podataka u tuple, onda trebate koristiti funkciju:

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

ona će pronaći posljednju poruku u torci (on ima b_cont bit će null) i pozvat će funkciju za ovu poruku appendb().

Možete saznati veličinu podataka u poruci ili tuple koristeći funkciju:

int msgdsize(const mblk_t *mp);

proći će kroz sve poruke u tuple i vratiti ukupnu količinu podataka u baferima podataka tih poruka. Za svaku poruku, količina podataka se izračunava na sljedeći način:

 mp->b_wptr - mp->b_rptr

Za kombiniranje dvije torke koristite funkciju:

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

ona dodaje tuple newm do repa torke mp i vraća pokazivač na posljednju poruku rezultirajuće tuple.

Ako je potrebno, tuple se može pretvoriti u jednu poruku s jednim blokom podataka; to radi funkcija:

void msgpullup(mblk_t *mp,int len);

ako argument len je -1, tada se veličina dodijeljenog bafera određuje automatski. Ako len je pozitivan broj, kreiraće se bafer ove veličine i podaci o poruci torke će biti kopirani u njega. Ako bafer ponestane, kopiranje će se tu zaustaviti. Prva poruka tuple će dobiti bafer nove veličine sa kopiranim podacima. Preostale poruke će biti izbrisane, a memorija vraćena u hrpu.

Prilikom brisanja strukture mblk_t broj referenci bloka podataka se uzima u obzir ako, prilikom pozivanja freeb() ispostavilo se da je nula, tada se bafer podataka briše zajedno sa instancom mblk_t, što ukazuje na to.

Inicijalizacija polja nove poruke:

void mblk_init(mblk_t *mp);

Dodavanje još jednog podatka u poruku:

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

Ako se novi podaci ne uklapaju u slobodni prostor međuspremnika podataka poruke, tada se uz poruku prilaže posebno kreirana poruka sa baferom potrebne veličine (u prvoj poruci se postavlja pokazivač na dodanu poruku) i poruka se pretvara u tuple.

Dodavanje dijela podataka u tuple:

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

Funkcija poziva appendb() u petlji.

Kombinovanje dva tuple u jedan:

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

Poruka newm će biti u prilogu mp.

Pravljenje kopije jedne poruke:

mblk_t *copyb(const mblk_t *mp);

Kompletno kopiranje tuple sa svim blokovima podataka:

mblk_t *copymsg(const mblk_t *mp);

Elemente tuple kopira funkcija copyb().

Napravite jednostavnu kopiju poruke mblk_t. U ovom slučaju, blok podataka se ne kopira, već se njegov referentni brojač povećava db_ref:

mblk_t *dupb(mblk_t *mp);

Izrada lagane kopije tuple. Blokovi podataka se ne kopiraju, samo se njihovi referentni brojači povećavaju db_ref:

mblk_t *dupmsg(mblk_t* m);

Lijepljenje svih poruka torke u jednu poruku:

void msgpullup(mblk_t *mp,size_t len);

Ako je argument len je -1, tada se veličina dodijeljenog bafera određuje automatski.

Brisanje poruke, tuple:

void freemsg(mblk_t *mp);

Broj referenci bloka podataka se smanjuje za jedan. Ako dostigne nulu, blok podataka se također briše.

Izračunavanje ukupne količine podataka u poruci ili tuple.

size_t msgdsize(const mblk_t *mp);

Preuzimanje poruke sa repa reda:

mblk_t *ms_queue_peek_last (q);

Kopiranje sadržaja rezerviranih polja jedne poruke u drugu poruku (u stvari, ova polja sadrže zastavice koje koristi medijski streamer):

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

Red čekanja queue_t

Red poruka u media streameru je implementiran kao kružna dvostruko povezana lista. Svaki element liste sadrži pokazivač na blok podataka sa uzorcima signala. Ispada da se samo pokazivači na blok podataka pomiču naizmjenično, dok sami podaci ostaju nepomični. One. premještaju se samo veze do njih.
Struktura koja opisuje red queue_t, prikazano ispod:

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

Struktura sadrži polje - pokazivač _q_stopper ukucajte *mblk_t, on pokazuje na prvi element (poruku) u redu čekanja. Drugo polje strukture je brojač poruka u redu čekanja.
Slika ispod prikazuje red pod nazivom q1 koji sadrži 4 poruke m1, m2, m3, m4.
Istraživanje Mediastreamer2 VoIP motora. Dio 11
Sljedeća slika prikazuje red pod nazivom q1 koji sadrži 4 poruke m1,m2,m3,m4. Poruka m2 je glava torke koja sadrži još dvije poruke m2_1 i m2_2.

Istraživanje Mediastreamer2 VoIP motora. Dio 11

Funkcije za rad sa redovima queue_t

Inicijalizacija reda čekanja:

void qinit(queue_t *q);

polje _q_stopper (u daljem tekstu ćemo ga zvati “stoper”) inicijalizira funkcija mblk_init(), njegov prethodni element i pokazivač sljedećeg elementa su prilagođeni da pokazuju na sebe. Brojač elemenata reda se resetuje na nulu.

Dodavanje novog elementa (poruke):

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

Novi element m se dodaje na kraj liste, pokazivači elemenata se podešavaju tako da mu stoper postaje sljedeći element, a postaje prethodni element za stoper. Brojač elemenata reda se povećava.

Preuzimanje elementa iz reda čekanja:

mblk_t * getq(queue_t *q); 

Poruka koja dolazi nakon zaustavljanja se preuzima, a brojač elemenata se smanjuje. Ako u redu nema elemenata osim stopera, onda se vraća 0.

Umetanje poruke u red čekanja:

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

Element mp umetnut prije elementa emp. Ako emp=0, tada se poruka dodaje na rep reda.

Preuzimanje poruke sa glave reda:

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

Brojač elemenata se smanjuje.

Čitanje pokazivača na prvi element u redu čekanja:

mblk_t * peekq(queue_t *q); 

Uklanjanje svih elemenata iz reda dok se brišu sami elementi:

void flushq(queue_t *q, int how);

Argument kako nije korišteno. Brojač elemenata reda je postavljen na nulu.

Makro za čitanje pokazivača na posljednji element reda:

mblk_t * qlast(queue_t *q);

Kada radite sa redovima poruka, imajte to na umu kada zovete ms_queue_put(q, m) sa nultim pokazivačem na poruku, funkcija se ponavlja. Vaš program će se zamrznuti. ponaša se slično ms_queue_next(q, m).

Povezivanje filtera

Gore opisani red se koristi za prosljeđivanje poruka od jednog filtera do drugog ili od jednog do nekoliko filtera. Filteri i njihove veze formiraju usmjereni graf. Ulaz ili izlaz filtera će se zvati opštom rečju "pin". Da bi opisao redosled u kojem su filteri međusobno povezani, medijski streamer koristi koncept „signalne tačke“. Signalna tačka je struktura _MSCPoint, koji sadrži pokazivač na filter i broj jednog od njegovih pinova; shodno tome, opisuje vezu jednog od ulaza ili izlaza filtera.

Signalna tačka grafa obrade podataka

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

Igle filtera su numerisane počevši od nule.

Povezivanje dva pina putem reda poruka opisano je strukturom _MSQueue, koji sadrži red poruka i pokazivače na dvije signalne tačke koje povezuje:

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

Ovu strukturu ćemo nazvati signalnom vezom. Svaki medijski streamer filter sadrži tabelu ulaznih veza i tabelu izlaznih veza (MSQueue). Veličina tabela se postavlja prilikom kreiranja filtera; to smo već uradili koristeći eksportovanu varijablu tipa MSFilterDesc, kada smo razvili vlastiti filter. Ispod je struktura koja opisuje bilo koji filter u medijskom streameru, 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;

Nakon što smo spojili filtere u C programu u skladu sa našim planom (ali nismo povezali tiker), kreirali smo usmjereni graf čiji su čvorovi instance strukture MSFilter, a ivice su instance veza MSQueue.

Aktivnosti iza kulisa

Kad sam vam rekao da je tiker filter za izvor krpelja, nije bila cijela istina o tome. Tiker je objekat koji pokreće funkcije na satu proces() sve filtere kola (grafa) na koje je povezan. Kada povežemo tiker sa filterom grafa u C programu, prikazujemo tiker graf kojim će od sada upravljati sve dok ga ne isključimo. Nakon povezivanja, ticker počinje ispitivati ​​graf koji mu je povjeren na brigu, sastavljajući listu filtera koji ga uključuju. Da se isti filter ne bi „prebrojao“ dvaput, detektovane filtere označava tako što u njih stavlja potvrdni okvir vidi. Pretraga se vrši pomoću tabela veza koje svaki filter ima.

Tokom svog uvodnog obilaska grafa, tiker provjerava da li među filterima postoji barem jedan koji djeluje kao izvor blokova podataka. Ako ih nema, tada se grafikon smatra netačnim i bilježnica pada.

Ako se pokaže da je graf "ispravan", za svaki pronađeni filter, funkcija se poziva za inicijalizaciju preprocess(). Čim dođe trenutak za sljedeći ciklus obrade (podrazumevano svakih 10 milisekundi), tiker poziva funkciju proces() za sve prethodno pronađene izvorne filtere, a zatim za preostale filtere na listi. Ako filter ima ulazne veze, tada se pokreće funkcija proces() ponavlja sve dok redovi ulaznih veza nisu prazni. Nakon toga, prelazi na sljedeći filter na listi i "skroluje" ga sve dok ulazne veze ne budu oslobođene poruka. Oznaka se pomiče od filtera do filtera dok se lista ne završi. Ovim se završava obrada ciklusa.

Sada ćemo se vratiti na torke i razgovarati o tome zašto je takav entitet dodan u medijski streamer. Općenito, količina podataka koju zahtijeva algoritam koji radi unutar filtera ne podudara se i nije višekratnik veličine bafera podataka primljenih na ulazu. Na primjer, pišemo filter koji izvodi brzu Fourierovu transformaciju, koji po definiciji može obraditi samo blokove podataka čija je veličina stepen dvojke. Neka bude 512 tačaka. Ako podatke generiše telefonski kanal, tada će nam bafer podataka svake poruke na ulazu donijeti 160 uzoraka signala. U iskušenju je ne prikupljati podatke sa ulaza dok ne postoji potrebna količina podataka. Ali u ovom slučaju, doći će do kolizije s tikerom, koji će neuspješno pokušati pomicati filter dok ulazna veza ne bude prazna. Prethodno smo ovo pravilo označili kao treći princip filtera. Prema ovom principu, funkcija filtera process() mora uzeti sve podatke iz ulaznih redova.

Osim toga, neće biti moguće uzeti samo 512 uzoraka sa ulaza, jer možete uzeti samo cijele blokove, tj. filter će morati uzeti 640 uzoraka i upotrijebiti 512 od njih, ostatak prije nego akumulira novi dio podataka. Dakle, naš filter, pored svog glavnog rada, mora da obezbedi i pomoćne radnje za međuskladištenje ulaznih podataka. Programeri media streamera i rješenja za ovaj opći problem razvili su poseban objekat - MSBufferizer (bufferer), koji rješava ovaj problem korištenjem tuple-ova.

Bufferizer (MSBufferizer)

Ovo je objekat koji će akumulirati ulazne podatke unutar filtera i početi ih slati na obradu čim količina informacija bude dovoljna za pokretanje algoritma filtera. Dok bafer akumulira podatke, filter će raditi u stanju mirovanja, bez iskorišćavanja procesorske snage. Ali čim funkcija čitanja iz bafera vrati vrijednost različitu od nule, funkcija process() filtera počinje uzimati i obrađivati ​​podatke iz bafera u dijelovima potrebne veličine, sve dok se ne iscrpe.
Podaci koji još nisu potrebni ostaju u međuspremniku kao prvi element tuple, na koji su pridruženi naredni blokovi ulaznih podataka.

Struktura koja opisuje bafer:

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

Funkcije za rad sa MSBufferizer-om

Kreiranje nove instance bafera:

MSBufferizer * ms_bufferizer_new(void);

Memorija je dodijeljena, inicijalizirana u ms_bufferizer_init() i pokazivač se vraća.

Funkcija inicijalizacije:

void ms_bufferizer_init(MSBufferizer *obj); 

Red se inicijalizira q, polje veličina je postavljen na nulu.

Dodavanje poruke:

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

Poruka m se dodaje u red čekanja. Izračunata veličina blokova podataka se dodaje veličina.

Prijenos svih poruka iz reda podataka veze u međuspremnik q:

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

Prijenos poruka sa veze q u baferu se izvodi pomoću funkcije ms_bufferizer_put().

Čitanje iz bafera:

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

Ako je veličina podataka akumuliranih u međuspremniku manja od tražene (datalen), tada funkcija vraća nulu, podaci se ne kopiraju u podatke. U suprotnom, vrši se sekvencijalno kopiranje podataka iz tuple-ova koji se nalaze u baferu. Nakon kopiranja, tuple se briše i memorija se oslobađa. Kopiranje se završava u trenutku kada se datalen bajtovi kopiraju. Ako ponestane prostora u sredini bloka podataka, tada će se u ovoj poruci blok podataka smanjiti na preostali nekopirani dio. Sljedeći put kada pozovete, kopiranje će se nastaviti od ove tačke.

Čitanje količine podataka koja je trenutno dostupna u međuspremniku:

int ms_bufferizer_get_avail(MSBufferizer *obj); 

Vraća polje veličina puferer.

Odbacivanje dijela podataka u međuspremniku:

void ms_bufferizer_skip_bytes(MSBufferizer *obj, int bytes);

Navedeni broj bajtova podataka se preuzima i odbacuje. Najstariji podaci se odbacuju.

Brisanje svih poruka u baferu:

void ms_bufferizer_flush(MSBufferizer *obj); 

Brojač podataka se resetuje na nulu.

Brisanje svih poruka u baferu:

void ms_bufferizer_uninit(MSBufferizer *obj); 

Brojač se ne resetuje.

Uklanjanje bafera i oslobađanje memorije:

void ms_bufferizer_destroy(MSBufferizer *obj);  

Primjeri korištenja baferera mogu se naći u izvornom kodu nekoliko filtera za prijenos medija. Na primjer, u filteru MS_L16_ENC, koji preuređuje bajtove u uzorcima iz mrežnog reda u redoslijed hosta: l16.c

U sljedećem članku ćemo se osvrnuti na pitanje procjene opterećenja tikera i kako se nositi s prekomjernim opterećenjem računara u media streameru.

izvor: www.habr.com

Dodajte komentar