RTP包的头构成为:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|X| CC |M| PT | sequence number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| synchronization source (SSRC) identifier |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
| contributing source (CSRC) identifiers |
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
通过wireshark解析的形式:
在C/C++中,对包的头信息解析的方法为,定义一个结构体:
struct RTP_Header
{
unsigned __int16 csrc_count:4;
unsigned __int16 extension:1;
unsigned __int16 padding:1;
unsigned __int16 version:2;
unsigned __int16 payloadtype:7;
unsigned __int16 marker:1;
unsigned __int16 seq;
unsigned __int32 timestamp;
unsigned __int32 ssrc;
};
结构体中,冒号后面数字为实际占的位数,注意8位字节的内部,网络序与本地序是相反的,csrc_count在第1字节的后4位,而在结构体声明中,csrc_count需要在前4位,应用的方法,以序列号的获取为例:
int RTPProcessor::getSequenceNumber(PacketBuffer* packet)
{
RTP_Header* pHeader = (RTP_Header*)packet->data;
return ntohs(pHeader->seq);
}
其中packet->data为recv的udp的原始包,通过RTP_Header的强制类型转换,即可直接通过pHeader->seq获取,这里需要网络序转换成字节序,调用ntohs的函数,同理,对序列号的修改如下:
void RTPProcessor::setSequenceNumber(PacketBuffer* packet)
{
RTP_Header* pHeader = (RTP_Header*)packet->data;
pHeader->seq= htons(m_sequenceNumer);
}
对于RTCP,方法与RTP相似,RTCP的包的头信息为:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P| CC | PT | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| synchronization source (SSRC) identifier |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
| source or chunk |
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
RTCP的包的头信息与RTP有点不同,wireshark的解析为:
在C/C++中,对包的头信息解析的方法为,定义一个结构体:
struct RTCP_Header
{
unsigned __int16 csrc_count:5;
unsigned __int16 padding:1;
unsigned __int16 version:2; //1 char
unsigned __int16 payloadtype:8; //2 char
unsigned __int16 length; //3,4 char
unsigned __int32 ssrc; //5,6,7,8 char
};
应用的方法,也是获取原始数据包的首地址,再通过RTCP_Header进行强制类型转换。