Prozkoumání enginu Mediastreamer2 VoIP. Část 11

Materiál článku je převzat z mého zenový kanál.

Prozkoumání enginu Mediastreamer2 VoIP. Část 11

Mechanismus pohybu dat

  • Datový blok dblk_t
  • Zpráva mblk_t
  • Funkce pro práci se zprávami mblk_t
  • Fronta queue_t
  • Funkce pro práci s frontami queue_t
  • Připojení filtrů
  • Signální bod grafu zpracování dat
  • Zákulisní aktivity tickeru
  • Bufferizer (MSBufferizer)
  • Funkce pro práci s MSBufferizer

V minulosti článek vyvinuli jsme vlastní filtr. Tento článek se zaměří na vnitřní mechanismus pro přesun dat mezi filtry streamování médií. To vám v budoucnu umožní psát sofistikované filtry s menší námahou.

Mechanismus pohybu dat

Přesun dat v media streameru se provádí pomocí front popsaných strukturou queue_t. Řetězce zpráv jako mblk_t, které samy o sobě neobsahují signální data, ale pouze odkazují na předchozí, další zprávu a na datový blok. Kromě toho chci zvláště zdůraznit, že je zde také pole pro odkaz na zprávu stejného typu, které umožňuje uspořádat jednotlivě propojený seznam zpráv. Skupinu zpráv sjednocenou takovým seznamem budeme nazývat n-tice. Jakýkoli prvek fronty tedy může být jedinou zprávou mblk_ta možná hlava n-tice zpráv mblk_t. Každá n-ticová zpráva může mít svůj vlastní blok dat oddělení. Proč jsou n-tice potřeba, probereme o něco později.

Jak již bylo zmíněno výše, samotná zpráva neobsahuje blok dat, místo toho obsahuje pouze ukazatel na oblast paměti, kde je blok uložen. V této části celkový obraz práce mediálního streamera připomíná sklad dveří v karikatuře „Monsters, Inc.“, kde se dveře (odkazy na data - místnosti) pohybují šílenou rychlostí podél horních dopravníků, zatímco samotné místnosti zůstat nehybný.

Nyní, když se pohybujeme v hierarchii zdola nahoru, podívejme se podrobně na uvedené entity mechanismu přenosu dat v mediálním streameru.

Datový blok dblk_t

Datový blok se skládá z hlavičky a datové vyrovnávací paměti. Hlavička je popsána následující strukturou,

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

Pole struktury obsahují ukazatele na začátek vyrovnávací paměti, konec vyrovnávací paměti a funkci pro smazání datové vyrovnávací paměti. Poslední prvek v záhlaví db_ref — referenční čítač, pokud dosáhne nuly, slouží jako signál k vymazání tohoto bloku z paměti. Pokud byl datový blok vytvořen funkcí datab_alloc() , pak bude datová vyrovnávací paměť umístěna do paměti bezprostředně za hlavičku. Ve všech ostatních případech může být vyrovnávací paměť umístěna někde samostatně. Datová vyrovnávací paměť bude obsahovat vzorky signálu nebo jiná data, která chceme zpracovat pomocí filtrů.

Nová instance datového bloku se vytvoří pomocí funkce:

dblk_t *datab_alloc(int size);

Jako vstupní parametr je dána velikost dat, která bude blok ukládat. Více paměti je alokováno za účelem umístění hlavičky - struktury - na začátek přidělené paměti datab. Ale při použití jiných funkcí se to nestává vždy, v některých případech může být datová vyrovnávací paměť umístěna odděleně od hlavičky datového bloku. Při vytváření struktury jsou pole konfigurována tak, že její pole db_base ukázal na začátek datové oblasti a db_lim do jejího konce. Počet odkazů db_ref je nastavena na jedničku. Ukazatel funkce vymazání dat je nastaven na nulu.

zpráva mblk_t

Jak bylo uvedeno, prvky fronty jsou typu mblk_t, je definován takto:

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 obsahuje ukazatele na začátku b_předchozí, b_další, které jsou nezbytné k uspořádání dvojitě propojeného seznamu (což je fronta queue_t).

Pak přichází ukazatel b_cont, který se používá pouze v případě, že je zpráva součástí n-tice. Pro poslední zprávu v n-tici tento ukazatel zůstává null.

Dále vidíme ukazatel na datový blok b_datap, pro které zpráva existuje. Za ním následují ukazatele na oblast uvnitř vyrovnávací paměti blokových dat. Pole b_rptr určuje umístění, ze kterého se budou číst data z vyrovnávací paměti. Pole b_wptr označuje místo, ze kterého budou provedeny zápisy do vyrovnávací paměti.

