Istraživanje Mediastreamer2 VoIP mehanizma. dio 11

Materijal članka preuzet je iz mog zen kanal.

Istraživanje Mediastreamer2 VoIP mehanizma. dio 11

Mehanizam kretanja podataka

  • Blok podataka dblk_t
  • Poruka mblk_t
  • Funkcije za rad s porukama mblk_t
  • Red čekanja queue_t
  • Funkcije za rad s redovima čekanja queue_t
  • Spajanje filtera
  • Signalna točka grafa obrade podataka
  • Aktivnosti iza kulisa tickera
  • Međuspremnik (MSBufferizer)
  • Funkcije za rad s MSBufferizer

U posljednjih članak razvili smo vlastiti filter. Ovaj će se članak usredotočiti na interni mehanizam za premještanje podataka između filtara streamera medija. To će vam omogućiti pisanje sofisticiranih filtara s manje truda u budućnosti.

Mehanizam kretanja podataka

Kretanje podataka u medijskom streameru izvodi se pomoću redova čekanja opisanih strukturom queue_t. Nizovi poruka poput mblk_t, koji sami ne sadrže signalne podatke, već samo poveznice na prethodnu, sljedeću poruku i na podatkovni blok. Osim toga, želim posebno naglasiti da postoji i polje za poveznicu na poruku iste vrste, što vam omogućuje organiziranje pojedinačno povezanog popisa poruka. Skupinu poruka objedinjenih takvim popisom nazvat ćemo torkom. Dakle, bilo koji element reda čekanja može biti jedna poruka mblk_t, a možda i glava torke poruka mblk_t. Svaka poruka torke može imati vlastiti blok podataka odjela. Razgovarat ćemo o tome zašto su torke potrebne malo kasnije.

Kao što je gore spomenuto, sama poruka ne sadrži blok podataka; umjesto toga, sadrži samo pokazivač na memorijsko područje gdje je blok pohranjen. U ovom dijelu cjelokupna slika rada media streamera podsjeća na skladište vrata u crtiću “Monsters, Inc.” gdje se vrata (linkovi na podatke – sobe) pomiču suludom brzinom duž pokretnih traka, dok same sobe ostati nepomičan.

Sada, krećući se hijerarhijom od dna prema vrhu, razmotrimo detaljno navedene entitete mehanizma prijenosa podataka u medijskom streameru.

Blok podataka dblk_t

Podatkovni blok sastoji se od zaglavlja i međuspremnika 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 međuspremnika, kraj međuspremnika i funkciju za brisanje međuspremnika podataka. Zadnji element u zaglavlju db_ref — referentni brojač, ako dosegne nulu, to služi kao signal za brisanje ovog bloka iz memorije. Ako je blok podataka kreirala funkcija datab_alloc() , tada će međuspremnik podataka biti smješten u memoriju odmah nakon zaglavlja. U svim ostalim slučajevima međuspremnik se može nalaziti negdje odvojeno. Međuspremnik podataka sadržavat će uzorke signala ili druge podatke koje želimo obraditi filtrima.

Nova instanca podatkovnog bloka stvara se pomoću funkcije:

dblk_t *datab_alloc(int size);

Kao ulazni parametar zadana je veličina podataka koje će blok pohraniti. Više memorije se dodjeljuje kako bi se zaglavlje - struktura - postavilo na početak dodijeljene memorije podacib. Ali kada koristite druge funkcije, to se ne događa uvijek; u nekim slučajevima međuspremnik podataka može se nalaziti odvojeno od zaglavlja bloka podataka. Prilikom izrade strukture polja se konfiguriraju tako da njezino polje baza_db pokazao na početak područja podataka, i db_lim do svog kraja. Broj veza db_ref je postavljen 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_pret, b_sljedeći, koji su neophodni za organiziranje dvostruko povezane liste (koja je red čekanja queue_t).

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

Zatim vidimo pokazivač na blok podataka b_datap, za koje poruka postoji. Nakon njega slijede pokazivači na područje unutar međuspremnika blok podataka. Polje b_rptr specificira mjesto s kojeg će se čitati podaci iz međuspremnika. Polje b_wptr označava mjesto s kojeg će se vršiti upisi u međuspremnik.

Ostala polja su servisne prirode i ne odnose se na rad mehanizma prijenosa podataka.

Ispod je jedna poruka s imenom m1 i blok podataka d1.
Istraživanje Mediastreamer2 VoIP mehanizma. dio 11
Sljedeća slika prikazuje skup od tri poruke m1, m1_1, m1_2.
Istraživanje Mediastreamer2 VoIP mehanizma. dio 11

Funkcije slanja poruka mblk_t

Nova poruka mblk_t kreirana funkcijom:

mblk_t *allocb(int size, int pri); 

ona stavlja novu poruku u memoriju mblk_t s podatkovnim blokom navedene veličine Veličina, drugi argument - pri ne koristi se u ovoj verziji biblioteke. Treba ostati nula. Tijekom 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, a zatim, koristeći gore navedeno datab_alloc(), stvorit će međuspremnik podataka. Nakon toga ć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 dobivamo novu poruku s inicijaliziranim poljima i praznim međuspremnikom podataka. Da biste poruci dodali podatke, trebate je kopirati u međuspremnik bloka podataka:

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

gdje datum je pokazivač na izvor podataka, i Veličina - njihovu veličinu.
tada trebate ažurirati pokazivač na točku pisanja tako da ponovno pokazuje na početak slobodnog područja u međuspremniku:

msg->b_wptr = msg->b_wptr + size

Ako trebate stvoriti poruku iz postojećeg međuspremnika, bez kopiranja, upotrijebite funkciju:

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

Funkcija će nakon kreiranja poruke i strukture podatkovnog bloka konfigurirati svoje pokazivače na podatke na adresi buff. Oni. u ovom slučaju, podatkovni međuspremnik se ne nalazi nakon polja zaglavlja podatkovnog bloka, kao što je bio slučaj kod stvaranja podatkovnog bloka s funkcijom datab_alloc(). Međuspremnik s podacima proslijeđenim funkciji ostat će tamo gdje je i bio, ali će se uz pomoć pokazivača pripojiti novostvorenom zaglavlju podatkovnog bloka, a ono, sukladno tome, poruci.

Na jednu poruku mblk_t Nekoliko blokova podataka može se uzastopno povezati. To se radi pomoću funkcije:

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

mp — poruka kojoj će se dodati još jedan blok podataka;
datum — pokazivač na blok, čija će kopija biti dodana u poruku;
Veličina — veličina podataka;
jastučić — oznaka da veličina dodijeljene memorije mora biti usklađena duž granice od 4 bajta (dopunjavanje će se izvršiti s nulama).

Ako ima dovoljno prostora u postojećem međuspremniku podataka poruke, tada će novi podaci biti zalijepljeni iza podataka koji se već nalaze. Ako u međuspremniku podataka poruke ima manje slobodnog prostora od Veličina, tada se stvara nova poruka s dovoljnom veličinom međuspremnika i podaci se kopiraju u njezin međuspremnik. Ovo je nova poruka, povezana s izvornom pomoću pokazivača b_nastavak. U tom se slučaju poruka pretvara u torku.

Ako trebate dodati još jedan blok podataka u torku, tada trebate koristiti funkciju:

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

ona će pronaći posljednju poruku u tuple (on ima b_nastavak bit će null) i pozvat će funkciju za ovu poruku dodatib().

Veličinu podataka u poruci ili torci možete saznati pomoću funkcije:

int msgdsize(const mblk_t *mp);

proći će kroz sve poruke u tupleu i vratiti ukupnu količinu podataka u podatkovnim međuspremnicima tih poruka. Za svaku se poruku količina podataka izračunava na sljedeći način:

 mp->b_wptr - mp->b_rptr

Za kombiniranje dvije torke upotrijebite funkciju:

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

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

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

void msgpullup(mblk_t *mp,int len);

ako argument len je -1, tada se veličina dodijeljenog međuspremnika određuje automatski. Ako len je pozitivan broj, stvorit će se međuspremnik ove veličine i u njega će se kopirati podaci o poruci torke. Ako se međuspremnik isprazni, kopiranje će se tamo zaustaviti. Prva poruka torke primit će međuspremnik nove veličine s kopiranim podacima. Preostale poruke bit će izbrisane, a memorija vraćena u gomilu.

Prilikom brisanja strukture mblk_t broj referenci bloka podataka uzima se u obzir ako, prilikom pozivanja slobodan() ispada da je nula, tada se međuspremnik podataka briše zajedno s 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 novi podaci ne stanu u slobodni prostor podatkovnog međuspremnika poruke, tada se poruci prilaže zasebno kreirana poruka s međuspremnikom potrebne veličine (pokazivač na dodanu poruku postavljen je u prvoj poruci) i poruka se pretvara u tuple.

Dodavanje dijela podataka u torku:

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

Funkcija poziva appendb() u petlji.

Spajanje dvije torke u jednu:

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

Poruka novom bit će priložen mp.

Izrada kopije jedne poruke:

mblk_t *copyb(const mblk_t *mp);

Potpuno kopiranje torke sa svim blokovima podataka:

mblk_t *copymsg(const mblk_t *mp);

Elementi torke se kopiraju pomoću funkcije copyb().

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

mblk_t *dupb(mblk_t *mp);

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

mblk_t *dupmsg(mblk_t* m);

Lijepljenje svih poruka iz tuple u jednu poruku:

void msgpullup(mblk_t *mp,size_t len);

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

Brisanje poruke, tuple:

void freemsg(mblk_t *mp);

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

Izračun ukupne količine podataka u poruci ili torci.

size_t msgdsize(const mblk_t *mp);

Dohvaćanje poruke s repa reda:

mblk_t *ms_queue_peek_last (q);

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

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

Red queue_t

Red poruka u streameru medija implementiran je kao kružna dvostruko povezana lista. Svaki element popisa sadrži pokazivač na podatkovni blok s uzorcima signala. Ispada da se samo pokazivači na podatkovni blok pomiču redom, dok sami podaci ostaju nepomični. Oni. premještaju se samo veze na njih.
Struktura koja opisuje red čekanja queue_t, prikazano ispod:

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

Struktura sadrži polje – pokazivač _q_čep tip *mblk_t, pokazuje na prvi element (poruku) u redu. Drugo polje strukture je brojač poruka u redu.
Donja slika prikazuje red pod nazivom q1 koji sadrži 4 poruke m1, m2, m3, m4.
Istraživanje Mediastreamer2 VoIP mehanizma. 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 mehanizma. dio 11

Funkcije za rad s redovima čekanja queue_t

Inicijalizacija reda čekanja:

void qinit(queue_t *q);

Polje _q_čep (u daljnjem tekstu ćemo ga zvati "čep") inicijalizira funkcija mblk_init(), njegov prethodni element i pokazivač sljedećeg elementa prilagođeni su tako da pokazuju na sebe. Brojač elementa reda se vraća na nulu.

Dodavanje novog elementa (poruke):

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

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

Dohvaćanje elementa iz reda:

mblk_t * getq(queue_t *q); 

Poruka koja dolazi nakon zaustavljanja je dohvaćena, a brojač elemenata se smanjuje. Ako u redu čekanja nema elemenata osim stopera, vraća se 0.

Umetanje poruke u red čekanja:

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

Элемент mp umetnut prije elementa EMP, ako EMP=0, tada se poruka dodaje na kraj reda čekanja.

Dohvaćanje poruke iz glave reda:

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

Brojač elemenata se smanjuje.

Čitanje pokazivača na prvi element u redu:

mblk_t * peekq(queue_t *q); 

Uklanjanje svih elemenata iz reda uz brisanje samih elemenata:

void flushq(queue_t *q, int how);

argument kako ne koristi se. Brojač elementa reda postavljen je na nulu.

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

mblk_t * qlast(queue_t *q);

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

Spajanje filtera

Gore opisani red čekanja koristi se za prosljeđivanje poruka od jednog filtra do drugog ili od jednog do nekoliko filtara. Filtri i njihove veze tvore usmjereni graf. Ulaz ili izlaz filtra nazivat će se općom riječi "pin". Kako bi opisao redoslijed kojim su filtri međusobno povezani, medijski streamer koristi koncept "signalne točke". Signalna točka je struktura _MSCPoint, koji sadrži pokazivač na filtar i broj jednog od njegovih pinova, prema tome opisuje spoj jednog od ulaza ili izlaza filtra.

Signalna točka grafa obrade podataka

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

Pinovi filtera su numerirani počevši od nule.

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

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

Ovu strukturu ćemo nazvati signalnom vezom. Svaki filtar medija streamer sadrži tablicu ulaznih veza i tablicu izlaznih veza (MSQueue). Veličina tablica postavlja se prilikom izrade filtra; to smo već učinili pomoću izvezene varijable tipa MSFilterDesc, kada smo razvili vlastiti filter. Ispod je struktura koja opisuje bilo koji filtar u streameru medija, 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 povezali filtere u C programu u skladu s našim planom (ali nismo povezali ticker), time smo kreirali usmjereni graf čiji su čvorovi instance strukture MSFilter, a rubovi su instance poveznica MSQueue.

Aktivnosti iza kulisa tickera

Kad sam vam rekao da je ticker filter za izvor tikova, to nije bila cijela istina. Ticker je objekt koji pokreće funkcije na satu postupak() sve filtre sklopa (grafa) na koji je spojen. Kada spojimo ticker na filter grafa u C programu, pokazaćemo tickeru graf koji će kontrolirati od sada pa nadalje dok ga ne isključimo. Nakon povezivanja, ticker počinje ispitivati ​​graf koji mu je povjeren, sastavljajući popis filtera koji ga uključuju. Kako se isti filtar ne bi “brojao” dvaput, označava otkrivene filtre postavljanjem potvrdnog okvira u njih vidio. Pretraživanje se provodi pomoću tablica veza koje ima svaki filter.

Tijekom svog uvodnog obilaska grafa, ticker provjerava postoji li među filtrima barem jedan koji djeluje kao izvor blokova podataka. Ako ih nema, tada se grafikon smatra netočnim i oznaka se ruši.

Ako se graf pokaže "točnim", za svaki pronađeni filtar, funkcija se poziva za inicijalizaciju pretproces(). Čim dođe trenutak za sljedeći ciklus obrade (svakih 10 milisekundi prema zadanim postavkama), ticker poziva funkciju postupak() za sve prethodno pronađene izvorne filtere, a zatim za preostale filtere na popisu. Ako filtar ima ulazne veze, tada se funkcija izvodi postupak() ponavlja se dok se redovi ulaznih veza ne isprazne. Nakon toga prelazi na sljedeći filtar na popisu i "skrola" ga sve dok ulazne veze ne oslobode poruka. Ticker se pomiče od filtra do filtra dok popis ne završi. Ovo dovršava obradu 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 filtra ne podudara se i nije višestruka veličina međuspremnika podataka primljenih na ulazu. Na primjer, pišemo filtar koji izvodi brzu Fourierovu transformaciju, koja po definiciji može obraditi samo blokove podataka čija je veličina potencija broja dva. Neka bude 512 točaka. Ako podatke generira telefonski kanal, tada će nam bafer podataka svake poruke na ulazu donijeti 160 uzoraka signala. Primamljivo je ne prikupljati podatke s ulaza dok se ne dobije potrebna količina podataka. Ali u ovom slučaju doći će do kolizije s tickerom, koji će neuspješno pokušati pomicati filtar dok ulazna veza ne bude prazna. Prethodno smo ovo pravilo označili kao treće načelo filtra. Prema ovom principu, funkcija filtera process() mora uzeti sve podatke iz ulaznih redova.

