diff --git a/src/engine/agent/Agent_Impl.cpp b/src/engine/agent/Agent_Impl.cpp index 2113ced2..e52e9819 100644 --- a/src/engine/agent/Agent_Impl.cpp +++ b/src/engine/agent/Agent_Impl.cpp @@ -535,6 +535,9 @@ void AgentImpl::processGetMediaStats(JsonCpp::Value& request, JsonCpp::Value& an #endif if (result.exists(SessionInfo_PacketLoss)) answer["rtp_lost"] = result[SessionInfo_LostRtp].asInt(); + if (result.exists(SessionInfo_DroppedRtp)) + answer["rtp_dropped"] = result[SessionInfo_DroppedRtp].asInt(); + if (result.exists(SessionInfo_SentRtp)) answer["rtp_sent"] = result[SessionInfo_SentRtp].asInt(); if (result.exists(SessionInfo_ReceivedRtp)) diff --git a/src/engine/endpoint/EP_AudioProvider.h b/src/engine/endpoint/EP_AudioProvider.h index f490cf00..b5968cbd 100644 --- a/src/engine/endpoint/EP_AudioProvider.h +++ b/src/engine/endpoint/EP_AudioProvider.h @@ -43,32 +43,32 @@ public: void sendData(PDatagramSocket s, InternetAddress& destination, const void* dataBuffer, unsigned int datasize); // Updates SDP offer - void updateSdpOffer(resip::SdpContents::Session::Medium& sdp, SdpDirection direction); + void updateSdpOffer(resip::SdpContents::Session::Medium& sdp, SdpDirection direction) override; // Called by user agent when session is deleted. - void sessionDeleted(); + void sessionDeleted() override; // Called by user agent when session is terminated. - void sessionTerminated(); + void sessionTerminated() override; // Called by user agent when session is started. - void sessionEstablished(int conntype); + void sessionEstablished(int conntype) override; // Called by user agent to save media socket for this provider - void setSocket(const RtpPair& p4, const RtpPair& p6); + void setSocket(const RtpPair& p4, const RtpPair& p6) override; // Called by user agent to get media socket for this provider - RtpPair& socket(int family); + RtpPair& socket(int family) override; // Called by user agent to process media stream description from remote peer. // Returns true if description is processed succesfully. Otherwise method returns false. // myAnswer sets if the answer will be sent after. - bool processSdpOffer(const resip::SdpContents::Session::Medium& media, SdpDirection sdpDirection); + bool processSdpOffer(const resip::SdpContents::Session::Medium& media, SdpDirection sdpDirection) override; void setState(unsigned state) override; - unsigned state(); - MT::Statistics getStatistics(); + unsigned state() override; + MT::Statistics getStatistics() override; MT::PStream activeStream(); void readFile(const Audio::PWavFileReader& stream, MT::Stream::MediaDirection direction); diff --git a/src/engine/endpoint/EP_Session.cpp b/src/engine/endpoint/EP_Session.cpp index 773fa0ed..af8792bc 100644 --- a/src/engine/endpoint/EP_Session.cpp +++ b/src/engine/endpoint/EP_Session.cpp @@ -478,6 +478,7 @@ void Session::getSessionInfo(Session::InfoOptions options, VariantMap& info) info[SessionInfo_ReceivedRtp] = static_cast(stat.mReceivedRtp); info[SessionInfo_ReceivedRtcp] = static_cast(stat.mReceivedRtcp); info[SessionInfo_LostRtp] = static_cast(stat.mPacketLoss); + info[SessionInfo_DroppedRtp] = static_cast(stat.mPacketDropped); info[SessionInfo_SentRtp] = static_cast(stat.mSentRtp); info[SessionInfo_SentRtcp] = static_cast(stat.mSentRtcp); if (stat.mFirstRtpTime) diff --git a/src/engine/endpoint/EP_Session.h b/src/engine/endpoint/EP_Session.h index e2f4d00a..0a45ecf2 100644 --- a/src/engine/endpoint/EP_Session.h +++ b/src/engine/endpoint/EP_Session.h @@ -66,12 +66,13 @@ enum SessionInfo SessionInfo_ReceivedRtp, SessionInfo_ReceivedRtcp, SessionInfo_LostRtp, + SessionInfo_DroppedRtp, SessionInfo_Duration, SessionInfo_Jitter, SessionInfo_Rtt, SessionInfo_BitrateSwitchCounter, // It is for AMR codecs only SessionInfo_RemotePeer, - SessionInfo_SSRC + SessionInfo_SSRC, }; diff --git a/src/engine/media/MT_AudioReceiver.cpp b/src/engine/media/MT_AudioReceiver.cpp index 5b749f28..d02f3f46 100644 --- a/src/engine/media/MT_AudioReceiver.cpp +++ b/src/engine/media/MT_AudioReceiver.cpp @@ -26,7 +26,7 @@ using namespace MT; // ----------------- RtpBuffer::Packet -------------- -RtpBuffer::Packet::Packet(std::shared_ptr packet, int timelength, int rate) +RtpBuffer::Packet::Packet(const std::shared_ptr& packet, int timelength, int rate) :mRtp(packet), mTimelength(timelength), mRate(rate) { } @@ -120,9 +120,8 @@ bool RtpBuffer::add(std::shared_ptr packet, int timelength, // New sequence number unsigned newSeqno = packet->GetExtendedSequenceNumber(); - for (PacketList::iterator iter = mPacketList.begin(); iter != mPacketList.end(); iter++) + for (Packet& p: mPacketList) { - Packet& p = *iter; unsigned seqno = p.rtp()->GetExtendedSequenceNumber(); if (seqno == newSeqno) @@ -138,6 +137,7 @@ bool RtpBuffer::add(std::shared_ptr packet, int timelength, minno = seqno; } + // Get amount of available audio (in milliseconds) in jitter buffer int available = findTimelength(); if (newSeqno > minno || (available < mHigh)) @@ -188,6 +188,9 @@ RtpBuffer::FetchResult RtpBuffer::fetch(ResultList& rl) // Erase from packet list mPacketList.erase(mPacketList.begin()); + + // Increase number in statistics + mStat.mPacketDropped++; } if (total < mLow) @@ -351,7 +354,7 @@ AudioReceiver::~AudioReceiver() } -bool AudioReceiver::add(std::shared_ptr p, Codec** codec) +bool AudioReceiver::add(const std::shared_ptr& p, Codec** codec) { // Increase codec counter mStat.mCodecCount[p->GetPayloadType()]++; @@ -373,20 +376,20 @@ bool AudioReceiver::add(std::shared_ptr p, Codec** codec) codecIter->second = mCodecList.codecAt(codecIndex).create(); } - // Return pointer to codec if needed + // Return pointer to codec if needed.get() if (codec) *codec = codecIter->second.get(); if (mStat.mCodecName.empty()) - mStat.mCodecName = codecIter->second.get()->name(); + mStat.mCodecName = codecIter->second->name(); // Estimate time length - int timelen = 0, payloadLength = p->GetPayloadLength(), ptype = p->GetPayloadType(); + int time_length = 0, payloadLength = p->GetPayloadLength(), ptype = p->GetPayloadType(); if (!codecIter->second->rtpLength()) - timelen = codecIter->second->frameTime(); + time_length = codecIter->second->frameTime(); else - timelen = int(double(payloadLength) / codecIter->second->rtpLength() * codecIter->second->frameTime() + 0.5); + time_length = lround(double(payloadLength) / codecIter->second->rtpLength() * codecIter->second->frameTime()); // Process jitter mJitterStats.process(p.get(), codecIter->second->samplerate()); @@ -394,19 +397,19 @@ bool AudioReceiver::add(std::shared_ptr p, Codec** codec) // Check if packet is CNG if (payloadLength >= 1 && payloadLength <= 6 && (ptype == 0 || ptype == 8)) - timelen = mLastPacketTimeLength ? mLastPacketTimeLength : 20; + time_length = mLastPacketTimeLength ? mLastPacketTimeLength : 20; else // Check if packet is too short from time length side - if (timelen < 2) + if (time_length < 2) { // It will cause statistics to report about bad RTP packet // I have to replay last packet payload here to avoid report about lost packet - mBuffer.add(p, timelen, codecIter->second->samplerate()); + mBuffer.add(p, time_length, codecIter->second->samplerate()); return false; } // Queue packet to buffer - return mBuffer.add(p, timelen, codecIter->second->samplerate()); + return mBuffer.add(p, time_length, codecIter->second->samplerate()); } void AudioReceiver::processDecoded(Audio::DataWindow& output, int options) diff --git a/src/engine/media/MT_AudioReceiver.h b/src/engine/media/MT_AudioReceiver.h index 730935d4..1f1cece3 100644 --- a/src/engine/media/MT_AudioReceiver.h +++ b/src/engine/media/MT_AudioReceiver.h @@ -45,7 +45,7 @@ namespace MT class Packet { public: - Packet(std::shared_ptr packet, int timelen, int rate); + Packet(const std::shared_ptr& packet, int timelen, int rate); std::shared_ptr rtp() const; int timelength() const; int rate() const; @@ -109,7 +109,7 @@ namespace MT // Returns false when packet is rejected as illegal. codec parameter will show codec which will be used for decoding. // Lifetime of pointer to codec is limited by lifetime of AudioReceiver (it is container). - bool add(std::shared_ptr p, Codec** codec = nullptr); + bool add(const std::shared_ptr& p, Codec** codec = nullptr); // Returns false when there is no rtp data from jitter enum DecodeOptions @@ -178,6 +178,7 @@ namespace MT void initPvqa(); void updatePvqa(const void* data, int size); float calculatePvqaMos(int rate, std::string& report); + std::shared_ptr mPvqaBuffer; #endif diff --git a/src/engine/media/MT_Statistics.cpp b/src/engine/media/MT_Statistics.cpp index ae2a1dd6..aa0c3c9d 100644 --- a/src/engine/media/MT_Statistics.cpp +++ b/src/engine/media/MT_Statistics.cpp @@ -40,7 +40,7 @@ void JitterStatistics::process(jrtplib::RTPPacket* packet, int rate) int64_t delta = receiveDelta - timestampDelta; // Update max delta in milliseconds - double delta_in_seconds = fabs(double(delta) / rate); + float delta_in_seconds = float(fabs(double(delta) / rate)); if (delta_in_seconds > mMaxDelta) mMaxDelta = delta_in_seconds; @@ -56,7 +56,7 @@ void JitterStatistics::process(jrtplib::RTPPacket* packet, int rate) mReceiveTimestamp = timestamp; // And mJitter are in seconds again - mJitter.process(mLastJitter.value() / rate); + mJitter.process(mLastJitter.value() / float(rate)); } } @@ -67,7 +67,7 @@ void JitterStatistics::process(jrtplib::RTPPacket* packet, int rate) Statistics::Statistics() :mReceived(0), mSent(0), mReceivedRtp(0), mSentRtp(0), mReceivedRtcp(0), mSentRtcp(0), mDuplicatedRtp(0), mOldRtp(0), mIllegalRtp(0), - mPacketLoss(0), mJitter(0.0), mAudioTime(0), mSsrc(0) + mPacketLoss(0), mJitter(0.0), mAudioTime(0), mSsrc(0), mPacketDropped(0) { mBitrateSwitchCounter = 0; memset(mLoss, 0, sizeof mLoss); @@ -94,64 +94,11 @@ void Statistics::reset() mIllegalRtp = 0; mJitter = 0.0; mAudioTime = 0; + mPacketDropped = 0; + memset(mLoss, 0, sizeof mLoss); } -/* -double calculate_mos_g711(double ppl, double burstr, int version) { -double r; -double bpl = 8.47627; //mos = -4.23836 + 0.29873 * r - 0.00416744 * r * r + 0.0000209855 * r * r * r; -double mos; - -if(ppl == 0 or burstr == 0) { -return 4.5; -} - -if(ppl > 0.5) { -return 1; -} - -switch(version) { -case 1: -case 2: -default: -// this mos is calculated for G.711 and PLC -bpl = 17.2647; -r = 93.2062077233 - 95.0 * (ppl*100/(ppl*100/burstr + bpl)); -mos = 2.06405 + 0.031738 * r - 0.000356641 * r * r + 2.93143 * pow(10,-6) * r * r * r; -if(mos < 1) -return 1; -if(mos > 4.5) -return 4.5; -} - -return mos; -} - - -double calculate_mos(double ppl, double burstr, int codec, unsigned int received) { -if(codec == PAYLOAD_G729) { -if(opt_mos_g729) { -if(received < 100) { -return 3.92; -} -return (double)mos_g729((long double)ppl, (long double)burstr); -} else { -if(received < 100) { -return 4.5; -} -return calculate_mos_g711(ppl, burstr, 2); -} -} else { -if(received < 100) { -return 4.5; -} -return calculate_mos_g711(ppl, burstr, 2); -} -} - -*/ - void Statistics::calculateBurstr(double* burstr, double* lossr) const { int lost = 0; @@ -230,8 +177,10 @@ Statistics& Statistics::operator += (const Statistics& src) mDuplicatedRtp += src.mDuplicatedRtp; mOldRtp += src.mOldRtp; mPacketLoss += src.mPacketLoss; + mPacketDropped += src.mPacketDropped; mAudioTime += src.mAudioTime; + for (auto codecStat: src.mCodecCount) { if (mCodecCount.find(codecStat.first) == mCodecCount.end()) @@ -277,6 +226,8 @@ Statistics& Statistics::operator -= (const Statistics& src) mDuplicatedRtp -= src.mDuplicatedRtp; mOldRtp -= src.mOldRtp; mPacketLoss -= src.mPacketLoss; + mPacketDropped -= src.mPacketDropped; + mAudioTime -= src.mAudioTime; for (auto codecStat: src.mCodecCount) { @@ -291,9 +242,10 @@ Statistics& Statistics::operator -= (const Statistics& src) std::string Statistics::toShortString() const { std::ostringstream oss; - oss << "Received: " << mReceivedRtp - << ", lost: " << mPacketLoss - << ", sent: " << mSentRtp; + oss << "Received: " << mReceivedRtp + << ", lost: " << mPacketLoss + << ", dropped: " << mPacketDropped + << ", sent: " << mSentRtp; return oss.str(); } diff --git a/src/engine/media/MT_Statistics.h b/src/engine/media/MT_Statistics.h index c8ea709c..e7d10f08 100644 --- a/src/engine/media/MT_Statistics.h +++ b/src/engine/media/MT_Statistics.h @@ -130,7 +130,9 @@ public: mDuplicatedRtp, // Number of received duplicated rtp packets mOldRtp, // Number of late rtp packets mPacketLoss, // Number of lost packets + mPacketDropped, // Number of dropped packets (due to time unsync when playing) mIllegalRtp; // Number of rtp packets with bad payload type + int mLoss[128]; // Every item is number of loss of corresping length size_t mAudioTime; // Decoded/found time in milliseconds uint16_t mSsrc; // Last known SSRC ID in a RTP stream