RTP头C编程

RTP头C编程,c,rtp,C,Rtp,我创建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中

我创建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;

从理论上讲,这是可以的。

您必须至少显示您正在使用的声明,甚至可能显示执行实际发送的代码。RTP版本使用第一个字节的前2位进行编码。如果添加rtph说明,则可以给出答案。这可能只是一个字段顺序问题。我尝试了这个结构定义,但它在Windows上不起作用。要修复它,请将Bits字段类型修改为unsigned char!我希望它能帮助别人!谢谢大家!@IvanDubynets,谢谢你的评论,你是对的,int是4字节,我们需要1个用于CC,X,PT,version,1个用于PT和M。很抱歉给你带来不便,我想当时它对我起作用的原因是编译特定的标志,它将字节压缩在一起。