Mediastreamer2 VoIP இன்ஜினை ஆராய்கிறது. பகுதி 11

கட்டுரையின் பொருள் என்னுடையது ஜென் சேனல்.

Mediastreamer2 VoIP இன்ஜினை ஆராய்கிறது. பகுதி 11

தரவு இயக்க பொறிமுறை

  • தரவுத் தொகுதி dblk_t
  • செய்தி mblk_t
  • mblk_t செய்திகளுடன் பணிபுரிவதற்கான செயல்பாடுகள்
  • வரிசை வரிசை_t
  • வரிசைகள் queue_t உடன் பணிபுரிவதற்கான செயல்பாடுகள்
  • வடிப்பான்களை இணைக்கிறது
  • தரவு செயலாக்க வரைபடத்தின் சமிக்ஞை புள்ளி
  • திரைக்குப் பின்னால் டிக்கரின் செயல்பாடுகள்
  • இடையக (MSBufferizer)
  • MSBufferizer உடன் பணிபுரிவதற்கான செயல்பாடுகள்

கடந்த காலத்தில் கட்டுரை நாங்கள் எங்கள் சொந்த வடிகட்டியை உருவாக்கியுள்ளோம். மீடியா ஸ்ட்ரீமர் வடிப்பான்களுக்கு இடையில் தரவை நகர்த்துவதற்கான உள் பொறிமுறையில் இந்தக் கட்டுரை கவனம் செலுத்தும். எதிர்காலத்தில் குறைந்த முயற்சியில் அதிநவீன வடிப்பான்களை எழுத இது உங்களை அனுமதிக்கும்.

தரவு இயக்க பொறிமுறை

மீடியா ஸ்ட்ரீமரில் தரவு இயக்கம் கட்டமைப்பால் விவரிக்கப்பட்ட வரிசைகளைப் பயன்படுத்தி செய்யப்படுகிறது வரிசை_டி. போன்ற செய்திகளின் சரங்கள் mblk_t, அவையே சிக்னல் தரவைக் கொண்டிருக்கவில்லை, ஆனால் முந்தைய, அடுத்த செய்தி மற்றும் தரவுத் தொகுதிக்கான இணைப்புகள் மட்டுமே. கூடுதலாக, ஒரே மாதிரியான செய்திக்கான இணைப்புக்கான ஒரு புலமும் உள்ளது என்பதை நான் குறிப்பாக வலியுறுத்த விரும்புகிறேன், இது செய்திகளின் தனித்தனியாக இணைக்கப்பட்ட பட்டியலை ஒழுங்கமைக்க உங்களை அனுமதிக்கிறது. அத்தகைய பட்டியலினால் ஒன்றிணைக்கப்பட்ட செய்திகளின் குழுவை டூப்பிள் என்று அழைப்போம். எனவே, வரிசையின் எந்த உறுப்பும் ஒரு செய்தியாக இருக்கலாம் mblk_t, மற்றும் ஒருவேளை ஒரு செய்தி tuple இன் தலைவர் 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_அடுத்து, இரட்டிப்பாக இணைக்கப்பட்ட பட்டியலை ஒழுங்கமைக்க தேவையானவை (இது ஒரு வரிசை வரிசை_டி).

பின்னர் சுட்டி வருகிறது b_cont, செய்தி ஒரு டூபிளின் பகுதியாக இருக்கும்போது மட்டுமே பயன்படுத்தப்படும். டூபிளில் உள்ள கடைசி செய்திக்கு, இந்த சுட்டி பூஜ்யமாக உள்ளது.

அடுத்து தரவுத் தொகுதிக்கான சுட்டியைக் காண்போம் b_datap, அதற்கான செய்தி உள்ளது. அதைத் தொடர்ந்து பிளாக் டேட்டா பஃப்பருக்குள் இருக்கும் பகுதிக்கான சுட்டிகள். களம் b_rptr இடையகத்திலிருந்து தரவு படிக்கப்படும் இடத்தைக் குறிப்பிடுகிறது. களம் b_wptr இடையகத்திற்கு எழுதப்படும் இடத்தைக் குறிக்கிறது.

மீதமுள்ள புலங்கள் சேவை இயல்புடையவை மற்றும் தரவு பரிமாற்ற பொறிமுறையின் செயல்பாட்டுடன் தொடர்புடையவை அல்ல.

பெயருடன் ஒரு செய்தி கீழே உள்ளது m1 மற்றும் தரவு தொகுதி d1.
Mediastreamer2 VoIP இன்ஜினை ஆராய்கிறது. பகுதி 11
பின்வரும் படம் மூன்று செய்திகளைக் காட்டுகிறது m1, மீ1_1, மீ1_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 பூஜ்யமாக இருக்கும்) மேலும் இந்த செய்திக்கான செயல்பாட்டை அழைக்கும் appendb().

செயல்பாட்டைப் பயன்படுத்தி ஒரு செய்தி அல்லது டூபிளில் உள்ள தரவின் அளவைக் கண்டறியலாம்:

int msgdsize(const mblk_t *mp);

இது டூபிளில் உள்ள அனைத்து செய்திகளையும் லூப் செய்து, அந்த செய்திகளின் டேட்டா பஃபர்களில் உள்ள மொத்த டேட்டாவை திருப்பி அனுப்பும். ஒவ்வொரு செய்திக்கும், தரவின் அளவு பின்வருமாறு கணக்கிடப்படுகிறது:

 mp->b_wptr - mp->b_rptr

இரண்டு டூப்பிள்களை இணைக்க, செயல்பாட்டைப் பயன்படுத்தவும்:

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

அவள் துப்பியை இணைக்கிறாள் புதிய துப்பியின் வால் வரை mp இதன் விளைவாக வரும் டூபிளின் கடைசி செய்திக்கு ஒரு சுட்டியை வழங்குகிறது.

தேவைப்பட்டால், ஒரு ட்யூபிளை ஒரு ஒற்றைத் தரவுத் தொகுதியுடன் ஒரு செய்தியாக மாற்றலாம்; இது செயல்பாட்டால் செய்யப்படுகிறது:

void msgpullup(mblk_t *mp,int len);

வாதம் என்றால் லென் -1 ஆகும், பின்னர் ஒதுக்கப்பட்ட இடையகத்தின் அளவு தானாகவே தீர்மானிக்கப்படும். என்றால் லென் ஒரு நேர்மறை எண், இந்த அளவு ஒரு இடையக உருவாக்கப்படும் மற்றும் tuple செய்தி தரவு அதில் நகலெடுக்கப்படும். இடையகம் தீர்ந்துவிட்டால், நகலெடுப்பது அங்கேயே நின்றுவிடும். டூபிளின் முதல் செய்தி நகலெடுக்கப்பட்ட தரவுகளுடன் புதிய அளவு இடையகத்தைப் பெறும். மீதமுள்ள செய்திகள் நீக்கப்பட்டு, நினைவகம் குவியலுக்குத் திரும்பும்.

ஒரு கட்டமைப்பை நீக்கும் போது mblk_t அழைக்கும் போது தரவுத் தொகுதியின் குறிப்பு எண்ணிக்கை கணக்கில் எடுத்துக்கொள்ளப்படும் freeb() அது பூஜ்ஜியமாக மாறிவிடும், பின்னர் தரவு இடையகமானது நிகழ்வுடன் நீக்கப்படும் 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() ஐ ஒரு லூப்பில் அழைக்கிறது.

இரண்டு டூப்பிள்களை ஒன்றாக இணைத்தல்:

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

செய்தி புதிய இணைக்கப்படும் mp.

ஒரு செய்தியின் நகலை உருவாக்குதல்:

mblk_t *copyb(const mblk_t *mp);

அனைத்து தரவுத் தொகுதிகளுடன் ஒரு டுபிளை முழுமையாக நகலெடுக்கவும்:

mblk_t *copymsg(const mblk_t *mp);

டூபிளின் கூறுகள் செயல்பாட்டின் மூலம் நகலெடுக்கப்படுகின்றன copyb().

ஒரு செய்தியின் எளிதான நகலை உருவாக்கவும் 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);

வாதம் என்றால் லென் -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);

முறை வரிசை_டி

மீடியா ஸ்ட்ரீமரில் உள்ள செய்தி வரிசையானது வட்ட இரட்டை இணைக்கப்பட்ட பட்டியலாக செயல்படுத்தப்படுகிறது. ஒவ்வொரு பட்டியல் உறுப்பிலும் சிக்னல் மாதிரிகளுடன் தரவுத் தொகுதிக்கான சுட்டி உள்ளது. தரவுத் தொகுதிக்கான சுட்டிகள் மட்டுமே நகர்கின்றன, அதே நேரத்தில் தரவு அசைவில்லாமல் இருக்கும். அந்த. அவற்றுக்கான இணைப்புகள் மட்டுமே நகர்த்தப்படுகின்றன.
வரிசையை விவரிக்கும் அமைப்பு வரிசை_டி, கீழே காட்டப்பட்டுள்ளது:

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

கட்டமைப்பில் ஒரு புலம் உள்ளது - ஒரு சுட்டிக்காட்டி _q_stopper *mblk_t என தட்டச்சு செய்க, இது வரிசையில் உள்ள முதல் உறுப்பை (செய்தி) சுட்டிக்காட்டுகிறது. கட்டமைப்பின் இரண்டாவது புலம் வரிசையில் உள்ள செய்திகளின் கவுண்டர் ஆகும்.
கீழே உள்ள படம் q1 என்ற பெயரிடப்பட்ட வரிசையை காட்டுகிறது, இதில் m4, m1, m2, m3 ஆகிய 4 செய்திகள் உள்ளன.
Mediastreamer2 VoIP இன்ஜினை ஆராய்கிறது. பகுதி 11
m1,m4,m1,m2 ஆகிய 3 செய்திகளைக் கொண்ட q4 என்ற வரிசையை பின்வரும் படம் காட்டுகிறது. M2_2 மற்றும் m1_2 ஆகிய இரண்டு செய்திகளைக் கொண்ட tuple இன் தலைப்பகுதி செய்தி m2 ஆகும்.

Mediastreamer2 VoIP இன்ஜினை ஆராய்கிறது. பகுதி 11

வரிசைகள் queue_t உடன் பணிபுரிவதற்கான செயல்பாடுகள்

வரிசை துவக்கம்:

void qinit(queue_t *q);

துறையில் _q_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;

வடிகட்டி ஊசிகள் பூஜ்ஜியத்தில் இருந்து எண்ணப்படுகின்றன.

ஒரு செய்தி வரிசை மூலம் இரண்டு ஊசிகளின் இணைப்பு கட்டமைப்பால் விவரிக்கப்படுகிறது _எம்எஸ் வரிசை, இது இணைக்கும் இரண்டு சிக்னல் புள்ளிகளுக்கான செய்தி வரிசை மற்றும் சுட்டிகளைக் கொண்டுள்ளது:

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;

எங்கள் திட்டத்திற்கு ஏற்ப சி நிரலில் உள்ள வடிப்பான்களை இணைத்த பிறகு (ஆனால் டிக்கரை இணைக்கவில்லை), இதன் மூலம் இயக்கிய வரைபடத்தை உருவாக்கினோம், அதன் முனைகள் கட்டமைப்பின் நிகழ்வுகளாகும். MSFilter, மற்றும் விளிம்புகள் இணைப்புகளின் நிகழ்வுகள் MSQueue.

திரைக்குப் பின்னால் டிக்கரின் செயல்பாடுகள்

டிக்கர் என்பது உண்ணிகளின் மூலத்திற்கான வடிகட்டி என்று நான் உங்களிடம் சொன்னபோது, ​​​​அதில் முழு உண்மை இல்லை. டிக்கர் என்பது கடிகாரத்தில் செயல்படும் ஒரு பொருள் செயல்முறை () அது இணைக்கப்பட்டுள்ள சர்க்யூட்டின் (வரைபடம்) அனைத்து வடிப்பான்களும். ஒரு சி நிரலில் உள்ள வரைபட வடிப்பானுடன் ஒரு டிக்கரை இணைக்கும்போது, ​​அதை அணைக்கும் வரை அது கட்டுப்படுத்தும் வரைபடத்தை டிக்கருக்குக் காட்டுவோம். இணைத்த பிறகு, டிக்கர் அதன் பராமரிப்பில் ஒப்படைக்கப்பட்ட வரைபடத்தை ஆய்வு செய்யத் தொடங்குகிறது, அதில் உள்ள வடிப்பான்களின் பட்டியலைத் தொகுக்கிறது. ஒரே வடிப்பானை இரண்டு முறை "கணக்கிட" கூடாது என்பதற்காக, கண்டறியப்பட்ட வடிப்பான்களில் ஒரு தேர்வுப்பெட்டியை வைப்பதன் மூலம் அது குறிக்கும். பார்த்த. ஒவ்வொரு வடிப்பான் கொண்டிருக்கும் இணைப்பு அட்டவணைகளைப் பயன்படுத்தி தேடல் மேற்கொள்ளப்படுகிறது.

