Esplora u mutore VoIP Mediastreamer2. Parte 11

U materiale di l'articulu hè pigliatu da u mo canale zen.

Esplora u mutore VoIP Mediastreamer2. Parte 11

Meccanisimu di muvimentu di dati

  • Bloccu dati dblk_t
  • Missaghju mblk_t
  • Funzioni per travaglià cù i missaghji mblk_t
  • Queue queue_t
  • Funzioni per travaglià cù file queue_t
  • Filtri di cunnessione
  • Puntu di signale di u graficu di trattamentu di dati
  • Dietro l'attività di u ticker
  • Bufferizer (MSBufferizer)
  • Funzioni per travaglià cù MSBufferizer

In l'ultimu articulu avemu sviluppatu u nostru propiu filtru. Questu articulu hà da fucalizza nantu à u mecanismu internu per u muvimentu di dati trà i filtri media streamer. Questu permetterà di scrive filtri sofisticati cù menu sforzu in u futuru.

Meccanisimu di muvimentu di dati

U muvimentu di dati in u streamer media hè realizatu utilizendu file descritte da a struttura fila_t. Strings di missaghji cum'è mblk_t, chì elli stessi ùn cuntenenu dati di signali, ma solu ligami à u missaghju precedente, prossimu è à u bloccu di dati. Inoltre, vogliu enfatizà sopratuttu chì ci hè ancu un campu per un ligame à un missaghju di u listessu tipu, chì permette di urganizà una lista di messagi ligata singolarmente. Chjameremu un gruppu di messagi uniti da una tale lista una tupla. Cusì, ogni elementu di a fila pò esse un missaghju unicu mblk_t, è forsi u capu di un missaghju tuple mblk_t. Ogni missaghju tuple pò avè u so propiu bloccu di dati di sala. Discuteremu perchè i tuppi sò necessarii un pocu dopu.

Cumu l'esitatu sopra, u missaghju stessu ùn cuntene micca un bloccu di dati; invece, cuntene solu un punteru à l'area di memoria induve u bloccu hè almacenatu. In questa parte, l'imaghjini generale di u travagliu di u media streamer hè una reminiscenza di u magazzinu di a porta in u cartone "Monsters, Inc.", induve e porte (ligami à dati - camere) si movenu à una velocità insane longu i trasportatori sopra, mentre chì e stanze stesse. resta immobile.

Avà, movendu longu a ghjerarchia da u fondu à a cima, cunsideremu in dettaglio l'entità listate di u mecanismu di trasmissione di dati in u media streamer.

Bloccu di dati dblk_t

U bloccu di dati hè custituitu da un header è un buffer di dati. L'intestazione hè descritta da a struttura seguente,

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

I campi di a struttura cuntenenu punters à u principiu di u buffer, a fine di u buffer, è a funzione per sguassà u buffer di dati. Ultimu elementu in header db_ref - contatore di riferimentu, s'ellu righjunghji u zero, questu serve com'è un signalu per sguassà stu bloccu da a memoria. Se u bloccu di dati hè statu creatu da a funzione datab_alloc() , allura u buffer di dati serà messu in memoria immediatamente dopu à l'intestazione. In tutti l'altri casi, u buffer pò esse situatu in un locu separatamente. U buffer di dati cuntene campioni di signali o altre dati chì vulemu processà cù filtri.

Una nova istanza di un bloccu di dati hè creata cù a funzione:

dblk_t *datab_alloc(int size);

Cum'è un paràmetru di input, hè datu a dimensione di e dati chì u bloccu guardà. Più memoria hè attribuita per mette un intestazione - struttura - à u principiu di a memoria assignata datab. Ma quandu si usanu altre funzioni, questu ùn succede micca sempre; in certi casi, u buffer di dati pò esse situatu separatamente da l'intestazione di u bloccu di dati. Quandu crea una struttura, i campi sò cunfigurati in modu chì u so campu db_base indicò u principiu di l'area di dati, è db_lim à a so fine. Conte di ligami db_ref hè pusatu à unu. L'indicatore di a funzione di cancellazione di dati hè pusatu à zero.

missaghju mblk_t

Cum'è dichjaratu, elementi di fila sò di tipu mblk_t, hè definitu cusì:

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;

strutura mblk_t cuntene puntatori à u principiu b_prev, b_appressu, chì sò necessarii per urganizà una lista doppiamente ligata (chì hè una fila fila_t).

Allora vene u puntatore b_cont, chì hè solu utilizatu quandu u messagiu hè parti di una tupla. Per l'ultimu missaghju in a tupla, stu puntatore resta nulu.

Dopu vedemu un punteru à un bloccu di dati b_datap, per quale u missaghju esiste. Hè seguitatu da punters à l'area in u buffer di dati di bloccu. Campu b_rptr specifica u locu da quale i dati da u buffer seranu leghje. Campu b_wptr indica u locu da quale scrive à u buffer serà realizatu.

I campi rimanenti sò di natura di serviziu è ùn sò micca in relazione cù l'operazione di u mecanismu di trasferimentu di dati.

Quì sottu hè un missaghju unicu cù u nome m1 è bloccu di dati d1.
Esplora u mutore VoIP Mediastreamer2. Parte 11
A figura seguente mostra una tupla di trè missaghji m1, m1_1, m1_2.
Esplora u mutore VoIP Mediastreamer2. Parte 11

Funzioni di messageria mblk_t

Un novu missaghju mblk_t creatu da a funzione:

mblk_t *allocb(int size, int pri); 

ella mette un novu missaghju in memoria mblk_t cù un bloccu di dati di a dimensione specifica grannizza, secondu argumentu - pri micca usatu in sta versione di a biblioteca. Si deve esse cero. Durante u funziunamentu di a funzione, a memoria serà attribuita per a struttura di u novu messagiu è a funzione serà chjamata mblk_init(), chì resettarà tutti i campi di l'istanza creata di a struttura è dopu, usendu u sopra citatu datab_alloc(), creà un buffer di dati. Dopu chì i campi in a struttura seranu cunfigurati:

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

À l'output, ricevemu un novu missaghju cù campi inizializzati è un buffer di dati viotu. Per aghjunghje dati à un missaghju, avete bisognu di cupià in u buffer di bloccu di dati:

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

induve données hè un puntatore à a fonte di dati, è grannizza - a so taglia.
allora avete bisognu di aghjurnà u punteru à u puntu di scrittura in modu chì indicà di novu à u principiu di l'area libera in u buffer:

msg->b_wptr = msg->b_wptr + size

Sè avete bisognu di creà un missaghju da un buffer esistente, senza copià, allora utilizate a funzione:

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

A funzione, dopu à creà u messagiu è a struttura di u bloccu di dati, cunfigurà i so punters à i dati à l'indirizzu buff. Quelli. in questu casu, u buffer di dati ùn hè micca situatu dopu à i campi di l'intestazione di u bloccu di dati, cum'è era u casu quandu crea un bloccu di dati cù a funzione datab_alloc(). U buffer cù dati passati à a funzione ferma induve era, ma cù l'aiutu di punters serà attaccatu à l'intestazione di novu creatu di u bloccu di dati, è chì, per quessa, à u messagiu.

À un missaghju mblk_t Diversi blocchi di dati ponu esse cuncatenati in sequenza. Questu hè fattu da a funzione:

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

mp - un missaghju à quale sarà aghjuntu un altru bloccu di dati;
données - puntatore à u bloccu, una copia di quale serà aghjuntu à u missaghju;
grannizza - dimensione di dati;
pad - una bandiera chì a dimensione di a memoria assignata deve esse allinata longu un cunfini di 4 byte (padding serà fattu cù zeri).

S'ellu ci hè abbastanza spaziu in u buffer di dati missaghju esistenti, allura i novi dati seranu incollati daretu à i dati digià quì. Se ci hè menu spaziu liberu in u buffer di dati missaghju cà grannizza, tandu un novu missaghju hè creatu cù una dimensione di buffer sufficiente è e dati sò copiati in u so buffer. Questu hè un novu missaghju, ligatu à l'uriginale cù un puntatore b_cont. In questu casu, u missaghju si trasforma in una tupla.

