د Mediastreamer2 VoIP انجن سپړنه. 11 برخه

د مقالې مواد زما څخه اخیستل شوي دي زین چینل.

د Mediastreamer2 VoIP انجن سپړنه. 11 برخه

د معلوماتو د حرکت میکانیزم

  • د ډاټا بلاک dblk_t
  • پیغام mblk_t
  • د پیغامونو سره د کار کولو لپاره دندې mblk_t
  • د قطار قطار_t
  • د queues queue_t سره د کار کولو لپاره دندې
  • د فلټرونو نښلول
  • د معلوماتو پروسس کولو ګراف سیګنال نقطه
  • د پردې تر شا د ټیکر فعالیتونه
  • بفریزر (MSBufferizer)
  • د MSBufferizer سره کار کولو لپاره دندې

په اخر کې مقالې موږ خپل فلټر جوړ کړی دی. دا مقاله به د میډیا سټیمر فلټرونو ترمینځ ډیټا حرکت کولو داخلي میکانیزم باندې تمرکز وکړي. دا به تاسو ته اجازه درکړي چې په راتلونکي کې د لږې هڅې سره پیچلي فلټرونه ولیکئ.

د معلوماتو د حرکت میکانیزم

د میډیا سټیمر کې د معلوماتو حرکت د جوړښت لخوا بیان شوي قطارونو په کارولو سره ترسره کیږي queue_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_base د معلوماتو ساحې پیل ته اشاره وکړه، او db_lim تر پایه. د لینک شمیره db_ref یو ته ټاکل شوی دی. د ډیټا روښانه فعالیت پوائنټر صفر ته ټاکل شوی.

پیغام 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_prev, b_بل، کوم چې د دوه ځله تړل شوي لیست تنظیم کولو لپاره اړین دي (کوم چې قطار دی queue_t).

بیا اشاره کوونکی راځي b_cont، کوم چې یوازې هغه وخت کارول کیږي کله چې پیغام د ټپل برخه وي. په ټیپل کې د وروستي پیغام لپاره، دا نښه پاتې ده.

بیا موږ د ډیټا بلاک ته اشاره کوو b_datapد کوم لپاره چې پیغام شتون لري. دا د بلاک ډیټا بفر دننه ساحې ته د اشارو لخوا تعقیب کیږي. ډګر b_rptr هغه ځای مشخص کوي چې د بفر څخه ډاټا به لوستل شي. ډګر b_wptr هغه ځای ته اشاره کوي چې له هغې څخه بفر ته لیکل کیږي.

پاتې برخې د خدمت طبیعت دي او د معلوماتو لیږد میکانیزم عملیاتو پورې اړه نلري.

لاندې د نوم سره یو واحد پیغام دی m1 او د معلوماتو بلاک d1.
د Mediastreamer2 VoIP انجن سپړنه. 11 برخه
لاندې انځور د دریو پیغامونو یوه برخه ښیي m1, m1_1, m1_2.
د Mediastreamer2 VoIP انجن سپړنه. 11 برخه

د پیغام رسولو دندې mblk_t

یو نوی پیغام mblk_t د فنکشن لخوا رامینځته شوی:

mblk_t *allocb(int size, int pri); 

هغه یو نوی پیغام په حافظه کې ځای په ځای کوي mblk_t د ټاکل شوي اندازې ډیټا بلاک سره اندازهدوهم دلیل - pri د کتابتون په دې نسخه کې نه کارول کیږي. دا باید صفر پاتې شي. د فنکشن د عملیاتو په جریان کې ، حافظه به د نوي پیغام جوړښت لپاره تخصیص شي او فنکشن به ورته ویل کیږي 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*)); 

فنکشن ، د پیغام رامینځته کولو وروسته او د ډیټا بلاک جوړښت به خپل پوائنټرونه په پته کې ډیټا ته تنظیم کړي بوف. هغوی. پدې حالت کې ، د ډیټا بفر د ډیټا بلاک د سرلیک ساحو وروسته موقعیت نلري ، لکه څنګه چې د فنکشن سره د ډیټا بلاک رامینځته کولو قضیه وه. datab_alloc(). فنکشن ته لیږدول شوي ډیټا سره بفر به هغه ځای پاتې شي چې دا و ، مګر د پوائنټرونو په مرسته به دا د ډیټا بلاک نوي رامینځته شوي سرلیک سره وصل شي ، او دا په وینا ، پیغام ته.

یو پیغام ته mblk_t د ډیټا ډیری بلاکونه په ترتیب سره یوځای کیدی شي. دا د فنکشن لخوا ترسره کیږي:

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

mp - یو پیغام چې بل ډیټا بلاک به اضافه شي؛
معلومات - بلاک ته اشاره کوونکی، یوه کاپي به په پیغام کې اضافه شي؛
اندازه - د معلوماتو اندازه؛
پیډ - یو بیرغ چې د تخصیص شوي حافظې اندازه باید د 4-بایټ سرحد سره سمون ولري (پډینګ به د صفر سره ترسره شي).

که چیرې د موجوده پیغام ډیټا بفر کې کافي ځای شتون ولري ، نو نوې ډیټا به د دمخه موجود ډیټا شاته پیسټ شي. که چیرې د پیغام ډیټا بفر کې لږ وړیا ځای شتون ولري په پرتله اندازه، بیا یو نوی پیغام د کافي بفر اندازې سره رامینځته کیږي او ډاټا د هغې بفر ته کاپي کیږي. دا یو نوی پیغام دی، چې د پوائنټر په کارولو سره د اصلي پیغام سره تړاو لري b_cont. په دې حالت کې، پیغام په ټوپل بدلیږي.

که تاسو اړتیا لرئ په ټپل کې د ډیټا بل بلاک اضافه کړئ ، نو تاسو اړتیا لرئ دا فنکشن وکاروئ:

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

هغه به په ټپل کې وروستی پیغام ومومي (هغه لري b_cont نول) او د دې پیغام لپاره به فنکشن ته زنګ ووهي ضمیمه ().

تاسو کولی شئ د فنکشن په کارولو سره په پیغام یا ټپل کې د ډیټا اندازه ومومئ:

int msgdsize(const mblk_t *mp);

دا به په ټپل کې د ټولو پیغامونو له لارې لوپ وکړي او د دې پیغامونو ډیټا بفرونو کې د ډیټا ټول مقدار بیرته راولي. د هر پیغام لپاره، د معلوماتو مقدار په لاندې ډول محاسبه کیږي:

 mp->b_wptr - mp->b_rptr

د دوه ټپلونو سره یوځای کولو لپاره، دا فنکشن وکاروئ:

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

هغې ټپل ضمیمه کړه newm د ټپل لکۍ ته mp او د پایله شوي ټپل وروستي پیغام ته یو پوائنټر بیرته راګرځوي.

که اړتیا وي، یو ټپل د ډیټا یو واحد بلاک سره په یو پیغام کې بدل کیدی شي؛ دا د فنکشن لخوا ترسره کیږي:

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); 

فنکشن په لوپ کې ضمیمه () غږوي.

دوه ټپلونه په یوه کې یوځای کول:

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

پیغام newm سره به وصل شي mp.

د یو پیغام یوه کاپي جوړول:

mblk_t *copyb(const mblk_t *mp);

د ټولو ډیټا بلاکونو سره د ټپل بشپړ کاپي کول:

mblk_t *copymsg(const mblk_t *mp);

د ټپل عناصر د فنکشن لخوا کاپي شوي کاپیب().

د پیغام یوه اسانه کاپي جوړه کړئ mblk_t. په دې حالت کې، د ډیټا بلاک کاپي شوی نه دی، مګر د حوالې کاونټر زیات شوی db_ref:

mblk_t *dupb(mblk_t *mp);

د ټوپل د سپک وزن کاپي جوړول. د ډیټا بلاکونه کاپي شوي ندي ، یوازې د دوی د حوالې شمیرې ډیریږي db_ref:

mblk_t *dupmsg(mblk_t* m);

د ټوپل ټول پیغامونه په یوه پیغام کې کښل:

void msgpullup(mblk_t *mp,size_t len);

که دلیل Len -1 دی، نو د تخصیص شوي بفر اندازه په اوتومات ډول ټاکل کیږي.

د پیغام ړنګول، ټپل:

void freemsg(mblk_t *mp);

د ډیټا بلاک د حوالې شمیره د یو لخوا کمیږي. که دا صفر ته ورسیږي، د ډیټا بلاک هم حذف کیږي.

په پیغام یا ټپل کې د ډیټا ټول مقدار محاسبه.

size_t msgdsize(const mblk_t *mp);

د قطار له پای څخه د پیغام ترلاسه کول:

mblk_t *ms_queue_peek_last (q);

د یو پیغام د خوندي برخو مینځپانګې بل پیغام ته کاپي کول (په حقیقت کې ، دا ساحې بیرغونه لري چې د میډیا سټیمر لخوا کارول کیږي):

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

کتار queue_t

د میډیا سټیمر کې د پیغام کتار د سرکلر دوه ځله تړل شوي لیست په توګه پلي کیږي. د لیست هر عنصر د سیګنال نمونو سره د ډیټا بلاک ته اشاره کوي. دا معلومه شوه چې یوازې د ډیټا بلاک ته اشارې په بدل کې حرکت کوي، پداسې حال کې چې ډاټا پخپله بې حرکته پاتې کیږي. هغوی. یوازې د دوی لینکونه لیږدول کیږي.
جوړښت چې د قطار تشریح کوي queue_t، لاندې ښودل شوی:

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

جوړښت یو ساحه لري - یو اشاره _q_Stopper ټایپ کړئ *mblk_t، دا په قطار کې لومړی عنصر (پیغام) ته اشاره کوي. د جوړښت دوهم ډګر په کتار کې د پیغامونو کاونټر دی.
لاندې انځور د q1 په نوم یو کتار ښیي چې 4 پیغامونه m1, m2, m3, m4 لري.
د Mediastreamer2 VoIP انجن سپړنه. 11 برخه
لاندې انځور د q1 په نوم یو کتار ښیي چې 4 پیغامونه m1,m2,m3,m4 لري. پیغام m2 د یو ټپل سر دی چې دوه نور پیغامونه m2_1 او m2_2 لري.

د Mediastreamer2 VoIP انجن سپړنه. 11 برخه

د queues queue_t سره د کار کولو لپاره دندې

د کتار پیل:

void qinit(queue_t *q);

ډګر _q_Stopper (له دې وروسته به موږ ورته "Stopper" ووایو) د فنکشن لخوا پیل کیږي 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) پیغام ته د نل پوائنټر سره، فنکشن لوپ کیږي. ستاسو برنامه به کنګل شي. ورته چلند کوي ms_queue_Next(q,m).

د فلټرونو نښلول

پورته بیان شوي قطار د یو فلټر څخه بل یا له یو څخه څو فلټرونو ته د پیغامونو لیږدولو لپاره کارول کیږي. فلټرونه او د دوی اړیکې یو لارښود ګراف جوړوي. د فلټر داخل یا محصول به د عمومي کلمې "پن" په نوم یادیږي. د دې ترتیب تشریح کولو لپاره چې فلټرونه یو له بل سره وصل دي ، د میډیا سټیمر د "سګنال نقطه" مفهوم کاروي. د سیګنال نقطه جوړښت دی _MSCPpoint، کوم چې د فلټر لپاره یو پوائنټر او د هغې د یو پن شمیره لري؛ په دې اساس ، دا د فلټر د یوې داخلې یا محصولاتو پیوستون بیانوي.

د معلوماتو پروسس کولو ګراف سیګنال نقطه

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

د فلټر پنونه شمیرل کیږي چې له صفر څخه پیل کیږي.

د پیغام کتار لخوا د دوه پنونو پیوستون د جوړښت لخوا تشریح شوی _MS کتار، کوم چې د پیغام کتار لري او دوه سیګنال پوائنټونو ته اشاره کوي چې دا وصل کوي:

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

موږ به دې جوړښت ته د سیګنال لینک ووایو. هر میډیا سټیمر فلټر د ان پټ لینکونو جدول او د محصول لینکونو جدول لري (MSQueue). د جدولونو اندازه ټاکل کیږي کله چې فلټر رامینځته کوي؛ موږ دمخه د ډول صادر شوي متغیر په کارولو سره دا کار کړی دی MSFilterDesc، کله چې موږ خپل فلټر جوړ کړو. لاندې یو جوړښت دی چې د میډیا سټیمر کې کوم فلټر تشریح کوي، 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;

وروسته له دې چې موږ د خپل پلان سره سم په C برنامه کې فلټرونه وصل کړل (مګر ټیکر یې وصل نه کړ)، موږ په دې توګه یو لارښود ګراف رامینځته کړ، کوم چې نوډونه د جوړښت مثالونه دي. MSFilter، او څنډې د لینکونو مثالونه دي MSQueue.

د پردې تر شا د ټیکر فعالیتونه

کله چې ما تاسو ته وویل چې ټیکر د ټیکونو سرچینې لپاره فلټر دی، دا د دې په اړه بشپړ حقیقت نه و. ټیکر یو څیز دی چې په ساعت کې فعالیت کوي پروسه() د سرکټ ټول فلټرونه (ګراف) چې ورسره وصل دی. کله چې موږ په C برنامه کې ټیکر د ګراف فلټر سره وصل کوو، موږ ټیکر هغه ګراف ښکاره کوو چې دا به له اوس څخه کنټرول کړي تر هغه چې موږ یې بند کړو. د نښلولو وروسته، ټیکر د هغه ګراف معاینه پیل کوي چې د هغې پاملرنې ته سپارل شوي، د فلټرونو لیست ترتیبوي چې پکې شامل دي. د دې لپاره چې ورته فلټر دوه ځله "شمېرل" نه شي، دا کشف شوي فلټرونه په دوی کې د چیک باکس په ځای کولو سره په نښه کوي ليدلي. لټون د لینک جدولونو په کارولو سره ترسره کیږي چې هر فلټر لري.

د ګراف د خپل ابتدايي سفر په جریان کې، ټیکر ګوري چې ایا د فلټرونو په مینځ کې لږترلږه یو شتون لري چې د ډیټا بلاکس سرچینې په توګه کار کوي. که چیرې هیڅ نه وي، نو ګراف غلط ګڼل کیږي او ټیکر خرابیږي.

که چیرې ګراف "درست" وګرځي، د هر موندل شوي فلټر لپاره، فنکشن د پیل کولو لپاره ویل کیږي. مخکې بهیر(). هرڅومره ژر چې شیبه د راتلونکي پروسس کولو دورې لپاره راشي (په ډیفالټ هر 10 ملی ثانیه) ، ټیکر فنکشن ته زنګ ووهي پروسه() د ټولو دمخه موندل شوي سرچینې فلټرونو لپاره، او بیا په لیست کې د پاتې فلټرونو لپاره. که چیرې فلټر د ننوتلو لینکونه ولري، نو بیا فعالیت چلوي پروسه() تکراروي تر هغه چې د ان پټ لینک کتارونه خالي نه وي. له دې وروسته، دا په لیست کې راتلونکي فلټر ته ځي او "سکرول" کوي تر هغه چې د ان پټ لینکونه د پیغامونو څخه خالي نه وي. ټیکر له فلټر څخه فلټر ته حرکت کوي تر هغه چې لیست پای ته ورسیږي. دا د دورې پروسس بشپړوي.

