www.pudn.com > rtp实现协议占.rar > rtppkt.h
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
#ifndef PMC_PREDEFINED_TYPES
#define PMC_PREDEFINED_TYPES
typedef char* pmc_string;
struct buffer {
UINT32 len;
INT8* data;
};
#endif/*PMC_PREDEFINED_TYPES*/
/* $Id: rtppkt.h,v 1.7 2003/09/30 16:15:42 csloan Exp $ */
#ifndef _RTPPKT_H_
#define _RTPPKT_H_
// op-codes
const int RTP_OP_PACKETFLAGS = 1; // opcode datalength = 1
const int RTP_OP_ASMRULES = 2; // packs asm_flags/asm_rule instead
// of op_code_data
// flags for opcode RTP_OP_PACKETFLAGS
const int RTP_FLAG_LASTPACKET = 0x00000001; // last packet in stream
const int RTP_FLAG_KEYFRAME = 0x00000002; // keyframe packet
// RTCP types
const int RTCP_SR = 200;
const int RTCP_RR = 201;
const int RTCP_SDES = 202;
const int RTCP_BYE = 203;
const int RTCP_APP = 204;
// SDES item types
const int SDES_CNAME = 1;
const int SDES_NAME = 2;
const int SDES_EMAIL = 3;
const int SDES_PHONE = 4;
const int SDES_LOC = 5;
const int SDES_TOOL = 6;
const int SDES_NOTE = 7;
const int SDES_PRIV = 8;
// APP tiem Types
const int APP_EOS = 1;
const int APP_BUFINFO = 2;
#include "bufnum.h"
#include "hxinline.h"
class RTPPacketBase
{
public:
UINT8* pack(UINT8* buf, UINT32 &len);
UINT8* unpack(UINT8* buf, UINT32 len);
const UINT32 static_size() {return 20;}
UINT8 version_flag;
UINT8 padding_flag;
UINT8 extension_flag;
UINT8 csrc_len;
UINT8 marker_flag;
UINT8 payload;
INT16 seq_no;
INT32 timestamp;
INT32 ssrc;
INT32 *csrc;
INT16 op_code;
INT16 op_code_data_length;
INT16 asm_flags;
INT16 asm_rule;
INT32 *op_code_data;
buffer data;
};
class ReceptionReport
{
public:
UINT8* pack(UINT8* buf, UINT32 &len);
UINT8* unpack(UINT8* buf, UINT32 len);
static const UINT32 static_size() {return 24;}
UINT32 ssrc;
UINT8 fraction;
UINT32 lost;
UINT32 last_seq;
UINT32 jitter;
UINT32 lsr;
UINT32 dlsr;
};
class SDESItem
{
public:
UINT8* pack(UINT8* buf, UINT32 &len);
UINT8* unpack(UINT8* buf, UINT32 len);
const UINT32 static_size() {return 2;}
UINT8 sdes_type;
UINT8 length;
UINT8 *data;
};
class APPItem
{
public:
UINT8* pack(UINT8* buf, UINT32 &len);
UINT8* unpack(UINT8* buf, UINT32 len);
const UINT32 static_size() {return 23;}
UINT8 app_type;/**/
UINT8 packet_sent;/**/
UINT16 seq_no;/*序列号*/
UINT32 timestamp;/*时间戳*/
UINT32 lowest_timestamp;/*最小时间戳*/
UINT32 highest_timestamp;/*最大时间戳*/
UINT32 bytes_buffered;/**/
UINT32 padding0;/**/
};
class RTCPPacketBase
{
public:
UINT8* pack(UINT8* buf, UINT32 &len);
UINT8* unpack(UINT8* buf, UINT32 len);
const UINT32 static_size() {return 40;}
UINT8 version_flag;
UINT8 padding_flag;
UINT8 count;
UINT8 packet_type;
UINT16 length;
UINT32 sr_ssrc;
UINT32 ntp_sec;
UINT32 ntp_frac;
UINT32 rtp_ts;
UINT32 psent;
UINT32 osent;
ReceptionReport *sr_data;
UINT32 rr_ssrc;
ReceptionReport *rr_data;
UINT8 *sdes_data;
UINT32 *bye_src;
UINT32 app_ssrc;
UINT8 app_name[4];
UINT8 *app_data;
};
#if defined (_DEFINE_INLINE)
HX_INLINE UINT8*
RTPPacketBase::pack(UINT8* buf, UINT32 &len)
{
UINT8* off = buf;
{
*off &= ~0xc0; *off |= (version_flag&0x3)<<6;
}
{*off &= ~(1<<5); *off |= (padding_flag&1)<<5;}
{*off &= ~(1<<4); *off |= (extension_flag&1)<<4;}
{
*off &= ~0xf; *off++ |= csrc_len&0xf;
}
{*off &= ~(1<<7); *off |= (marker_flag&1)<<7;}
{
*off &= ~0x7f; *off++ |= payload&0x7f;
}
{*off++ = (UINT8) (seq_no>>8); *off++ = (UINT8) (seq_no);}
{
*off++ = (UINT8) (timestamp>>24); *off++ = (UINT8) (timestamp>>16); *off++ = (UINT8) (timestamp>>8); *off++ = (UINT8) (timestamp);
}
{
*off++ = (UINT8) (ssrc>>24); *off++ = (UINT8) (ssrc>>16); *off++ = (UINT8) (ssrc>>8); *off++ = (UINT8) (ssrc);
}
if ((csrc_len > 0))
{
{for (int i = 0; i < csrc_len; i++)
{
*off++ = (UINT8) (csrc[i]>>24); *off++ = (UINT8) (csrc[i]>>16); *off++ = (UINT8) (csrc[i]>>8); *off++ = (UINT8) (csrc[i]);
}
}
}
if ((extension_flag == 1))
{
{*off++ = (UINT8) (op_code>>8); *off++ = (UINT8) (op_code);}
{*off++ = (UINT8) (op_code_data_length>>8); *off++ = (UINT8) (op_code_data_length);}
if ((op_code == 2))
{
{*off++ = (UINT8) (asm_flags>>8); *off++ = (UINT8) (asm_flags);}
{*off++ = (UINT8) (asm_rule>>8); *off++ = (UINT8) (asm_rule);}
}
else
{
{for (int i = 0; i < op_code_data_length; i++)
{
*off++ = (UINT8) (op_code_data[i]>>24); *off++ = (UINT8) (op_code_data[i]>>16); *off++ = (UINT8) (op_code_data[i]>>8); *off++ = (UINT8) (op_code_data[i]);
}
}
}
}
{
memcpy(off, data.data, data.len); off += data.len; /* Flawfinder: ignore */
}
len = off-buf;
return off;
}
HX_INLINE UINT8*
RTPPacketBase::unpack(UINT8* buf, UINT32 len)
{
if (!buf || !len)
return 0;
UINT8* off = buf;
{
version_flag = (*off&0xc0)>>6;
}
padding_flag = (*off>>5)&1;
extension_flag = (*off>>4)&1;
{
csrc_len = *off++&0xf;
}
marker_flag = (*off>>7)&1;
{
payload = *off++&0x7f;
}
{seq_no = *off++<<8; seq_no |= *off++;}
{
timestamp = GetDwordFromBufAndInc(off);
}
{
ssrc = GetDwordFromBufAndInc(off);
}
if ((csrc_len > 0))
{
{
csrc = new INT32[csrc_len];
for (int i = 0; i < csrc_len; i++)
{
csrc[i] = GetDwordFromBufAndInc(off);
}
}
}
if ((extension_flag == 1))
{
{op_code = *off++<<8; op_code |= *off++;}
{op_code_data_length = *off++<<8; op_code_data_length |= *off++;}
if ((op_code == 2))
{
{asm_flags = *off++<<8; asm_flags |= *off++;}
{asm_rule = *off++<<8; asm_rule |= *off++;}
}
else
{
{
op_code_data = new INT32[op_code_data_length];
for (int i = 0; i < op_code_data_length; i++)
{
op_code_data[i] = GetDwordFromBufAndInc(off);
}
}
}
}
{
data.len = len - (off - buf);
if (off-buf+data.len > (int)len)
return 0;
data.data = (INT8 *)off; off += data.len;
}
return off;
}
HX_INLINE UINT8*
ReceptionReport::pack(UINT8* buf, UINT32 &len)
{
UINT8* off = buf;
{
*off++ = (UINT8) (ssrc>>24); *off++ = (UINT8) (ssrc>>16); *off++ = (UINT8) (ssrc>>8); *off++ = (UINT8) (ssrc);
}
{
*off++ = (UINT8) (fraction);
}
{
*off++ = (UINT8) (lost>>16);
*off++ = (UINT8) (lost>>8);
*off++ = (UINT8) (lost);
}
{
*off++ = (UINT8) (last_seq>>24); *off++ = (UINT8) (last_seq>>16); *off++ = (UINT8) (last_seq>>8); *off++ = (UINT8) (last_seq);
}
{
*off++ = (UINT8) (jitter>>24); *off++ = (UINT8) (jitter>>16); *off++ = (UINT8) (jitter>>8); *off++ = (UINT8) (jitter);
}
{
*off++ = (UINT8) (lsr>>24); *off++ = (UINT8) (lsr>>16); *off++ = (UINT8) (lsr>>8); *off++ = (UINT8) (lsr);
}
{
*off++ = (UINT8) (dlsr>>24); *off++ = (UINT8) (dlsr>>16); *off++ = (UINT8) (dlsr>>8); *off++ = (UINT8) (dlsr);
}
len = off-buf;
return off;
}
HX_INLINE UINT8*
ReceptionReport::unpack(UINT8* buf, UINT32 len)
{
if (!buf || !len)
return 0;
UINT8* off = buf;
{
ssrc = GetDwordFromBufAndInc(off);
}
{
fraction = *off++;
}
{
lost = *off++<<16;
lost |= *off++<<8;
lost |= *off++;
}
{
last_seq = GetDwordFromBufAndInc(off);
}
{
jitter = GetDwordFromBufAndInc(off);
}
{
lsr = GetDwordFromBufAndInc(off);
}
{
dlsr = GetDwordFromBufAndInc(off);
}
return off;
}
HX_INLINE UINT8*
SDESItem::pack(UINT8* buf, UINT32 &len)
{
UINT8* off = buf;
*off++ = sdes_type;
if ((sdes_type != 0))
{
*off++ = length;
{memcpy(off, data, length); off += length; } /* Flawfinder: ignore */
}
len = off-buf;
return off;
}
HX_INLINE UINT8*
SDESItem::unpack(UINT8* buf, UINT32 len)
{
if (!buf || !len)
return 0;
UINT8* off = buf;
sdes_type = *off++;
if ((sdes_type != 0))
{
length = *off++;
if (off-buf+length > (int)len)
return 0;
{data = (UINT8 *)off; off += length;}
}
return off;
}
/**
数据打包
*/
HX_INLINE UINT8*
APPItem::pack(UINT8* buf, UINT32 &len)
{
UINT8* off = buf;/*数据包*/
*off++ = app_type;
if ((1 == app_type))
{
{
*off++ = (UINT8) (packet_sent);
}
{//序列号
*off++ = (UINT8) (seq_no>>8);/*高8位*/ *off++ = (UINT8) (seq_no);/*低8位*/}
{
// 时间戳
*off++ = (UINT8) (timestamp>>24);/*一8位*/ *off++ = (UINT8) (timestamp>>16);/*二8位*/ *off++ = (UINT8) (timestamp>>8);/*三8位*/ *off++ = (UINT8) (timestamp);/*四8位*/
}
}
if ((2 == app_type))
{
{
*off++ = (UINT8) (lowest_timestamp>>24); *off++ = (UINT8) (lowest_timestamp>>16); *off++ = (UINT8) (lowest_timestamp>>8); *off++ = (UINT8) (lowest_timestamp);
}
{
*off++ = (UINT8) (highest_timestamp>>24); *off++ = (UINT8) (highest_timestamp>>16); *off++ = (UINT8) (highest_timestamp>>8); *off++ = (UINT8) (highest_timestamp);
}
{
*off++ = (UINT8) (bytes_buffered>>24); *off++ = (UINT8) (bytes_buffered>>16); *off++ = (UINT8) (bytes_buffered>>8); *off++ = (UINT8) (bytes_buffered);
}
{
*off++ = (UINT8) (padding0>>16);
*off++ = (UINT8) (padding0>>8);
*off++ = (UINT8) (padding0);
}
}
len = off-buf;
return off;
}
HX_INLINE UINT8*
APPItem::unpack(UINT8* buf, UINT32 len)
{
if (!buf || !len)
return 0;
UINT8* off = buf;
app_type = *off++;
if ((1 == app_type))
{
{
packet_sent = *off++;
}
{seq_no = *off++<<8; seq_no |= *off++;}
{
timestamp = GetDwordFromBufAndInc(off);
}
}
if ((2 == app_type))
{
{
lowest_timestamp = GetDwordFromBufAndInc(off);
}
{
highest_timestamp = GetDwordFromBufAndInc(off);
}
{
bytes_buffered = GetDwordFromBufAndInc(off);
}
{
padding0 = *off++<<16;
padding0 |= *off++<<8;
padding0 |= *off++;
}
}
return off;
}
HX_INLINE UINT8*
RTCPPacketBase::pack(UINT8* buf, UINT32 &len)
{
UINT8* off = buf;
{
*off &= ~0xc0; *off |= (version_flag&0x3)<<6;
}
{*off &= ~(1<<5); *off |= (padding_flag&1)<<5;}
{
*off &= ~0x1f; *off++ |= count&0x1f;
}
{
*off++ = (UINT8) (packet_type);
}
{*off++ = (UINT8) (length>>8); *off++ = (UINT8) (length);}
if ((packet_type == 200))
{
{
*off++ = (UINT8) (sr_ssrc>>24); *off++ = (UINT8) (sr_ssrc>>16); *off++ = (UINT8) (sr_ssrc>>8); *off++ = (UINT8) (sr_ssrc);
}
{
*off++ = (UINT8) (ntp_sec>>24); *off++ = (UINT8) (ntp_sec>>16); *off++ = (UINT8) (ntp_sec>>8); *off++ = (UINT8) (ntp_sec);
}
{
*off++ = (UINT8) (ntp_frac>>24); *off++ = (UINT8) (ntp_frac>>16); *off++ = (UINT8) (ntp_frac>>8); *off++ = (UINT8) (ntp_frac);
}
{
*off++ = (UINT8) (rtp_ts>>24); *off++ = (UINT8) (rtp_ts>>16); *off++ = (UINT8) (rtp_ts>>8); *off++ = (UINT8) (rtp_ts);
}
{
*off++ = (UINT8) (psent>>24); *off++ = (UINT8) (psent>>16); *off++ = (UINT8) (psent>>8); *off++ = (UINT8) (psent);
}
{
*off++ = (UINT8) (osent>>24); *off++ = (UINT8) (osent>>16); *off++ = (UINT8) (osent>>8); *off++ = (UINT8) (osent);
}
{for (int i = 0; i < count; i++)
off = sr_data[i].pack(off, len);
}
}
if ((packet_type == 201))
{
{
*off++ = (UINT8) (rr_ssrc>>24); *off++ = (UINT8) (rr_ssrc>>16); *off++ = (UINT8) (rr_ssrc>>8); *off++ = (UINT8) (rr_ssrc);
}
{for (int i = 0; i < count; i++)
off = rr_data[i].pack(off, len);
}
}
if ((packet_type == 202))
{
{memcpy(off, sdes_data, (length * 4)); off += (length * 4); } /* Flawfinder: ignore */
}
if ((packet_type == 203))
{
{for (int i = 0; i < count; i++)
{
*off++ = (UINT8) (bye_src[i]>>24); *off++ = (UINT8) (bye_src[i]>>16); *off++ = (UINT8) (bye_src[i]>>8); *off++ = (UINT8) (bye_src[i]);
}
}
}
if ((packet_type == 204))
{
{
*off++ = (UINT8) (app_ssrc>>24); *off++ = (UINT8) (app_ssrc>>16); *off++ = (UINT8) (app_ssrc>>8); *off++ = (UINT8) (app_ssrc);
}
{memcpy(off, app_name, 4); off += 4; } /* Flawfinder: ignore */
{memcpy(off, app_data, ((length - 2) * 4)); off += ((length - 2) * 4); } /* Flawfinder: ignore */
}
len = off-buf;
return off;
}
HX_INLINE UINT8*
RTCPPacketBase::unpack(UINT8* buf, UINT32 len)
{
if (!buf || len < 4)
return 0;
UINT8* off = buf;
{
version_flag = (*off&0xc0)>>6;
}
padding_flag = (*off>>5)&1;
{
count = *off++&0x1f;
}
{
packet_type = *off++;
}
{length = *off++<<8; length |= *off++;}
if (len < (UINT32)4*(length + 1))
{
count = 0;
return 0;
}
if ((packet_type == 200))
{
if (length < 6)
{
count = 0;
return buf + 4 + 4*length;
}
{
sr_ssrc = GetDwordFromBufAndInc(off);
}
{
ntp_sec = GetDwordFromBufAndInc(off);
}
{
ntp_frac = GetDwordFromBufAndInc(off);
}
{
rtp_ts = GetDwordFromBufAndInc(off);
}
{
psent = GetDwordFromBufAndInc(off);
}
{
osent = GetDwordFromBufAndInc(off);
}
if (length < 6 + count*(ReceptionReport::static_size() / 4))
{
count = 0;
return buf + 4 + length*4;
}
{
sr_data = new ReceptionReport[count];
for (int i = 0; i < count; i++)
off = sr_data[i].unpack(off, len);
}
}
if ((packet_type == 201))
{
if (length < 1)
{
count = 0;
return buf + 4 + 4*length;
}
{
rr_ssrc = GetDwordFromBufAndInc(off);
}
if (length < 1 + count*(ReceptionReport::static_size() / 4))
{
count = 0;
return buf + 4 + length*4;
}
{
rr_data = new ReceptionReport[count];
for (int i = 0; i < count; i++)
off = rr_data[i].unpack(off, len);
}
}
if ((packet_type == 202))
{
if (off-buf+(length * 4) > (int)len)
return 0;
{sdes_data = (UINT8 *)off; off += (length * 4);}
}
if ((packet_type == 203))
{
if (length < count)
{
count = 0;
return buf + 4 + length*4;
}
{
bye_src = new UINT32[count];
for (int i = 0; i < count; i++)
{
bye_src[i] = GetDwordFromBufAndInc(off);
}
}
}
if ((packet_type == 204))
{
{
app_ssrc = GetDwordFromBufAndInc(off);
}
if (off-buf+4 > (int)len)
return 0;
{memcpy(app_name, off, 4); off += 4; } /* Flawfinder: ignore */
if (off-buf+((length - 2) * 4) > (int)len)
return 0;
{app_data = (UINT8 *)off; off += ((length - 2) * 4);}
}
return off;
}
#endif //_DEFINE_INLINE
#endif /* _RTPPKT_H_ */