📄 rtp.cxx
字号:
* Added RTP statistics display.
*
* Revision 1.12 1999/11/14 11:41:07 robertj
* Added access functions to RTP statistics.
*
* Revision 1.11 1999/10/18 23:55:11 robertj
* Fixed bug in setting contributing sources, length put into wrong spot in PDU header
*
* Revision 1.10 1999/09/21 14:10:04 robertj
* Removed warnings when no tracing enabled.
*
* Revision 1.9 1999/09/05 00:58:37 robertj
* Removed requirement that OpenLogicalChannalAck sessionId match original OLC.
*
* Revision 1.8 1999/09/03 02:17:50 robertj
* Added more debugging
*
* Revision 1.7 1999/08/31 12:34:19 robertj
* Added gatekeeper support.
*
* Revision 1.6 1999/07/16 02:13:54 robertj
* Slowed down the control channel statistics packets.
*
* Revision 1.5 1999/07/13 09:53:24 robertj
* Fixed some problems with jitter buffer and added more debugging.
*
* Revision 1.4 1999/07/09 06:09:52 robertj
* Major implementation. An ENORMOUS amount of stuff added everywhere.
*
* Revision 1.3 1999/06/22 13:49:40 robertj
* Added GSM support and further RTP protocol enhancements.
*
* Revision 1.2 1999/06/14 08:42:52 robertj
* Fixed bug in dropped packets display was negative.
*
* Revision 1.1 1999/06/14 06:12:25 robertj
* Changes for using RTP sessions correctly in H323 Logical Channel context
*
*/
#include <ptlib.h>
#ifdef __GNUC__
#pragma implementation "rtp.h"
#endif
#include <rtp/rtp.h>
#include <rtp/jitter.h>
#include <ptclib/random.h>
#include <ptclib/pstun.h>
#include "Encryption.h"
#include "ResourceCounter.h"
using namespace Tools;
#define new PNEW
#if !PTRACING // Stuff to remove unised parameters warning
#define PTRACE_sender
#define PTRACE_reports
#define PTRACE_count
#define PTRACE_src
#define PTRACE_description
#define PTRACE_reason
#define PTRACE_type
#define PTRACE_subtype
#define PTRACE_size
#define PTRACE_port
#endif
const unsigned SecondsFrom1900to1970 = (70*365+17)*24*60*60U;
#define UDP_BUFFER_SIZE 32768
#define MIN_HEADER_SIZE 12
#define RTP_MAX_FRAME_SIZE 1024
/////////////////////////////////////////////////////////////////////////////
RTP_DataFrame::RTP_DataFrame(PINDEX sz)
: PBYTEArray(MIN_HEADER_SIZE+sz)
{
payloadSize = sz;
theArray[0] = '\x80';
}
void RTP_DataFrame::SetExtension(BOOL ext)
{
if (ext)
theArray[0] |= 0x10;
else
theArray[0] &= 0xef;
}
void RTP_DataFrame::SetMarker(BOOL m)
{
if (m)
theArray[1] |= 0x80;
else
theArray[1] &= 0x7f;
}
void RTP_DataFrame::SetPayloadType(PayloadTypes t)
{
PAssert(t <= 0x7f, PInvalidParameter);
theArray[1] &= 0x80;
theArray[1] |= t;
}
DWORD RTP_DataFrame::GetContribSource(PINDEX idx) const
{
PAssert(idx < GetContribSrcCount(), PInvalidParameter);
return ((PUInt32b *)&theArray[MIN_HEADER_SIZE])[idx];
}
void RTP_DataFrame::SetContribSource(PINDEX idx, DWORD src)
{
PAssert(idx <= 15, PInvalidParameter);
if (idx >= GetContribSrcCount()) {
BYTE * oldPayload = GetPayloadPtr();
theArray[0] &= 0xf0;
theArray[0] |= idx+1;
SetSize(GetHeaderSize()+payloadSize);
memmove(GetPayloadPtr(), oldPayload, payloadSize);
}
((PUInt32b *)&theArray[MIN_HEADER_SIZE])[idx] = src;
}
PINDEX RTP_DataFrame::GetHeaderSize() const
{
PINDEX sz = MIN_HEADER_SIZE + 4*GetContribSrcCount();
if (GetExtension())
sz += 4 + GetExtensionSize();
return sz;
}
int RTP_DataFrame::GetExtensionType() const
{
if (GetExtension())
return *(PUInt16b *)&theArray[MIN_HEADER_SIZE + 4*GetContribSrcCount()];
return -1;
}
void RTP_DataFrame::SetExtensionType(int type)
{
if (type < 0)
SetExtension(FALSE);
else {
if (!GetExtension())
SetExtensionSize(0);
*(PUInt16b *)&theArray[MIN_HEADER_SIZE + 4*GetContribSrcCount()] = (WORD)type;
}
}
PINDEX RTP_DataFrame::GetExtensionSize() const
{
if (GetExtension())
return *(PUInt16b *)&theArray[MIN_HEADER_SIZE + 4*GetContribSrcCount() + 2];
return 0;
}
BOOL RTP_DataFrame::SetExtensionSize(PINDEX sz)
{
if (!SetMinSize(MIN_HEADER_SIZE + 4*GetContribSrcCount() + 4+4*sz + payloadSize))
return FALSE;
SetExtension(TRUE);
*(PUInt16b *)&theArray[MIN_HEADER_SIZE + 4*GetContribSrcCount() + 2] = (WORD)sz;
return TRUE;
}
BYTE * RTP_DataFrame::GetExtensionPtr() const
{
if (GetExtension())
return (BYTE *)&theArray[MIN_HEADER_SIZE + 4*GetContribSrcCount() + 4];
return NULL;
}
BOOL RTP_DataFrame::SetPayloadSize(PINDEX sz)
{
payloadSize = sz;
return SetMinSize(GetHeaderSize()+payloadSize);
}
#if PTRACING
static const char * const PayloadTypesNames[RTP_DataFrame::LastKnownPayloadType] = {
"PCMU",
"FS1016",
"G721",
"GSM",
"G7231",
"DVI4_8k",
"DVI4_16k",
"LPC",
"PCMA",
"G722",
"L16_Stereo",
"L16_Mono",
"G723",
"CN",
"MPA",
"G728",
"DVI4_11k",
"DVI4_22k",
"G729",
"CiscoCN",
NULL, NULL, NULL, NULL, NULL,
"CelB",
"JPEG",
NULL, NULL, NULL, NULL,
"H261",
"MPV",
"MP2T",
"H263"
};
ostream & operator<<(ostream & o, RTP_DataFrame::PayloadTypes t)
{
if ((PINDEX)t < PARRAYSIZE(PayloadTypesNames) && PayloadTypesNames[t] != NULL)
o << PayloadTypesNames[t];
else
o << "[pt=" << (int)t << ']';
return o;
}
#endif
/////////////////////////////////////////////////////////////////////////////
RTP_ControlFrame::RTP_ControlFrame(PINDEX sz)
: PBYTEArray(sz)
{
compoundOffset = 0;
compoundSize = 0;
theArray[0] = '\x80'; // Set version 2
}
void RTP_ControlFrame::SetCount(unsigned count)
{
PAssert(count < 32, PInvalidParameter);
theArray[compoundOffset] &= 0xe0;
theArray[compoundOffset] |= count;
}
void RTP_ControlFrame::SetPayloadType(unsigned t)
{
PAssert(t < 256, PInvalidParameter);
theArray[compoundOffset+1] = (BYTE)t;
}
void RTP_ControlFrame::SetPayloadSize(PINDEX sz)
{
sz = (sz+3)/4;
PAssert(sz <= 0xffff, PInvalidParameter);
compoundSize = compoundOffset+4*(sz+1);
SetMinSize(compoundSize+1);
*(PUInt16b *)&theArray[compoundOffset+2] = (WORD)sz;
}
BOOL RTP_ControlFrame::ReadNextCompound()
{
compoundOffset += GetPayloadSize()+4;
if (compoundOffset+4 > GetSize())
return FALSE;
return compoundOffset+GetPayloadSize()+4 <= GetSize();
}
BOOL RTP_ControlFrame::WriteNextCompound()
{
compoundOffset += GetPayloadSize()+4;
if (!SetMinSize(compoundOffset+4))
return FALSE;
theArray[compoundOffset] = '\x80'; // Set version 2
theArray[compoundOffset+1] = 0; // Set payload type to illegal
theArray[compoundOffset+2] = 0; // Set payload size to zero
theArray[compoundOffset+3] = 0;
return TRUE;
}
RTP_ControlFrame::SourceDescription & RTP_ControlFrame::AddSourceDescription(DWORD src)
{
SetPayloadType(RTP_ControlFrame::e_SourceDescription);
PINDEX index = GetCount();
SetCount(index+1);
PINDEX originalPayloadSize = index != 0 ? GetPayloadSize() : 0;
SetPayloadSize(originalPayloadSize+sizeof(SourceDescription));
SourceDescription & sdes = *(SourceDescription *)(GetPayloadPtr()+originalPayloadSize);
sdes.src = src;
sdes.item[0].type = e_END;
return sdes;
}
RTP_ControlFrame::SourceDescription::Item &
RTP_ControlFrame::AddSourceDescriptionItem(SourceDescription & sdes,
unsigned type,
const PString & data)
{
PINDEX dataLength = data.GetLength();
SetPayloadSize(GetPayloadSize()+sizeof(SourceDescription::Item)+dataLength-1);
SourceDescription::Item * item = sdes.item;
while (item->type != e_END)
item = item->GetNextItem();
item->type = (BYTE)type;
item->length = (BYTE)dataLength;
memcpy(item->data, (const char *)data, item->length);
item->GetNextItem()->type = e_END;
return *item;
}
void RTP_ControlFrame::ReceiverReport::SetLostPackets(unsigned packets)
{
lost[0] = (BYTE)(packets >> 16);
lost[1] = (BYTE)(packets >> 8);
lost[2] = (BYTE)packets;
}
/////////////////////////////////////////////////////////////////////////////
void RTP_UserData::OnTxStatistics(const RTP_Session & /*session*/) const
{
}
void RTP_UserData::OnRxStatistics(const RTP_Session & /*session*/) const
{
}
/////////////////////////////////////////////////////////////////////////////
RTP_Session::RTP_Session(unsigned id, RTP_UserData * data, BOOL autoDelete)
: canonicalName(PProcess::Current().GetUserName()),
toolName(PProcess::Current().GetName()),
reportTimeInterval(0, 12), // Seconds
reportTimer(reportTimeInterval)
{
PAssert(id > 0 && id < 256, PInvalidParameter);
sessionID = (BYTE)id;
referenceCount = 1;
userData = data;
autoDeleteUserData = autoDelete;
jitter = NULL;
ignoreOtherSources = TRUE;
ignoreOutOfOrderPackets = TRUE;
syncSourceOut = PRandom::Number();
syncSourceIn = 0;
allowSyncSourceInChange = FALSE;
allowRemoteTransmitAddressChange = FALSE;
allowSequenceChange = FALSE;
txStatisticsInterval = 100; // Number of data packets between tx reports
rxStatisticsInterval = 100; // Number of data packets between rx reports
lastSentSequenceNumber = (WORD)PRandom::Number();
expectedSequenceNumber = 0;
lastRRSequenceNumber = 0;
consecutiveOutOfOrderPackets = 0;
packetsSent = 0;
octetsSent = 0;
packetsReceived = 0;
octetsReceived = 0;
packetsLost = 0;
packetsOutOfOrder = 0;
averageSendTime = 0;
maximumSendTime = 0;
minimumSendTime = 0;
averageReceiveTime = 0;
maximumReceiveTime = 0;
minimumReceiveTime = 0;
jitterLevel = 0;
maximumJitterLevel = 0;
txStatisticsCount = 0;
rxStatisticsCount = 0;
averageSendTimeAccum = 0;
maximumSendTimeAccum = 0;
minimumSendTimeAccum = 0xffffffff;
averageReceiveTimeAccum = 0;
maximumReceiveTimeAccum = 0;
minimumReceiveTimeAccum = 0xffffffff;
packetsLostSinceLastRR = 0;
lastTransitTime = 0;
ResourceCounter::IncrementRTPSession();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -