Mediastreamer2 VoIP အင်ဂျင်ကို စူးစမ်းခြင်း။ အပိုင်း 11

ဆောင်းပါး၏ အကြောင်းအရာကို ကျွန်ုပ်ထံမှ ယူပါသည်။ zen ချန်နယ်.

Mediastreamer2 VoIP အင်ဂျင်ကို စူးစမ်းခြင်း။ အပိုင်း 11

ဒေတာလှုပ်ရှားမှုယန္တရား

  • ဒေတာပိတ်ဆို့ dblk_t
  • mblk_t သို့ မက်ဆေ့ချ်ပို့ပါ။
  • mblk_t မက်ဆေ့ချ်များနှင့် အလုပ်လုပ်ရန်အတွက် လုပ်ဆောင်ချက်များ
  • တန်းစီသည် queue_t
  • တန်းစီခြင်း queue_t ဖြင့် လုပ်ဆောင်ခြင်းအတွက် လုပ်ဆောင်ချက်များ
  • စစ်ထုတ်မှုများကို ချိတ်ဆက်ခြင်း။
  • ဒေတာလုပ်ဆောင်ခြင်းဂရပ်၏ အချက်ပြအမှတ်
  • ကြော်ငြာ၏ နောက်ကွယ်တွင် လှုပ်ရှားမှုများ
  • ကြားခံကိရိယာ (MSBufferizer)
  • MSBufferizer ဖြင့် လုပ်ဆောင်ရန် လုပ်ဆောင်ချက်များ

နောက်ဆုံး၌ ဆောင်းပါး ကျွန်ုပ်တို့သည် ကျွန်ုပ်တို့၏ကိုယ်ပိုင် filter ကိုတီထွင်ခဲ့သည်။ ဤဆောင်းပါးသည် media streamer filters များကြား ဒေတာများကို ရွှေ့ပြောင်းရန်အတွက် အတွင်းပိုင်းယန္တရားအပေါ် အာရုံစိုက်ပါမည်။ ၎င်းသည် သင့်အား အနာဂတ်တွင် အားစိုက်ထုတ်မှုနည်း၍ ခေတ်မီဆန်းပြားသော စစ်ထုတ်မှုများကို ရေးသားနိုင်စေမည်ဖြစ်သည်။

ဒေတာလှုပ်ရှားမှုယန္တရား

ဖွဲ့စည်းတည်ဆောက်ပုံအရ ဖော်ပြထားသော စီတန်းများကို အသုံးပြု၍ မီဒီယာထုတ်လွှင့်သူရှိ ဒေတာလှုပ်ရှားမှုကို လုပ်ဆောင်သည်။ တန်းစီသည်. စာတန်းတွေ ကြိုက်တယ်။ mblk_t၎င်းတို့တွင် အချက်ပြဒေတာမပါဝင်သော်လည်း ယခင်၊ နောက်မက်ဆေ့ဂျ်နှင့် ဒေတာဘလောက်ဆီသို့ လင့်ခ်များသာဖြစ်သည်။ ထို့အပြင်၊ သင်သည် တစ်ခုတည်းသော လင့်ခ်ချိတ်ထားသော မက်ဆေ့ချ်များစာရင်းကို စုစည်းနိုင်စေမည့် အမျိုးအစားတူ မက်ဆေ့ချ်တစ်ခုသို့ လင့်ခ်တစ်ခုလည်း ရှိကြောင်း အထူးအလေးပေး ပြောကြားလိုပါသည်။ ထိုသို့သောစာရင်းဖြင့် စုစည်းထားသော မက်ဆေ့ချ်အုပ်စုတစ်စုကို tuple ဟုခေါ်ဆိုပါမည်။ ထို့ကြောင့်၊ တန်းစီ၏ မည်သည့်ဒြပ်စင်မဆို မက်ဆေ့ချ်တစ်ခုတည်း ဖြစ်နိုင်သည်။ mblk_tနှင့် မက်ဆေ့ခ်ျတစ်ခု၏ ဦးခေါင်းဖြစ်နိုင်သည်။ mblk_t. tuple မက်ဆေ့ဂျ်တစ်ခုစီတွင် ၎င်း၏ကိုယ်ပိုင်ရပ်ကွက်ဒေတာပိတ်ဆို့နိုင်သည်။ Tuple တွေကို ဘာကြောင့် လိုအပ်သလဲ ဆိုတာ နည်းနည်းကြာမှ ဆွေးနွေးပါမယ်။

အထက်တွင်ဖော်ပြခဲ့သည့်အတိုင်း၊ မက်ဆေ့ချ်တွင် ဒေတာဘလောက်တစ်ခုမပါဝင်ပါ၊ ယင်းအစား ဘလောက်ကိုသိမ်းဆည်းထားသည့်မှတ်ဉာဏ်ဧရိယာသို့ ညွှန်ပြချက်တစ်ခုသာပါရှိသည်။ ဤအပိုင်းတွင်၊ မီဒီယာထုတ်လွှင့်သူ၏အလုပ်၏ ခြုံငုံရုပ်ပုံသည် အခန်းများ (ဒေတာ-အခန်းများဆီသို့ လင့်ခ်များ) မှ တံခါးများ (ဒေတာ-အခန်းများ) သို့ ရွေ့လျားနေသည့် ကာတွန်း “Monsters, Inc.” ရှိ တံခါးဂိုဒေါင်ကို အမှတ်ရနေသည်၊ မလှုပ်မယှက် ဖြစ်နေသည်။

ယခု၊ အောက်ခြေမှ အထက်မှ အထက်သို့ ရွေ့လျားပြီး၊ မီဒီယာ လွှင့်စက်ရှိ ဒေတာပို့လွှတ်မှု ယန္တရား၏ စာရင်းသွင်းထားသော အရာများကို အသေးစိတ် သုံးသပ်ကြည့်ကြပါစို့။

ဒေတာပိတ်ဆို့ dblk_t

ဒေတာဘလောက်တွင် ခေါင်းစီးတစ်ခုနှင့် ဒေတာကြားခံတစ်ခု ပါဝင်ပါသည်။ ခေါင်းစီးကို အောက်ပါဖွဲ့စည်းပုံဖြင့် ဖော်ပြသည်၊

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

ဖွဲ့စည်းပုံ၏ အကွက်များသည် ကြားခံ၏အစ၊ ကြားခံ၏အဆုံးနှင့် ဒေတာကြားခံကို ဖျက်ရန်အတွက် ညွှန်ပြချက်များပါရှိသည်။ ခေါင်းစီးရှိ နောက်ဆုံးအစိတ်အပိုင်း db_ref — ရည်ညွှန်းကောင်တာ၊ ၎င်းသည် သုညသို့ရောက်ရှိပါက၊ ၎င်းသည် ဤပိတ်ဆို့ခြင်းကို မှတ်ဉာဏ်မှဖျက်ပစ်ရန် အချက်ပြမှုတစ်ခုအဖြစ် လုပ်ဆောင်သည်။ အကယ်၍ function သည် data block ကိုဖန်တီးခဲ့သည်။ datab_alloc() ထို့နောက် header ပြီးနောက် ချက်ချင်း data buffer ကို memory တွင် ထားရှိပါမည်။ အခြားကိစ္စများတွင် ကြားခံအား သီးခြားတစ်နေရာ၌ ထားရှိနိုင်သည်။ ဒေတာကြားခံတွင် ကျွန်ုပ်တို့သည် စစ်ထုတ်မှုများဖြင့် လုပ်ဆောင်လိုသော အချက်ပြနမူနာများ သို့မဟုတ် အခြားဒေတာများ ပါဝင်မည်ဖြစ်သည်။

လုပ်ဆောင်ချက်ကို အသုံးပြု၍ ဒေတာပိတ်ဆို့ခြင်း၏ နမူနာအသစ်ကို ဖန်တီးသည်-

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 အစတွင် pointers များပါရှိသည်။ b_prev, b_နောက်တစ်ခုနှစ်ထပ်ချိတ်ဆက်ထားသောစာရင်းကို စုစည်းရန် လိုအပ်သော (တန်းစီတစ်ခုဖြစ်သည်။ တန်းစီသည်).

ပြီးရင် pointer လာမယ်။ b_contမက်ဆေ့ချ်သည် tuple ၏ အစိတ်အပိုင်းဖြစ်မှသာ အသုံးပြုသည်။ tuple ရှိ နောက်ဆုံးစာအတွက်၊ ဤညွှန်ပြချက်သည် null ဖြစ်နေဆဲဖြစ်သည်။

နောက်တစ်ခုကတော့ data block တစ်ခုဆီကို pointer တစ်ခုကိုတွေ့ရမှာပါ။ b_datapဟူသော သတင်းစကား တည်ရှိနေပါသည်။ ၎င်းကို block data buffer အတွင်းရှိ ဧရိယာသို့ ညွှန်ပြခြင်းဖြင့် နောက်တွင် လုပ်ဆောင်သည်။ လယ်ကွင်း b_rptr ကြားခံမှ ဒေတာကို ဖတ်မည့် တည်နေရာကို သတ်မှတ်သည်။ လယ်ကွင်း b_wptr ကြားခံလုပ်ဆောင်မည့်နေရာကို ညွှန်ပြသည်။

ကျန်အကွက်များသည် ဝန်ဆောင်မှုသဘောသဘာဝဖြစ်ပြီး ဒေတာလွှဲပြောင်းမှုယန္တရား၏ လုပ်ဆောင်မှုနှင့် မသက်ဆိုင်ပါ။

အောက်တွင် အမည်ပါသော မက်ဆေ့ချ်တစ်ခု ပါဝင်သည်။ m1 နှင့်ဒေတာပိတ်ဆို့ d1.
Mediastreamer2 VoIP အင်ဂျင်ကို စူးစမ်းခြင်း။ အပိုင်း 11
အောက်ပါပုံသည် မက်ဆေ့ချ်သုံးစောင်၏ tuple ကိုပြသည်။ 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*)); 

လုပ်ဆောင်ချက်သည် မက်ဆေ့ချ်နှင့် ဒေတာဘလောက်၏ ဖွဲ့စည်းပုံကို ဖန်တီးပြီးနောက်၊ ၎င်းသည် လိပ်စာရှိ ဒေတာထံသို့ ၎င်း၏ညွှန်ပြချက်များကို သတ်မှတ်ပေးမည်ဖြစ်သည်။ buff. အဲဒါတွေ။ ဤကိစ္စတွင်၊ လုပ်ဆောင်ချက်ဖြင့် ဒေတာဘလောက်တစ်ခုကို ဖန်တီးသောအခါတွင် ဖြစ်သကဲ့သို့ ဒေတာဘလောက်၏ ခေါင်းစီးအကွက်များနောက်တွင် ဒေတာကြားခံကို မတွေ့ပါ။ datab_alloc(). လုပ်ဆောင်ချက်သို့ ပေးပို့ထားသော ဒေတာပါရှိသော ကြားခံသည် ၎င်းသည် ၎င်း၏နေရာတွင် ရှိနေမည်ဖြစ်သော်လည်း ညွှန်ပြမှုများ၏အကူအညီဖြင့် ၎င်းသည် အသစ်ဖန်တီးထားသော ဒေတာဘလောက်၏ ခေါင်းစီးနှင့် ၎င်းကို မက်ဆေ့ချ်တွင် ချိတ်ဆက်ထားမည်ဖြစ်သည်။

မက်ဆေ့ခ်ျတစ်ခုသို့ mblk_t ဒေတာဘလောက်များစွာကို ဆက်တိုက်ပေါင်းစပ်နိုင်သည်။ ၎င်းကို function အားဖြင့်လုပ်ဆောင်သည်-

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

mp — အခြားဒေတာဘလောက်ကို ထပ်ထည့်မည့် မက်ဆေ့ချ်။
ဒေတာ — ဘလောက်ကိုညွှန်ပြပါ၊ မက်ဆေ့ချ်တွင်ထည့်မည့်မိတ္တူ၊
အရွယ် - ဒေတာအရွယ်အစား;
pad ပါ - ခွဲဝေသတ်မှတ်ထားသောမှတ်ဉာဏ်၏အရွယ်အစားသည် 4-byte နယ်နိမိတ်တစ်လျှောက် ချိန်ညှိရမည်ဖြစ်သည် (padding ကို သုညဖြင့်လုပ်ဆောင်မည်)။

ရှိပြီးသား မက်ဆေ့ဂျ်ဒေတာကြားခံတွင် နေရာအလုံအလောက်ရှိလျှင် ဒေတာအသစ်ကို ထိုနေရာရှိ ဒေတာနောက်ကွယ်တွင် ကူးထည့်မည်ဖြစ်သည်။ မက်ဆေ့ချ်တွင် နေရာလွတ်နည်းပါးပါက data buffer ထက် အရွယ်ထို့နောက် လုံလောက်သော ကြားခံအရွယ်အစားဖြင့် မက်ဆေ့ခ်ျအသစ်ကို ဖန်တီးပြီး ဒေတာကို ၎င်း၏ကြားခံသို့ ကူးယူပါသည်။ ဤသည်မှာ ညွှန်တံကို အသုံးပြု၍ မူရင်းစာနှင့် ချိတ်ဆက်ထားသော မက်ဆေ့ဂျ်အသစ်ဖြစ်သည်။ b_cont. ဤကိစ္စတွင်၊ မက်ဆေ့ချ်သည် tuple အဖြစ်ပြောင်းလဲသွားသည်။

tuple တွင် အခြားသော ဒေတာဘလောက်များကို ထည့်ရန် လိုအပ်ပါက၊ လုပ်ဆောင်ချက်ကို အသုံးပြုရန် လိုအပ်သည်-

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

သူမသည် tuple တွင်နောက်ဆုံးမက်ဆေ့ခ်ျကိုတွေ့လိမ့်မည် (သူ့တွင်ရှိသည်။ b_cont null ဖြစ်လိမ့်မည်) နှင့် ဤမက်ဆေ့ချ်အတွက် လုပ်ဆောင်ချက်ကို ခေါ်ပါမည်။ နောက်ဆက်တွဲ().

လုပ်ဆောင်ချက်ကို အသုံးပြု၍ မက်ဆေ့ခ်ျ သို့မဟုတ် tuple တွင် ဒေတာအရွယ်အစားကို သင်ရှာဖွေနိုင်သည်-

int msgdsize(const mblk_t *mp);

၎င်းသည် tuple ရှိ မက်ဆေ့ခ်ျအားလုံးကို လှည့်ပတ်ပြီး ထိုမက်ဆေ့ချ်များ၏ ဒေတာကြားခံအတွင်းရှိ ဒေတာစုစုပေါင်းပမာဏကို ပြန်ပေးမည်ဖြစ်သည်။ မက်ဆေ့ချ်တစ်ခုစီအတွက်၊ ဒေတာပမာဏကို အောက်ပါအတိုင်း တွက်ချက်သည်။

 mp->b_wptr - mp->b_rptr

tuple နှစ်ခုကို ပေါင်းစပ်ရန် လုပ်ဆောင်ချက်ကို အသုံးပြုပါ-

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

သူမသည် tuple ကိုထည့်သည်။ အသစ် tuple ၏အမြီးအထိ mp ရလဒ် tuple ၏ နောက်ဆုံးမက်ဆေ့ဂျ်သို့ ညွှန်ပြချက်ကို ပြန်ပေးသည်။

လိုအပ်ပါက tuple ကို data တစ်ခုတည်းဖြင့် မက်ဆေ့ချ်တစ်ခုအဖြစ်သို့ ပြောင်းလဲနိုင်သည်၊ ၎င်းကို လုပ်ဆောင်ချက်ဖြင့် လုပ်ဆောင်သည်-

void msgpullup(mblk_t *mp,int len);

အငြင်းအခုံဖြစ်လျှင် Len သည် -1 ဖြစ်ပြီး၊ ထို့နောက် ခွဲဝေပေးထားသော ကြားခံ၏ အရွယ်အစားကို အလိုအလျောက် ဆုံးဖြတ်သည်။ အကယ်လို့ Len အပေါင်းကိန်းဂဏန်းတစ်ခုဖြစ်ပြီး၊ ဤအရွယ်အစား၏ ကြားခံတစ်ခုကို ဖန်တီးမည်ဖြစ်ပြီး tuple မက်ဆေ့ခ်ျဒေတာကို ၎င်းထဲသို့ ကူးယူမည်ဖြစ်သည်။ ကြားခံကုန်သွားပါက ကူးယူခြင်းသည် ထိုနေရာတွင် ရပ်သွားပါမည်။ tuple ၏ပထမမက်ဆေ့ချ်သည် ကူးယူထားသောဒေတာနှင့်အတူ အရွယ်အစားကြားခံအသစ်တစ်ခုကို လက်ခံရရှိမည်ဖြစ်သည်။ ကျန်ရှိသော မက်ဆေ့ဂျ်များကို ဖျက်ပြီး မှတ်ဉာဏ်ကို အမှိုက်ပုံသို့ ပြန်သွားပါမည်။

ဖွဲ့စည်းပုံကို ဖျက်လိုက်တာ mblk_t ဖုန်းခေါ်ဆိုသောအခါတွင် data block ၏ရည်ညွှန်းအရေအတွက်ကိုထည့်သွင်းစဉ်းစားသည်။ freeb() သုညဖြစ်သွားသည်၊ ထို့နောက် data buffer ကို instance နှင့်အတူ ဖျက်လိုက်သည် mblk_tအဲဒါကို ထောက်ပြတယ်။

မက်ဆေ့ဂျ်အသစ်တစ်ခု၏ နယ်ပယ်များကို အစပြုနေသည်-

void mblk_init(mblk_t *mp);

မက်ဆေ့ဂျ်တွင် အခြားဒေတာအပိုင်းကို ထည့်နေသည်-

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

ဒေတာအသစ်သည် မက်ဆေ့ဂျ်ဒေတာကြားခံ၏ နေရာလွတ်တွင် မကိုက်ညီပါက၊ လိုအပ်သည့်အရွယ်အစား၏ ကြားခံတစ်ခုပါသည့် သီးခြားဖန်တီးထားသော စာတိုကို မက်ဆေ့ခ်ျတွင် တွဲပေးမည် (ထပ်ထည့်ထားသည့် မက်ဆေ့ချ်သို့ ညွှန်ပြချက်ကို ပထမမက်ဆေ့ချ်တွင် သတ်မှတ်ထားသည်) နှင့် မက်ဆေ့ချ်သည် tuple အဖြစ်ပြောင်းလဲသွားသည်။

ဒေတာအပိုင်းအစကို tuple တစ်ခုသို့ထည့်ခြင်း-

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

function သည် loop တစ်ခုတွင် appendb() ကိုခေါ်ဆိုသည်။

tuple နှစ်ခုကို တစ်ခုတည်းအဖြစ် ပေါင်းစပ်ခြင်း

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

မက်ဆေ့ခ်ျကို အသစ် တွဲထားမယ်။ mp.

မက်ဆေ့ချ်တစ်ခု၏ မိတ္တူတစ်ခုကို ပြုလုပ်ခြင်း-

mblk_t *copyb(const mblk_t *mp);

ဒေတာဘလောက်များအားလုံးဖြင့် tuple တစ်ခုအား အပြီးသတ်ကူးယူခြင်း-

mblk_t *copymsg(const mblk_t *mp);

tuple ၏ဒြပ်စင်များကို function မှကူးယူသည်။ copyb().

လွယ်ကူသောစာတစ်စောင်ကို ဖန်တီးပါ။ mblk_t. ဤကိစ္စတွင်၊ ဒေတာဘလောက်ကို ကူးယူခြင်းမပြုသော်လည်း ၎င်း၏ ကိုးကားမှုကောင်တာသည် တိုးလာသည်။ db_ref:

mblk_t *dupb(mblk_t *mp);

tuple ၏ပေါ့ပါးသောကော်ပီတစ်ခုပြုလုပ်ခြင်း။ ဒေတာဘလောက်များကို ကူးယူခြင်းမပြုပါ၊ ၎င်းတို့၏ ရည်ညွှန်းကောင်တာများကိုသာ တိုးမြှင့်ထားသည်။ db_ref:

mblk_t *dupmsg(mblk_t* m);

tuple တစ်ခု၏ မက်ဆေ့ချ်အားလုံးကို မက်ဆေ့ခ်ျတစ်ခုထဲသို့ ပေါင်းထည့်ပါ

void msgpullup(mblk_t *mp,size_t len);

အငြင်းအခုံဖြစ်လျှင် Len သည် -1 ဖြစ်ပြီး၊ ထို့နောက် ခွဲဝေပေးထားသော ကြားခံ၏ အရွယ်အစားကို အလိုအလျောက် ဆုံးဖြတ်သည်။

မက်ဆေ့ချ်ကို ဖျက်နေသည်၊ tuple-

void freemsg(mblk_t *mp);

ဒေတာဘလောက်၏ ရည်ညွှန်းကိန်းကို တစ်ခုပြီးတစ်ခု လျှော့ချသည်။ သုညသို့ရောက်လျှင် ဒေတာဘလောက်ကိုလည်း ဖျက်ပစ်သည်။

မက်ဆေ့ချ် သို့မဟုတ် tuple တစ်ခုရှိ ဒေတာစုစုပေါင်းပမာဏကို တွက်ချက်ခြင်း။

size_t msgdsize(const mblk_t *mp);

တန်းစီ၏အမြီးမှ မက်ဆေ့ချ်ကို ပြန်လည်ရယူနေသည်-

mblk_t *ms_queue_peek_last (q);

မက်ဆေ့ချ်တစ်ခု၏ သီးသန့်အကွက်များ၏ အကြောင်းအရာများကို အခြားမက်ဆေ့ဂျ်တစ်ခုသို့ ကူးယူခြင်း (တကယ်တော့၊ ဤအကွက်များတွင် မီဒီယာထုတ်လွှင့်သူမှ အသုံးပြုသည့် အလံများပါရှိသည်)

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

လှည့် တန်းစီသည်

မီဒီယာထုတ်လွှင့်သူရှိ မက်ဆေ့ချ်တန်းစီခြင်းကို စက်ဝိုင်းပုံနှစ်ထပ်ချိတ်ဆက်ထားသောစာရင်းအဖြစ် အကောင်အထည်ဖော်သည်။ စာရင်းဒြပ်စင်တစ်ခုစီတွင် အချက်ပြနမူနာများပါရှိသော ဒေတာဘလောက်ဆီသို့ ညွှန်ပြချက်တစ်ခုပါရှိသည်။ ဒေတာဘလောက်ကို ညွှန်ပြရုံမျှသာ အလှည့်အပြောင်းဖြစ်ပြီး ဒေတာကိုယ်တိုင်က မလှုပ်မယှက်ဖြစ်နေပါသည်။ အဲဒါတွေ။ ၎င်းတို့ထံသို့ လင့်ခ်များကိုသာ ရွှေ့ထားသည်။
တန်းစီခြင်းကို ဖော်ပြသည့် ဖွဲ့စည်းပုံ တန်းစီသည်, အောက်တွင်ဖော်ပြထားသော:

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