Sè avete bisognu di aghjunghje un altru bloccu di dati à a tupla, allora avete bisognu di utilizà a funzione:

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

ella truverà l'ultimu missaghju in u tuple (hà b_cont serà nulla) è chjamarà a funzione per stu missaghju appendb ().

Pudete truvà a dimensione di dati in un missaghju o tuple cù a funzione:

int msgdsize(const mblk_t *mp);

ci sarà loop à traversu tutti i missaghji in u tuple è torna a quantità tutali di dati in i buffers di dati di quelli missaghji. Per ogni missaghju, a quantità di dati hè calculata cusì:

 mp->b_wptr - mp->b_rptr

Per unisce duie tuple, utilizate a funzione:

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

ella aghjusta a tupla novu à a cuda di a tupla mp è torna un punteru à l'ultimu missaghju di a tupla resultante.

Se necessariu, una tupla pò esse trasfurmata in un missaghju cù un solu bloccu di dati; questu hè fattu da a funzione:

void msgpullup(mblk_t *mp,int len);

se argumentu piscina hè -1, allora a dimensione di u buffer assignata hè determinata automaticamente. Se piscina hè un numeru pusitivu, un buffer di questa dimensione serà creatu è i dati di u messagiu di tuple seranu copiati in questu. Se u buffer si esaurisce, a copia si ferma quì. U primu messagiu di a tupla riceverà un novu buffer di dimensione cù e dati copiati. I missaghji rimanenti seranu sguassati è a memoria tornata à u munzeddu.

Quandu sguassate una struttura mblk_t u contu di rifarenza di u bloccu di dati hè pigliatu in contu si, quandu chjama freeb () risulta esse zero, allora u buffer di dati hè sguassatu cù l'istanza mblk_t, chì indica.

Inizializza i campi di un novu messagiu:

void mblk_init(mblk_t *mp);

Aghjunghjendu un altru pezzu di dati à u messagiu:

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

Se a nova data ùn si mette micca in u spaziu liberu di u buffer di dati di u messagiu, allora un missaghju creatu separatamente cù un buffer di a dimensione necessaria hè attaccatu à u messagiu (un punteru à u messagiu aghjuntu hè stallatu in u primu missaghju) è u missaghju si trasforma in una tupla.

Aghjunghjendu un pezzu di dati à una tupla:

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

A funzione chjama appendb() in un ciclu.

Cumminendu dui tuppi in unu:

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

missaghju novu sarà attaccatu à mp.

Fà una copia di un missaghju unicu:

mblk_t *copyb(const mblk_t *mp);

Copia cumpleta di una tupla cù tutti i blocchi di dati:

mblk_t *copymsg(const mblk_t *mp);

L'elementi di a tupla sò copiati da a funzione copyb ().

Crea una copia faciule di un missaghju mblk_t. In questu casu, u bloccu di dati ùn hè micca copiatu, ma u so contatore di riferimentu hè aumentatu db_ref:

mblk_t *dupb(mblk_t *mp);

Fà una copia ligera di una tupla. I blocchi di dati ùn sò micca copiati, solu i so contatori di riferimentu sò aumentati db_ref:

mblk_t *dupmsg(mblk_t* m);

Incolla tutti i missaghji di una tupla in un missaghju:

void msgpullup(mblk_t *mp,size_t len);

Se l'argumentu piscina hè -1, allora a dimensione di u buffer assignata hè determinata automaticamente.

Eliminazione di un missaghju, tupla:

void freemsg(mblk_t *mp);

U conte di riferimentu di u bloccu di dati hè diminuitu da unu. S'ellu ghjunghje à zero, u bloccu di dati hè ancu sguassatu.

Càlculu di a quantità tutale di dati in un missaghju o tuple.

size_t msgdsize(const mblk_t *mp);

Ritruvà un missaghju da a cuda di a fila:

mblk_t *ms_queue_peek_last (q);

Copià u cuntenutu di i campi riservati di un missaghju in un altru missaghju (in fatti, sti campi cuntenenu bandieri chì sò usati da u media streamer):

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

Gira fila_t

A fila di messagi in u media streamer hè implementata cum'è una lista circular doppiamente ligata. Ogni elementu di a lista cuntene un puntatore à un bloccu di dati cù campioni di signali. Ci hè chì solu i puntatori à u bloccu di dati si movenu in turnu, mentre chì i dati stessi fermanu immobile. Quelli. solu i ligami per elli sò spustati.
Struttura chì descrive a fila fila_t, mostratu quì sottu:

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

A struttura cuntene un campu - un puntatore _q_stopper tipu *mblk_t, punta à u primu elementu (messaghju) in a fila. U sicondu campu di a struttura hè u contatore di missaghji in a fila.
A figura sottu mostra una fila chjamata q1 chì cuntene 4 missaghji m1, m2, m3, m4.
Esplora u mutore VoIP Mediastreamer2. Parte 11
A figura seguente mostra una fila chjamata q1 chì cuntene 4 missaghji m1,m2,m3,m4. Missaghju m2 hè u capu di una tupla chì cuntene dui più missaghji m2_1 è m2_2.

Esplora u mutore VoIP Mediastreamer2. Parte 11

Funzioni per travaglià cù file queue_t

Inizializazione di a fila:

void qinit(queue_t *q);

chjosu _q_stopper (in seguitu chjameremu "tappa") hè inizializatu da a funzione mblk_init(), u so elementu precedente è u punteru di l'elementu prossimu sò adattati per indicà à ellu stessu. U contatore di elementi di fila hè resettatu à zero.

Aghjunghjendu un novu elementu (messages):

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

Elementu novu m hè aghjuntu à a fine di a lista, i punteri di l'elementu sò aghjustati in modu chì u stopper diventa l'elementu prossimu per questu, è diventa l'elementu precedente per u stopper. U contatore di elementi di fila hè aumentatu.

Ritruvà un elementu da a fila:

mblk_t * getq(queue_t *q); 

U missaghju chì vene dopu à u stopper hè ritruvatu, è u contatore di l'elementu hè diminuitu. Se ùn ci hè micca elementi in a fila, salvu u tappu, allora 0 hè tornatu.

Inserisce un missaghju in una fila:

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

Elementu mp inseritu prima di l'elementu E emp... Sì E emp= 0, allura u messagiu hè aghjuntu à a cuda di a fila.

Ritruvà un missaghju da u capu di a fila:

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

U contatore di elementi hè diminuitu.

Leghje un puntatore à u primu elementu in a fila:

mblk_t * peekq(queue_t *q); 

Eliminazione di tutti l'elementi da a fila mentre sguassate l'elementi stessi:

void flushq(queue_t *q, int how);

argumentu quantu micca usatu. U contatore di l'elementu di fila hè pusatu à zero.

Macro per leghje un puntatore à l'ultimu elementu di a fila:

mblk_t * qlast(queue_t *q);

Quandu u travagliu cù file di messagi, sia cuscenti chì quandu chjamate ms_queue_put(q, m) cù un punteru nulu à u messagiu, a funzione loops. U vostru prugramma si congelarà. si cumporta u listessu ms_queue_next(q, m).

Filtri di cunnessione

A fila descritta sopra hè aduprata per passà missaghji da un filtru à l'altru o da unu à parechji filtri. I filtri è e so cunnessione formanu un graficu direttu. L'input o output di u filtru serà chjamatu a parolla generale "pin". Per discrìviri l'ordine in quale i filtri sò cunnessi à l'altri, u media streamer usa u cuncettu di "puntu di signale". U puntu di signale hè struttura _MSCPoint, chì cuntene un punteru à u filtru è u numeru di unu di i so pin; per quessa, descrive a cunnessione di unu di l'inputs o outputs di u filtru.

Puntu di signale di u graficu di trattamentu di dati

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

I pins di filtru sò numerati partendu da zero.

A cunnessione di dui pin da una fila di messagi hè descritta da a struttura _MSQueue, chì cuntene una fila di messagi è punters à i dui punti di signale chì cunnetta:

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

Chjameremu sta struttura un ligame di signale. Ogni filtru media streamer cuntene una tabella di ligami di input è una tabella di ligami di output (MSQueue). A dimensione di e tavule hè stabilita quandu crea un filtru; avemu digià fattu questu utilizendu una variabile di tipu esportata MSFilterDesc, quandu avemu sviluppatu u nostru propiu filtru. A sottu hè una struttura chì descrive qualsiasi filtru in un streamer media, 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;

Dopu avè cunnessu i filtri in u prugramma C in cunfurmità cù u nostru pianu (ma ùn hà micca cunnessu u ticker), avemu creatu cusì un graficu direttu, i nodi di quale sò esempi di a struttura. MSFilter, è i bordi sò esempi di ligami MSQueue.

Dietro l'attività di u ticker

Quandu vi dicu chì u ticker hè un filtru per a fonte di ticks, ùn era micca tutta a verità nantu à questu. Un ticker hè un oggettu chì esegue funzioni nantu à u clock prucessu () tutti i filtri di u circuitu (graficu) à quale hè cunnessu. Quandu avemu cunnessu un ticker à un filtru di graficu in un prugramma C, mustramu u ticker u graficu chì hà da cuntrullà da avà finu à chì l'avemu disattivatu. Dopu a cunnessione, u ticker principia à esaminà u graficu affidatu à a so cura, cumpilendu una lista di filtri chì includenu. Per ùn "cuntà" u listessu filtru duie volte, marca i filtri rilevati mettendu una casella di spunta in elli vistu. A ricerca hè realizata cù e tavule di ligame chì ogni filtru hà.

Durante a so visita introduttiva di u graficu, u ticker verifica se trà i filtri ci hè almenu unu chì agisce cum'è una fonte di blocchi di dati. Se ùn ci hè nimu, allura u graficu hè cunsideratu incorrectu è u ticker crashes.

Se u graficu hè "correttu", per ogni filtru truvatu, a funzione hè chjamata per l'inizializazione preprocessu (). Appena ghjuntu u mumentu per u prossimu ciclu di trasfurmazioni (ogni 10 millisecondi per difettu), u ticker chjama a funzione prucessu () per tutti i filtri di fonte truvati prima, è dopu per i filtri rimanenti in a lista. Se u filtru hà ligami di input, allora eseguisce a funzione prucessu () ripete finu à chì e file di ligami di input sò viote. Dopu questu, passa à u filtru prossimu in a lista è "scrolls" finu à chì i ligami di input sò liberi di missaghji. U ticker si move da filtru à filtru finu à a fine di a lista. Stu compie u prucessu di u ciclu.

Avà torneremu à tuples è parlemu perchè una tale entità hè stata aghjunta à u media streamer. In generale, a quantità di dati necessaria da l'algoritmu chì opera in u filtru ùn coincide micca è ùn hè micca un multiplu di a dimensione di i buffer di dati ricevuti à l'input. Per esempiu, scrivemu un filtru chì eseguisce una trasformazione di Fourier veloce, chì per definizione pò processà solu blocchi di dati chì a dimensione hè una putenza di dui. Chì sia 512 cunti. Se i dati sò generati da un canale telefuninu, u buffer di dati di ogni missaghju à l'input ci purterà 160 campioni di signali. Hè tentativu di ùn cullà dati da l'input finu à chì a quantità necessaria di dati hè quì. Ma in questu casu, una scontru hè accadutu cù u ticker, chì hà da pruvà senza successu à scroll u filtru finu à chì u ligame di input hè viotu. Prima, avemu designatu sta regula cum'è u terzu principiu di u filtru. Sicondu stu principiu, a funzione di prucessu di filtru () deve piglià tutte e dati da e file di input.

