Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion apps/statswriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ struct SrtStatsTableInit
STAT(SEND, msBuf, msSndBuf);
STAT(SEND, mbitRate, mbpsSendRate);
STAT(SEND, sendPeriod, usPktSndPeriod);
STAT(SEND, sendPeriod, usSendingJitter);

STAT(RECV, packets, pktRecv);
STAT(RECV, packetsUnique, pktRecvUnique);
Expand All @@ -85,6 +86,8 @@ struct SrtStatsTableInit
STAT(RECV, msBuf, msRcvBuf);
STAT(RECV, mbitRate, mbpsRecvRate);
STAT(RECV, msTsbPdDelay, msRcvTsbPdDelay);
STAT(RECV, usInterArrivalJitter, usInterArrivalJitter);
STAT(RECV, usDeliveryJitter, usDeliveryJitter);
}
} g_SrtStatsTableInit (g_SrtStatsTable);

Expand Down Expand Up @@ -304,8 +307,9 @@ class SrtStatsCols : public SrtStatsWriter
output << "BELATED RECEIVED: " << setw(11) << mon.pktRcvBelated << " AVG TIME: " << setw(11) << mon.pktRcvAvgBelatedTime << endl;
output << "REORDER DISTANCE: " << setw(11) << mon.pktReorderDistance << endl;
output << "WINDOW FLOW: " << setw(11) << mon.pktFlowWindow << " CONGESTION: " << setw(11) << mon.pktCongestionWindow << " FLIGHT: " << setw(11) << mon.pktFlightSize << endl;
output << "LINK RTT: " << setw(9) << mon.msRTT << "ms BANDWIDTH: " << setw(7) << mon.mbpsBandwidth << "Mb/s " << endl;
output << "LINK RTT: " << setw(9) << mon.msRTT << "ms BANDWIDTH: " << setw(7) << mon.mbpsBandwidth << "Mb/s " << endl;
output << "BUFFERLEFT: SND: " << setw(11) << mon.byteAvailSndBuf << " RCV: " << setw(11) << mon.byteAvailRcvBuf << endl;
output << "Jitter (us): SND: " << setw(11) << mon.usSendingJitter << " RCV (TsbPd):" << setw(11) << mon.usDeliveryJitter << endl;
return output.str();
}

Expand Down
16 changes: 16 additions & 0 deletions srtcore/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6920,6 +6920,8 @@ int srt::CUDT::receiveMessage(char* data, int len, SRT_MSGCTRL& w_mctrl, int by_
HLOGC(arlog.Debug, log << CONID() << "CURRENT BANDWIDTH: " << bw << "Mbps (" << m_iBandwidth << " buffers per second)");
#endif
}

m_JitterTracer.onDataPktDelivery(srt::sync::steady_clock::time_point() + microseconds_from(w_mctrl.srctime));
return res;
}

Expand Down Expand Up @@ -7053,6 +7055,8 @@ int srt::CUDT::receiveMessage(char* data, int len, SRT_MSGCTRL& w_mctrl, int by_
throw CUDTException(MJ_AGAIN, MN_XMTIMEOUT, 0);
}

m_JitterTracer.onDataPktDelivery(srt::sync::steady_clock::time_point() + microseconds_from(w_mctrl.srctime));

return res;
}

Expand Down Expand Up @@ -7402,6 +7406,10 @@ void srt::CUDT::bstats(CBytePerfMon *perf, bool clear, bool instantaneous)
: m_CongCtl.ready() ? Bps2Mbps(m_CongCtl->sndBandwidth())
: 0;

perf->usDeliveryJitter = m_JitterTracer.deliveryJitter();
perf->usSendingJitter = m_JitterTracer.sendingJitter();
perf->usInterArrivalJitter = m_JitterTracer.jitter();

if (clear)
{
m_stats.sndr.resetTrace();
Expand Down Expand Up @@ -9830,6 +9838,14 @@ int srt::CUDT::processData(CUnit* in_unit)
// otherwise measurement must be rejected.
m_RcvTimeWindow.probeArrival(packet, unordered || retransmitted);

// The 17th packet is a probing packet that arrives with reduced IAT
if (!retransmitted && ((packet.m_iSeqNo & PUMASK_SEQNO_PROBE) != 1))
{
const uint32_t timestamp = packet.getMsgTimeStamp();
const time_point tsbpdTime = m_pRcvBuffer->getTsbPdTimeBase(timestamp);
m_JitterTracer.onDataPktArrival(packet, tsbpdTime);
}

enterCS(m_StatsLock);
m_stats.rcvr.recvd.count(pktsz);
leaveCS(m_StatsLock);
Expand Down
3 changes: 3 additions & 0 deletions srtcore/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ modified by
#include "handshake.h"
#include "congctl.h"
#include "packetfilter.h"
#include "jitter_tracer.h"
#include "socketconfig.h"
#include "utilities.h"
#include "logger_defs.h"
Expand Down Expand Up @@ -905,6 +906,7 @@ class CUDT

CACKWindow<ACK_WND_SIZE> m_ACKWindow; // ACK history window
CPktTimeWindow<16, 64> m_RcvTimeWindow; // Packet arrival time window
CJitterTracer m_JitterTracer; //< RFC3550-like packet jitter tracer

int32_t m_iRcvLastAck; // First unacknowledged packet seqno sent in the latest ACK.
#ifdef ENABLE_LOGGING
Expand Down Expand Up @@ -1101,6 +1103,7 @@ class CUDT
int traceReorderDistance;
double traceBelatedTime;

uint64_t ullJitter; // Packet inter-arrival jitter (microseconds)
int64_t sndDuration; // real time for sending
time_point sndDurationCounter; // timers to record the sending Duration
} m_stats;
Expand Down
2 changes: 2 additions & 0 deletions srtcore/filelist.maf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ crypto.cpp
epoll.cpp
fec.cpp
handshake.cpp
jitter_tracer.cpp
list.cpp
logger_default.cpp
logger_defs.cpp
Expand Down Expand Up @@ -62,6 +63,7 @@ core.h
crypto.h
epoll.h
handshake.h
jitter_tracer.h
list.h
logging.h
md5.h
Expand Down
67 changes: 67 additions & 0 deletions srtcore/jitter_tracer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* SRT - Secure, Reliable, Transport
* Copyright (c) 2020 Haivision Systems Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/

