[英]RTP Header C Programming
I create UDP packets (insert IP and UDP headers) and send across the UDP socket. 我创建UDP数据包(插入IP和UDP标头)并通过UDP套接字发送。 I want to add a dummy RTP header to the packet that I create.
我想向我创建的数据包中添加一个虚拟RTP标头。 I created the RTP structure and inserting the RTP header as below:
我创建了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
When I capture in the wireshasrk I get Unknown RTP Version 3. 当我捕捉到wireshasrk时,我得到了未知的RTP版本3。
Any help is appreciated 任何帮助表示赞赏
If you define your own struct in C for RTP you must take the byte order into account. 如果在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
The struct must be 12 bytes long, so you need force the compiler to pack it into a 12bytes long struct and not padding it. 该结构必须为12个字节长,因此您需要强制编译器将其打包为12个字节长的结构,而不要填充它。 Also I would add a static assert to check at compile time weather the struct really 12 bytes long, so:
我还要添加一个静态断言,以便在编译时检查结构是否真的长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
The version number must be 2 and then if you write to the bytes with this struct, like this: 版本号必须为2,然后使用此结构写入字节,如下所示:
char buffer[1400];
RTPHeader *rtph = (RTPHeader*) buffer;
rtph->version = 2;
then theoretically it would be ok. 从理论上讲就可以了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.