Inoltre, ùn serà micca pussibule di piglià solu 512 samples da l'input, postu chì pudete piglià solu blocchi sanu, i.e. u filtru duverà piglià 640 campioni è aduprà 512 di elli, u restu prima di accumulà una nova parte di dati. Cusì, u nostru filtru, in più di u so travagliu principale, deve furnisce l'azzioni ausiliarii per l'almacenamiento intermediu di dati di input. I sviluppatori di u media streamer è a suluzione à stu prublema generale anu sviluppatu un ughjettu speciale - MSBufferizer (bufferer), chì risolve stu prublema cù tuples.

Bufferizer (MSBufferizer)

Questu hè un ughjettu chì accumulerà dati di input in u filtru è cumincià à sottumettenu per u processu appena a quantità di informazioni hè abbastanza per eseguisce l'algoritmu di filtru. Mentre u buffer accumula dati, u filtru operarà in modu inattivu, senza aduprà a putenza di trasfurmazioni di u processatore. Ma appena a funzione di lettura da u bufferer torna un valore altru ch'è cero, a funzione di processu () di u filtru principia à piglià è processà e dati da u bufferer in porzioni di a dimensione necessaria, finu à chì hè esaurita.
I dati chì ùn sò ancu necessarii restanu in u buffer cum'è u primu elementu di a tupla, à quale i blocchi successivi di dati di input sò attaccati.

A struttura chì descrive u buffer:

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

Funzioni per travaglià cù MSBufferizer

Crià una nova istanza di buffer:

MSBufferizer * ms_bufferizer_new(void);

A memoria hè attribuita, inizializzata in ms_bufferizer_init() è un puntatore hè tornatu.

Funzione di inizializazione:

void ms_bufferizer_init(MSBufferizer *obj); 

A fila hè inizializzata q, campu grannizza hè pusatu à zero.

Aghjunghjendu un missaghju:

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

U messagiu m hè aghjuntu à a fila. A dimensione calculata di i blocchi di dati hè aghjuntu grannizza.

Trasferendu tutti i missaghji da a fila di dati di u ligame à u buffer q:

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

Trasferendu missaghji da un ligame q in u buffer hè realizatu cù a funzione ms_bufferizer_put().

Lettura da u buffer:

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

Se a dimensione di e dati accumulate in u buffer hè menu di quella dumandata (datalen), allura a funzione torna cero, i dati ùn sò micca copiati à dati. Altrimenti, a copia sequenziale di dati da tuples situati in u buffer hè realizatu. Dopu a copia, a tupla hè sguassata è a memoria hè liberata. A copia finisci in u mumentu quandu i bytes di dati sò copiati. Se u spaziu scorri in u mità di un bloccu di dati, allora in questu missaghju, u bloccu di dati serà ridutta à a parte restante senza copia. A prossima volta chì chjamate, a copia continuarà da questu puntu.

Leghje a quantità di dati chì hè attualmente dispunibule in u buffer:

int ms_bufferizer_get_avail(MSBufferizer *obj); 

Ritorna u campu grannizza bufferer.

Scartà una parte di e dati in u buffer:

void ms_bufferizer_skip_bytes(MSBufferizer *obj, int bytes);

U numaru specificatu di bytes di dati sò recuperati è scartati. I dati più antichi sò scartati.

Eliminazione di tutti i missaghji in u buffer:

void ms_bufferizer_flush(MSBufferizer *obj); 

U contatore di dati hè resettatu à zero.

Eliminazione di tutti i missaghji in u buffer:

void ms_bufferizer_uninit(MSBufferizer *obj); 

U contatore ùn hè micca resettatu.

Eliminazione di u buffer è liberazione di memoria:

void ms_bufferizer_destroy(MSBufferizer *obj);  

Esempii di usu di u bufferer ponu esse truvati in u codice fonte di parechji filtri media streamer. Per esempiu, in u filtru MS_L16_ENC, chì rearranges i bytes in i campioni da l'ordine di a reta à l'ordine di l'ospiti: l16.c

In u prossimu articulu, guardemu u prublema di stima di a carica nantu à un ticker è e manere di cummattiri a carica eccessiva di l'informatica in un streamer media.

Source: www.habr.com

Add a comment