Calculate per stream jitter using latency values
We calculate "average jitter". The changes include only the server side, not the client/GUI side which will be done in a future commit.
This commit is contained in:
parent
1fa84ec644
commit
5eb2ad1979
@ -293,6 +293,7 @@ message StreamStats {
|
||||
|
||||
optional double tx_duration = 3; // in seconds
|
||||
optional uint64 latency = 4; // in nanoseconds
|
||||
optional uint64 jitter = 5; // in nanoseconds
|
||||
|
||||
optional uint64 rx_pkts = 11;
|
||||
optional uint64 rx_bytes = 12;
|
||||
|
@ -26,7 +26,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
#include "devicemanager.h"
|
||||
#include "interfaceinfo.h"
|
||||
#include "packetbuffer.h"
|
||||
#include "streamtiming.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QIODevice>
|
||||
@ -886,9 +885,9 @@ void AbstractPort::stats(PortStats *stats)
|
||||
stats_.rxFrameErrors + (maxStatsValue_ - epochStats_.rxFrameErrors);
|
||||
}
|
||||
|
||||
quint64 AbstractPort::streamTimingDelay(uint guid)
|
||||
StreamTiming::Stats AbstractPort::streamTimingStats(uint guid)
|
||||
{
|
||||
return streamTiming_->delay(id(), guid);
|
||||
return streamTiming_->stats(id(), guid);
|
||||
}
|
||||
|
||||
void AbstractPort::clearStreamTiming(uint guid)
|
||||
@ -909,12 +908,14 @@ void AbstractPort::streamStats(uint guid, OstProto::StreamStatsList *stats)
|
||||
{
|
||||
StreamStatsTuple sst = streamStats_.value(guid);
|
||||
OstProto::StreamStats *s = stats->add_stream_stats();
|
||||
StreamTiming::Stats t = streamTimingStats(guid);
|
||||
|
||||
s->mutable_stream_guid()->set_id(guid);
|
||||
s->mutable_port_id()->set_id(id());
|
||||
|
||||
s->set_tx_duration(lastTransmitDuration());
|
||||
s->set_latency(streamTimingDelay(guid));
|
||||
s->set_latency(t.latency);
|
||||
s->set_jitter(t.jitter);
|
||||
|
||||
s->set_tx_pkts(sst.tx_pkts);
|
||||
s->set_tx_bytes(sst.tx_bytes);
|
||||
@ -941,12 +942,14 @@ void AbstractPort::streamStatsAll(OstProto::StreamStatsList *stats)
|
||||
i.next();
|
||||
StreamStatsTuple sst = i.value();
|
||||
OstProto::StreamStats *s = stats->add_stream_stats();
|
||||
StreamTiming::Stats t = streamTimingStats(i.key());
|
||||
|
||||
s->mutable_stream_guid()->set_id(i.key());
|
||||
s->mutable_port_id()->set_id(id());
|
||||
|
||||
s->set_tx_duration(txDur);
|
||||
s->set_latency(streamTimingDelay(i.key()));
|
||||
s->set_latency(t.latency);
|
||||
s->set_jitter(t.jitter);
|
||||
|
||||
s->set_tx_pkts(sst.tx_pkts);
|
||||
s->set_tx_bytes(sst.tx_bytes);
|
||||
|
@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
#include "../common/protocol.pb.h"
|
||||
#include "streamstats.h"
|
||||
#include "streamtiming.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QReadWriteLock>
|
||||
@ -34,7 +35,6 @@ struct InterfaceInfo;
|
||||
class PacketBuffer;
|
||||
class QIODevice;
|
||||
class StreamBase;
|
||||
class StreamTiming;
|
||||
|
||||
// TODO: send notification back to client(s)
|
||||
#define Xnotify qWarning
|
||||
@ -125,7 +125,7 @@ public:
|
||||
void stats(PortStats *stats);
|
||||
void resetStats() { epochStats_ = stats_; }
|
||||
|
||||
quint64 streamTimingDelay(uint guid);
|
||||
StreamTiming::Stats streamTimingStats(uint guid);
|
||||
void clearStreamTiming(uint guid = UINT_MAX);
|
||||
|
||||
// FIXME: combine single and All calls?
|
||||
|
@ -62,8 +62,10 @@ void StreamTiming::stop(uint portId)
|
||||
}
|
||||
}
|
||||
|
||||
quint64 StreamTiming::delay(uint portId, uint guid)
|
||||
StreamTiming::Stats StreamTiming::stats(uint portId, uint guid)
|
||||
{
|
||||
Stats stats = {0, 0};
|
||||
|
||||
Q_ASSERT(guid <= SignProtocol::kMaxGuid);
|
||||
|
||||
// Process anything pending first
|
||||
@ -72,13 +74,16 @@ quint64 StreamTiming::delay(uint portId, uint guid)
|
||||
QMutexLocker locker(&timingLock_);
|
||||
|
||||
if (!timing_.contains(portId))
|
||||
return 0;
|
||||
return stats;
|
||||
|
||||
Timing t = timing_.value(portId)->value(guid);
|
||||
if (t.countDelays == 0)
|
||||
return 0;
|
||||
return stats;
|
||||
|
||||
return timespecToNsecs(t.sumDelays)/t.countDelays;
|
||||
stats.latency = timespecToNsecs(t.sumDelays)/t.countDelays;
|
||||
stats.jitter = t.sumJitter/(t.countDelays-1);
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
void StreamTiming::clear(uint portId, uint guid)
|
||||
@ -127,6 +132,12 @@ int StreamTiming::processRecords()
|
||||
PortTiming *portTiming = timing_.value(portId);
|
||||
Timing &guidTiming = (*portTiming)[guid];
|
||||
timespecadd(&guidTiming.sumDelays, &diff, &guidTiming.sumDelays);
|
||||
if (guidTiming.countDelays)
|
||||
guidTiming.sumJitter += abs(
|
||||
diff.tv_sec*long(1e9) + diff.tv_nsec
|
||||
- guidTiming.lastDelay.tv_sec*long(1e9)
|
||||
- guidTiming.lastDelay.tv_nsec);
|
||||
guidTiming.lastDelay = diff;
|
||||
guidTiming.countDelays++;
|
||||
|
||||
count++;
|
||||
@ -136,10 +147,10 @@ int StreamTiming::processRecords()
|
||||
diff.tv_sec, diff.tv_nsec,
|
||||
rxTime.tv_sec, rxTime.tv_nsec,
|
||||
txTime.tv_sec, txTime.tv_nsec);
|
||||
timingDebug("[%u/%u](%d) total %ld.%09ld count %u",
|
||||
timingDebug("[%u/%u](%d) total %ld.%09ld count %u jittersum %09llu",
|
||||
i.value().portId, guid, count,
|
||||
guidTiming.sumDelays.tv_sec, guidTiming.sumDelays.tv_nsec,
|
||||
guidTiming.countDelays);
|
||||
guidTiming.countDelays, guidTiming.sumJitter);
|
||||
}
|
||||
i = rxHash_.erase(i);
|
||||
}
|
||||
|
@ -34,6 +34,12 @@ class StreamTiming : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
struct Stats
|
||||
{
|
||||
quint64 latency;
|
||||
quint64 jitter;
|
||||
};
|
||||
|
||||
bool recordTxTime(uint portId, uint guid, uint ttagId,
|
||||
const struct timespec ×tamp);
|
||||
bool recordRxTime(uint portId, uint guid, uint ttagId,
|
||||
@ -47,7 +53,7 @@ public:
|
||||
bool recordTxTime(uint portId, uint *ttagList, int count,
|
||||
const struct timespec ×tamp);
|
||||
|
||||
quint64 delay(uint portId, uint guid);
|
||||
Stats stats(uint portId, uint guid);
|
||||
void clear(uint portId, uint guid = SignProtocol::kInvalidGuid);
|
||||
|
||||
static StreamTiming* instance();
|
||||
@ -72,8 +78,13 @@ private:
|
||||
uint portId;
|
||||
};
|
||||
|
||||
// XXX: used only as a Qt Container value, so members will get init to 0
|
||||
// when this struct is retrieved from the container due to Qt's default-
|
||||
// cosntructed value semantics
|
||||
struct Timing {
|
||||
struct timespec sumDelays; // nanosec resolution
|
||||
struct timespec lastDelay;
|
||||
quint64 sumJitter; // nanosec resolution
|
||||
uint countDelays;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user