diff options
-rw-r--r-- | modules/rtp_rtcp/interface/receive_statistics.h | 23 | ||||
-rw-r--r-- | modules/rtp_rtcp/source/receive_statistics_impl.cc | 42 | ||||
-rw-r--r-- | modules/rtp_rtcp/source/receive_statistics_impl.h | 21 | ||||
-rw-r--r-- | modules/rtp_rtcp/source/receive_statistics_unittest.cc | 83 | ||||
-rw-r--r-- | modules/rtp_rtcp/source/rtcp_sender.cc | 2 | ||||
-rw-r--r-- | modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc | 2 | ||||
-rw-r--r-- | video/video_send_stream_tests.cc | 6 | ||||
-rw-r--r-- | video_engine/vie_channel.cc | 15 | ||||
-rw-r--r-- | video_engine/vie_channel.h | 4 | ||||
-rw-r--r-- | video_engine/vie_rtp_rtcp_impl.cc | 32 | ||||
-rw-r--r-- | voice_engine/channel.cc | 88 | ||||
-rw-r--r-- | voice_engine/channel.h | 2 |
12 files changed, 260 insertions, 60 deletions
diff --git a/modules/rtp_rtcp/interface/receive_statistics.h b/modules/rtp_rtcp/interface/receive_statistics.h index 707adaa0..d034b495 100644 --- a/modules/rtp_rtcp/interface/receive_statistics.h +++ b/modules/rtp_rtcp/interface/receive_statistics.h @@ -23,24 +23,9 @@ class Clock; class StreamStatistician { public: - struct Statistics { - Statistics() - : fraction_lost(0), - cumulative_lost(0), - extended_max_sequence_number(0), - jitter(0), - max_jitter(0) {} - - uint8_t fraction_lost; - uint32_t cumulative_lost; - uint32_t extended_max_sequence_number; - uint32_t jitter; - uint32_t max_jitter; - }; - virtual ~StreamStatistician(); - virtual bool GetStatistics(Statistics* statistics, bool reset) = 0; + virtual bool GetStatistics(RtcpStatistics* statistics, bool reset) = 0; virtual void GetDataCounters(uint32_t* bytes_received, uint32_t* packets_received) const = 0; virtual uint32_t BitrateReceived() const = 0; @@ -78,6 +63,10 @@ class ReceiveStatistics : public Module { // Sets the max reordering threshold in number of packets. virtual void SetMaxReorderingThreshold(int max_reordering_threshold) = 0; + + // Called on new RTCP stats creation. + virtual void RegisterRtcpStatisticsCallback( + RtcpStatisticsCallback* callback) = 0; }; class NullReceiveStatistics : public ReceiveStatistics { @@ -89,6 +78,8 @@ class NullReceiveStatistics : public ReceiveStatistics { virtual int32_t TimeUntilNextProcess() OVERRIDE; virtual int32_t Process() OVERRIDE; virtual void SetMaxReorderingThreshold(int max_reordering_threshold) OVERRIDE; + virtual void RegisterRtcpStatisticsCallback(RtcpStatisticsCallback* callback) + OVERRIDE; }; } // namespace webrtc diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.cc b/modules/rtp_rtcp/source/receive_statistics_impl.cc index 3ed44b83..2b085c38 100644 --- a/modules/rtp_rtcp/source/receive_statistics_impl.cc +++ b/modules/rtp_rtcp/source/receive_statistics_impl.cc @@ -24,14 +24,15 @@ const int kStatisticsProcessIntervalMs = 1000; StreamStatistician::~StreamStatistician() {} -StreamStatisticianImpl::StreamStatisticianImpl(Clock* clock) +StreamStatisticianImpl::StreamStatisticianImpl( + Clock* clock, + RtcpStatisticsCallback* rtcp_callback) : clock_(clock), crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), incoming_bitrate_(clock, NULL), ssrc_(0), max_reordering_threshold_(kDefaultMaxReorderingThreshold), jitter_q4_(0), - jitter_max_q4_(0), cumulative_loss_(0), jitter_q4_transmission_time_offset_(0), last_receive_time_ms_(0), @@ -50,7 +51,8 @@ StreamStatisticianImpl::StreamStatisticianImpl(Clock* clock) last_report_inorder_packets_(0), last_report_old_packets_(0), last_report_seq_max_(0), - last_reported_statistics_() {} + last_reported_statistics_(), + rtcp_callback_(rtcp_callback) {} void StreamStatisticianImpl::ResetStatistics() { CriticalSectionScoped cs(crit_sect_.get()); @@ -59,7 +61,6 @@ void StreamStatisticianImpl::ResetStatistics() { last_report_seq_max_ = 0; memset(&last_reported_statistics_, 0, sizeof(last_reported_statistics_)); jitter_q4_ = 0; - jitter_max_q4_ = 0; cumulative_loss_ = 0; jitter_q4_transmission_time_offset_ = 0; received_seq_wraps_ = 0; @@ -173,7 +174,8 @@ void StreamStatisticianImpl::SetMaxReorderingThreshold( max_reordering_threshold_ = max_reordering_threshold; } -bool StreamStatisticianImpl::GetStatistics(Statistics* statistics, bool reset) { +bool StreamStatisticianImpl::GetStatistics(RtcpStatistics* statistics, + bool reset) { CriticalSectionScoped cs(crit_sect_.get()); if (received_seq_first_ == 0 && received_byte_count_ == 0) { // We have not received anything. @@ -235,16 +237,11 @@ bool StreamStatisticianImpl::GetStatistics(Statistics* statistics, bool reset) { // We need a counter for cumulative loss too. cumulative_loss_ += missing; - - if (jitter_q4_ > jitter_max_q4_) { - jitter_max_q4_ = jitter_q4_; - } statistics->cumulative_lost = cumulative_loss_; statistics->extended_max_sequence_number = (received_seq_wraps_ << 16) + received_seq_max_; // Note: internal jitter value is in Q4 and needs to be scaled by 1/16. statistics->jitter = jitter_q4_ >> 4; - statistics->max_jitter = jitter_max_q4_ >> 4; if (reset) { // Store this report. last_reported_statistics_ = *statistics; @@ -254,6 +251,8 @@ bool StreamStatisticianImpl::GetStatistics(Statistics* statistics, bool reset) { last_report_old_packets_ = received_retransmitted_packets_; last_report_seq_max_ = received_seq_max_; } + + rtcp_callback_->StatisticsUpdated(last_reported_statistics_, ssrc_); return true; } @@ -349,7 +348,8 @@ ReceiveStatistics* ReceiveStatistics::Create(Clock* clock) { ReceiveStatisticsImpl::ReceiveStatisticsImpl(Clock* clock) : clock_(clock), crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), - last_rate_update_ms_(0) {} + last_rate_update_ms_(0), + rtcp_stats_callback_(NULL) {} ReceiveStatisticsImpl::~ReceiveStatisticsImpl() { while (!statisticians_.empty()) { @@ -365,7 +365,7 @@ void ReceiveStatisticsImpl::IncomingPacket(const RTPHeader& header, if (it == statisticians_.end()) { std::pair<StatisticianImplMap::iterator, uint32_t> insert_result = statisticians_.insert(std::make_pair( - header.ssrc, new StreamStatisticianImpl(clock_))); + header.ssrc, new StreamStatisticianImpl(clock_, this))); it = insert_result.first; } statisticians_[header.ssrc]->IncomingPacket(header, bytes, old_packet); @@ -433,6 +433,21 @@ int32_t ReceiveStatisticsImpl::TimeUntilNextProcess() { return std::max(kStatisticsProcessIntervalMs - time_since_last_update, 0); } +void ReceiveStatisticsImpl::RegisterRtcpStatisticsCallback( + RtcpStatisticsCallback* callback) { + CriticalSectionScoped cs(crit_sect_.get()); + if (callback != NULL) + assert(rtcp_stats_callback_ == NULL); + rtcp_stats_callback_ = callback; +} + +void ReceiveStatisticsImpl::StatisticsUpdated(const RtcpStatistics& statistics, + uint32_t ssrc) { + CriticalSectionScoped cs(crit_sect_.get()); + if (rtcp_stats_callback_) { + rtcp_stats_callback_->StatisticsUpdated(statistics, ssrc); + } +} void NullReceiveStatistics::IncomingPacket(const RTPHeader& rtp_header, size_t bytes, @@ -454,4 +469,7 @@ int32_t NullReceiveStatistics::TimeUntilNextProcess() { return 0; } int32_t NullReceiveStatistics::Process() { return 0; } +void NullReceiveStatistics::RegisterRtcpStatisticsCallback( + RtcpStatisticsCallback* callback) {} + } // namespace webrtc diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.h b/modules/rtp_rtcp/source/receive_statistics_impl.h index 0af074c4..bb6de338 100644 --- a/modules/rtp_rtcp/source/receive_statistics_impl.h +++ b/modules/rtp_rtcp/source/receive_statistics_impl.h @@ -25,11 +25,10 @@ class CriticalSectionWrapper; class StreamStatisticianImpl : public StreamStatistician { public: - explicit StreamStatisticianImpl(Clock* clock); - + StreamStatisticianImpl(Clock* clock, RtcpStatisticsCallback* rtcp_callback); virtual ~StreamStatisticianImpl() {} - virtual bool GetStatistics(Statistics* statistics, bool reset) OVERRIDE; + virtual bool GetStatistics(RtcpStatistics* statistics, bool reset) OVERRIDE; virtual void GetDataCounters(uint32_t* bytes_received, uint32_t* packets_received) const OVERRIDE; virtual uint32_t BitrateReceived() const OVERRIDE; @@ -55,7 +54,6 @@ class StreamStatisticianImpl : public StreamStatistician { // Stats on received RTP packets. uint32_t jitter_q4_; - uint32_t jitter_max_q4_; uint32_t cumulative_loss_; uint32_t jitter_q4_transmission_time_offset_; @@ -79,10 +77,13 @@ class StreamStatisticianImpl : public StreamStatistician { uint32_t last_report_inorder_packets_; uint32_t last_report_old_packets_; uint16_t last_report_seq_max_; - Statistics last_reported_statistics_; + RtcpStatistics last_reported_statistics_; + + RtcpStatisticsCallback* const rtcp_callback_; }; -class ReceiveStatisticsImpl : public ReceiveStatistics { +class ReceiveStatisticsImpl : public ReceiveStatistics, + public RtcpStatisticsCallback { public: explicit ReceiveStatisticsImpl(Clock* clock); @@ -101,6 +102,12 @@ class ReceiveStatisticsImpl : public ReceiveStatistics { void ChangeSsrc(uint32_t from_ssrc, uint32_t to_ssrc); + virtual void RegisterRtcpStatisticsCallback(RtcpStatisticsCallback* callback) + OVERRIDE; + + virtual void StatisticsUpdated(const RtcpStatistics& statistics, + uint32_t ssrc) OVERRIDE; + private: typedef std::map<uint32_t, StreamStatisticianImpl*> StatisticianImplMap; @@ -108,6 +115,8 @@ class ReceiveStatisticsImpl : public ReceiveStatistics { scoped_ptr<CriticalSectionWrapper> crit_sect_; int64_t last_rate_update_ms_; StatisticianImplMap statisticians_; + + RtcpStatisticsCallback* rtcp_stats_callback_; }; } // namespace webrtc #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RECEIVE_STATISTICS_IMPL_H_ diff --git a/modules/rtp_rtcp/source/receive_statistics_unittest.cc b/modules/rtp_rtcp/source/receive_statistics_unittest.cc index be8f2fcd..6969bbc8 100644 --- a/modules/rtp_rtcp/source/receive_statistics_unittest.cc +++ b/modules/rtp_rtcp/source/receive_statistics_unittest.cc @@ -131,4 +131,87 @@ TEST_F(ReceiveStatisticsTest, ActiveStatisticians) { EXPECT_EQ(200u, bytes_received); EXPECT_EQ(2u, packets_received); } + +TEST_F(ReceiveStatisticsTest, Callbacks) { + class TestCallback : public RtcpStatisticsCallback { + public: + TestCallback() + : RtcpStatisticsCallback(), num_calls_(0), ssrc_(0), stats_() {} + virtual ~TestCallback() {} + + virtual void StatisticsUpdated(const RtcpStatistics& statistics, + uint32_t ssrc) { + ssrc_ = ssrc; + stats_ = statistics; + ++num_calls_; + } + + uint32_t num_calls_; + uint32_t ssrc_; + RtcpStatistics stats_; + } callback; + + receive_statistics_->RegisterRtcpStatisticsCallback(&callback); + + // Add some arbitrary data, with loss and jitter. + header1_.sequenceNumber = 1; + clock_.AdvanceTimeMilliseconds(7); + header1_.timestamp += 3; + receive_statistics_->IncomingPacket(header1_, kPacketSize1, false); + header1_.sequenceNumber += 2; + clock_.AdvanceTimeMilliseconds(9); + header1_.timestamp += 9; + receive_statistics_->IncomingPacket(header1_, kPacketSize1, false); + --header1_.sequenceNumber; + clock_.AdvanceTimeMilliseconds(13); + header1_.timestamp += 47; + receive_statistics_->IncomingPacket(header1_, kPacketSize1, true); + header1_.sequenceNumber += 3; + clock_.AdvanceTimeMilliseconds(11); + header1_.timestamp += 17; + receive_statistics_->IncomingPacket(header1_, kPacketSize1, false); + ++header1_.sequenceNumber; + + EXPECT_EQ(0u, callback.num_calls_); + + // Call GetStatistics, simulating a timed rtcp sender thread. + RtcpStatistics statistics; + receive_statistics_->GetStatistician(kSsrc1) + ->GetStatistics(&statistics, true); + + EXPECT_EQ(1u, callback.num_calls_); + EXPECT_EQ(callback.ssrc_, kSsrc1); + EXPECT_EQ(statistics.cumulative_lost, callback.stats_.cumulative_lost); + EXPECT_EQ(statistics.extended_max_sequence_number, + callback.stats_.extended_max_sequence_number); + EXPECT_EQ(statistics.fraction_lost, callback.stats_.fraction_lost); + EXPECT_EQ(statistics.jitter, callback.stats_.jitter); + + receive_statistics_->RegisterRtcpStatisticsCallback(NULL); + + // Add some more data. + header1_.sequenceNumber = 1; + clock_.AdvanceTimeMilliseconds(7); + header1_.timestamp += 3; + receive_statistics_->IncomingPacket(header1_, kPacketSize1, false); + header1_.sequenceNumber += 2; + clock_.AdvanceTimeMilliseconds(9); + header1_.timestamp += 9; + receive_statistics_->IncomingPacket(header1_, kPacketSize1, false); + --header1_.sequenceNumber; + clock_.AdvanceTimeMilliseconds(13); + header1_.timestamp += 47; + receive_statistics_->IncomingPacket(header1_, kPacketSize1, true); + header1_.sequenceNumber += 3; + clock_.AdvanceTimeMilliseconds(11); + header1_.timestamp += 17; + receive_statistics_->IncomingPacket(header1_, kPacketSize1, false); + ++header1_.sequenceNumber; + + receive_statistics_->GetStatistician(kSsrc1) + ->GetStatistics(&statistics, true); + + // Should not have been called after deregister. + EXPECT_EQ(1u, callback.num_calls_); +} } // namespace webrtc diff --git a/modules/rtp_rtcp/source/rtcp_sender.cc b/modules/rtp_rtcp/source/rtcp_sender.cc index a407a42c..8cac9969 100644 --- a/modules/rtp_rtcp/source/rtcp_sender.cc +++ b/modules/rtp_rtcp/source/rtcp_sender.cc @@ -2065,7 +2065,7 @@ bool RTCPSender::PrepareReport(const FeedbackState& feedback_state, RTCPReportBlock* report_block, uint32_t* ntp_secs, uint32_t* ntp_frac) { // Do we have receive statistics to send? - StreamStatistician::Statistics stats; + RtcpStatistics stats; if (!statistician->GetStatistics(&stats, true)) return false; report_block->fractionLost = stats.fraction_lost; diff --git a/modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc b/modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc index 3df06a21..1e715187 100644 --- a/modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc +++ b/modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc @@ -336,7 +336,7 @@ TEST_F(RtpRtcpRtcpTest, RTCP) { StreamStatistician *statistician = receive_statistics2_->GetStatistician(reportBlockReceived.sourceSSRC); - StreamStatistician::Statistics stats; + RtcpStatistics stats; EXPECT_TRUE(statistician->GetStatistics(&stats, true)); EXPECT_EQ(0, stats.fraction_lost); EXPECT_EQ((uint32_t)0, stats.cumulative_lost); diff --git a/video/video_send_stream_tests.cc b/video/video_send_stream_tests.cc index b03b76a5..42259e38 100644 --- a/video/video_send_stream_tests.cc +++ b/video/video_send_stream_tests.cc @@ -348,7 +348,8 @@ class FakeReceiveStatistics : public NullReceiveStatistics { stats_.cumulative_lost = cumulative_lost; stats_.extended_max_sequence_number = extended_max_sequence_number; } - virtual bool GetStatistics(Statistics* statistics, bool reset) OVERRIDE { + virtual bool GetStatistics(RtcpStatistics* statistics, + bool reset) OVERRIDE { *statistics = stats_; return true; } @@ -367,7 +368,8 @@ class FakeReceiveStatistics : public NullReceiveStatistics { virtual bool IsPacketInOrder(uint16_t sequence_number) const OVERRIDE { return true; } - Statistics stats_; + + RtcpStatistics stats_; }; scoped_ptr<LossyStatistician> lossy_stats_; diff --git a/video_engine/vie_channel.cc b/video_engine/vie_channel.cc index 2305ea78..54731775 100644 --- a/video_engine/vie_channel.cc +++ b/video_engine/vie_channel.cc @@ -345,6 +345,8 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec, } rtp_rtcp->SetSendingStatus(rtp_rtcp_->Sending()); rtp_rtcp->SetSendingMediaStatus(rtp_rtcp_->SendingMedia()); + rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback( + rtp_rtcp_->GetSendChannelRtcpStatisticsCallback()); simulcast_rtp_rtcp_.push_back(rtp_rtcp); } // Remove last in list if we have too many. @@ -1297,7 +1299,7 @@ int32_t ViEChannel::GetReceivedRtcpStatistics(uint16_t* fraction_lost, uint32_t remote_ssrc = vie_receiver_.GetRemoteSsrc(); StreamStatistician* statistician = vie_receiver_.GetReceiveStatistics()->GetStatistician(remote_ssrc); - StreamStatistician::Statistics receive_stats; + RtcpStatistics receive_stats; if (!statistician || !statistician->GetStatistics( &receive_stats, rtp_rtcp_->RTCP() == kRtcpOff)) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), @@ -1319,6 +1321,17 @@ int32_t ViEChannel::GetReceivedRtcpStatistics(uint16_t* fraction_lost, return 0; } +void ViEChannel::RegisterReceiveChannelRtcpStatisticsCallback( + RtcpStatisticsCallback* callback) { + WEBRTC_TRACE(kTraceInfo, + kTraceVideo, + ViEId(engine_id_, channel_id_), + "%s", + __FUNCTION__); + vie_receiver_.GetReceiveStatistics()->RegisterRtcpStatisticsCallback( + callback); +} + int32_t ViEChannel::GetRtpStatistics(uint32_t* bytes_sent, uint32_t* packets_sent, uint32_t* bytes_received, diff --git a/video_engine/vie_channel.h b/video_engine/vie_channel.h index 33bf7bf2..dd602eed 100644 --- a/video_engine/vie_channel.h +++ b/video_engine/vie_channel.h @@ -185,6 +185,10 @@ class ViEChannel uint32_t* jitter_samples, int32_t* rtt_ms); + // Called on generation of RTCP stats + void RegisterReceiveChannelRtcpStatisticsCallback( + RtcpStatisticsCallback* callback); + // Gets sent/received packets statistics. int32_t GetRtpStatistics(uint32_t* bytes_sent, uint32_t* packets_sent, diff --git a/video_engine/vie_rtp_rtcp_impl.cc b/video_engine/vie_rtp_rtcp_impl.cc index 2bd47bec..d9f2211d 100644 --- a/video_engine/vie_rtp_rtcp_impl.cc +++ b/video_engine/vie_rtp_rtcp_impl.cc @@ -1168,15 +1168,35 @@ int ViERTP_RTCPImpl::DeregisterSendChannelRtcpStatisticsCallback( } int ViERTP_RTCPImpl::RegisterReceiveChannelRtcpStatisticsCallback( - int channel, RtcpStatisticsCallback* callback) { - // TODO(sprang): Implement - return -1; + const int video_channel, + RtcpStatisticsCallback* callback) { + WEBRTC_TRACE(kTraceApiCall, + kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s(channel: %d)", + __FUNCTION__, + video_channel); + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + assert(vie_channel != NULL); + vie_channel->RegisterReceiveChannelRtcpStatisticsCallback(callback); + return 0; } int ViERTP_RTCPImpl::DeregisterReceiveChannelRtcpStatisticsCallback( - int channel, RtcpStatisticsCallback* callback) { - // TODO(sprang): Implement - return -1; + const int video_channel, + RtcpStatisticsCallback* callback) { + WEBRTC_TRACE(kTraceApiCall, + kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s(channel: %d)", + __FUNCTION__, + video_channel); + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + assert(vie_channel != NULL); + vie_channel->RegisterReceiveChannelRtcpStatisticsCallback(NULL); + return 0; } int ViERTP_RTCPImpl::RegisterSendChannelRtpStatisticsCallback( diff --git a/voice_engine/channel.cc b/voice_engine/channel.cc index 1eb55afa..2724f528 100644 --- a/voice_engine/channel.cc +++ b/voice_engine/channel.cc @@ -38,6 +38,54 @@ namespace webrtc { namespace voe { +// Extend the default RTCP statistics struct with max_jitter, defined as the +// maximum jitter value seen in an RTCP report block. +struct ChannelStatistics : public RtcpStatistics { + ChannelStatistics() : rtcp(), max_jitter(0) {} + + RtcpStatistics rtcp; + uint32_t max_jitter; +}; + +// Statistics callback, called at each generation of a new RTCP report block. +class StatisticsProxy : public RtcpStatisticsCallback { + public: + StatisticsProxy(uint32_t ssrc) + : stats_lock_(CriticalSectionWrapper::CreateCriticalSection()), + ssrc_(ssrc) {} + virtual ~StatisticsProxy() {} + + virtual void StatisticsUpdated(const RtcpStatistics& statistics, + uint32_t ssrc) OVERRIDE { + if (ssrc != ssrc_) + return; + + CriticalSectionScoped cs(stats_lock_.get()); + stats_.rtcp = statistics; + if (statistics.jitter > stats_.max_jitter) { + stats_.max_jitter = statistics.jitter; + } + } + + void ResetStatistics() { + CriticalSectionScoped cs(stats_lock_.get()); + stats_ = ChannelStatistics(); + } + + ChannelStatistics GetStats() { + CriticalSectionScoped cs(stats_lock_.get()); + return stats_; + } + + private: + // StatisticsUpdated calls are triggered from threads in the RTP module, + // while GetStats calls can be triggered from the public voice engine API, + // hence synchronization is needed. + scoped_ptr<CriticalSectionWrapper> stats_lock_; + const uint32_t ssrc_; + ChannelStatistics stats_; +}; + int32_t Channel::SendData(FrameType frameType, uint8_t payloadType, @@ -361,6 +409,7 @@ void Channel::ResetStatistics(uint32_t ssrc) { if (statistician) { statistician->ResetStatistics(); } + statistics_proxy_->ResetStatistics(); } void @@ -883,6 +932,7 @@ Channel::Channel(int32_t channelId, _rtpDumpOut(*RtpDump::CreateRtpDump()), _outputAudioLevel(), _externalTransport(false), + _audioLevel_dBov(0), _inputFilePlayerPtr(NULL), _outputFilePlayerPtr(NULL), _outputFileRecorderPtr(NULL), @@ -909,6 +959,7 @@ Channel::Channel(int32_t channelId, jitter_buffer_playout_timestamp_(0), playout_timestamp_rtp_(0), playout_timestamp_rtcp_(0), + playout_delay_ms_(0), _numberOfDiscardedPackets(0), send_sequence_number_(0), _engineStatisticsPtr(NULL), @@ -984,10 +1035,15 @@ Channel::Channel(int32_t channelId, configuration.receive_statistics = rtp_receive_statistics_.get(); _rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration)); + + statistics_proxy_.reset(new StatisticsProxy(_rtpRtcpModule->SSRC())); + rtp_receive_statistics_->RegisterRtcpStatisticsCallback( + statistics_proxy_.get()); } Channel::~Channel() { + rtp_receive_statistics_->RegisterRtcpStatisticsCallback(NULL); WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId), "Channel::~Channel() - dtor"); @@ -3863,23 +3919,25 @@ Channel::GetRTPStatistics( { // The jitter statistics is updated for each received RTP packet and is // based on received packets. - StreamStatistician::Statistics statistics; - StreamStatistician* statistician = - rtp_receive_statistics_->GetStatistician(rtp_receiver_->SSRC()); - if (!statistician || !statistician->GetStatistics( - &statistics, _rtpRtcpModule->RTCP() == kRtcpOff)) { - _engineStatisticsPtr->SetLastError( - VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning, - "GetRTPStatistics() failed to read RTP statistics from the " - "RTP/RTCP module"); + if (_rtpRtcpModule->RTCP() == kRtcpOff) { + // If RTCP is off, there is no timed thread in the RTCP module regularly + // generating new stats, trigger the update manually here instead. + StreamStatistician* statistician = + rtp_receive_statistics_->GetStatistician(rtp_receiver_->SSRC()); + if (statistician) { + // Don't use returned statistics, use data from proxy instead so that + // max jitter can be fetched atomically. + RtcpStatistics s; + statistician->GetStatistics(&s, true); + } } + ChannelStatistics stats = statistics_proxy_->GetStats(); const int32_t playoutFrequency = audio_coding_->PlayoutFrequency(); - if (playoutFrequency > 0) - { - // Scale RTP statistics given the current playout frequency - maxJitterMs = statistics.max_jitter / (playoutFrequency / 1000); - averageJitterMs = statistics.jitter / (playoutFrequency / 1000); + if (playoutFrequency > 0) { + // Scale RTP statistics given the current playout frequency + maxJitterMs = stats.max_jitter / (playoutFrequency / 1000); + averageJitterMs = stats.rtcp.jitter / (playoutFrequency / 1000); } discardedPackets = _numberOfDiscardedPackets; @@ -3959,7 +4017,7 @@ Channel::GetRTPStatistics(CallStatistics& stats) // The jitter statistics is updated for each received RTP packet and is // based on received packets. - StreamStatistician::Statistics statistics; + RtcpStatistics statistics; StreamStatistician* statistician = rtp_receive_statistics_->GetStatistician(rtp_receiver_->SSRC()); if (!statistician || !statistician->GetStatistics( diff --git a/voice_engine/channel.h b/voice_engine/channel.h index f8b04fdd..48d50c20 100644 --- a/voice_engine/channel.h +++ b/voice_engine/channel.h @@ -59,6 +59,7 @@ struct SenderInfo; namespace voe { class Statistics; +class StatisticsProxy; class TransmitMixer; class OutputMixer; @@ -455,6 +456,7 @@ private: scoped_ptr<RtpHeaderParser> rtp_header_parser_; scoped_ptr<RTPPayloadRegistry> rtp_payload_registry_; scoped_ptr<ReceiveStatistics> rtp_receive_statistics_; + scoped_ptr<StatisticsProxy> statistics_proxy_; scoped_ptr<RtpReceiver> rtp_receiver_; TelephoneEventHandler* telephone_event_handler_; scoped_ptr<RtpRtcp> _rtpRtcpModule; |