diff --git a/src/engine/media/MT_AudioReceiver.cpp b/src/engine/media/MT_AudioReceiver.cpp index ee891f1d..d608a31a 100644 --- a/src/engine/media/MT_AudioReceiver.cpp +++ b/src/engine/media/MT_AudioReceiver.cpp @@ -224,11 +224,6 @@ RtpBuffer::FetchResult RtpBuffer::fetch(ResultList& rl) } 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 (mPacketList.empty()) @@ -239,7 +234,8 @@ RtpBuffer::FetchResult RtpBuffer::fetch(ResultList& rl) else { // 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 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; 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; result = FetchResult::Gap; } diff --git a/src/engine/media/MT_AudioReceiver.h b/src/engine/media/MT_AudioReceiver.h index 8c2c23b2..af739dce 100644 --- a/src/engine/media/MT_AudioReceiver.h +++ b/src/engine/media/MT_AudioReceiver.h @@ -18,37 +18,44 @@ #include "../audio/Audio_Resampler.h" #include +#include +using namespace std::chrono_literals; namespace MT { - using jrtplib::RTPPacket; - class RtpBuffer - { - public: +using jrtplib::RTPPacket; +class RtpBuffer +{ +public: enum class FetchResult { - RegularPacket, - Gap, - NoPacket + RegularPacket, + Gap, + NoPacket }; // Owns rtp packet data class Packet { public: - Packet(const std::shared_ptr& packet, int timelen, int rate); - std::shared_ptr rtp() const; + Packet(const std::shared_ptr& packet, int timelen, int rate); + std::shared_ptr rtp() const; - int timelength() const; - int rate() const; + int timelength() const; + int rate() const; - const std::vector& pcm() const; - std::vector& pcm(); + const std::vector& pcm() const; + std::vector& pcm(); + + const std::chrono::microseconds& timestamp() const; + std::chrono::microseconds& timestamp(); protected: - std::shared_ptr mRtp; - int mTimelength = 0, mRate = 0; - std::vector mPcm; + std::shared_ptr mRtp; + int mTimelength = 0, + mRate = 0; + std::vector mPcm; + std::chrono::microseconds mTimestamp = 0us; }; RtpBuffer(Statistics& stat); @@ -80,13 +87,13 @@ namespace MT FetchResult fetch(ResultList& rl); - protected: +protected: unsigned mSsrc = 0; int mHigh = RTP_BUFFER_HIGH, - mLow = RTP_BUFFER_LOW, - mPrebuffer = RTP_BUFFER_PREBUFFER; + mLow = RTP_BUFFER_LOW, + mPrebuffer = RTP_BUFFER_PREBUFFER; int mReturnedCounter = 0, - mAddCounter = 0; + mAddCounter = 0; mutable Mutex mGuard; typedef std::vector> PacketList; @@ -99,21 +106,21 @@ namespace MT // To calculate average interval between packet add. It is close to jitter but more useful in debugging. float mLastAddTime = 0.0; - }; +}; - class Receiver - { - public: +class Receiver +{ +public: Receiver(Statistics& stat); virtual ~Receiver(); - protected: +protected: Statistics& mStat; - }; +}; - class AudioReceiver: public Receiver - { - public: +class AudioReceiver: public Receiver +{ +public: AudioReceiver(const CodecList::Settings& codecSettings, Statistics& stat); ~AudioReceiver(); @@ -127,10 +134,10 @@ namespace MT // Returns false when there is no rtp data from jitter enum DecodeOptions { - DecodeOptions_ResampleToMainRate = 0, - DecodeOptions_DontResample = 1, - DecodeOptions_FillCngGap = 2, - DecodeOptions_SkipDecode = 4 + DecodeOptions_ResampleToMainRate = 0, + DecodeOptions_DontResample = 1, + DecodeOptions_FillCngGap = 2, + DecodeOptions_SkipDecode = 4 }; enum DecodeResult @@ -155,9 +162,9 @@ namespace MT // Return samplerate for given packet int samplerateFor(jrtplib::RTPPacket& p); - protected: +protected: RtpBuffer mBuffer; - CodecMap mCodecMap; + CodecMap mCodecMap; PCodec mCodec; int mFrameCount = 0; CodecList::Settings mCodecSettings; @@ -186,7 +193,7 @@ namespace MT int mFailedCount = 0; Audio::Resampler mResampler8, mResampler16, - mResampler32, mResampler48; + mResampler32, mResampler48; Audio::PWavFileWriter mDecodedDump; @@ -202,16 +209,16 @@ namespace MT void processDecoded(Audio::DataWindow& output, int options); void processStatisticsWithAmrCodec(Codec* c); - }; - - class DtmfReceiver: public Receiver - { - public: +}; + +class DtmfReceiver: public Receiver +{ +public: DtmfReceiver(Statistics& stat); ~DtmfReceiver(); void add(std::shared_ptr p); - }; +}; } #endif diff --git a/src/engine/media/MT_Statistics.h b/src/engine/media/MT_Statistics.h index b5d1c6ac..9c838b0f 100644 --- a/src/engine/media/MT_Statistics.h +++ b/src/engine/media/MT_Statistics.h @@ -50,6 +50,12 @@ protected: float mMaxDelta = 0.0f; }; +struct PacketLossEvent +{ + int mGap = 0; + std::chrono::microseconds mTimestamp; +}; + class Statistics { public: @@ -78,13 +84,15 @@ public: // AMR codec bitrate switch counter int mBitrateSwitchCounter = 0; std::string mCodecName; - float mJitter = 0.0f; // Jitter - TestResult mRttDelay; // RTT delay + float mJitter = 0.0f; // Jitter + TestResult mRttDelay; // RTT delay // Timestamp when first RTP packet has arrived std::optional mFirstRtpTime; - std::map mCodecCount; // Stats on used codecs + std::map mCodecCount; // Stats on used codecs + + std::vector mPacketLossTimeline; // Packet loss timeline // It is to calculate network MOS void calculateBurstr(double* burstr, double* loss) const;