اوس به موږ ټیپلونو ته راستون شو او په دې اړه وغږیږو چې ولې دا ډول اداره د میډیا سټیمر کې اضافه شوې. په عموم کې ، د الګوریتم لخوا اړین ډیټا مقدار چې د فلټر دننه فعالیت کوي سره سمون نه لري او په ان پټ کې ترلاسه شوي ډیټا بفرونو اندازې څو چنده ندي. د مثال په توګه، موږ یو فلټر لیکو چې د ګړندي فویریر بدلون ترسره کوي، کوم چې د تعریف له مخې یوازې د ډیټا بلاکس پروسس کولی شي چې اندازه یې دوه ځواک وي. اجازه راکړئ چې دا 512 شمیرې وي. که چیرې ډاټا د تلیفون چینل لخوا رامینځته شي ، نو په ان پټ کې د هر پیغام ډیټا بفر به موږ ته د 160 سیګنال نمونې راوړي. دا په زړه پوري ده چې د ان پټ څخه ډاټا راټول نه کړئ تر هغه چې د ډیټا اړین مقدار شتون ولري. مګر پدې حالت کې ، ټکر به د ټیکر سره رامینځته شي ، کوم چې به په ناکامۍ سره د فلټر سکرول کولو هڅه وکړي تر هغه چې د ان پټ لینک خالي نه وي. مخکې، موږ دا قاعده د فلټر دریم اصول په توګه ټاکلې. د دې اصولو له مخې، د فلټر پروسې() فنکشن باید ټول معلومات د ان پټ کتارونو څخه واخلي.

سربیره پردې ، دا به امکان ونلري چې د ان پټ څخه یوازې 512 نمونې واخلئ ، ځکه چې تاسو کولی شئ یوازې ټول بلاکونه واخلئ ، د بیلګې په توګه. فلټر باید 640 نمونې واخلي او له دوی څخه 512 وکاروي، پاتې نور د معلوماتو نوې برخې راټولولو دمخه. په دې توګه، زموږ فلټر، د دې اصلي کار سربیره، باید د داخلي معلوماتو منځګړیتوب ذخیره کولو لپاره مرستندویه کړنې چمتو کړي. د میډیا سټیمر پراختیا کونکو او د دې عمومي ستونزې حل لپاره یو ځانګړی څیز رامینځته کړی - MSBufferizer (بفرر) ، کوم چې دا ستونزه د ټپلونو په کارولو سره حل کوي.

بفریزر (MSBufferizer)

دا یو څیز دی چې په فلټر کې دننه معلومات راټولوي او د پروسس لپاره یې سپارل پیل کړي کله چې د معلوماتو مقدار د فلټر الګوریتم چلولو لپاره کافي وي. پداسې حال کې چې بفر ډاټا راټولوي، فلټر به په غیر فعال حالت کې کار وکړي، پرته له دې چې د پروسیسر پروسس کولو ځواک کاروي. مګر هرڅومره ژر چې د بفرر څخه د لوستلو فعالیت د صفر پرته بل ارزښت بیرته راوباسي ، د فلټر پروسس () فعالیت د بفرر څخه د اړین اندازې برخو کې ډیټا اخیستل او پروسس کول پیل کوي ، تر هغه چې دا ختم نشي.
هغه معلومات چې تر اوسه ورته اړتیا نه وي په بفر کې د ټپل د لومړي عنصر په توګه پاتې کیږي، کوم چې د ان پټ ډیټا وروستي بلاکونه تړل کیږي.

هغه جوړښت چې بفر تشریح کوي:

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

د MSBufferizer سره کار کولو لپاره دندې

د نوي بفر مثال رامینځته کول:

MSBufferizer * ms_bufferizer_new(void);

حافظه تخصیص شوې، په پیل کې ms_buffeizer_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_buffeizer_put().

له بفر څخه لوستل:

int ms_bufferizer_read(MSBufferizer *obj, uint8_t *data, int 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

په راتلونکې مقاله کې ، موږ به د ټیکر بار اندازې مسلې ته وګورو او څنګه د میډیا سټیمر کې د ډیر کمپیوټري بار سره معامله وکړو.

سرچینه: www.habr.com

Add a comment