வரைபடத்தின் அறிமுகச் சுற்றுப்பயணத்தின் போது, ​​வடிகட்டிகளில் குறைந்தபட்சம் ஒன்று தரவுத் தொகுதிகளின் ஆதாரமாகச் செயல்படுகிறதா என்பதை டிக்கர் சரிபார்க்கிறது. எதுவும் இல்லை என்றால், வரைபடம் தவறாகக் கருதப்பட்டு, டிக்கர் செயலிழக்கும்.

வரைபடம் "சரியானது" என மாறிவிட்டால், ஒவ்வொரு கண்டுபிடிக்கப்பட்ட வடிகட்டிக்கும், செயல்பாடு துவக்கத்திற்கு அழைக்கப்படுகிறது முன்செயல்முறை(). அடுத்த செயலாக்க சுழற்சிக்கான தருணம் வந்தவுடன் (இயல்புநிலையாக ஒவ்வொரு 10 மில்லி விநாடிகளிலும்), டிக்கர் செயல்பாட்டை அழைக்கிறது செயல்முறை () முன்பு கண்டுபிடிக்கப்பட்ட அனைத்து மூல வடிப்பான்களுக்கும், பின்னர் பட்டியலில் உள்ள மீதமுள்ள வடிப்பான்களுக்கும். வடிகட்டியில் உள்ளீட்டு இணைப்புகள் இருந்தால், செயல்பாட்டை இயக்கவும் செயல்முறை () உள்ளீட்டு இணைப்பு வரிசைகள் காலியாகும் வரை மீண்டும் நிகழ்கிறது. இதற்குப் பிறகு, அது பட்டியலில் உள்ள அடுத்த வடிப்பானிற்குச் சென்று, உள்ளீட்டு இணைப்புகள் செய்திகள் இல்லாமல் இருக்கும் வரை அதை "ஸ்க்ரோல்" செய்கிறது. பட்டியல் முடியும் வரை டிக்கர் ஃபில்டரில் இருந்து ஃபில்டருக்கு நகரும். இது சுழற்சியின் செயலாக்கத்தை நிறைவு செய்கிறது.

இப்போது நாம் டூபிள்ஸுக்குத் திரும்பி, மீடியா ஸ்ட்ரீமரில் ஏன் அத்தகைய நிறுவனம் சேர்க்கப்பட்டது என்பதைப் பற்றி பேசுவோம். பொதுவாக, வடிகட்டியின் உள்ளே செயல்படும் அல்காரிதத்திற்குத் தேவையான தரவுகளின் அளவு ஒத்துப்போவதில்லை மற்றும் உள்ளீட்டில் பெறப்பட்ட தரவு இடையகங்களின் அளவின் பல மடங்கு அல்ல. எடுத்துக்காட்டாக, வேகமான ஃபோரியர் உருமாற்றத்தைச் செய்யும் ஒரு வடிப்பானை நாங்கள் எழுதுகிறோம், இது வரையறையின்படி இரண்டு சக்தி கொண்ட தரவுத் தொகுதிகளை மட்டுமே செயலாக்க முடியும். அது 512 எண்ணிக்கையாக இருக்கட்டும். ஒரு தொலைபேசி சேனலால் தரவு உருவாக்கப்பட்டால், உள்ளீட்டில் உள்ள ஒவ்வொரு செய்தியின் தரவு இடையகமும் நமக்கு 160 சமிக்ஞை மாதிரிகளைக் கொண்டு வரும். தேவையான அளவு தரவு இருக்கும் வரை உள்ளீட்டிலிருந்து தரவைச் சேகரிக்க வேண்டாம் என்று தூண்டுகிறது. ஆனால் இந்த வழக்கில், டிக்கருடன் மோதல் ஏற்படும், இது உள்ளீட்டு இணைப்பு காலியாகும் வரை வடிப்பானை உருட்ட முயற்சிக்கும். முன்னதாக, இந்த விதியை வடிகட்டியின் மூன்றாவது கொள்கையாக நாங்கள் நியமித்தோம். இந்தக் கொள்கையின்படி, வடிகட்டியின் செயல்முறை() செயல்பாடு உள்ளீட்டு வரிசைகளிலிருந்து எல்லா தரவையும் எடுக்க வேண்டும்.

கூடுதலாக, உள்ளீட்டிலிருந்து 512 மாதிரிகளை மட்டுமே எடுக்க முடியாது, ஏனெனில் நீங்கள் முழு தொகுதிகளை மட்டுமே எடுக்க முடியும், அதாவது. வடிகட்டி 640 மாதிரிகளை எடுத்து அவற்றில் 512 மாதிரிகளைப் பயன்படுத்த வேண்டும், மீதமுள்ளவை தரவுகளின் புதிய பகுதியைக் குவிக்கும் முன். எனவே, எங்கள் வடிகட்டி, அதன் முக்கிய பணிக்கு கூடுதலாக, உள்ளீட்டு தரவின் இடைநிலை சேமிப்பிற்கான துணை செயல்களை வழங்க வேண்டும். மீடியா ஸ்ட்ரீமரின் டெவலப்பர்கள் மற்றும் இந்த பொதுவான சிக்கலுக்கான தீர்வு ஒரு சிறப்பு பொருளை உருவாக்கியுள்ளனர் - MSBufferizer (bufferer), இது tuples ஐப் பயன்படுத்தி இந்த சிக்கலை தீர்க்கிறது.

இடையக (MSBufferizer)

இது ஒரு பொருளாகும், இது வடிப்பானுக்குள் உள்ளீட்டுத் தரவைக் குவித்து, வடிகட்டி அல்காரிதத்தை இயக்க போதுமான தகவலின் அளவு இருந்தால், செயலாக்கத்திற்குச் சமர்ப்பிக்கத் தொடங்கும். இடையகமானது தரவைக் குவிக்கும் போது, ​​செயலியின் செயலாக்க சக்தியைப் பயன்படுத்தாமல், செயலற்ற பயன்முறையில் வடிகட்டி இயங்கும். ஆனால் இடையகத்திலிருந்து படிக்கும் செயல்பாடு பூஜ்ஜியத்தைத் தவிர வேறு ஒரு மதிப்பை வழங்கியவுடன், வடிகட்டியின் செயல்முறை() செயல்பாடு, அது தீர்ந்து போகும் வரை, இடையகத்திலிருந்து தேவையான அளவுகளில் தரவை எடுத்து செயலாக்கத் தொடங்குகிறது.
இதுவரை தேவைப்படாத தரவு, டூப்பிளின் முதல் உறுப்பாக இடையகத்தில் உள்ளது, அதன் பின் உள்ளீட்டுத் தரவுத் தொகுதிகள் இணைக்கப்பட்டுள்ளன.

இடையகத்தை விவரிக்கும் கட்டமைப்பு:

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

பஃபரில் திரட்டப்பட்ட தரவின் அளவு கோரப்பட்டதை விட குறைவாக இருந்தால் (டேட்டாலென்), பின்னர் செயல்பாடு பூஜ்ஜியத்தைத் தரும், தரவு தரவுக்கு நகலெடுக்கப்படவில்லை. இல்லையெனில், பஃப்பரில் அமைந்துள்ள டூப்பிள்களில் இருந்து தரவை வரிசையாக நகலெடுப்பது செய்யப்படுகிறது. நகலெடுத்த பிறகு, டூப்பிள் நீக்கப்பட்டு நினைவகம் விடுவிக்கப்படும். டேட்டாலென் பைட்டுகள் நகலெடுக்கப்படும் தருணத்தில் நகலெடுப்பது முடிவடைகிறது. தரவுத் தொகுதியின் நடுவில் இடம் தீர்ந்தால், இந்தச் செய்தியில், தரவுத் தொகுதியானது நகலெடுக்கப்படாத மீதமுள்ள பகுதிக்குக் குறைக்கப்படும். அடுத்த முறை நீங்கள் அழைக்கும் போது, ​​இந்த இடத்தில் இருந்து நகலெடுப்பது தொடரும்.

இடையகத்தில் தற்போது கிடைக்கும் தரவின் அளவைப் படித்தல்:

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

கருத்தைச் சேர்