📄 rtp.cxx
字号:
RTP_Session::~RTP_Session()
{
PTRACE_IF(2, packetsSent != 0 || packetsReceived != 0,
"RTP\tFinal statistics:\n"
" packetsSent = " << packetsSent << "\n"
" octetsSent = " << octetsSent << "\n"
" averageSendTime = " << averageSendTime << "\n"
" maximumSendTime = " << maximumSendTime << "\n"
" minimumSendTime = " << minimumSendTime << "\n"
" packetsReceived = " << packetsReceived << "\n"
" octetsReceived = " << octetsReceived << "\n"
" packetsLost = " << packetsLost << "\n"
" packetsTooLate = " << GetPacketsTooLate() << "\n"
" packetsOutOfOrder = " << packetsOutOfOrder << "\n"
" averageReceiveTime= " << averageReceiveTime << "\n"
" maximumReceiveTime= " << maximumReceiveTime << "\n"
" minimumReceiveTime= " << minimumReceiveTime << "\n"
" averageJitter = " << (jitterLevel >> 7) << "\n"
" maximumJitter = " << (maximumJitterLevel >> 7)
);
if (autoDeleteUserData)
delete userData;
delete jitter;
ResourceCounter::DecrementRTPSession();
}
PString RTP_Session::GetCanonicalName() const
{
PWaitAndSignal mutex(reportMutex);
PString s = canonicalName;
s.MakeUnique();
return s;
}
void RTP_Session::SetCanonicalName(const PString & name)
{
PWaitAndSignal mutex(reportMutex);
canonicalName = name;
}
PString RTP_Session::GetToolName() const
{
PWaitAndSignal mutex(reportMutex);
PString s = toolName;
s.MakeUnique();
return s;
}
void RTP_Session::SetToolName(const PString & name)
{
PWaitAndSignal mutex(reportMutex);
toolName = name;
}
void RTP_Session::SetUserData(RTP_UserData * data, BOOL autoDelete)
{
if (autoDeleteUserData)
delete userData;
userData = data;
autoDeleteUserData = autoDelete;
}
void RTP_Session::SetJitterBufferSize(unsigned minJitterDelay,
unsigned maxJitterDelay,
unsigned timeUnits,
PINDEX stackSize)
{
if (minJitterDelay == 0 && maxJitterDelay == 0) {
delete jitter;
jitter = NULL;
}
else if (jitter != NULL)
jitter->SetDelay(minJitterDelay, maxJitterDelay);
else {
SetIgnoreOutOfOrderPackets(FALSE);
jitter = new RTP_JitterBuffer(*this, minJitterDelay, maxJitterDelay, timeUnits, stackSize);
}
}
unsigned RTP_Session::GetJitterBufferSize() const
{
return jitter != NULL ? jitter->GetJitterTime() : 0;
}
unsigned RTP_Session::GetJitterTimeUnits() const
{
return jitter != NULL ? jitter->GetTimeUnits() : 0;
}
BOOL RTP_Session::ReadBufferedData(DWORD timestamp, RTP_DataFrame & frame)
{
if (jitter != NULL)
return jitter->ReadData(timestamp, frame);
else
return ReadData(frame);
}
void RTP_Session::SetTxStatisticsInterval(unsigned packets)
{
txStatisticsInterval = PMAX(packets, 2);
txStatisticsCount = 0;
averageSendTimeAccum = 0;
maximumSendTimeAccum = 0;
minimumSendTimeAccum = 0xffffffff;
}
void RTP_Session::SetRxStatisticsInterval(unsigned packets)
{
rxStatisticsInterval = PMAX(packets, 2);
rxStatisticsCount = 0;
averageReceiveTimeAccum = 0;
maximumReceiveTimeAccum = 0;
minimumReceiveTimeAccum = 0xffffffff;
}
void RTP_Session::AddReceiverReport(RTP_ControlFrame::ReceiverReport & receiver)
{
receiver.ssrc = syncSourceIn;
receiver.SetLostPackets(packetsLost);
if (expectedSequenceNumber > lastRRSequenceNumber)
receiver.fraction = (BYTE)((packetsLostSinceLastRR<<8)/(expectedSequenceNumber - lastRRSequenceNumber));
else
receiver.fraction = 0;
packetsLostSinceLastRR = 0;
receiver.last_seq = lastRRSequenceNumber;
lastRRSequenceNumber = expectedSequenceNumber;
receiver.jitter = jitterLevel >> 4; // Allow for rounding protection bits
// The following have not been calculated yet.
receiver.lsr = 0;
receiver.dlsr = 0;
PTRACE(3, "RTP\tSentReceiverReport:"
" ssrc=" << receiver.ssrc
<< " fraction=" << (unsigned)receiver.fraction
<< " lost=" << receiver.GetLostPackets()
<< " last_seq=" << receiver.last_seq
<< " jitter=" << receiver.jitter
<< " lsr=" << receiver.lsr
<< " dlsr=" << receiver.dlsr);
}
RTP_Session::SendReceiveStatus RTP_Session::OnSendData(RTP_DataFrame & frame)
{
PTimeInterval tick = PTimer::Tick(); // Timestamp set now
frame.SetSequenceNumber(++lastSentSequenceNumber);
frame.SetSyncSource(syncSourceOut);
PTRACE_IF(2, packetsSent == 0, "RTP\tFirst sent data:"
" ver=" << frame.GetVersion()
<< " pt=" << frame.GetPayloadType()
<< " psz=" << frame.GetPayloadSize()
<< " m=" << frame.GetMarker()
<< " x=" << frame.GetExtension()
<< " seq=" << frame.GetSequenceNumber()
<< " ts=" << frame.GetTimestamp()
<< " src=" << frame.GetSyncSource()
<< " ccnt=" << frame.GetContribSrcCount());
if (packetsSent != 0 && !frame.GetMarker()) {
// Only do statistics on subsequent packets
DWORD diff = (tick - lastSentPacketTime).GetInterval();
averageSendTimeAccum += diff;
if (diff > maximumSendTimeAccum)
maximumSendTimeAccum = diff;
if (diff < minimumSendTimeAccum)
minimumSendTimeAccum = diff;
txStatisticsCount++;
}
lastSentTimestamp = frame.GetTimestamp();
lastSentPacketTime = tick;
octetsSent += frame.GetPayloadSize();
packetsSent++;
// Call the statistics call-back on the first PDU with total count == 1
if (packetsSent == 1 && userData != NULL)
userData->OnTxStatistics(*this);
if (!SendReport())
return e_AbortTransport;
if (txStatisticsCount < txStatisticsInterval)
return e_ProcessPacket;
txStatisticsCount = 0;
averageSendTime = averageSendTimeAccum/txStatisticsInterval;
maximumSendTime = maximumSendTimeAccum;
minimumSendTime = minimumSendTimeAccum;
averageSendTimeAccum = 0;
maximumSendTimeAccum = 0;
minimumSendTimeAccum = 0xffffffff;
PTRACE(2, "RTP\tTransmit statistics: "
" packets=" << packetsSent <<
" octets=" << octetsSent <<
" avgTime=" << averageSendTime <<
" maxTime=" << maximumSendTime <<
" minTime=" << minimumSendTime
);
if (userData != NULL)
userData->OnTxStatistics(*this);
return e_ProcessPacket;
}
RTP_Session::SendReceiveStatus RTP_Session::OnReceiveData(const RTP_DataFrame & frame)
{
// Check that the PDU is the right version
if (frame.GetVersion() != RTP_DataFrame::ProtocolVersion)
return e_IgnorePacket; // Non fatal error, just ignore
// Check for if a control packet rather than data packet.
if (frame.GetPayloadType() > RTP_DataFrame::MaxPayloadType)
return e_IgnorePacket; // Non fatal error, just ignore
PTimeInterval tick = PTimer::Tick(); // Get timestamp now
// Have not got SSRC yet, so grab it now
if (syncSourceIn == 0)
syncSourceIn = frame.GetSyncSource();
// Check packet sequence numbers
if (packetsReceived == 0) {
expectedSequenceNumber = (WORD)(frame.GetSequenceNumber() + 1);
PTRACE(2, "RTP\tFirst receive data:"
" ver=" << frame.GetVersion()
<< " pt=" << frame.GetPayloadType()
<< " psz=" << frame.GetPayloadSize()
<< " m=" << frame.GetMarker()
<< " x=" << frame.GetExtension()
<< " seq=" << frame.GetSequenceNumber()
<< " ts=" << frame.GetTimestamp()
<< " src=" << frame.GetSyncSource()
<< " ccnt=" << frame.GetContribSrcCount());
}
else {
if (!ignoreOtherSources && frame.GetSyncSource() != syncSourceIn) {
if (allowSyncSourceInChange) {
syncSourceIn = frame.GetSyncSource();
allowSyncSourceInChange = FALSE;
}
else {
PTRACE(2, "RTP\tPacket from SSRC=" << frame.GetSyncSource() << " ignored, expecting SSRC=" << syncSourceIn);
return e_IgnorePacket; // Non fatal error, just ignore
}
}
WORD sequenceNumber = frame.GetSequenceNumber();
if (sequenceNumber == expectedSequenceNumber) {
expectedSequenceNumber++;
consecutiveOutOfOrderPackets = 0;
// Only do statistics on packets after first received in talk burst
if (!frame.GetMarker()) {
DWORD diff = (tick - lastReceivedPacketTime).GetInterval();
averageReceiveTimeAccum += diff;
if (diff > maximumReceiveTimeAccum)
maximumReceiveTimeAccum = diff;
if (diff < minimumReceiveTimeAccum)
minimumReceiveTimeAccum = diff;
rxStatisticsCount++;
// The following has the implicit assumption that something that has jitter
// is an audio codec and thus is in 8kHz timestamp units.
diff *= 8;
long variance = diff - lastTransitTime;
lastTransitTime = diff;
if (variance < 0)
variance = -variance;
jitterLevel += variance - ((jitterLevel+8) >> 4);
if (jitterLevel > maximumJitterLevel)
maximumJitterLevel = jitterLevel;
}
}
else if (allowSequenceChange) {
expectedSequenceNumber = (WORD) (sequenceNumber + 1);
allowSequenceChange = FALSE;
}
else if (sequenceNumber < expectedSequenceNumber) {
PTRACE(3, "RTP\tOut of order packet, received "
<< sequenceNumber << " expected " << expectedSequenceNumber
<< " ssrc=" << syncSourceIn);
packetsOutOfOrder++;
// Check for Cisco bug where sequence numbers suddenly start incrementing
// from a different base.
if (++consecutiveOutOfOrderPackets > 10) {
expectedSequenceNumber = (WORD)(sequenceNumber + 1);
PTRACE(1, "RTP\tAbnormal change of sequence numbers, adjusting to expect " << expectedSequenceNumber << " ssrc=" << syncSourceIn);
}
if (ignoreOutOfOrderPackets)
return e_IgnorePacket; // Non fatal error, just ignore
}
else {
unsigned dropped = sequenceNumber - expectedSequenceNumber;
packetsLost += dropped;
packetsLostSinceLastRR += dropped;
PTRACE(3, "RTP\tDropped " << dropped << " packet(s) at " << sequenceNumber
<< ", ssrc=" << syncSourceIn);
expectedSequenceNumber = (WORD)(sequenceNumber + 1);
consecutiveOutOfOrderPackets = 0;
}
}
lastReceivedPacketTime = tick;
octetsReceived += frame.GetPayloadSize();
packetsReceived++;
// Call the statistics call-back on the first PDU with total count == 1
if (packetsReceived == 1 && userData != NULL)
userData->OnRxStatistics(*this);
if (!SendReport())
return e_AbortTransport;
if (rxStatisticsCount < rxStatisticsInterval)
return e_ProcessPacket;
rxStatisticsCount = 0;
averageReceiveTime = averageReceiveTimeAccum/rxStatisticsInterval;
maximumReceiveTime = maximumReceiveTimeAccum;
minimumReceiveTime = minimumReceiveTimeAccum;
averageReceiveTimeAccum = 0;
maximumReceiveTimeAccum = 0;
minimumReceiveTimeAccum = 0xffffffff;
PTRACE(2, "RTP\tReceive statistics: "
" packets=" << packetsReceived <<
" octets=" << octetsReceived <<
" lost=" << packetsLost <<
" tooLate=" << GetPacketsTooLate() <<
" order=" << packetsOutOfOrder <<
" avgTime=" << averageReceiveTime <<
" maxTime=" << maximumReceiveTime <<
" minTime=" << minimumReceiveTime <<
" jitter=" << (jitterLevel >> 7) <<
" maxJitter=" << (maximumJitterLevel >> 7)
);
if (userData != NULL)
userData->OnRxStatistics(*this);
return e_ProcessPacket;
}
BOOL RTP_Session::SendReport()
{
PWaitAndSignal mutex(reportMutex);
if (reportTimer.IsRunning())
return TRUE;
// Have not got anything yet, do nothing
if (packetsSent == 0 && packetsReceived == 0) {
reportTimer = reportTimeInterval;
return TRUE;
}
RTP_ControlFrame report;
// No packets sent yet, so only send RR
if (packetsSent == 0) {
// Send RR as we are not transmitting
report.SetPayloadType(RTP_ControlFrame::e_ReceiverReport);
report.SetPayloadSize(4+sizeof(RTP_ControlFrame::ReceiverReport));
report.SetCount(1);
PUInt32b * payload = (PUInt32b *)report.GetPayloadPtr();
*payload = syncSourceOut;
AddReceiverReport(*(RTP_ControlFrame::ReceiverReport *)&payload[1]);
}
else {
report.SetPayloadType(RTP_ControlFrame::e_SenderReport);
report.SetPayloadSize(sizeof(RTP_ControlFrame::SenderReport));
RTP_ControlFrame::SenderReport * sender =
(RTP_ControlFrame::SenderReport *)report.GetPayloadPtr();
sender->ssrc = syncSourceOut;
PTime now;
sender->ntp_sec = now.GetTimeInSeconds()+SecondsFrom1900to1970; // Convert from 1970 to 1900
sender->ntp_frac = now.GetMicrosecond()*4294; // Scale microseconds to "fraction" from 0 to 2^32
sender->rtp_ts = lastSentTimestamp;
sender->psent = packetsSent;
sender->osent = octetsSent;
PTRACE(3, "RTP\tSentSenderReport: "
" ssrc=" << sender->ssrc
<< " ntp=" << sender->ntp_sec << '.' << sender->ntp_frac
<< " rtp=" << sender->rtp_ts
<< " psent=" << sender->psent
<< " osent=" << sender->osent);
if (syncSourceIn != 0) {
report.SetPayloadSize(sizeof(RTP_ControlFrame::SenderReport) +
sizeof(RTP_ControlFrame::ReceiverReport));
report.SetCount(1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -