- report packet loss timeline
This commit is contained in:
@@ -224,11 +224,6 @@ RtpBuffer::FetchResult RtpBuffer::fetch(ResultList& rl)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Did we fetch any packet before ?
|
|
||||||
bool is_fetched_packet = mFetchedPacket.get() != nullptr;
|
|
||||||
if (is_fetched_packet)
|
|
||||||
is_fetched_packet &= mFetchedPacket->rtp().get() != nullptr;
|
|
||||||
|
|
||||||
if (mLastSeqno.has_value())
|
if (mLastSeqno.has_value())
|
||||||
{
|
{
|
||||||
if (mPacketList.empty())
|
if (mPacketList.empty())
|
||||||
@@ -239,7 +234,8 @@ RtpBuffer::FetchResult RtpBuffer::fetch(ResultList& rl)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Current sequence number ?
|
// Current sequence number ?
|
||||||
uint32_t seqno = mPacketList.front()->rtp()->GetExtendedSequenceNumber();
|
auto& packet = *mPacketList.front();
|
||||||
|
uint32_t seqno = packet.rtp()->GetExtendedSequenceNumber();
|
||||||
|
|
||||||
// Gap between new packet and previous on
|
// Gap between new packet and previous on
|
||||||
int gap = (int64_t)seqno - (int64_t)*mLastSeqno - 1;
|
int gap = (int64_t)seqno - (int64_t)*mLastSeqno - 1;
|
||||||
@@ -248,7 +244,8 @@ RtpBuffer::FetchResult RtpBuffer::fetch(ResultList& rl)
|
|||||||
{
|
{
|
||||||
// std::cout << "Increase the packet loss for SSRC " << std::hex << mSsrc << std::endl;
|
// std::cout << "Increase the packet loss for SSRC " << std::hex << mSsrc << std::endl;
|
||||||
mStat.mPacketLoss++;
|
mStat.mPacketLoss++;
|
||||||
//mStat.mLoss[gap]++;
|
auto currentTimestamp = uint64_t(packet.rtp()->GetReceiveTime().GetDouble() * 1000000);
|
||||||
|
mStat.mPacketLossTimeline.push_back({gap, std::chrono::microseconds(currentTimestamp)});
|
||||||
mLastSeqno = *mLastSeqno + 1;
|
mLastSeqno = *mLastSeqno + 1;
|
||||||
result = FetchResult::Gap;
|
result = FetchResult::Gap;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,37 +18,44 @@
|
|||||||
#include "../audio/Audio_Resampler.h"
|
#include "../audio/Audio_Resampler.h"
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <chrono>
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
namespace MT
|
namespace MT
|
||||||
{
|
{
|
||||||
using jrtplib::RTPPacket;
|
using jrtplib::RTPPacket;
|
||||||
class RtpBuffer
|
class RtpBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class FetchResult
|
enum class FetchResult
|
||||||
{
|
{
|
||||||
RegularPacket,
|
RegularPacket,
|
||||||
Gap,
|
Gap,
|
||||||
NoPacket
|
NoPacket
|
||||||
};
|
};
|
||||||
|
|
||||||
// Owns rtp packet data
|
// Owns rtp packet data
|
||||||
class Packet
|
class Packet
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Packet(const std::shared_ptr<RTPPacket>& packet, int timelen, int rate);
|
Packet(const std::shared_ptr<RTPPacket>& packet, int timelen, int rate);
|
||||||
std::shared_ptr<RTPPacket> rtp() const;
|
std::shared_ptr<RTPPacket> rtp() const;
|
||||||
|
|
||||||
int timelength() const;
|
int timelength() const;
|
||||||
int rate() const;
|
int rate() const;
|
||||||
|
|
||||||
const std::vector<short>& pcm() const;
|
const std::vector<short>& pcm() const;
|
||||||
std::vector<short>& pcm();
|
std::vector<short>& pcm();
|
||||||
|
|
||||||
|
const std::chrono::microseconds& timestamp() const;
|
||||||
|
std::chrono::microseconds& timestamp();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::shared_ptr<RTPPacket> mRtp;
|
std::shared_ptr<RTPPacket> mRtp;
|
||||||
int mTimelength = 0, mRate = 0;
|
int mTimelength = 0,
|
||||||
std::vector<short> mPcm;
|
mRate = 0;
|
||||||
|
std::vector<short> mPcm;
|
||||||
|
std::chrono::microseconds mTimestamp = 0us;
|
||||||
};
|
};
|
||||||
|
|
||||||
RtpBuffer(Statistics& stat);
|
RtpBuffer(Statistics& stat);
|
||||||
@@ -80,13 +87,13 @@ namespace MT
|
|||||||
|
|
||||||
FetchResult fetch(ResultList& rl);
|
FetchResult fetch(ResultList& rl);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
unsigned mSsrc = 0;
|
unsigned mSsrc = 0;
|
||||||
int mHigh = RTP_BUFFER_HIGH,
|
int mHigh = RTP_BUFFER_HIGH,
|
||||||
mLow = RTP_BUFFER_LOW,
|
mLow = RTP_BUFFER_LOW,
|
||||||
mPrebuffer = RTP_BUFFER_PREBUFFER;
|
mPrebuffer = RTP_BUFFER_PREBUFFER;
|
||||||
int mReturnedCounter = 0,
|
int mReturnedCounter = 0,
|
||||||
mAddCounter = 0;
|
mAddCounter = 0;
|
||||||
|
|
||||||
mutable Mutex mGuard;
|
mutable Mutex mGuard;
|
||||||
typedef std::vector<std::shared_ptr<Packet>> PacketList;
|
typedef std::vector<std::shared_ptr<Packet>> PacketList;
|
||||||
@@ -99,21 +106,21 @@ namespace MT
|
|||||||
|
|
||||||
// To calculate average interval between packet add. It is close to jitter but more useful in debugging.
|
// To calculate average interval between packet add. It is close to jitter but more useful in debugging.
|
||||||
float mLastAddTime = 0.0;
|
float mLastAddTime = 0.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Receiver
|
class Receiver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Receiver(Statistics& stat);
|
Receiver(Statistics& stat);
|
||||||
virtual ~Receiver();
|
virtual ~Receiver();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Statistics& mStat;
|
Statistics& mStat;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AudioReceiver: public Receiver
|
class AudioReceiver: public Receiver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AudioReceiver(const CodecList::Settings& codecSettings, Statistics& stat);
|
AudioReceiver(const CodecList::Settings& codecSettings, Statistics& stat);
|
||||||
~AudioReceiver();
|
~AudioReceiver();
|
||||||
|
|
||||||
@@ -127,10 +134,10 @@ namespace MT
|
|||||||
// Returns false when there is no rtp data from jitter
|
// Returns false when there is no rtp data from jitter
|
||||||
enum DecodeOptions
|
enum DecodeOptions
|
||||||
{
|
{
|
||||||
DecodeOptions_ResampleToMainRate = 0,
|
DecodeOptions_ResampleToMainRate = 0,
|
||||||
DecodeOptions_DontResample = 1,
|
DecodeOptions_DontResample = 1,
|
||||||
DecodeOptions_FillCngGap = 2,
|
DecodeOptions_FillCngGap = 2,
|
||||||
DecodeOptions_SkipDecode = 4
|
DecodeOptions_SkipDecode = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DecodeResult
|
enum DecodeResult
|
||||||
@@ -155,9 +162,9 @@ namespace MT
|
|||||||
// Return samplerate for given packet
|
// Return samplerate for given packet
|
||||||
int samplerateFor(jrtplib::RTPPacket& p);
|
int samplerateFor(jrtplib::RTPPacket& p);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RtpBuffer mBuffer;
|
RtpBuffer mBuffer;
|
||||||
CodecMap mCodecMap;
|
CodecMap mCodecMap;
|
||||||
PCodec mCodec;
|
PCodec mCodec;
|
||||||
int mFrameCount = 0;
|
int mFrameCount = 0;
|
||||||
CodecList::Settings mCodecSettings;
|
CodecList::Settings mCodecSettings;
|
||||||
@@ -186,7 +193,7 @@ namespace MT
|
|||||||
|
|
||||||
int mFailedCount = 0;
|
int mFailedCount = 0;
|
||||||
Audio::Resampler mResampler8, mResampler16,
|
Audio::Resampler mResampler8, mResampler16,
|
||||||
mResampler32, mResampler48;
|
mResampler32, mResampler48;
|
||||||
|
|
||||||
Audio::PWavFileWriter mDecodedDump;
|
Audio::PWavFileWriter mDecodedDump;
|
||||||
|
|
||||||
@@ -202,16 +209,16 @@ namespace MT
|
|||||||
void processDecoded(Audio::DataWindow& output, int options);
|
void processDecoded(Audio::DataWindow& output, int options);
|
||||||
|
|
||||||
void processStatisticsWithAmrCodec(Codec* c);
|
void processStatisticsWithAmrCodec(Codec* c);
|
||||||
};
|
};
|
||||||
|
|
||||||
class DtmfReceiver: public Receiver
|
class DtmfReceiver: public Receiver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DtmfReceiver(Statistics& stat);
|
DtmfReceiver(Statistics& stat);
|
||||||
~DtmfReceiver();
|
~DtmfReceiver();
|
||||||
|
|
||||||
void add(std::shared_ptr<RTPPacket> p);
|
void add(std::shared_ptr<RTPPacket> p);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -50,6 +50,12 @@ protected:
|
|||||||
float mMaxDelta = 0.0f;
|
float mMaxDelta = 0.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PacketLossEvent
|
||||||
|
{
|
||||||
|
int mGap = 0;
|
||||||
|
std::chrono::microseconds mTimestamp;
|
||||||
|
};
|
||||||
|
|
||||||
class Statistics
|
class Statistics
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -78,13 +84,15 @@ public:
|
|||||||
// AMR codec bitrate switch counter
|
// AMR codec bitrate switch counter
|
||||||
int mBitrateSwitchCounter = 0;
|
int mBitrateSwitchCounter = 0;
|
||||||
std::string mCodecName;
|
std::string mCodecName;
|
||||||
float mJitter = 0.0f; // Jitter
|
float mJitter = 0.0f; // Jitter
|
||||||
TestResult<float> mRttDelay; // RTT delay
|
TestResult<float> mRttDelay; // RTT delay
|
||||||
|
|
||||||
// Timestamp when first RTP packet has arrived
|
// Timestamp when first RTP packet has arrived
|
||||||
std::optional<timepoint_t> mFirstRtpTime;
|
std::optional<timepoint_t> mFirstRtpTime;
|
||||||
|
|
||||||
std::map<int, int> mCodecCount; // Stats on used codecs
|
std::map<int, int> mCodecCount; // Stats on used codecs
|
||||||
|
|
||||||
|
std::vector<PacketLossEvent> mPacketLossTimeline; // Packet loss timeline
|
||||||
|
|
||||||
// It is to calculate network MOS
|
// It is to calculate network MOS
|
||||||
void calculateBurstr(double* burstr, double* loss) const;
|
void calculateBurstr(double* burstr, double* loss) const;
|
||||||
|
|||||||
Reference in New Issue
Block a user