ဖွဲ့စည်းပုံတွင် အကွက်တစ်ခု - ညွှန်ပြချက်တစ်ခု ပါရှိသည်။ _q_ဆို့ *mblk_t ဟုရိုက်ပါ၊ ၎င်းသည် တန်းစီရှိ ပထမဒြပ်စင် (မက်ဆေ့ခ်ျ) ကိုညွှန်ပြသည်။ ဖွဲ့စည်းပုံ၏ ဒုတိယအကွက်သည် တန်းစီရှိ မက်ဆေ့ချ်များ၏ တန်ပြန်ဖြစ်သည်။
အောက်ပါပုံသည် m1၊ m4၊ m1၊ m2 မက်ဆေ့ဂျ် 3 စောင်ပါရှိသော q4 အမည်ရှိ တန်းစီတစ်ခုကို ပြသထားသည်။
Mediastreamer2 VoIP အင်ဂျင်ကို စူးစမ်းခြင်း။ အပိုင်း 11
အောက်ပါပုံသည် m1,m4,m1,m2 မက်ဆေ့ဂျ် 3 စောင်ပါရှိသော q4 အမည်ရှိ တန်းစီတစ်ခုကို ပြသထားသည်။ Message m2 သည် m2_1 နှင့် m2_2 နှစ်ခုပါရှိသော tuple တစ်ခု၏ ခေါင်းဖြစ်သည်။

Mediastreamer2 VoIP အင်ဂျင်ကို စူးစမ်းခြင်း။ အပိုင်း 11

တန်းစီခြင်း queue_t ဖြင့် လုပ်ဆောင်ခြင်းအတွက် လုပ်ဆောင်ချက်များ

တန်းစီအစပျိုးခြင်း-

void qinit(queue_t *q);

လယ်ယာ _q_ဆို့ (နောက်မှကျွန်ုပ်တို့၎င်းကို "stopper" ဟုခေါ်သည်) လုပ်ဆောင်ချက်ဖြင့်စတင်သည်။ mblk_init()၎င်း၏ယခင်ဒြပ်စင်နှင့် နောက်ဒြပ်စင်ညွှန်ပြချက်ကို သူ့ဘာသာသူညွှန်ပြရန် ချိန်ညှိထားသည်။ တန်းစီဒြပ်စင်ကောင်တာကို သုညသို့ ပြန်လည်သတ်မှတ်ထားသည်။

ဒြပ်စင်အသစ် (မက်ဆေ့ဂျ်များထည့်ခြင်း)

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

ဒြပ်စင်အသစ် m စာရင်း၏အဆုံးတွင် ထည့်သွင်းထားသည်၊ ဒြပ်စင်ညွှန်ပြမှုများကို ချိန်ညှိထားသောကြောင့် stopper သည် ၎င်းအတွက် နောက်ထပ်ဒြပ်စင်ဖြစ်လာပြီး ၎င်းသည် ဆို့ပါအတွက် ယခင်ဒြပ်စင်ဖြစ်လာမည်ဖြစ်သည်။ တန်းစီဒြပ်စင်ကောင်တာကို တိုးထားသည်။

တန်းစီမှ အစိတ်အပိုင်းတစ်ခုကို ပြန်လည်ရယူနေသည်-

mblk_t * getq(queue_t *q); 

ပိတ်စကို ပြန်ယူပြီးနောက် ထွက်ပေါ်လာသည့် မက်ဆေ့ဂျ်နှင့် ဒြပ်စင်ကောင်တာကို လျှော့ချထားသည်။ ဆို့ပါမှလွဲ၍ တန်းစီတွင် အစိတ်အပိုင်းများ မရှိပါက 0 ကို ပြန်ပေးသည်။

တန်းစီတစ်ခုထဲသို့ မက်ဆေ့ချ်ကို ထည့်သွင်းခြင်း-

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

ဓါတ် mp ဒြပ်စင်ရှေ့တွင်ထည့်သွင်းထားသည်။ ဝင်းနိုင်ထွန်း။ လျှင် ဝင်းနိုင်ထွန်း=0၊ ထို့နောက် စာကို တန်းစီ၏အမြီးတွင် ထည့်ထားသည်။

တန်းစီ၏ အကြီးအကဲထံမှ မက်ဆေ့ဂျ်ကို ပြန်လည်ရယူနေသည်-

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

ဒြပ်စင်တန်ပြန်ကို လျှော့ချထားသည်။

တန်းစီရှိ ပထမဒြပ်စင်ဆီသို့ ညွှန်ပြချက်ကို ဖတ်နေသည်-

mblk_t * peekq(queue_t *q); 

ဒြပ်စင်များကိုယ်တိုင်ဖျက်နေစဉ် တန်းစီမှ အစိတ်အပိုင်းအားလုံးကို ဖယ်ရှားခြင်း-

void flushq(queue_t *q, int how);

အငြင်းပွားမှု ဘယ်လို အသုံးမပြုပါ။ တန်းစီဒြပ်စင်ကောင်တာကို သုညဟု သတ်မှတ်ထားသည်။

တန်းစီ၏နောက်ဆုံးဒြပ်စင်ဆီသို့ ညွှန်ပြချက်ကိုဖတ်ရန်အတွက် Macro

mblk_t * qlast(queue_t *q);

မက်ဆေ့ချ်တန်းစီခြင်းများဖြင့် အလုပ်လုပ်သောအခါ၊ သင်ဖုန်းခေါ်သည့်အခါ သတိထားပါ။ ms_queue_put(q၊ m) မက်ဆေ့ချ်သို့ null pointer ဖြင့်၊ function သည် loops ဖြစ်သည်။ သင်၏ပရိုဂရမ်သည် အေးခဲသွားလိမ့်မည်။ အလားတူပြုမူသည်။ ms_queue_next(q၊ m).

စစ်ထုတ်မှုများကို ချိတ်ဆက်ခြင်း။

အထက်တွင်ဖော်ပြထားသော တန်းစီသည် မက်ဆေ့ဂျ်များကို စစ်ထုတ်မှုတစ်ခုမှ အခြားတစ်ခုသို့ သို့မဟုတ် တစ်ခုမှ စစ်ထုတ်မှုများစွာသို့ ပေးပို့ရန် အသုံးပြုသည်။ စစ်ထုတ်မှုများနှင့် ၎င်းတို့၏ချိတ်ဆက်မှုများသည် ညွှန်ကြားဂရပ်ပုံစံတစ်ခုဖြစ်သည်။ စစ်ထုတ်မှု၏ အဝင် သို့မဟုတ် အထွက်ကို ယေဘုယျစကားလုံး “ပင်” ဟုခေါ်သည်။ တစ်ခုနှင့်တစ်ခုချိတ်ဆက်ထားသည့် filter များကိုဖော်ပြရန်၊ media streamer သည် "signal point" ၏သဘောတရားကိုအသုံးပြုသည်။ အချက်ပြအချက်မှာ ဖွဲ့စည်းပုံဖြစ်သည်။ _MSCPPointစစ်ထုတ်ရန်အတွက် ညွှန်ပြချက်တစ်ခုနှင့် ၎င်း၏ပင်နံပါတ်တစ်ခု၏ နံပါတ်ပါ၀င်သည်၊ ထို့ကြောင့်၊ ၎င်းသည် filter ၏ input သို့မဟုတ် output တစ်ခု၏ ချိတ်ဆက်မှုကို ဖော်ပြသည်။

ဒေတာလုပ်ဆောင်ခြင်းဂရပ်၏ အချက်ပြအမှတ်

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

Filter pin များကို သုညမှစတင်၍ နံပါတ်တပ်ထားပါသည်။

မက်ဆေ့ချ်တစ်ခုဖြင့် ပင်တန်းနှစ်ခု၏ ချိတ်ဆက်မှုကို ဖွဲ့စည်းပုံဖြင့် ဖော်ပြသည်။ _MSQueueမက်ဆေ့ချ်တန်းစီခြင်းနှင့် ၎င်းနှင့်ချိတ်ဆက်ထားသည့် အချက်ပြအချက်နှစ်ခုဆီသို့ ညွှန်ပြချက်များပါရှိသော၊

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

ဤဖွဲ့စည်းပုံကို signal link ဟုခေါ်ပါမည်။ media streamer filter တစ်ခုစီတွင် input link ဇယားတစ်ခုနှင့် output link ဇယားတစ်ခုပါရှိသည် (MSQueue) စစ်ထုတ်မှုဖန်တီးရာတွင် ဇယားများ၏ အရွယ်အစားကို သတ်မှတ်ထားသည်၊ ကျွန်ုပ်တို့သည် အမျိုးအစား၏ ထုတ်ယူထားသော ပြောင်းလွဲပြောင်းကို အသုံးပြု၍ ၎င်းကို လုပ်ဆောင်ပြီးဖြစ်သည်။ MSFilterDescကျွန်ုပ်တို့၏ကိုယ်ပိုင် filter ကိုတီထွင်သောအခါ။ အောက်တွင်ဖော်ပြထားသောပုံစံသည် မီဒီယာထုတ်လွှင့်သူရှိ မည်သည့် filter ကိုမဆိုဖော်ပြသောဖွဲ့စည်းပုံဖြစ်သည်၊ 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 ပရိုဂရမ်ရှိ filters များကိုချိတ်ဆက်ပြီးနောက် (သို့သော် ticker ကိုမချိတ်ဆက်ခဲ့ပါ)၊ သို့ဖြင့် ကျွန်ုပ်တို့သည် directed graph တစ်ခု၊ တည်ဆောက်ပုံ၏ဥပမာများဖြစ်သည့် node များကိုဖန်တီးခဲ့ပါသည်။ MSFilterနှင့် edges များသည် လင့်ခ်များ၏ ဥပမာများဖြစ်သည်။ MSQueue.

ကြော်ငြာ၏ နောက်ကွယ်တွင် လှုပ်ရှားမှုများ

ticker သည် tick များ၏ရင်းမြစ်အတွက် filter တစ်ခုဖြစ်ကြောင်း သင့်အားပြောသောအခါ၊ ၎င်းနှင့်ပတ်သက်သည့် အလုံးစုံအမှန်တရားမဟုတ်ပေ။ ticker သည် နာရီပေါ်တွင် လုပ်ဆောင်နိုင်သော အရာတစ်ခုဖြစ်သည်။ လုပ်ငန်းစဉ်() ၎င်းနှင့်ချိတ်ဆက်ထားသည့် circuit (ဂရပ်) ၏ filter များအားလုံး။ ကျွန်ုပ်တို့သည် C ပရိုဂရမ်ရှိ ဂရပ်ဖစ်ဖစ်တစ်ခုနှင့် ချိတ်ဆက်သောအခါ၊ ကျွန်ုပ်တို့ ၎င်းကို မပိတ်မချင်း ၎င်းမှ ထိန်းချုပ်မည့် ဂရပ်ဖစ်ကို ပြသပေးပါသည်။ ချိတ်ဆက်ပြီးနောက်၊ ticker သည် ၎င်း၏စောင့်ရှောက်မှုအတွက် အပ်နှင်းထားသည့် ဂရပ်ကို စတင်စစ်ဆေးပြီး ၎င်းတွင်ပါဝင်သည့် စစ်ထုတ်မှုများစာရင်းကို ပြုစုပါ။ တူညီသောစစ်ထုတ်မှုကို နှစ်ကြိမ်ရေတွက်ခြင်းမပြုစေရန်၊ ၎င်းတို့တွင် အမှန်ခြစ်ဘောက်စ်တစ်ခုထည့်ခြင်းဖြင့် ရှာဖွေတွေ့ရှိထားသော စစ်ထုတ်မှုများကို အမှတ်အသားပြုပါသည်။ မြင်ကြ. စစ်ထုတ်မှုတစ်ခုစီပါရှိသော လင့်ခ်ဇယားများကို အသုံးပြု၍ ရှာဖွေမှုကို လုပ်ဆောင်သည်။

ဂရပ်၏ မိတ်ဆက်ခရီးစဉ်အတွင်း၊ ticker သည် ဒေတာပိတ်ဆို့ခြင်း၏ရင်းမြစ်အဖြစ် လုပ်ဆောင်သည့် စစ်ထုတ်မှုများတွင် အနည်းဆုံးတစ်ခုရှိမရှိ စစ်ဆေးပါသည်။ တစ်ခုမျှမရှိပါက၊ ဂရပ်ဖစ်သည် မှားယွင်းသည်ဟု ယူဆပြီး လက်မှတ်ပျက်သွားသည်။

ဂရပ်သည် “မှန်ကန်သည်” ဟု ပေါ်လာပါက၊ တွေ့ရှိသော filter တစ်ခုစီအတွက်၊ လုပ်ဆောင်ချက်ကို ကနဦးလုပ်ဆောင်ရန် ခေါ်သည်။ ကြိုတင်လုပ်ဆောင်မှု(). နောက်ထပ်လုပ်ဆောင်ခြင်းစက်ဝန်းအတွက် အခိုက်အတန့်ရောက်ရှိသည်နှင့်တပြိုင်နက် (ပုံမှန်အားဖြင့် 10 မီလီစက္ကန့်တိုင်း)၊ ticker သည် လုပ်ဆောင်ချက်ကို ခေါ်သည် လုပ်ငန်းစဉ်() ယခင်က တွေ့ရှိခဲ့သော အရင်းအမြစ် စစ်ထုတ်မှုများ အားလုံးအတွက်၊ ထို့နောက် စာရင်းရှိ ကျန်ရှိသော စစ်ထုတ်မှုများ အတွက်။ filter တွင် input link များရှိပါက function ကို run ပါ။ လုပ်ငန်းစဉ်() ထည့်သွင်းသည့်လင့်ခ်တန်းစီများ လွတ်သွားသည်အထိ ထပ်လုပ်ပါ။ ၎င်းပြီးနောက်၊ ၎င်းသည် စာရင်းရှိနောက် filter သို့ရွှေ့ပြီး ထည့်သွင်းသည့်လင့်ခ်များသည် မက်ဆေ့ချ်များမပါဝင်မချင်း ၎င်းကို "scroll" လုပ်ပါ။ လက်မှတ်သည် စာရင်းပြီးဆုံးသည်အထိ စစ်ထုတ်မှုမှ စစ်ထုတ်ရန် ရွှေ့သည်။ ၎င်းသည် စက်ဝန်း၏လုပ်ဆောင်မှုကို ပြီးမြောက်စေသည်။

ယခုကျွန်ုပ်တို့သည် tuples သို့ပြန်သွားကာ အဘယ်ကြောင့်ထိုကဲ့သို့သောအကြောင်းအရာကို မီဒီယာထုတ်လွှင့်သူထံထည့်သွင်းခဲ့သည်ကို ဆွေးနွေးပါမည်။ ယေဘုယျအားဖြင့်၊ စစ်ထုတ်မှုအတွင်း လုပ်ဆောင်နေသော algorithm မှ လိုအပ်သော ဒေတာပမာဏသည် တူညီမှုမရှိသည့်အပြင် ထည့်သွင်းမှုတွင် လက်ခံရရှိသည့် ဒေတာကြားခံပမာဏ၏ များပြားခြင်းမဟုတ်ပါ။ ဥပမာအားဖြင့်၊ ကျွန်ုပ်တို့သည် လျင်မြန်သော Fourier အသွင်ပြောင်းမှုကို လုပ်ဆောင်သည့် စစ်ထုတ်မှုတစ်ခုကို ရေးသားနေသည်၊ အဓိပ္ပါယ်အားဖြင့် အရွယ်အစားနှစ်ခုရှိသော ပါဝါရှိသော ဒေတာဘလောက်များကိုသာ လုပ်ဆောင်နိုင်သည်။ 512 အရေအတွက်ဖြစ်ပါစေ။ အကယ်၍ ဒေတာကို တယ်လီဖုန်းချန်နယ်တစ်ခုမှ ထုတ်ပေးပါက၊ ထည့်သွင်းမှုတွင် မက်ဆေ့ချ်တစ်ခုစီ၏ ဒေတာကြားခံသည် ကျွန်ုပ်တို့အား အချက်ပြနမူနာ ၁၆၀ ကို ယူဆောင်လာမည်ဖြစ်သည်။ ၎င်းသည် လိုအပ်သော ဒေတာပမာဏရှိသည်အထိ ထည့်သွင်းမှုမှ ဒေတာကို မစုဆောင်းရန် ဆွဲဆောင်နေသည်။ သို့သော် ဤကိစ္စတွင်၊ ထည့်သွင်းသည့်လင့်ခ်သည် ဗလာဖြစ်နေသည်အထိ စစ်ထုတ်မှုအား လှိမ့်ရန်ကြိုးစားသော်လည်း မအောင်မြင်ပါက ticker နှင့် တိုက်မိမည်ဖြစ်သည်။ ယခင်က ကျွန်ုပ်တို့သည် ဤစည်းမျဉ်းကို စစ်ထုတ်ခြင်း၏ တတိယနိယာမအဖြစ် သတ်မှတ်ခဲ့သည်။ ဤသဘောတရားအရ၊ filter ၏ process() function သည် input queues မှ data အားလုံးကိုယူရပါမည်။

ထို့အပြင်၊ သင်ထည့်သွင်းမှုမှနမူနာ 512 ကိုသာယူရန်မဖြစ်နိုင်ပါ၊ ဆိုလိုသည်မှာသင်တစ်တုံးလုံးကိုသာယူနိုင်သောကြောင့်၊ filter သည် နမူနာ 640 ကိုယူ၍ ၎င်းတို့ထဲမှ 512 ခုကိုအသုံးပြုရမည်ဖြစ်ပြီး၊ ကျန်ရှိသော data ၏အစိတ်အပိုင်းအသစ်ကိုမစုဆောင်းမီ။ ထို့ကြောင့်၊ ကျွန်ုပ်တို့၏ filter သည် ၎င်း၏အဓိကအလုပ်အပြင်၊ ထည့်သွင်းသည့်ဒေတာကို အလယ်အလတ်သိုလှောင်မှုအတွက် အရန်လုပ်ဆောင်ချက်များကို ပေးရပါမည်။ media streamer ၏ developer များသည် tuples ကိုအသုံးပြု၍ ဤပြဿနာကိုဖြေရှင်းပေးသည့် အထူး object - MSBufferizer (buffer) ကို တီထွင်ခဲ့ကြသည်။

ကြားခံကိရိယာ (MSBufferizer)

ဤအရာသည် စစ်ထုတ်မှုအတွင်း ထည့်သွင်းသည့်ဒေတာကို စုပြုံစေပြီး အချက်အလက်ပမာဏလုံလောက်သည်နှင့် စစ်ထုတ်မှု အယ်လဂိုရီသမ်ကို လုပ်ဆောင်ရန် လုံလောက်သည်နှင့် ၎င်းကို စတင်လုပ်ဆောင်ရန်အတွက် စတင်တင်ပြသည့် အရာတစ်ခုဖြစ်သည်။ ကြားခံသည် ဒေတာစုဆောင်းနေစဉ်၊ ပရိုဆက်ဆာ၏ လုပ်ဆောင်နိုင်စွမ်းကို အသုံးမပြုဘဲ၊ စစ်ထုတ်မှုသည် လှုပ်လှုပ်ရှားရှားမုဒ်တွင် လည်ပတ်မည်ဖြစ်သည်။ သို့သော် buffer မှဖတ်ရှုခြင်းလုပ်ဆောင်ချက်သည် သုညမှလွဲ၍ အခြားတန်ဖိုးတစ်ခုပြန်လာသည်နှင့်တပြိုင်နက်၊ filter ၏ process() function သည် လိုအပ်သည့်အရွယ်အစား၏အပိုင်းများတွင် buffer မှဒေတာများကိုရယူပြီး ကုန်ဆုံးသည်အထိလုပ်ဆောင်ပါသည်။
မလိုအပ်သေးသောဒေတာသည် tuple ၏ပထမဒြပ်စင်အဖြစ် buffer တွင်ကျန်ရှိနေပြီး၊ ၎င်းနောက်ဆက်တွဲထည့်သွင်းသည့်ဒေတာကိုထည့်သွင်းထားသည့်ပိတ်ဆို့ထားသည်။

ကြားခံကိုဖော်ပြသည့်ဖွဲ့စည်းပုံ-

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

MSBufferizer ဖြင့် လုပ်ဆောင်ရန် လုပ်ဆောင်ချက်များ

ကြားခံဥပမာအသစ်တစ်ခုကို ဖန်တီးနေသည်-

MSBufferizer * ms_bufferizer_new(void);

Memory ကို ခွဲဝေပေးသည်၊ တွင် အစပြုပါသည်။ 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 buffer တွင် function ကိုအသုံးပြုပြီးလုပ်ဆောင်သည်။ ms_bufferizer_put().

ကြားခံမှဖတ်ခြင်း-

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

ကြားခံတွင် စုဆောင်းထားသော ဒေတာအရွယ်အစားသည် တောင်းဆိုထားသည့်တစ်ခုထက် လျော့နည်းပါက (datalen) ထို့နောက် function သည် သုညသို့ပြန်သွားသည်၊ data သည် data သို့ကူးယူမည်မဟုတ်ပါ။ သို့မဟုတ်ပါက ကြားခံအတွင်းရှိ tuples များမှ ဒေတာများကို ဆက်တိုက်ကူးယူခြင်းကို လုပ်ဆောင်ပါသည်။ ကူးယူပြီးနောက်၊ tuple ကိုဖျက်ပြီး memory လွတ်သွားသည်။ datalen bytes များကို ကူးယူသောအခါတွင် ကူးယူခြင်း ပြီးဆုံးပါသည်။ ဒေတာဘလောက်တစ်ခု၏အလယ်တွင် နေရာလွတ်ကုန်သွားပါက၊ ဤမက်ဆေ့ချ်တွင်၊ ဒေတာဘလောက်ကို ကူးယူမထားသော ကျန်အပိုင်းသို့ လျှော့ချသွားမည်ဖြစ်သည်။ နောက်တစ်ကြိမ် ဖုန်းခေါ်သည့်အခါ၊ ကူးယူခြင်းကို ဤအချက်မှ ဆက်လက်လုပ်ဆောင်ပါမည်။

ကြားခံတွင် လက်ရှိရရှိနိုင်သော ဒေတာပမာဏကို ဖတ်ခြင်း-

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

ကောင်တာက reset မဟုတ်ဘူး။

ကြားခံကို ဖယ်ရှားခြင်းနှင့် မှတ်ဉာဏ်ကို ဖယ်ရှားခြင်း-

void ms_bufferizer_destroy(MSBufferizer *obj);  

ကြားခံအသုံးပြုခြင်း၏နမူနာများကို media streamer filter အများအပြား၏ source code တွင်တွေ့နိုင်ပါသည်။ ဥပမာအားဖြင့်၊ MS_L16_ENC စစ်ထုတ်မှုတွင်၊ နမူနာများတွင် ဘိုက်များကို ကွန်ရက်အစီအစဥ်မှ လက်ခံဆောင်ရွက်ပေးသည့် အစီအစဥ်အထိ ပြန်လည်စီစဉ်ပေးသော၊ l16.c

နောက်ဆောင်းပါးတွင်၊ ticker load estimation ပြဿနာနှင့် media streamer တွင် အလွန်အကျွံ တွက်ချက်ခြင်း load ကို မည်သို့ကိုင်တွယ်ရမည်ကို လေ့လာပါမည်။

source: www.habr.com

မှတ်ချက် Add