Mediastreamer2 VoIP ゚ンゞンを探玢したす。 パヌト11

蚘事の玠材は私のものから匕甚したした 犅チャンネル.

Mediastreamer2 VoIP ゚ンゞンを探玢したす。 パヌト11

デヌタ移動メカニズム

  • デヌタブロック dblk_t
  • メッセヌゞmblk_t
  • メッセヌゞを操䜜するための関数 mblk_t
  • キュヌ queue_t
  • キュヌを操䜜するための関数 queue_t
  • フィルタヌの接続
  • デヌタ凊理グラフの信号点
  • ティッカヌの舞台裏の掻動
  • バッファラむザヌ (MSBufferizer)
  • MSBufferizer を操䜜するための関数

過去に статье 独自のフィルタヌを開発したした。この蚘事では、メディア ストリヌマヌ フィルタヌ間でデヌタを移動するための内郚メカニズムに焊点を圓おたす。これにより、将来的には、より少ない劎力で高床なフィルタヌを䜜成できるようになりたす。

デヌタ移動メカニズム

メディア ストリヌマヌでのデヌタの移動は、次の構造で蚘述されたキュヌを䜿甚しお実行されたす。 キュヌ_t。のようなメッセヌゞの文字列 mblk_t、それ自䜓には信号デヌタは含たれおおらず、前、次のメッセヌゞ、およびデヌタ ブロックぞのリンクのみが含たれおいたす。さらに、同じタむプのメッセヌゞぞのリンク甚のフィヌルドもあり、単䞀リンクされたメッセヌゞのリストを敎理できるこずを特に匷調したいず思いたす。このようなリストでたずめられたメッセヌゞのグルヌプをタプルず呌びたす。したがっお、キュヌの任意の芁玠を単䞀のメッセヌゞにするこずができたす。 mblk_t、おそらくメッセヌゞタプルの先頭 mblk_t。各タプル メッセヌゞは独自のワヌド デヌタ ブロックを持぀こずができたす。なぜタプルが必芁なのかに぀いおは、埌ほど説明したす。

前述したように、メッセヌゞ自䜓にはデヌタのブロックは含たれおおらず、代わりに、ブロックが保存されおいるメモリ領域ぞのポむンタのみが含たれおいたす。この郚分では、メディア ストリヌマヌの仕事の党䜓像は、挫画「モンスタヌズ むンク」のドア倉庫を思い出させたす。ドア (デヌタぞのリンク - 郚屋) が頭䞊のコンベアに沿っお異垞な速床で移動する䞀方で、郚屋自䜓は動かないたたです。

次に、階局に沿っお䞋から䞊に移動しお、メディア ストリヌマヌ内のデヌタ送信メカニズムのリストされた゚ンティティを詳现に怜蚎しおみたしょう。

デヌタブロック dblk_t

デヌタブロックはヘッダヌずデヌタバッファヌで構成されたす。ヘッダヌは以䞋の構造で蚘述されたす。

typedef struct datab
{
unsigned char *db_base; // Указатель Ма МачалП буфер ЎаММых.
unsigned char *db_lim;  // Указатель Ма кПМец буфер ЎаММых.
void (*db_freefn)(void*); // ЀуМкцОя ПсвПбПжЎеМОя паЌятО прО уЎалеМОО блПка.
int db_ref; // СчетчОк ссылПк.
} dblk_t;

構造䜓のフィヌルドには、バッファの先頭、バッファの末尟、およびデヌタ バッファを削陀する関数ぞのポむンタが含たれおいたす。ヘッダヌの最埌の芁玠 db_ref — 参照カりンタ。れロに達するず、このブロックをメモリから削陀する信号ずしお機胜したす。デヌタブロックが関数によっお䜜成された堎合 datab_alloc() 、デヌタ バッファヌはヘッダヌの盎埌にメモリに配眮されたす。それ以倖の堎合はすべお、バッファヌは別の堎所に配眮できたす。デヌタ バッファヌには、フィルタヌで凊理する信号サンプルたたはその他のデヌタが含たれたす。

デヌタ ブロックの新しいむンスタンスは、次の関数を䜿甚しお䜜成されたす。

dblk_t *datab_alloc(int size);

入力パラメヌタずしお、ブロックが栌玍するデヌタのサむズが指定されたす。割り圓おられたメモリの先頭にヘッダヌ構造䜓を配眮するために、より倚くのメモリが割り圓おられたす。 デヌタベヌス。ただし、他の関数を䜿甚する堎合、これは垞に起こるわけではなく、堎合によっおは、デヌタ バッファヌがデヌタ ブロック ヘッダヌずは別に配眮される堎合がありたす。構造䜓を䜜成するずき、フィヌルドは、そのフィヌルドが デヌタベヌスベヌス デヌタ領域の先頭を指し、そしお db_lim その終わりたで。リンク数 db_ref は 1 に蚭定されたす。デヌタクリア関数ポむンタはれロに蚭定されたす。

メッセヌゞ mblk_t

前述したように、キュヌ芁玠のタむプは次のずおりです。 mblk_t、 それは次のように定矩されたす。

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;

構造 mblk_t 先頭にポむンタが含たれおいたす b_前, b_next、二重リンクリスト (キュヌ) を敎理するために必芁です。 キュヌ_t).

次にポむンタヌが来たす b_続き、メッセヌゞがタプルの䞀郚である堎合にのみ䜿甚されたす。タプル内の最埌のメッセヌゞでは、このポむンタは null のたたです。

次に、デヌタ ブロックぞのポむンタヌが衚瀺されたす。 b_datap、メッセヌゞが存圚したす。その埌に、ブロック デヌタ バッファヌ内の領域ぞのポむンタヌが続きたす。分野 b_rptr バッファからデヌタを読み取る堎所を指定したす。分野 b_wptr バッファぞの曞き蟌みが実行される堎所を瀺したす。

残りのフィヌルドはサヌビスの性質のものであり、デヌタ転送メカニズムの動䜜には関係したせん。

以䞋は名前を含む単䞀のメッセヌゞです m1 そしおデヌタブロック d1.
Mediastreamer2 VoIP ゚ンゞンを探玢したす。 パヌト11
次の図は、3 ぀のメッセヌゞのタプルを瀺しおいたす。 m1, m1_1, m1_2.
Mediastreamer2 VoIP ゚ンゞンを探玢したす。 パヌト11

メッセヌゞ機胜 mblk_t

新しいメッセヌゞ mblk_t 関数によっお䜜成されたした:

mblk_t *allocb(int size, int pri); 

圌女はメモリに新しいメッセヌゞを眮きたす mblk_t 指定されたサむズのデヌタ​​ ブロックを持぀ サむズ、第 2 匕数 - プリ このバヌゞョンのラむブラリでは䜿甚されたせん。れロのたたでなければなりたせん。関数の操䜜䞭に、新しいメッセヌゞの構造にメモリが割り圓おられ、関数が呌び出されたす。 mblk_init()これにより、䜜成された構造䜓のむンスタンスのすべおのフィヌルドがリセットされ、その埌、䞊蚘のメ゜ッドを䜿甚したす。 datab_alloc()、デヌタバッファを䜜成したす。その埌、構造内のフィヌルドが構成されたす。

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

出力では、初期化されたフィヌルドず空のデヌタ バッファヌを含む新しいメッセヌゞを受け取りたす。メッセヌゞにデヌタを远加するには、デヌタ ブロック バッファヌにデヌタをコピヌする必芁がありたす。

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

どこ デヌタ デヌタ゜ヌスぞのポむンタであり、 サむズ - そのサむズ。
次に、バッファ内の空き領域の先頭を再び指すように、曞き蟌みポむントぞのポむンタを曎新する必芁がありたす。

msg->b_wptr = msg->b_wptr + size

コピヌせずに既存のバッファからメッセヌゞを䜜成する必芁がある堎合は、次の関数を䜿甚したす。

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

この関数は、メッセヌゞずデヌタ ブロックの構造を䜜成した埌、次のアドレスのデヌタぞのポむンタヌを構成したす。 BUF。それらの。この堎合、関数を䜿甚しおデヌタ ブロックを䜜成した堎合ずは異なり、デヌタ バッファヌはデヌタ ブロックのヘッダヌ フィヌルドの埌に配眮されたせん。 datab_alloc()。関数に枡されたデヌタを含むバッファヌは元の堎所に残りたすが、ポむンタヌの助けを借りお、デヌタ ブロックの新しく䜜成されたヘッダヌに添付され、それに応じおメッセヌゞにも添付されたす。

䞀぀のメッセヌゞに mblk_t 耇数のデヌタ ブロックを連続しお連結できたす。これは次の関数によっお行われたす。

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

mp — 別のデヌタ ブロックが远加されるメッセヌゞ。
デヌタ — ブロックぞのポむンタ。そのコピヌがメッセヌゞに远加されたす。
サむズ — デヌタサむズ。
パッド — 割り圓おられたメモリのサむズが 4 バむト境界に沿っお敎列する必芁があるこずを瀺すフラグ (パディングはれロで行われたす)。

既存のメッセヌゞ デヌタ バッファヌに十分なスペヌスがある堎合は、新しいデヌタが既存のデヌタの埌ろに貌り付けられたす。メッセヌゞ デヌタ バッファヌの空き領域が少ない堎合は、 サむズ、その埌、十分なバッファ サむズで新しいメッセヌゞが䜜成され、デヌタがそのバッファにコピヌされたす。これは新しいメッセヌゞであり、ポむンタを䜿甚しお元のメッセヌゞにリンクされおいたす b_続き。この堎合、メッセヌゞはタプルに倉わりたす。

タプルに別のデヌタ ブロックを远加する必芁がある堎合は、次の関数を䜿甚する必芁がありたす。

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

圌女はタプル内の最埌のメッセヌゞを芋぀けたす (圌は b_続き null になりたす)、このメッセヌゞの関数を呌び出したす appendb().

次の関数を䜿甚しお、メッセヌゞたたはタプル内のデヌタのサむズを確認できたす。

int msgdsize(const mblk_t *mp);

タプル内のすべおのメッセヌゞをルヌプし、それらのメッセヌゞのデヌタ バッファヌ内のデヌタの総量を返したす。各メッセヌゞのデヌタ量は次のように蚈算されたす。

 mp->b_wptr - mp->b_rptr

2 ぀のタプルを結合するには、次の関数を䜿甚したす。

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

圌女はタプルを远加したす ニュヌム タプルの末尟たで mp そしお、結果のタプルの最埌のメッセヌゞぞのポむンタを返したす。

必芁に応じお、タプルを 1 ぀のデヌタ ブロックを含む 1 ぀のメッセヌゞに倉換できたす。これは次の関数によっお行われたす。

void msgpullup(mblk_t *mp,int len);

匕数の堎合 LEN が -1 の堎合、割り圓おられるバッファのサむズは自動的に決定されたす。もし LEN が正の数の堎合、このサむズのバッファが䜜成され、そこにタプル メッセヌゞ デヌタがコピヌされたす。バッファがなくなるず、コピヌはそこで停止したす。タプルの最初のメッセヌゞは、コピヌされたデヌタを含む新しいサむズのバッファヌを受け取りたす。残りのメッセヌゞは削陀され、メモリがヒヌプに戻されたす。

構造物を削陀する堎合 mblk_t 呌び出し時に、デヌタ ブロックの参照カりントが考慮される フリヌブ() れロであるこずが刀明した堎合、デヌタ バッファはむンスタンスずずもに削陀されたす。 mblk_t、それを指したす。

新しいメッセヌゞのフィヌルドを初期化したす。

void mblk_init(mblk_t *mp);

メッセヌゞに別のデヌタを远加したす。

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

新しいデヌタがメッセヌゞ デヌタ バッファの空き領域に収たらない堎合は、必芁なサむズのバッファを持぀別途䜜成されたメッセヌゞがメッセヌゞに添付されたす (远加されたメッセヌゞぞのポむンタが最初のメッセヌゞに蚭定されたす)。メッセヌゞはタプルに倉わりたす。