Zbývající pole mají charakter služeb a nesouvisejí s fungováním mechanismu přenosu dat.

Níže je jediná zpráva s názvem m1 a datový blok d1.
Prozkoumání enginu Mediastreamer2 VoIP. Část 11
Následující obrázek ukazuje n-tici tří zpráv m1, m1_1, m1_2.
Prozkoumání enginu Mediastreamer2 VoIP. Část 11

Funkce zpráv mblk_t

Nová zpráva mblk_t vytvořený funkcí:

mblk_t *allocb(int size, int pri); 

vloží do paměti novou zprávu mblk_t s datovým blokem zadané velikosti velikost, druhý argument - u nepoužívá se v této verzi knihovny. Mělo by zůstat nulové. Během činnosti funkce bude přidělena paměť pro strukturu nové zprávy a funkce bude volána mblk_init(), který resetuje všechna pole vytvořené instance struktury a poté pomocí výše uvedeného datab_alloc(), vytvoří datovou vyrovnávací paměť. Poté budou konfigurována pole ve struktuře:

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

Na výstupu obdržíme novou zprávu s inicializovanými poli a prázdným datovým bufferem. Chcete-li do zprávy přidat data, musíte je zkopírovat do vyrovnávací paměti bloku dat:

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

kde datum je ukazatel na zdroj dat a velikost - jejich velikost.
pak musíte aktualizovat ukazatel na bod zápisu tak, aby znovu ukazoval na začátek volné oblasti ve vyrovnávací paměti:

msg->b_wptr = msg->b_wptr + size

Pokud potřebujete vytvořit zprávu z existující vyrovnávací paměti bez kopírování, použijte funkci:

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

Funkce po vytvoření zprávy a struktury datového bloku nakonfiguruje své ukazatele na data na adrese buf. Tito. v tomto případě se datová vyrovnávací paměť nenachází za záhlavími datového bloku, jako tomu bylo při vytváření datového bloku s funkcí datab_alloc(). Buffer s daty předanými funkci zůstane tam, kde byl, ale pomocí ukazatelů se připojí k nově vytvořené hlavičce datového bloku a tím ke zprávě.

Na jednu zprávu mblk_t Několik datových bloků lze zřetězit postupně. To se provádí funkcí:

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

mp — zpráva, ke které bude přidán další datový blok;
datum — ukazatel na blok, jehož kopie bude přidána do zprávy;
velikost — velikost dat;
podložka — příznak, že velikost alokované paměti musí být zarovnána podél 4bajtové hranice (vyplnění bude provedeno nulami).

Pokud je ve vyrovnávací paměti dat existující zprávy dostatek místa, budou nová data vložena za data, která tam již jsou. Pokud je ve vyrovnávací paměti dat zprávy méně volného místa než velikost, poté se vytvoří nová zpráva s dostatečnou velikostí bufferu a data se zkopírují do jeho bufferu. Toto je nová zpráva, propojená s původní pomocí ukazatele b_cont. V tomto případě se zpráva změní na n-tici.

Pokud potřebujete přidat další blok dat do n-tice, musíte použít funkci:

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

ona najde poslední zprávu v n-tici (on má b_cont bude null) a zavolá funkci pro tuto zprávu appendb().

Velikost dat ve zprávě nebo n-tice můžete zjistit pomocí funkce:

int msgdsize(const mblk_t *mp);

bude procházet všemi zprávami v n-tice a vrátí celkové množství dat v datových bufferech těchto zpráv. Pro každou zprávu se množství dat vypočítá takto:

 mp->b_wptr - mp->b_rptr

Chcete-li spojit dvě n-tice, použijte funkci:

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

ona připojí n-tici newm k ocasu tuple mp a vrátí ukazatel na poslední zprávu výsledné n-tice.

V případě potřeby lze n-tici proměnit v jednu zprávu s jediným blokem dat; to se provádí funkcí:

void msgpullup(mblk_t *mp,int len);

pokud argument jenom je -1, pak se velikost přidělené vyrovnávací paměti určí automaticky. Li jenom je kladné číslo, vytvoří se vyrovnávací paměť této velikosti a do ní se zkopírují data zprávy n-tice. Pokud dojde vyrovnávací paměť, kopírování se tam zastaví. První zpráva n-tice obdrží novou velikost vyrovnávací paměti se zkopírovanými daty. Zbývající zprávy budou vymazány a paměť se vrátí na hromadu.

Při mazání struktury mblk_t referenční počet datového bloku se bere v úvahu, pokud při volání freeb() ukáže se, že je nula, pak se datová vyrovnávací paměť vymaže spolu s instancí mblk_t, který na to poukazuje.

Inicializace polí nové zprávy:

void mblk_init(mblk_t *mp);

Přidání další části dat do zprávy:

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

Pokud se nová data nevejdou do volného místa datové vyrovnávací paměti zprávy, pak se ke zprávě připojí samostatně vytvořená zpráva s vyrovnávací pamětí požadované velikosti (v první zprávě se nastaví ukazatel na přidanou zprávu) a zpráva se změní na n-tici.

Přidání části dat do n-tice:

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

Funkce volá appendb() ve smyčce.

Sloučení dvou n-tic do jedné:

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

zpráva newm bude připojen k mp.

Vytvoření kopie jedné zprávy:

mblk_t *copyb(const mblk_t *mp);

Kompletní zkopírování n-tice se všemi datovými bloky:

mblk_t *copymsg(const mblk_t *mp);

Prvky n-tice funkce zkopíruje copyb().

Vytvořte snadnou kopii zprávy mblk_t. V tomto případě se datový blok nezkopíruje, ale zvýší se jeho referenční čítač db_ref:

mblk_t *dupb(mblk_t *mp);

Vytvoření odlehčené kopie n-tice. Datové bloky se nekopírují, pouze se zvýší jejich referenční čítače db_ref:

mblk_t *dupmsg(mblk_t* m);

Spojení všech zpráv n-tice do jedné zprávy:

void msgpullup(mblk_t *mp,size_t len);

Pokud argument jenom je -1, pak se velikost přidělené vyrovnávací paměti určí automaticky.

Mazání zprávy, tuple:

void freemsg(mblk_t *mp);

Počet referencí bloku dat se sníží o jednu. Pokud dosáhne nuly, smaže se také datový blok.

Výpočet celkového množství dat ve zprávě nebo n-tice.

size_t msgdsize(const mblk_t *mp);

Načtení zprávy z konce fronty:

mblk_t *ms_queue_peek_last (q);

Kopírování obsahu vyhrazených polí jedné zprávy do jiné zprávy (tato pole ve skutečnosti obsahují příznaky, které používá streamer médií):

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

Fronta queue_t

Fronta zpráv v streameru médií je implementována jako kruhový dvojitě propojený seznam. Každý prvek seznamu obsahuje ukazatel na datový blok se vzorky signálu. Ukazuje se, že se postupně pohybují pouze ukazatele na datový blok, zatímco samotná data zůstávají nehybná. Tito. přesunou se pouze odkazy na ně.
Struktura popisující frontu queue_t, je uvedeno níže:

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

Struktura obsahuje pole - ukazatel _q_stopper zadejte *mblk_t, ukazuje na první prvek (zprávu) ve frontě. Druhým polem struktury je počítadlo zpráv ve frontě.
Obrázek níže ukazuje frontu s názvem q1 obsahující 4 zprávy m1, m2, m3, m4.
Prozkoumání enginu Mediastreamer2 VoIP. Část 11
Následující obrázek ukazuje frontu s názvem q1 obsahující 4 zprávy m1,m2,m3,m4. Zpráva m2 je hlava n-tice, která obsahuje další dvě zprávy m2_1 a m2_2.

Prozkoumání enginu Mediastreamer2 VoIP. Část 11

Funkce pro práci s frontami queue_t

Inicializace fronty:

void qinit(queue_t *q);

Pole _q_stopper (dále to budeme nazývat „zátka“) je inicializována funkcí mblk_init(), jeho předchozí prvek a ukazatel dalšího prvku jsou upraveny tak, aby ukazovaly na sebe. Čítač prvků fronty se vynuluje.

Přidání nového prvku (zprávy):

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

Nový prvek m se přidá na konec seznamu, ukazatele prvků se upraví tak, že zátka se pro něj stane dalším prvkem a stane se předchozím prvkem zátka. Počítadlo prvků fronty se zvýší.

Načtení prvku z fronty:

mblk_t * getq(queue_t *q); 

Zpráva, která se objeví po vytažení zátky a počítadlo prvků se sníží. Pokud ve frontě nejsou žádné prvky kromě zarážky, vrátí se 0.

Vložení zprávy do fronty:

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

Prvek mp vložen před prvek emp. Pokud emp=0, pak je zpráva přidána na konec fronty.

Načítání zprávy z hlavy fronty:

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

Počítadlo prvků se sníží.

Čtení ukazatele na první prvek ve frontě:

mblk_t * peekq(queue_t *q); 

Odebrání všech prvků z fronty při mazání samotných prvků:

void flushq(queue_t *q, int how);

argument jak nepoužívá. Čítač prvků fronty je nastaven na nulu.

Makro pro čtení ukazatele na poslední prvek fronty:

mblk_t * qlast(queue_t *q);

Při práci s frontami zpráv si uvědomte, že když voláte ms_queue_put(q, m) s nulovým ukazatelem na zprávu se funkce zacyklí. Váš program zamrzne. se chová podobně ms_queue_next(q, m).

Připojení filtrů

Výše popsaná fronta se používá k předávání zpráv z jednoho filtru do druhého nebo z jednoho do několika filtrů. Filtry a jejich propojení tvoří orientovaný graf. Vstup nebo výstup filtru se bude nazývat obecným slovem „pin“. Pro popis pořadí, ve kterém jsou filtry vzájemně propojeny, používá streamer médií koncept „signálního bodu“. Signálním bodem je struktura _MSCPoint, který obsahuje ukazatel na filtr a číslo jednoho z jeho pinů, podle toho popisuje zapojení jednoho ze vstupů nebo výstupů filtru.

Signální bod grafu zpracování dat

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

Filtrové kolíky jsou číslovány od nuly.

Spojení dvou pinů frontou zpráv popisuje struktura _MSQueue, který obsahuje frontu zpráv a ukazatele na dva signálové body, které spojuje:

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

Tuto strukturu budeme nazývat signální spojka. Každý filtr streamování médií obsahuje tabulku vstupních odkazů a tabulku výstupních odkazů (MSQueue). Velikost tabulek se nastavuje při vytváření filtru, to jsme již provedli pomocí exportované proměnné typu MSFilterDesc, kdy jsme vyvinuli vlastní filtr. Níže je struktura, která popisuje jakýkoli filtr v streameru médií, 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;

Poté, co jsme v programu C propojili filtry podle našeho plánu (ale nepřipojili ticker), vytvořili jsme tím orientovaný graf, jehož uzly jsou instancemi struktury MSFilter, a hrany jsou instancemi odkazů MSQueue.

Zákulisní aktivity tickeru

Když jsem vám řekl, že ticker je filtr na zdroj klíšťat, nebyla to celá pravda. Ticker je objekt, který spouští funkce na hodinách proces() všechny filtry obvodu (grafu), ke kterému je připojen. Když připojíme ticker ke filtru grafu v programu C, ukážeme tickeru graf, který bude od této chvíle ovládat, dokud jej nevypneme. Po připojení začne ticker zkoumat graf svěřený do jeho péče a sestaví seznam filtrů, které jej obsahují. Aby se stejný filtr „nepočítal“ dvakrát, označí nalezené filtry zaškrtnutím viděl. Vyhledávání se provádí pomocí tabulek odkazů, které má každý filtr.

Během úvodní prohlídky grafu ticker zkontroluje, zda mezi filtry existuje alespoň jeden, který funguje jako zdroj datových bloků. Pokud žádné nejsou, pak je graf považován za nesprávný a ticker se zhroutí.

Pokud se ukáže, že graf je „správný“, pro každý nalezený filtr je funkce volána k inicializaci preprocess(). Jakmile nastane okamžik pro další cyklus zpracování (standardně každých 10 milisekund), ticker zavolá funkci proces() pro všechny dříve nalezené zdrojové filtry a poté pro zbývající filtry v seznamu. Pokud má filtr vstupní odkazy, spustí se funkce proces() opakuje, dokud nejsou fronty vstupních odkazů prázdné. Poté přejde k dalšímu filtru v seznamu a „roluje“ jej, dokud vstupní odkazy neobsahují žádné zprávy. Ticker se pohybuje od filtru k filtru, dokud seznam neskončí. Tím je zpracování cyklu dokončeno.

Nyní se vrátíme k n-ticím a povíme si o tom, proč byla taková entita přidána do media streameru. Obecně se množství dat požadovaných algoritmem pracujícím uvnitř filtru neshoduje a není násobkem velikosti datových vyrovnávacích pamětí přijatých na vstupu. Například píšeme filtr, který provádí rychlou Fourierovu transformaci, která podle definice dokáže zpracovat pouze datové bloky, jejichž velikost je mocninou dvou. Nechť je to 512 počtů. Pokud jsou data generována telefonním kanálem, pak nám datová vyrovnávací paměť každé zprávy na vstupu přinese 160 vzorků signálu. Je lákavé nesbírat data ze vstupu, dokud tam není požadované množství dat. V tomto případě ale dojde ke kolizi s tickerem, který se neúspěšně pokusí posouvat filtr, dokud není vstupní odkaz prázdný. Dříve jsme toto pravidlo označili jako třetí princip filtru. Podle tohoto principu musí funkce process() filtru převzít všechna data ze vstupních front.

Ze vstupu navíc nebude možné odebrat pouze 512 vzorků, jelikož lze odebírat pouze celé bloky, tzn. filtr bude muset odebrat 640 vzorků a použít 512 z nich, zbytek před akumulací nové části dat. Náš filtr tedy kromě své hlavní práce musí poskytovat pomocné akce pro meziukládání vstupních dat. Vývojáři media streameru a řešení tohoto obecného problému vyvinuli speciální objekt - MSBufferizer (bufferer), který tento problém řeší pomocí n-tic.

Bufferizer (MSBufferizer)

Jedná se o objekt, který bude shromažďovat vstupní data uvnitř filtru a začne je odesílat ke zpracování, jakmile je množství informací dostatečné pro spuštění algoritmu filtru. Zatímco vyrovnávací paměť shromažďuje data, filtr bude pracovat v klidovém režimu, aniž by spotřeboval výpočetní výkon procesoru. Jakmile ale funkce čtení z vyrovnávací paměti vrátí jinou hodnotu než nulu, funkce process() filtru začne odebírat a zpracovávat data z vyrovnávací paměti po částech požadované velikosti, dokud nejsou vyčerpána.
Data, která ještě nejsou požadována, zůstávají ve vyrovnávací paměti jako první prvek n-tice, ke kterému jsou připojeny následné bloky vstupních dat.

Struktura, která popisuje vyrovnávací paměť:

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

Funkce pro práci s MSBufferizer

Vytvoření nové instance vyrovnávací paměti:

MSBufferizer * ms_bufferizer_new(void);

Paměť je přidělena, inicializována ms_bufferizer_init() a vrátí se ukazatel.

Inicializační funkce:

void ms_bufferizer_init(MSBufferizer *obj); 

Fronta se inicializuje q, pole velikost je nastaven na nulu.

Přidání zprávy:

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

Zpráva m je přidána do fronty. Vypočtená velikost datových bloků se přičte velikost.

Přenos všech zpráv z fronty dat spojení do vyrovnávací paměti q:

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

Přenos zpráv z odkazu q ve vyrovnávací paměti se provádí pomocí funkce ms_bufferizer_put().

Čtení z vyrovnávací paměti:

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

Pokud je velikost dat nashromážděných ve vyrovnávací paměti menší než požadovaná (datalen), pak funkce vrátí nulu, data se do dat nezkopírují. V opačném případě se provádí sekvenční kopírování dat z n-tic umístěných ve vyrovnávací paměti. Po zkopírování se n-tice smaže a paměť se uvolní. Kopírování je ukončeno v okamžiku, kdy jsou zkopírovány bajty dat. Pokud dojde místo uprostřed datového bloku, pak v této zprávě bude datový blok zmenšen na zbývající nezkopírovanou část. Při příštím volání bude kopírování pokračovat od tohoto bodu.

Čtení množství dat, které je aktuálně dostupné ve vyrovnávací paměti:

int ms_bufferizer_get_avail(MSBufferizer *obj); 

Vrátí pole velikost vyrovnávací paměť.

Zahození části dat ve vyrovnávací paměti:

void ms_bufferizer_skip_bytes(MSBufferizer *obj, int bytes);

Zadaný počet bajtů dat se načte a zahodí. Nejstarší data jsou vyřazena.

Smazání všech zpráv ve vyrovnávací paměti:

void ms_bufferizer_flush(MSBufferizer *obj); 

Počítadlo dat se vynuluje.

Smazání všech zpráv ve vyrovnávací paměti:

void ms_bufferizer_uninit(MSBufferizer *obj); 

Čítač není resetován.

Odstranění vyrovnávací paměti a uvolnění paměti:

void ms_bufferizer_destroy(MSBufferizer *obj);  

Příklady použití bufferu lze nalézt ve zdrojovém kódu několika filtrů media streameru. Například ve filtru MS_L16_ENC, který přeskupuje bajty ve vzorcích ze síťového pořadí na hostitelské pořadí: l16.c

V příštím článku se podíváme na problematiku odhadu zátěže na tickeru a na způsoby, jak bojovat s nadměrnou výpočetní zátěží v media streameru.

Zdroj: www.habr.com

Přidat komentář