簡體   English   中英

RTP標頭C編程

[英]RTP Header C Programming

我創建UDP數據包(插入IP和UDP標頭)並通過UDP套接字發送。 我想向我創建的數據包中添加一個虛擬RTP標頭。 我創建了RTP結構並按如下所示插入RTP標頭:

rtph->cc = 4
rtph->x = 1
rtph->p = 1
rtph->version = 2
rtph->pt = 7
rtph->m = 1
rtph->seq = 0
rtph->ts = random()
rtph->ssrc = 0

當我捕捉到wireshasrk時,我得到了未知的RTP版本3。

任何幫助表示贊賞

如果在C中為RTP定義自己的結構,則必須考慮字節順序。

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

該結構必須為12個字節長,因此您需要強制編譯器將其打包為12個字節長的結構,而不要填充它。 我還要添加一個靜態斷言,以便在編譯時檢查結構是否真的長12個字節,因此:

#ifdef __WIN32__

#define PACKED
#pragma pack(push,1)

#else
#define PACKED __attribute__ ((__packed__))
#endif

//---------------------- STATIC ASSERT ----------------------------------
//Source: http://www.pixelbeat.org/programming/gcc/static_assert.html
#define ASSERT_CONCAT_(a, b) a##b
#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
/* These can't be used after statements in c89. */
#ifdef __COUNTER__
#define STATIC_ASSERT(e,m) \
    ;enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1/(!!(e)) }
#else
  /* This can't be used twice on the same line so ensure if using in headers
   * that the headers are not included twice (by wrapping in #ifndef...#endif)
   * Note it doesn't cause an issue when used on same line of separate modules
   * compiled with gcc -combine -fwhole-program.  */
#define STATIC_ASSERT(e,m) \
    ;enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) }
#endif

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

STATIC_ASSERT (sizeof (RTPHeader) == 12, "RTPHeader size doesn't seem to be cool.");

#ifdef __WIN32__
#pragma pack(pop)
#undef PACKED

#else
#undef PACKED
#endif

版本號必須為2,然后使用此結構寫入字節,如下所示:

char buffer[1400];
RTPHeader *rtph = (RTPHeader*) buffer;
rtph->version = 2;

從理論上講就可以了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM