Извлечение последовательности RTP

Пакет RTP состоит из 12-байтового заголовка RTP и последующей полезной нагрузки RTP. 3-й и 4-й байты заголовка содержат старший и младший значащие байты порядкового номера пакета RTP Seq Num= (MSB‹ ‹8)+младший разряд

char pszPacket[12];

...

длинный lSeq = ???? - Как получить порядковый номер из пакета?


person SEA    schedule 16.07.2009    source источник


Ответы (5)


unsigned short seq = (packet[2] << 8) | packet[3];

Обратите внимание, что это предполагает, что packet является массивом unsigned char.

person unwind    schedule 16.07.2009
comment
unsigned short — правильный тип для 'seq', а не (signed) long. «char» и «unsigned char» не имеют значения для этого набора операций (‹‹ и |), хотя заголовок RTP должен быть массивом байтов без знака. - person jesup; 17.09.2009
comment
В системах, где char имеет знак, вы получите неверный результат, когда packet[3] будет отрицательным (поскольку он будет расширен по знаку до int перед использованием в качестве RHS для |). - person Toby Speight; 16.09.2019

Конечно, это просто «long lSeq = (unsigned char)(pszPacket[2] ‹‹ 8) | (unsigned char)pszPacket[3];»?

person Goz    schedule 16.07.2009
comment
Кроме того, pszPacket также должен быть беззнаковым char[], а не простым char[]. - person AProgrammer; 16.07.2009
comment
Благодарю вас! может быть небольшое исправление в скобках: long lSeq = ((unsigned char)pszPacket[2] ‹‹ 8) | (беззнаковый символ)pszPacket[3]; - person SEA; 17.07.2009
comment
на самом деле не имеет значения, в какую сторону .. но да, если вы предпочитаете делать это так :) - person Goz; 17.07.2009

Если вам нужна правильная реализация для этого:

typedef struct _RTPHeader
{
  //first byte
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
  unsigned int         CC:4;        /* CC field */
  unsigned int         X:1;         /* X field */
  unsigned int         P:1;         /* padding flag */
  unsigned int         version:2;
#elif G_BYTE_ORDER == G_BIG_ENDIAN
  unsigned int         version:2;
  unsigned int         P:1;         /* padding flag */
  unsigned int         X:1;         /* X field */
  unsigned int         CC:4;        /* CC field*/
#else
#error "G_BYTE_ORDER should be big or little endian."
#endif
  //second byte
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
  unsigned int         PT:7;     /* PT field */
  unsigned int         M:1;       /* M field */
#elif G_BYTE_ORDER == G_BIG_ENDIAN
  unsigned int         M:1;         /* M field */
  unsigned int         PT:7;       /* PT field */
#else
#error "G_BYTE_ORDER should be big or little endian."
#endif
  guint16              seq_num;      /* length of the recovery */
  guint32              TS;                   /* Timestamp */
  guint32              ssrc;
} RTPHeader; //12 bytes

И что вы можете сделать, это:

char pszPacket[12];
RTPHeader* myRTPPacket = (RTPHeader*) pszPacket;
printf("Sequence number is: %hu", myRTPPacket->seq_num;
person Balázs Kreith    schedule 18.02.2019

Предполагая, что у нас есть указатель на буфер байтов, который содержит весь пакет RTP (включая заголовок RTP), называемый rtpBuffer, мы можем извлечь 16-битное слово в позиции 2 и 3 с помощью следующего кода:

int8_t *rtpBuffer;

uint16_t packetSeqNbr = ntohs(*(reinterpret_cast<uint16_t *>(rtpBuffer + 2)));

ntohs() используется для преобразования сетевого порядка байтов в порядок байтов хоста, чтобы код был переносимым на разные машины.

person DarkJediNinja    schedule 14.10.2019

person    schedule
comment
Это полностью зависит от порядка байтов хоста - если запустить в системе с прямым порядком байтов, вы получите неправильный результат. - person Toby Speight; 16.09.2019
comment
Заголовок Rtp всегда записывается в порядке байтов с обратным порядком байтов, как описано в [RFC 3550 — RTP: транспортный протокол для приложений реального времени] (tools.ietf.org/html/rfc3550). - person rooltex; 18.09.2019
comment
Именно так, поэтому вам нужно преобразовать результат, используя ntohs(). - person Toby Speight; 18.09.2019
comment
unsigned __int16 seq = _rotr16((unsigned __int16)&packet[2], 8) — делает то же самое. - person rooltex; 19.09.2019
comment
Предполагая, что _rotr16() является встроенным компилятором Microsoft, он (а) не переносим и (б) делает совершенно не то, что нужно на хостах с обратным порядком байтов. - person Toby Speight; 19.09.2019