Osim toga, neće biti moguće uzeti samo 512 uzoraka s ulaza, jer možete uzeti samo cijele blokove, tj. filtar će morati uzeti 640 uzoraka i upotrijebiti njih 512, ostatak prije akumuliranja novog dijela podataka. Dakle, naš filter, uz svoj glavni posao, mora osigurati pomoćne radnje za međupohranu ulaznih podataka. Programeri media streamera i rješenja za ovaj opći problem razvili su poseban objekt - MSBufferizer (međuspremnik), koji ovaj problem rješava korištenjem tuplea.

Međuspremnik (MSBufferizer)

Ovo je objekt koji će akumulirati ulazne podatke unutar filtra i početi ih slati na obradu čim količina informacija bude dovoljna za pokretanje algoritma filtra. Dok međuspremnik prikuplja podatke, filtar će raditi u stanju mirovanja, bez korištenja procesorske snage procesora. Ali čim funkcija čitanja iz međuspremnika vrati vrijednost različitu od nule, funkcija process() filtra počinje uzimati i obrađivati ​​podatke iz međuspremnika u dijelovima potrebne veličine, sve dok se ne iscrpi.
Podaci koji još nisu potrebni ostaju u međuspremniku kao prvi element torke, na koji se pridružuju sljedeći blokovi ulaznih podataka.

Struktura koja opisuje međuspremnik:

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

Funkcije za rad s MSBufferizer

Stvaranje nove instance međuspremnika:

MSBufferizer * ms_bufferizer_new(void);

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

Funkcija inicijalizacije:

void ms_bufferizer_init(MSBufferizer *obj); 

Red čekanja 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. Dodaje se izračunata veličina podatkovnih blokova Veličina.

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

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

Prijenos poruka s veze q u međuspremniku se izvodi pomoću funkcije ms_bufferizer_put().

Čitanje iz međuspremnika:

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 protivnom se vrši sekvencijalno kopiranje podataka iz torki smještenih u međuspremniku. Nakon kopiranja, tuple se briše i memorija se oslobađa. Kopiranje završava u trenutku kada se kopira jedan bajt podataka. Ako ponestane prostora u sredini podatkovnog bloka, tada će se u ovoj poruci podatkovni blok smanjiti na preostali nekopirani dio. Sljedeći put kada nazovete, kopiranje će se nastaviti od ove točke.

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

int ms_bufferizer_get_avail(MSBufferizer *obj); 

Vraća polje Veličina međuspremnik.

Odbacivanje dijela podataka u međuspremniku:

void ms_bufferizer_skip_bytes(MSBufferizer *obj, int bytes);

Navedeni broj bajtova podataka se dohvaća i odbacuje. Najstariji podaci se odbacuju.

Brisanje svih poruka u međuspremniku:

void ms_bufferizer_flush(MSBufferizer *obj); 

Brojač podataka se vraća na nulu.

Brisanje svih poruka u međuspremniku:

void ms_bufferizer_uninit(MSBufferizer *obj); 

Brojač nije resetiran.

Uklanjanje međuspremnika i oslobađanje memorije:

void ms_bufferizer_destroy(MSBufferizer *obj);  

Primjeri korištenja međuspremnika mogu se pronaći u izvornom kodu nekoliko filtara medijskih strujalica. Na primjer, u filtru MS_L16_ENC, koji preuređuje bajtove u uzorcima iz mrežnog redoslijeda u redoslijed glavnog računala: l16.c

U sljedećem ćemo članku razmotriti pitanje procjene opterećenja tickera i kako se nositi s prekomjernim računalnim opterećenjem u streameru medija.

Izvor: www.habr.com

Dodajte komentar