#include "jitter_tracer.h"

namespace srt {
using namespace sync;


void CJitterTracer::onDataPktArrival(const CPacket& pkt, const time_point& tsbpdBaseTime)
{
const uint32_t timestamp_us = pkt.getMsgTimeStamp();

// RFC 3550 suggests to calculate the relative transit time.
// The relative transit time is the difference between a packet's
// timestamp and the receiver's clock at the time of arrival,
// measured in the same units.
// SRT Data packet does not have an absolute time, the relative time is used instead.
// The timestamp of SRT data packet added to the TSBPD base time is the prediction
// of the current time on the receiver.
// Therefore we calculate the difference between the prediction and the actual value.
// Note the measure difference also includes packet processing delay.
const steady_clock::duration delay =
steady_clock::now() - (tsbpdBaseTime + microseconds_from(timestamp_us));

const uint64_t di = abs(count_microseconds(delay - m_dPrevArrivalDelay));
m_uiJitter = avg_iir<16>(m_uiJitter, di);
m_dPrevArrivalDelay = delay;
}

void CJitterTracer::onDataPktDelivery(const time_point& tsbpdTargetTime)
{
// RFC 3550 suggests to calculate the relative transit time.
// The relative transit time is the difference between a packet's
// timestamp and the receiver's clock at the time of arrival,
// measured in the same units.
// SRT Data packet does not have an absolute time, the relative time is used instead.
// The timestamp of SRT data packet added to the TSBPD base time is the prediction
// of the current time on the receiver.
// Therefore we calculate the difference between the prediction and the actual value.
// Note the measure difference also includes packet processing delay.
const steady_clock::duration delay =
steady_clock::now() - tsbpdTargetTime;

const uint64_t di = abs(count_microseconds(delay - m_dPrevDeliverDelay));
m_uiDeliverJitter = avg_iir<16>(m_uiDeliverJitter, di);
m_dPrevDeliverDelay = delay;
}

void CJitterTracer::onDataPktSent(const time_point& tsPktOrigin)
{
const steady_clock::duration delay =
steady_clock::now() - tsPktOrigin;

const uint64_t di = abs(count_microseconds(delay - m_dPrevSendDelay));
m_uiSendJitter = avg_iir<16>(m_uiSendJitter, di);
m_dPrevSendDelay = delay;
}

} // namespace srt
50 changes: 50 additions & 0 deletions srtcore/jitter_tracer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* SRT - Secure, Reliable, Transport
* Copyright (c) 2020 Haivision Systems Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
#pragma once
#ifndef INC_JITTER_TRACER_H
#define INC_JITTER_TRACER_H

#include "packet.h"
#include "sync.h"

namespace srt {

class CJitterTracer
{
typedef sync::steady_clock::time_point time_point;
typedef sync::steady_clock::duration duration;

public:
CJitterTracer()
: m_uiJitter(0)
{}

public:
void onDataPktArrival(const CPacket& pkt, const time_point& tsbpdBaseTime);
void onDataPktDelivery(const time_point& tsbpdTargetTime);
void onDataPktSent(const time_point& tsPktOrigin);

uint64_t jitter() const { return m_uiJitter; }
uint64_t deliveryJitter() const { return m_uiDeliverJitter; }
uint64_t sendingJitter() const { return m_uiSendJitter; }

private:
duration m_dPrevArrivalDelay;
duration m_dPrevDeliverDelay;
duration m_dPrevSendDelay;
uint64_t m_uiJitter;
uint64_t m_uiDeliverJitter;
uint64_t m_uiSendJitter;
};


} // namespace srt

#endif // INC_JITTER_TRACER_H
6 changes: 6 additions & 0 deletions srtcore/srt.h
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,12 @@ struct CBytePerfMon
int64_t pktRecvUnique; // number of packets to be received by the application
uint64_t byteSentUnique; // number of data bytes, sent by the application
uint64_t byteRecvUnique; // number of data bytes to be received by the application

uint64_t usInterSendingJitter; // NOT IMPLEMENTED! RFC3550 inter jitter jitter of data packets
uint64_t usInterArrivalJitter; // RFC3550 inter arrival jitter of data packets
uint64_t usDeliveryJitter; // RFC3550 inter delivery jitter of data packets
uint64_t usSendingJitter; // RFC3550 inter sending jitter of data packets (excluding probing packets)
int64_t usDrift;
};

////////////////////////////////////////////////////////////////////////////////
Expand Down