summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/rtp_rtcp/interface/receive_statistics.h23
-rw-r--r--modules/rtp_rtcp/source/receive_statistics_impl.cc42
-rw-r--r--modules/rtp_rtcp/source/receive_statistics_impl.h21
-rw-r--r--modules/rtp_rtcp/source/receive_statistics_unittest.cc83
-rw-r--r--modules/rtp_rtcp/source/rtcp_sender.cc2
-rw-r--r--modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc2
-rw-r--r--video/video_send_stream_tests.cc6
-rw-r--r--video_engine/vie_channel.cc15
-rw-r--r--video_engine/vie_channel.h4
-rw-r--r--video_engine/vie_rtp_rtcp_impl.cc32
-rw-r--r--voice_engine/channel.cc88
-rw-r--r--voice_engine/channel.h2
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;