デヌタの䞀郚をタプルに远加したす。

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

この関数はルヌプ内で appendb() を呌び出したす。

2 ぀のタプルを 1 ぀に結合したす。

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

メッセヌゞ ニュヌム に付属したす mp.

単䞀メッセヌゞのコピヌを䜜成する:

mblk_t *copyb(const mblk_t *mp);

すべおのデヌタ ブロックを含むタプルのコピヌを完了したす。

mblk_t *copymsg(const mblk_t *mp);

タプルの芁玠は関数によっおコピヌされたす コピヌb().

メッセヌゞの簡単なコピヌを䜜成する mblk_t。この堎合、デヌタ ブロックはコピヌされたせんが、その参照カりンタヌは増加したす。 db_ref:

mblk_t *dupb(mblk_t *mp);

タプルの軜量コピヌを䜜成したす。デヌタ ブロックはコピヌされず、参照カりンタヌのみがむンクリメントされたす。 db_ref:

mblk_t *dupmsg(mblk_t* m);

タプルのすべおのメッセヌゞを 1 ぀のメッセヌゞに結合したす。

void msgpullup(mblk_t *mp,size_t len);

匕数の堎合 LEN が -1 の堎合、割り圓おられるバッファのサむズは自動的に決定されたす。

メッセヌゞの削陀、タプル:

void freemsg(mblk_t *mp);

デヌタ ブロックの参照カりントは 1 ぀枛りたす。れロになるず、デヌタ ブロックも削陀されたす。

メッセヌゞたたはタプル内のデヌタの合蚈量の蚈算。

size_t msgdsize(const mblk_t *mp);

キュヌの最埌尟からメッセヌゞを取埗したす。

mblk_t *ms_queue_peek_last (q);

あるメッセヌゞの予玄フィヌルドの内容を別のメッセヌゞにコピヌしたす (実際、これらのフィヌルドにはメディア ストリヌマヌによっお䜿甚されるフラグが含たれおいたす)。

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

埅ち行列 キュヌ_t

メディア ストリヌマのメッセヌゞ キュヌは、埪環二重リンク リストずしお実装されたす。各リスト芁玠には、信号サンプルを含むデヌタ ブロックぞのポむンタヌが含たれおいたす。デヌタ ブロックぞのポむンタだけが順番に移動し、デヌタ自䜓は動かないこずがわかりたす。それらの。それらぞのリンクのみが移動されたす。
キュヌを説明する構造 キュヌ_t、 䞋に瀺された

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

構造䜓にはフィヌルド、぀たりポむンタが含たれおいたす _q_ストッパヌ *mblk_t ず入力するず、キュヌ内の最初の芁玠 (メッセヌゞ) を指したす。この構造䜓の 2 番目のフィヌルドは、キュヌ内のメッセヌゞのカりンタヌです。
次の図は、1 ぀のメッセヌゞ m4、m1、m2、m3 を含む q4 ずいう名前のキュヌを瀺しおいたす。
Mediastreamer2 VoIP ゚ンゞンを探玢したす。 パヌト11
次の図は、1 ぀のメッセヌゞ m4、m1、m2、m3 を含む q4 ずいう名前のキュヌを瀺しおいたす。メッセヌゞ m2 は、さらに 2 ぀のメッセヌゞ m1_2 および m2_XNUMX を含むタプルの先頭です。

Mediastreamer2 VoIP ゚ンゞンを探玢したす。 パヌト11

キュヌを操䜜するための関数 queue_t

キュヌの初期化:

void qinit(queue_t *q);

フィヌルド _q_ストッパヌ (以䞋「ストッパヌ」ず呌びたす)は関数によっお初期化されたす mblk_init()、その前の芁玠ず次の芁玠のポむンタヌは、それ自䜓を指すように調敎されたす。キュヌ芁玠カりンタヌはれロにリセットされたす。

新しい芁玠 (メッセヌゞ) を远加したす。

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

新しい芁玠 m がリストの最埌に远加されるず、ストッパヌがその次の芁玠になり、ストッパヌが前の芁玠になるように芁玠ポむンタヌが調敎されたす。キュヌ芁玠カりンタヌがむンクリメントされたす。

キュヌから芁玠を取埗したす。

mblk_t * getq(queue_t *q); 

ストッパヌの埌に来るメッセヌゞが取埗され、芁玠カりンタヌがデクリメントされたす。キュヌにストッパヌ以倖の芁玠がない堎合は、0 が返されたす。

メッセヌゞをキュヌに挿入する:

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

芁玠 mp 芁玠の前に挿入される EMP。 もし EMP=0 の堎合、メッセヌゞはキュヌの最埌尟に远加されたす。

キュヌの先頭からメッセヌゞを取埗したす。

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

芁玠カりンタヌがデクリメントされたす。

キュヌ内の最初の芁玠ぞのポむンタヌを読み取りたす。

mblk_t * peekq(queue_t *q); 

芁玠自䜓を削陀しながら、キュヌからすべおの芁玠を削陀したす。

void flushq(queue_t *q, int how);

匕数 の 䜿甚されおいない。キュヌ芁玠カりンタヌはれロに蚭定されたす。

キュヌの最埌の芁玠ぞのポむンタヌを読み取るマクロ:

mblk_t * qlast(queue_t *q);

メッセヌゞ キュヌを操䜜するずきは、次の点に泚意しおください。 ms_queue_put(q, m) メッセヌゞぞの null ポむンタヌを䜿甚するず、関数はルヌプしたす。プログラムがフリヌズしおしたいたす。同様に動䜜したす ms_queue_next(q, m).

フィルタヌの接続

䞊で説明したキュヌは、あるフィルタヌから別のフィルタヌぞ、たたは 1 ぀から耇数のフィルタヌぞメッセヌゞを枡すために䜿甚されたす。フィルタヌずその接続は有向グラフを圢成したす。フィルタの入力たたは出力を総称しお「ピン」ず呌びたす。フィルタヌが互いに接続される順序を説明するために、メディア ストリヌマヌは「信号ポむント」の抂念を䜿甚したす。信号点は構造物です _MSCポむント、これにはフィルタヌぞのポむンタヌずそのピンの番号が含たれおおり、それに応じおフィルタヌの入力たたは出力の 1 ぀の接続を蚘述したす。

デヌタ凊理グラフの信号点

typedef struct _MSCPoint{
struct _MSFilter *filter; // Указатель Ма фОльтр ЌеЎОастрОЌера.
int pin;                        // НПЌер ПЎМПгП Оз вхПЎПв ОлО выхПЎПв фОльтра, т.е. пОМ.
} MSCPoint;

フィルタヌ ピンには 0 から始たる番号が付けられたす。

メッセヌゞキュヌによる 2 ぀のピンの接続は、次の構造で蚘述されたす。 _MSキュヌこれには、メッセヌゞ キュヌず、それが接続する 2 ぀の信号ポむントぞのポむンタが含たれおいたす。

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

この構造を信号リンクず呌びたす。各メディア ストリヌマ フィルタには、入力リンクのテヌブルず出力リンクのテヌブルが含たれおいたす (MSキュヌ。テヌブルのサむズはフィルタヌの䜜成時に蚭定されたす。これは、次のタむプの゚クスポヌトされた倉数を䜿甚しおすでに行っおいたす。 MSフィルタヌ蚘述、独自のフィルタヌを開発したずき。以䞋は、メディア ストリヌマヌ内のフィルタヌを蚘述する構造です。 MSフィルタヌ:


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;

蚈画に埓っお C プログラムでフィルタヌを接続した埌 (ティッカヌは接続したせんでした)、それによっお有向グラフを䜜成したした。そのノヌドは構造のむンスタンスです。 MSフィルタヌ、゚ッゞはリンクのむンスタンスです MSキュヌ.

ティッカヌの舞台裏の掻動

ティッカヌはダニの発生源をフィルタリングするものであるずお話したしたが、それはすべお真実ではありたせんでした。ティッカヌは、時蚈に応じお機胜を実行するオブゞェクトです 凊理する 接続されおいる回路 (グラフ) のすべおのフィルタヌ。 C プログラムでティッカヌをグラフ フィルタヌに接続するず、今埌オフにするたで制埡するグラフがティッカヌに衚瀺されたす。接続埌、ティッカヌは、管理を委蚗されたグラフの怜査を開始し、グラフを含むフィルタヌのリストを䜜成したす。同じフィルタヌを 2 回「カりント」しないように、怜出されたフィルタヌにチェックボックスを入れおマヌクしたす。 芋お。怜玢は各フィルタが持぀リンクテヌブルを利甚しお行われたす。

グラフの玹介ツアヌ䞭に、ティッカヌはフィルタヌの䞭にデヌタ ブロックの゜ヌスずしお機胜するものが少なくずも 1 ぀あるかどうかをチェックしたす。䜕もない堎合、グラフは正しくないずみなされ、ティッカヌがクラッシュしたす。

グラフが「正しい」ず刀明した堎合、芋぀かったフィルタヌごずに初期化のために関数が呌び出されたす。 前凊理()。次の凊理サむクルの瞬間が来るずすぐ (デフォルトでは 10 ミリ秒ごず)、ティッカヌは関数を呌び出したす。 凊理する 以前に芋぀かったすべおの゜ヌス フィルタヌに察しお、次にリスト内の残りのフィルタヌに察しお。フィルタヌに入力リンクがある堎合、関数を実行したす。 凊理する 入力リンク キュヌが空になるたで繰り返したす。この埌、リスト内の次のフィルタに移動し、入力リンクにメッセヌゞがなくなるたでフィルタを「スクロヌル」したす。ティッカヌは、リストが終了するたでフィルタヌからフィルタヌぞず移動したす。これでサむクルの凊理が完了したす。

ここでタプルに戻り、そのような゚ンティティがメディア ストリヌマヌに远加された理由に぀いお説明したす。䞀般に、フィルタヌ内で動䜜するアルゎリズムが必芁ずするデヌタの量は䞀臎せず、入力で受信されるデヌタ バッファヌのサむズの倍数ではありたせん。たずえば、高速フヌリ゚倉換を実行するフィルタヌを䜜成しおいたすが、定矩䞊、サむズが 512 のべき乗であるデヌタ ブロックのみを凊理できたす。 160カりントずしたしょう。デヌタが電話チャネルによっお生成された堎合、入力偎の各メッセヌゞのデヌタ バッファヌから XNUMX 個の信号サンプルが埗られたす。必芁な量のデヌタが存圚するたでは、入力からデヌタを収集しないように誘惑されたす。ただしこの堎合、ティッカヌずの衝突が発生し、入力リンクが空になるたでフィルタヌをスクロヌルしようずしおも倱敗したす。以前は、このルヌルをフィルタヌの XNUMX 番目の原則ずしお指定したした。この原則に埓っお、フィルタヌの process() 関数は入力キュヌからすべおのデヌタを取埗する必芁がありたす。

さらに、ブロック党䜓、぀たりブロック党䜓しか取埗できないため、入力から 512 個のサンプルのみを取埗するこずはできたせん。フィルタヌは 640 個のサンプルを取埗し、そのうちの 512 個を䜿甚し、デヌタの新しい郚分を蓄積する前に残りを䜿甚する必芁がありたす。したがっお、フィルタヌは、その䞻な機胜に加えお、入力デヌタの䞭間ストレヌゞのための補助アクションを提䟛する必芁がありたす。メディア ストリヌマずこの䞀般的な問題の解決策の開発者は、タプルを䜿甚しおこの問題を解決する特別なオブゞェクト MSBufferizer (バッファラヌ) を開発したした。

バッファラむザヌ (MSBufferizer)

これは、フィルタヌ内に入力デヌタを蓄積し、フィルタヌ アルゎリズムを実行するのに十分な情報量が埗られるずすぐに、凊理のためにデヌタの送信を開始するオブゞェクトです。バッファがデヌタを蓄積しおいる間、フィルタはプロセッサの凊理胜力を䜿い果たさずにアむドル モヌドで動䜜したす。ただし、バッファラヌからの読み取り関数がれロ以倖の倀を返すずすぐに、フィルタヌの process() 関数はバッファラヌから必芁なサむズのデヌタ​​を取埗し、デヌタが䜿い果たされるたで凊理を開始したす。
ただ必芁でないデヌタはタプルの最初の芁玠ずしおバッファ内に残り、入力デヌタの埌続のブロックがこの芁玠に添付されたす。

バッファを蚘述する構造䜓は次のずおりです。

struct _MSBufferizer{
queue_t q; /* ОчереЎь сППбщеМОй. */
int size; /* СуЌЌарМый разЌер ЎаММых МахПЎящОхся в буферОзатПре в ЎаММый ЌПЌеМт. */
};
typedef struct _MSBufferizer MSBufferizer;

MSBufferizer を操䜜するための関数

新しいバッファむンスタンスを䜜成したす。

MSBufferizer * ms_bufferizer_new(void);

メモリが割り圓おられ、初期化されたす ms_bufferizer_init() そしおポむンタが返されたす。

初期化関数:

void ms_bufferizer_init(MSBufferizer *obj); 

キュヌは初期化䞭です q、 分野 サむズ はれロに蚭定されたす。

メッセヌゞを远加する:

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

メッセヌゞ m がキュヌに远加されたす。蚈算されたデヌタ ブロックのサむズが远加されたす。 サむズ.

すべおのメッセヌゞをリンク デヌタ キュヌからバッファに転送する q:

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

リンクからメッセヌゞを転送する q バッファ内の凊理は関数を䜿甚しお実行されたす ms_bufferizer_put().

バッファからの読み取り:

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

バッファに蓄積されたデヌタのサむズが芁求されたサむズより小さい堎合 (デヌタレン)、関数はれロを返し、デヌタはデヌタにコピヌされたせん。それ以倖の堎合は、バッファ内にあるタプルからのデヌタの順次コピヌが実行されたす。コピヌ埌、タプルは削陀され、メモリが解攟されたす。 datalen バむトがコピヌされた時点でコピヌは終了したす。デヌタ ブロックの途䞭でスペヌスが足りなくなった堎合、このメッセヌゞでは、デヌタ ブロックはコピヌされおいない残りの郚分に枛らされたす。次回電話をかけるずきは、この時点からコピヌが続行されたす。

珟圚バッファ内で利甚可胜なデヌタ量を読み取る:

int ms_bufferizer_get_avail(MSBufferizer *obj); 

フィヌルドを返したす サむズ バッファラヌ。

バッファ内のデヌタの䞀郚を砎棄したす。

void ms_bufferizer_skip_bytes(MSBufferizer *obj, int bytes);

指定されたバむト数のデヌタが取埗され、砎棄されたす。最も叀いデヌタは砎棄されたす。

バッファ内のすべおのメッセヌゞを削陀したす。

void ms_bufferizer_flush(MSBufferizer *obj); 

デヌタカりンタヌはれロにリセットされたす。

バッファ内のすべおのメッセヌゞを削陀したす。

void ms_bufferizer_uninit(MSBufferizer *obj); 

カりンタはリセットされたせん。

バッファを削陀しおメモリを解攟したす。

void ms_bufferizer_destroy(MSBufferizer *obj);  

バッファラヌの䜿甚䟋は、いく぀かのメディア ストリヌマヌ フィルタヌの゜ヌス コヌドにありたす。たずえば、MS_L16_ENC フィルタヌでは、サンプル内のバむトをネットワヌク順からホスト順に再配眮したす。 l16.c

次の蚘事では、ティッカヌの負荷を芋積もる問題ず、メディア ストリヌマヌの過床のコンピュヌティング負荷に察凊する方法に぀いお説明したす。

出所 habr.com

DDoS 保護機胜を備えた信頌性の高いサむト甚ホスティング、VPS VDS サヌバヌを賌入する 🔥 DDoS攻撃察策付きの信頌性の高いりェブサむトホスティング、VPS/VDSサヌバヌを賌入したしょう | ProHoster