diff options
author | henrike@webrtc.org <henrike@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d> | 2013-08-21 19:44:13 +0000 |
---|---|---|
committer | henrike@webrtc.org <henrike@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d> | 2013-08-21 19:44:13 +0000 |
commit | c0976d247fedbe48d703f1ef3d5fb0fd70fdab93 (patch) | |
tree | 8b1e0d2a2f9b8fb2102334113ad42e892f5cd4d7 | |
parent | efe1f0f566a6a102bce8d961a1135b987b41d36d (diff) | |
download | webrtc-c0976d247fedbe48d703f1ef3d5fb0fd70fdab93.tar.gz |
Revert 4582 "Reverts a second set of reverts caused by a bug in ..."
> Reverts a second set of reverts caused by a bug in a dependency.
>
> Revert "Revert r4328"
>
> Revert "Revert r4322 "Support sending multiple report blocks and keeping track
> of statistics on"
>
> BUG=1811
> R=henrika@webrtc.org, pbos@webrtc.org, tina.legrand@webrtc.org
>
> Review URL: https://webrtc-codereview.appspot.com/2072004
TBR=stefan@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/2087004
git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@4585 4adac7df-926f-26a2-2b94-8c16560cd09d
22 files changed, 751 insertions, 988 deletions
diff --git a/modules/modules.gyp b/modules/modules.gyp index 34930da0..75bf7bf2 100644 --- a/modules/modules.gyp +++ b/modules/modules.gyp @@ -171,7 +171,6 @@ 'rtp_rtcp/source/nack_rtx_unittest.cc', 'rtp_rtcp/source/producer_fec_unittest.cc', 'rtp_rtcp/source/receiver_fec_unittest.cc', - 'rtp_rtcp/source/receive_statistics_unittest.cc', 'rtp_rtcp/source/rtcp_format_remb_unittest.cc', 'rtp_rtcp/source/rtcp_sender_unittest.cc', 'rtp_rtcp/source/rtcp_receiver_unittest.cc', diff --git a/modules/rtp_rtcp/interface/receive_statistics.h b/modules/rtp_rtcp/interface/receive_statistics.h index 2ea155f9..fc47bf89 100644 --- a/modules/rtp_rtcp/interface/receive_statistics.h +++ b/modules/rtp_rtcp/interface/receive_statistics.h @@ -11,8 +11,6 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_INTERFACE_RECEIVE_STATISTICS_H_ #define WEBRTC_MODULES_RTP_RTCP_INTERFACE_RECEIVE_STATISTICS_H_ -#include <map> - #include "webrtc/modules/interface/module.h" #include "webrtc/modules/interface/module_common_types.h" #include "webrtc/typedefs.h" @@ -21,16 +19,9 @@ namespace webrtc { class Clock; -class StreamStatistician { +class ReceiveStatistics : public Module { public: - struct Statistics { - Statistics() - : fraction_lost(0), - cumulative_lost(0), - extended_max_sequence_number(0), - jitter(0), - max_jitter(0) {} - + struct RtpReceiveStatistics { uint8_t fraction_lost; uint32_t cumulative_lost; uint32_t extended_max_sequence_number; @@ -38,45 +29,26 @@ class StreamStatistician { uint32_t max_jitter; }; - virtual ~StreamStatistician(); - - virtual bool GetStatistics(Statistics* statistics, bool reset) = 0; - virtual void GetDataCounters(uint32_t* bytes_received, - uint32_t* packets_received) const = 0; - virtual uint32_t BitrateReceived() const = 0; - // Resets all statistics. - virtual void ResetStatistics() = 0; -}; - -typedef std::map<uint32_t, StreamStatistician*> StatisticianMap; - -class ReceiveStatistics : public Module { - public: virtual ~ReceiveStatistics() {} static ReceiveStatistics* Create(Clock* clock); - // Updates the receive statistics with this packet. virtual void IncomingPacket(const RTPHeader& rtp_header, size_t bytes, bool retransmitted, bool in_order) = 0; - // Returns a map of all statisticians which have seen an incoming packet - // during the last two seconds. - virtual StatisticianMap GetActiveStatisticians() const = 0; + virtual bool Statistics(RtpReceiveStatistics* statistics, bool reset) = 0; - // Returns a pointer to the statistician of an ssrc. - virtual StreamStatistician* GetStatistician(uint32_t ssrc) const = 0; -}; + virtual bool Statistics(RtpReceiveStatistics* statistics, int32_t* missing, + bool reset) = 0; -class NullReceiveStatistics : public ReceiveStatistics { - public: - virtual void IncomingPacket(const RTPHeader& rtp_header, size_t bytes, - bool retransmitted, bool in_order) OVERRIDE; - virtual StatisticianMap GetActiveStatisticians() const OVERRIDE; - virtual StreamStatistician* GetStatistician(uint32_t ssrc) const OVERRIDE; - virtual int32_t TimeUntilNextProcess() OVERRIDE; - virtual int32_t Process() OVERRIDE; -}; + virtual void GetDataCounters(uint32_t* bytes_received, + uint32_t* packets_received) const = 0; + + virtual uint32_t BitrateReceived() = 0; + virtual void ResetStatistics() = 0; + + virtual void ResetDataCounters() = 0; +}; } // namespace webrtc #endif // WEBRTC_MODULES_RTP_RTCP_INTERFACE_RECEIVE_STATISTICS_H_ diff --git a/modules/rtp_rtcp/interface/rtp_rtcp_defines.h b/modules/rtp_rtcp/interface/rtp_rtcp_defines.h index c56b71ff..31b38aba 100644 --- a/modules/rtp_rtcp/interface/rtp_rtcp_defines.h +++ b/modules/rtp_rtcp/interface/rtp_rtcp_defines.h @@ -205,13 +205,13 @@ public: const uint32_t rate) = 0; virtual void OnIncomingSSRCChanged( const int32_t id, - const uint32_t ssrc) = 0; + const uint32_t SSRC) = 0; virtual void OnIncomingCSRCChanged( const int32_t id, const uint32_t CSRC, const bool added) = 0; - virtual void ResetStatistics(uint32_t ssrc) = 0; + virtual void ResetStatistics() = 0; protected: virtual ~RtpFeedback() {} @@ -281,13 +281,13 @@ class NullRtpFeedback : public RtpFeedback { } virtual void OnIncomingSSRCChanged(const int32_t id, - const uint32_t ssrc) OVERRIDE {} + const uint32_t SSRC) OVERRIDE {} virtual void OnIncomingCSRCChanged(const int32_t id, const uint32_t CSRC, const bool added) OVERRIDE {} - virtual void ResetStatistics(uint32_t ssrc) OVERRIDE {} + virtual void ResetStatistics() OVERRIDE {} }; // Null object version of RtpData. diff --git a/modules/rtp_rtcp/source/nack_rtx_unittest.cc b/modules/rtp_rtcp/source/nack_rtx_unittest.cc index 56b49cc5..ecf4a07c 100644 --- a/modules/rtp_rtcp/source/nack_rtx_unittest.cc +++ b/modules/rtp_rtcp/source/nack_rtx_unittest.cc @@ -56,8 +56,8 @@ class TestRtpFeedback : public NullRtpFeedback { virtual ~TestRtpFeedback() {} virtual void OnIncomingSSRCChanged(const int32_t id, - const uint32_t ssrc) { - rtp_rtcp_->SetRemoteSSRC(ssrc); + const uint32_t SSRC) { + rtp_rtcp_->SetRemoteSSRC(SSRC); } private: diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.cc b/modules/rtp_rtcp/source/receive_statistics_impl.cc index c8269387..2189cce5 100644 --- a/modules/rtp_rtcp/source/receive_statistics_impl.cc +++ b/modules/rtp_rtcp/source/receive_statistics_impl.cc @@ -17,39 +17,41 @@ namespace webrtc { -const int64_t kStatisticsTimeoutMs = 8000; -const int kStatisticsProcessIntervalMs = 1000; +enum { kRateUpdateIntervalMs = 1000 }; -StreamStatistician::~StreamStatistician() {} +ReceiveStatistics* ReceiveStatistics::Create(Clock* clock) { + return new ReceiveStatisticsImpl(clock); +} -StreamStatisticianImpl::StreamStatisticianImpl(Clock* clock) - : clock_(clock), - crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), +ReceiveStatisticsImpl::ReceiveStatisticsImpl(Clock* clock) + : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), + clock_(clock), incoming_bitrate_(clock), ssrc_(0), jitter_q4_(0), jitter_max_q4_(0), cumulative_loss_(0), jitter_q4_transmission_time_offset_(0), - last_receive_time_secs_(0), - last_receive_time_frac_(0), + local_time_last_received_timestamp_(0), last_received_timestamp_(0), last_received_transmission_time_offset_(0), + received_seq_first_(0), received_seq_max_(0), received_seq_wraps_(0), - first_packet_(true), + received_packet_overhead_(12), received_byte_count_(0), received_retransmitted_packets_(0), received_inorder_packet_count_(0), + last_report_inorder_packets_(0), last_report_old_packets_(0), last_report_seq_max_(0), last_reported_statistics_() {} -void StreamStatisticianImpl::ResetStatistics() { - CriticalSectionScoped cs(crit_sect_.get()); +void ReceiveStatisticsImpl::ResetStatistics() { + CriticalSectionScoped lock(crit_sect_.get()); last_report_inorder_packets_ = 0; last_report_old_packets_ = 0; last_report_seq_max_ = 0; @@ -64,25 +66,33 @@ void StreamStatisticianImpl::ResetStatistics() { received_byte_count_ = 0; received_retransmitted_packets_ = 0; received_inorder_packet_count_ = 0; - first_packet_ = true; } -void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header, - size_t bytes, - bool retransmitted, - bool in_order) { - CriticalSectionScoped cs(crit_sect_.get()); +void ReceiveStatisticsImpl::ResetDataCounters() { + CriticalSectionScoped lock(crit_sect_.get()); + received_byte_count_ = 0; + received_retransmitted_packets_ = 0; + received_inorder_packet_count_ = 0; + last_report_inorder_packets_ = 0; +} + +void ReceiveStatisticsImpl::IncomingPacket(const RTPHeader& header, + size_t bytes, + bool retransmitted, + bool in_order) { ssrc_ = header.ssrc; incoming_bitrate_.Update(bytes); + received_byte_count_ += bytes; - if (first_packet_) { - first_packet_ = false; + if (received_seq_max_ == 0 && received_seq_wraps_ == 0) { // This is the first received report. received_seq_first_ = header.sequenceNumber; received_seq_max_ = header.sequenceNumber; received_inorder_packet_count_ = 1; - clock_->CurrentNtp(last_receive_time_secs_, last_receive_time_frac_); + // Current time in samples. + local_time_last_received_timestamp_ = + ModuleRTPUtility::GetCurrentRTP(clock_, header.payload_type_frequency); return; } @@ -90,9 +100,8 @@ void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header, // are received, 4 will be ignored. if (in_order) { // Current time in samples. - uint32_t receive_time_secs; - uint32_t receive_time_frac; - clock_->CurrentNtp(receive_time_secs, receive_time_frac); + const uint32_t RTPtime = + ModuleRTPUtility::GetCurrentRTP(clock_, header.payload_type_frequency); received_inorder_packet_count_++; // Wrong if we use RetransmitOfOldPacket. @@ -107,12 +116,8 @@ void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header, if (header.timestamp != last_received_timestamp_ && received_inorder_packet_count_ > 1) { - uint32_t receive_time_rtp = ModuleRTPUtility::ConvertNTPTimeToRTP( - receive_time_secs, receive_time_frac, header.payload_type_frequency); - uint32_t last_receive_time_rtp = ModuleRTPUtility::ConvertNTPTimeToRTP( - last_receive_time_secs_, last_receive_time_frac_, - header.payload_type_frequency); - int32_t time_diff_samples = (receive_time_rtp - last_receive_time_rtp) - + int32_t time_diff_samples = + (RTPtime - local_time_last_received_timestamp_) - (header.timestamp - last_received_timestamp_); time_diff_samples = abs(time_diff_samples); @@ -129,7 +134,7 @@ void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header, // Extended jitter report, RFC 5450. // Actual network jitter, excluding the source-introduced jitter. int32_t time_diff_samples_ext = - (receive_time_rtp - last_receive_time_rtp) - + (RTPtime - local_time_last_received_timestamp_) - ((header.timestamp + header.extension.transmissionTimeOffset) - (last_received_timestamp_ + @@ -145,8 +150,7 @@ void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header, } } last_received_timestamp_ = header.timestamp; - last_receive_time_secs_ = receive_time_secs; - last_receive_time_frac_ = receive_time_frac; + local_time_last_received_timestamp_ = RTPtime; } else { if (retransmitted) { received_retransmitted_packets_++; @@ -162,8 +166,18 @@ void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header, received_packet_overhead_ = (15 * received_packet_overhead_ + packet_oh) >> 4; } -bool StreamStatisticianImpl::GetStatistics(Statistics* statistics, bool reset) { - CriticalSectionScoped cs(crit_sect_.get()); +bool ReceiveStatisticsImpl::Statistics(RtpReceiveStatistics* statistics, + bool reset) { + int32_t missing; + return Statistics(statistics, &missing, reset); +} + +bool ReceiveStatisticsImpl::Statistics(RtpReceiveStatistics* statistics, + int32_t* missing, bool reset) { + CriticalSectionScoped lock(crit_sect_.get()); + + assert(missing); + if (received_seq_first_ == 0 && received_byte_count_ == 0) { // We have not received anything. return false; @@ -210,20 +224,20 @@ bool StreamStatisticianImpl::GetStatistics(Statistics* statistics, bool reset) { received_retransmitted_packets_ - last_report_old_packets_; rec_since_last += retransmitted_packets; - int32_t missing = 0; + *missing = 0; if (exp_since_last > rec_since_last) { - missing = (exp_since_last - rec_since_last); + *missing = (exp_since_last - rec_since_last); } uint8_t local_fraction_lost = 0; if (exp_since_last) { // Scale 0 to 255, where 255 is 100% loss. local_fraction_lost = - static_cast<uint8_t>(255 * missing / exp_since_last); + static_cast<uint8_t>((255 * (*missing)) / exp_since_last); } statistics->fraction_lost = local_fraction_lost; // We need a counter for cumulative loss too. - cumulative_loss_ += missing; + cumulative_loss_ += *missing; if (jitter_q4_ > jitter_max_q4_) { jitter_max_q4_ = jitter_q4_; @@ -246,9 +260,10 @@ bool StreamStatisticianImpl::GetStatistics(Statistics* statistics, bool reset) { return true; } -void StreamStatisticianImpl::GetDataCounters( +void ReceiveStatisticsImpl::GetDataCounters( uint32_t* bytes_received, uint32_t* packets_received) const { - CriticalSectionScoped cs(crit_sect_.get()); + CriticalSectionScoped lock(crit_sect_.get()); + if (bytes_received) { *bytes_received = received_byte_count_; } @@ -258,124 +273,19 @@ void StreamStatisticianImpl::GetDataCounters( } } -uint32_t StreamStatisticianImpl::BitrateReceived() const { - CriticalSectionScoped cs(crit_sect_.get()); +uint32_t ReceiveStatisticsImpl::BitrateReceived() { return incoming_bitrate_.BitrateNow(); } -void StreamStatisticianImpl::ProcessBitrate() { - CriticalSectionScoped cs(crit_sect_.get()); - incoming_bitrate_.Process(); -} - -void StreamStatisticianImpl::LastReceiveTimeNtp(uint32_t* secs, - uint32_t* frac) const { - CriticalSectionScoped cs(crit_sect_.get()); - *secs = last_receive_time_secs_; - *frac = last_receive_time_frac_; -} - -ReceiveStatistics* ReceiveStatistics::Create(Clock* clock) { - return new ReceiveStatisticsImpl(clock); -} - -ReceiveStatisticsImpl::ReceiveStatisticsImpl(Clock* clock) - : clock_(clock), - crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), - last_rate_update_ms_(0) {} - -ReceiveStatisticsImpl::~ReceiveStatisticsImpl() { - while (!statisticians_.empty()) { - delete statisticians_.begin()->second; - statisticians_.erase(statisticians_.begin()); - } -} - -void ReceiveStatisticsImpl::IncomingPacket(const RTPHeader& header, - size_t bytes, bool old_packet, - bool in_order) { - CriticalSectionScoped cs(crit_sect_.get()); - StatisticianImplMap::iterator it = statisticians_.find(header.ssrc); - if (it == statisticians_.end()) { - std::pair<StatisticianImplMap::iterator, uint32_t> insert_result = - statisticians_.insert(std::make_pair( - header.ssrc, new StreamStatisticianImpl(clock_))); - it = insert_result.first; - } - statisticians_[header.ssrc]->IncomingPacket(header, bytes, old_packet, - in_order); -} - -void ReceiveStatisticsImpl::ChangeSsrc(uint32_t from_ssrc, uint32_t to_ssrc) { - CriticalSectionScoped cs(crit_sect_.get()); - StatisticianImplMap::iterator from_it = statisticians_.find(from_ssrc); - if (from_it == statisticians_.end()) - return; - if (statisticians_.find(to_ssrc) != statisticians_.end()) - return; - statisticians_[to_ssrc] = from_it->second; - statisticians_.erase(from_it); -} - -StatisticianMap ReceiveStatisticsImpl::GetActiveStatisticians() const { - CriticalSectionScoped cs(crit_sect_.get()); - StatisticianMap active_statisticians; - for (StatisticianImplMap::const_iterator it = statisticians_.begin(); - it != statisticians_.end(); ++it) { - uint32_t secs; - uint32_t frac; - it->second->LastReceiveTimeNtp(&secs, &frac); - if (clock_->CurrentNtpInMilliseconds() - - Clock::NtpToMs(secs, frac) < kStatisticsTimeoutMs) { - active_statisticians[it->first] = it->second; - } - } - return active_statisticians; -} - -StreamStatistician* ReceiveStatisticsImpl::GetStatistician( - uint32_t ssrc) const { - CriticalSectionScoped cs(crit_sect_.get()); - StatisticianImplMap::const_iterator it = statisticians_.find(ssrc); - if (it == statisticians_.end()) - return NULL; - return it->second; -} - -int32_t ReceiveStatisticsImpl::Process() { - CriticalSectionScoped cs(crit_sect_.get()); - for (StatisticianImplMap::iterator it = statisticians_.begin(); - it != statisticians_.end(); ++it) { - it->second->ProcessBitrate(); - } - last_rate_update_ms_ = clock_->TimeInMilliseconds(); - return 0; -} - int32_t ReceiveStatisticsImpl::TimeUntilNextProcess() { - CriticalSectionScoped cs(crit_sect_.get()); int time_since_last_update = clock_->TimeInMilliseconds() - - last_rate_update_ms_; - return std::max(kStatisticsProcessIntervalMs - time_since_last_update, 0); + incoming_bitrate_.time_last_rate_update(); + return std::max(kRateUpdateIntervalMs - time_since_last_update, 0); } - -void NullReceiveStatistics::IncomingPacket(const RTPHeader& rtp_header, - size_t bytes, - bool retransmitted, - bool in_order) {} - -StatisticianMap NullReceiveStatistics::GetActiveStatisticians() const { - return StatisticianMap(); -} - -StreamStatistician* NullReceiveStatistics::GetStatistician( - uint32_t ssrc) const { - return NULL; +int32_t ReceiveStatisticsImpl::Process() { + incoming_bitrate_.Process(); + return 0; } -int32_t NullReceiveStatistics::TimeUntilNextProcess() { return 0; } - -int32_t NullReceiveStatistics::Process() { return 0; } - } // namespace webrtc diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.h b/modules/rtp_rtcp/source/receive_statistics_impl.h index f9631233..03a39483 100644 --- a/modules/rtp_rtcp/source/receive_statistics_impl.h +++ b/modules/rtp_rtcp/source/receive_statistics_impl.h @@ -23,43 +23,43 @@ namespace webrtc { class CriticalSectionWrapper; -class StreamStatisticianImpl : public StreamStatistician { +class ReceiveStatisticsImpl : public ReceiveStatistics { public: - explicit StreamStatisticianImpl(Clock* clock); - - virtual ~StreamStatisticianImpl() {} - - virtual bool GetStatistics(Statistics* statistics, bool reset) OVERRIDE; - virtual void GetDataCounters(uint32_t* bytes_received, - uint32_t* packets_received) const OVERRIDE; - virtual uint32_t BitrateReceived() const OVERRIDE; - virtual void ResetStatistics() OVERRIDE; + explicit ReceiveStatisticsImpl(Clock* clock); - void IncomingPacket(const RTPHeader& rtp_header, size_t bytes, - bool retransmitted, bool in_order); - void ProcessBitrate(); - virtual void LastReceiveTimeNtp(uint32_t* secs, uint32_t* frac) const; + // Implements ReceiveStatistics. + void IncomingPacket(const RTPHeader& header, size_t bytes, + bool old_packet, bool in_order); + bool Statistics(RtpReceiveStatistics* statistics, bool reset); + bool Statistics(RtpReceiveStatistics* statistics, int32_t* missing, + bool reset); + void GetDataCounters(uint32_t* bytes_received, + uint32_t* packets_received) const; + uint32_t BitrateReceived(); + void ResetStatistics(); + void ResetDataCounters(); + + // Implements Module. + int32_t TimeUntilNextProcess(); + int32_t Process(); private: - Clock* clock_; scoped_ptr<CriticalSectionWrapper> crit_sect_; + Clock* clock_; Bitrate incoming_bitrate_; uint32_t ssrc_; - // 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_; - uint32_t last_receive_time_secs_; - uint32_t last_receive_time_frac_; + uint32_t local_time_last_received_timestamp_; uint32_t last_received_timestamp_; int32_t last_received_transmission_time_offset_; uint16_t received_seq_first_; uint16_t received_seq_max_; uint16_t received_seq_wraps_; - bool first_packet_; // Current counter values. uint16_t received_packet_overhead_; @@ -71,34 +71,7 @@ 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_; -}; - -class ReceiveStatisticsImpl : public ReceiveStatistics { - public: - explicit ReceiveStatisticsImpl(Clock* clock); - - ~ReceiveStatisticsImpl(); - - // Implement ReceiveStatistics. - virtual void IncomingPacket(const RTPHeader& header, size_t bytes, - bool old_packet, bool in_order) OVERRIDE; - virtual StatisticianMap GetActiveStatisticians() const OVERRIDE; - virtual StreamStatistician* GetStatistician(uint32_t ssrc) const OVERRIDE; - - // Implement Module. - virtual int32_t Process() OVERRIDE; - virtual int32_t TimeUntilNextProcess() OVERRIDE; - - void ChangeSsrc(uint32_t from_ssrc, uint32_t to_ssrc); - - private: - typedef std::map<uint32_t, StreamStatisticianImpl*> StatisticianImplMap; - - Clock* clock_; - scoped_ptr<CriticalSectionWrapper> crit_sect_; - int64_t last_rate_update_ms_; - StatisticianImplMap statisticians_; + RtpReceiveStatistics last_reported_statistics_; }; } // 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 deleted file mode 100644 index a69e408e..00000000 --- a/modules/rtp_rtcp/source/receive_statistics_unittest.cc +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h" -#include "webrtc/system_wrappers/interface/clock.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" - -namespace webrtc { - -const int kPacketSize1 = 100; -const int kPacketSize2 = 300; -const uint32_t kSsrc1 = 1; -const uint32_t kSsrc2 = 2; -const uint32_t kSsrc3 = 3; - -class ReceiveStatisticsTest : public ::testing::Test { - public: - ReceiveStatisticsTest() : - clock_(0), - receive_statistics_(ReceiveStatistics::Create(&clock_)) { - memset(&header1_, 0, sizeof(header1_)); - header1_.ssrc = kSsrc1; - header1_.sequenceNumber = 0; - memset(&header2_, 0, sizeof(header2_)); - header2_.ssrc = kSsrc2; - header2_.sequenceNumber = 0; - } - - protected: - SimulatedClock clock_; - scoped_ptr<ReceiveStatistics> receive_statistics_; - RTPHeader header1_; - RTPHeader header2_; -}; - -TEST_F(ReceiveStatisticsTest, TwoIncomingSsrcs) { - receive_statistics_->IncomingPacket(header1_, kPacketSize1, false, true); - ++header1_.sequenceNumber; - receive_statistics_->IncomingPacket(header2_, kPacketSize2, false, true); - ++header2_.sequenceNumber; - clock_.AdvanceTimeMilliseconds(100); - receive_statistics_->IncomingPacket(header1_, kPacketSize1, false, true); - ++header1_.sequenceNumber; - receive_statistics_->IncomingPacket(header2_, kPacketSize2, false, true); - ++header2_.sequenceNumber; - - StreamStatistician* statistician = - receive_statistics_->GetStatistician(kSsrc1); - ASSERT_TRUE(statistician != NULL); - EXPECT_GT(statistician->BitrateReceived(), 0u); - uint32_t bytes_received = 0; - uint32_t packets_received = 0; - statistician->GetDataCounters(&bytes_received, &packets_received); - EXPECT_EQ(200u, bytes_received); - EXPECT_EQ(2u, packets_received); - - statistician = - receive_statistics_->GetStatistician(kSsrc2); - ASSERT_TRUE(statistician != NULL); - EXPECT_GT(statistician->BitrateReceived(), 0u); - statistician->GetDataCounters(&bytes_received, &packets_received); - EXPECT_EQ(600u, bytes_received); - EXPECT_EQ(2u, packets_received); - - StatisticianMap statisticians = receive_statistics_->GetActiveStatisticians(); - EXPECT_EQ(2u, statisticians.size()); - // Add more incoming packets and verify that they are registered in both - // access methods. - receive_statistics_->IncomingPacket(header1_, kPacketSize1, false, true); - ++header1_.sequenceNumber; - receive_statistics_->IncomingPacket(header2_, kPacketSize2, false, true); - ++header2_.sequenceNumber; - - statisticians[kSsrc1]->GetDataCounters(&bytes_received, &packets_received); - EXPECT_EQ(300u, bytes_received); - EXPECT_EQ(3u, packets_received); - statisticians[kSsrc2]->GetDataCounters(&bytes_received, &packets_received); - EXPECT_EQ(900u, bytes_received); - EXPECT_EQ(3u, packets_received); - - receive_statistics_->GetStatistician(kSsrc1)->GetDataCounters( - &bytes_received, &packets_received); - EXPECT_EQ(300u, bytes_received); - EXPECT_EQ(3u, packets_received); - receive_statistics_->GetStatistician(kSsrc2)->GetDataCounters( - &bytes_received, &packets_received); - EXPECT_EQ(900u, bytes_received); - EXPECT_EQ(3u, packets_received); -} - -TEST_F(ReceiveStatisticsTest, ActiveStatisticians) { - receive_statistics_->IncomingPacket(header1_, kPacketSize1, false, true); - ++header1_.sequenceNumber; - clock_.AdvanceTimeMilliseconds(1000); - receive_statistics_->IncomingPacket(header2_, kPacketSize2, false, true); - ++header2_.sequenceNumber; - StatisticianMap statisticians = receive_statistics_->GetActiveStatisticians(); - // Nothing should time out since only 1000 ms has passed since the first - // packet came in. - EXPECT_EQ(2u, statisticians.size()); - - clock_.AdvanceTimeMilliseconds(7000); - // kSsrc1 should have timed out. - statisticians = receive_statistics_->GetActiveStatisticians(); - EXPECT_EQ(1u, statisticians.size()); - - clock_.AdvanceTimeMilliseconds(1000); - // kSsrc2 should have timed out. - statisticians = receive_statistics_->GetActiveStatisticians(); - EXPECT_EQ(0u, statisticians.size()); - - receive_statistics_->IncomingPacket(header1_, kPacketSize1, false, true); - ++header1_.sequenceNumber; - // kSsrc1 should be active again and the data counters should have survived. - statisticians = receive_statistics_->GetActiveStatisticians(); - EXPECT_EQ(1u, statisticians.size()); - StreamStatistician* statistician = - receive_statistics_->GetStatistician(kSsrc1); - ASSERT_TRUE(statistician != NULL); - uint32_t bytes_received = 0; - uint32_t packets_received = 0; - statistician->GetDataCounters(&bytes_received, &packets_received); - EXPECT_EQ(200u, bytes_received); - EXPECT_EQ(2u, packets_received); -} -} // namespace webrtc diff --git a/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc b/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc index 2a7902fa..e7c7bcbf 100644 --- a/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc +++ b/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc @@ -61,7 +61,6 @@ class RtcpFormatRembTest : public ::testing::Test { RtcpFormatRembTest() : over_use_detector_options_(), system_clock_(Clock::GetRealTimeClock()), - receive_statistics_(ReceiveStatistics::Create(system_clock_)), remote_bitrate_observer_(), remote_bitrate_estimator_( RemoteBitrateEstimatorFactory().Create( @@ -73,7 +72,6 @@ class RtcpFormatRembTest : public ::testing::Test { OverUseDetectorOptions over_use_detector_options_; Clock* system_clock_; ModuleRtpRtcpImpl* dummy_rtp_rtcp_impl_; - scoped_ptr<ReceiveStatistics> receive_statistics_; RTCPSender* rtcp_sender_; RTCPReceiver* rtcp_receiver_; TestTransport* test_transport_; @@ -88,8 +86,7 @@ void RtcpFormatRembTest::SetUp() { configuration.clock = system_clock_; configuration.remote_bitrate_estimator = remote_bitrate_estimator_.get(); dummy_rtp_rtcp_impl_ = new ModuleRtpRtcpImpl(configuration); - rtcp_sender_ = new RTCPSender(0, false, system_clock_, dummy_rtp_rtcp_impl_, - receive_statistics_.get()); + rtcp_sender_ = new RTCPSender(0, false, system_clock_, dummy_rtp_rtcp_impl_); rtcp_receiver_ = new RTCPReceiver(0, system_clock_, dummy_rtp_rtcp_impl_); test_transport_ = new TestTransport(rtcp_receiver_); @@ -118,13 +115,15 @@ TEST_F(RtcpFormatRembTest, TestNonCompund) { uint32_t SSRC = 456789; EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpNonCompound)); EXPECT_EQ(0, rtcp_sender_->SetREMBData(1234, 1, &SSRC)); - EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRemb)); + EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRemb, NULL)); } TEST_F(RtcpFormatRembTest, TestCompund) { uint32_t SSRCs[2] = {456789, 98765}; EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpCompound)); EXPECT_EQ(0, rtcp_sender_->SetREMBData(1234, 2, SSRCs)); - EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRemb)); + ReceiveStatistics::RtpReceiveStatistics receive_stats; + memset(&receive_stats, 0, sizeof(receive_stats)); + EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRemb, &receive_stats)); } } // namespace diff --git a/modules/rtp_rtcp/source/rtcp_sender.cc b/modules/rtp_rtcp/source/rtcp_sender.cc index 551e1c55..a7c7dbc5 100644 --- a/modules/rtp_rtcp/source/rtcp_sender.cc +++ b/modules/rtp_rtcp/source/rtcp_sender.cc @@ -68,8 +68,7 @@ std::string NACKStringBuilder::GetResult() RTCPSender::RTCPSender(const int32_t id, const bool audio, Clock* clock, - ModuleRtpRtcpImpl* owner, - ReceiveStatistics* receive_statistics) : + ModuleRtpRtcpImpl* owner) : _id(id), _audio(audio), _clock(clock), @@ -93,9 +92,7 @@ RTCPSender::RTCPSender(const int32_t id, _SSRC(0), _remoteSSRC(0), _CNAME(), - receive_statistics_(receive_statistics), - internal_report_blocks_(), - external_report_blocks_(), + _reportBlocks(), _csrcCNAMEs(), _cameraDelayMS(0), @@ -140,15 +137,11 @@ RTCPSender::~RTCPSender() { delete [] _rembSSRC; delete [] _appData; - while (!internal_report_blocks_.empty()) { - delete internal_report_blocks_.begin()->second; - internal_report_blocks_.erase(internal_report_blocks_.begin()); - } - while (!external_report_blocks_.empty()) { + while (!_reportBlocks.empty()) { std::map<uint32_t, RTCPReportBlock*>::iterator it = - external_report_blocks_.begin(); + _reportBlocks.begin(); delete it->second; - external_report_blocks_.erase(it); + _reportBlocks.erase(it); } while (!_csrcCNAMEs.empty()) { std::map<uint32_t, RTCPCnameInformation*>::iterator it = @@ -278,7 +271,7 @@ RTCPSender::SetSendingStatus(const bool sending) } if(sendRTCPBye) { - return SendRTCP(kRtcpBye); + return SendRTCP(kRtcpBye, NULL); } return 0; } @@ -566,59 +559,52 @@ RTCPSender::SendTimeOfSendReport(const uint32_t sendReport) return 0; } -int32_t RTCPSender::AddExternalReportBlock( - uint32_t SSRC, - const RTCPReportBlock* reportBlock) { - CriticalSectionScoped lock(_criticalSectionRTCPSender); - return AddReportBlock(SSRC, &external_report_blocks_, reportBlock); -} - -int32_t RTCPSender::AddReportBlock( - uint32_t SSRC, - std::map<uint32_t, RTCPReportBlock*>* report_blocks, - const RTCPReportBlock* reportBlock) { +int32_t RTCPSender::AddReportBlock(const uint32_t SSRC, + const RTCPReportBlock* reportBlock) { if (reportBlock == NULL) { WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__); return -1; } + CriticalSectionScoped lock(_criticalSectionRTCPSender); - if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) { + if (_reportBlocks.size() >= RTCP_MAX_REPORT_BLOCKS) { WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__); return -1; } std::map<uint32_t, RTCPReportBlock*>::iterator it = - report_blocks->find(SSRC); - if (it != report_blocks->end()) { + _reportBlocks.find(SSRC); + if (it != _reportBlocks.end()) { delete it->second; - report_blocks->erase(it); + _reportBlocks.erase(it); } RTCPReportBlock* copyReportBlock = new RTCPReportBlock(); memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock)); - (*report_blocks)[SSRC] = copyReportBlock; + _reportBlocks[SSRC] = copyReportBlock; return 0; } -int32_t RTCPSender::RemoveExternalReportBlock(uint32_t SSRC) { +int32_t RTCPSender::RemoveReportBlock(const uint32_t SSRC) { CriticalSectionScoped lock(_criticalSectionRTCPSender); std::map<uint32_t, RTCPReportBlock*>::iterator it = - external_report_blocks_.find(SSRC); + _reportBlocks.find(SSRC); - if (it == external_report_blocks_.end()) { + if (it == _reportBlocks.end()) { return -1; } delete it->second; - external_report_blocks_.erase(it); + _reportBlocks.erase(it); return 0; } int32_t RTCPSender::BuildSR(uint8_t* rtcpbuffer, - int& pos, + uint32_t& pos, const uint32_t NTPsec, - const uint32_t NTPfrac) + const uint32_t NTPfrac, + const RTCPReportBlock* received) { // sanity if(pos + 52 >= IP_PACKET_SIZE) @@ -686,15 +672,12 @@ RTCPSender::BuildSR(uint8_t* rtcpbuffer, pos += 4; uint8_t numberOfReportBlocks = 0; - int32_t retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos, - numberOfReportBlocks, - NTPsec, NTPfrac); + int32_t retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac); if(retVal < 0) { // return retVal ; } - pos = retVal; rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks; uint16_t len = uint16_t((pos/4) -1); @@ -703,7 +686,8 @@ RTCPSender::BuildSR(uint8_t* rtcpbuffer, } -int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer, int& pos) { +int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer, + uint32_t& pos) { size_t lengthCname = strlen(_CNAME); assert(lengthCname < RTCP_CNAME_SIZE); @@ -798,9 +782,10 @@ int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer, int& pos) { int32_t RTCPSender::BuildRR(uint8_t* rtcpbuffer, - int& pos, + uint32_t& pos, const uint32_t NTPsec, - const uint32_t NTPfrac) + const uint32_t NTPfrac, + const RTCPReportBlock* received) { // sanity one block if(pos + 32 >= IP_PACKET_SIZE) @@ -821,14 +806,11 @@ RTCPSender::BuildRR(uint8_t* rtcpbuffer, pos += 4; uint8_t numberOfReportBlocks = 0; - int retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos, - numberOfReportBlocks, - NTPsec, NTPfrac); + int32_t retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac); if(retVal < 0) { - return pos; + return retVal; } - pos = retVal; rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks; uint16_t len = uint16_t((pos)/4 -1); @@ -857,10 +839,10 @@ RTCPSender::BuildRR(uint8_t* rtcpbuffer, int32_t RTCPSender::BuildExtendedJitterReport( uint8_t* rtcpbuffer, - int& pos, + uint32_t& pos, const uint32_t jitterTransmissionTimeOffset) { - if (external_report_blocks_.size() > 0) + if (_reportBlocks.size() > 0) { WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented."); return 0; @@ -888,7 +870,7 @@ RTCPSender::BuildExtendedJitterReport( } int32_t -RTCPSender::BuildPLI(uint8_t* rtcpbuffer, int& pos) +RTCPSender::BuildPLI(uint8_t* rtcpbuffer, uint32_t& pos) { // sanity if(pos + 12 >= IP_PACKET_SIZE) @@ -915,7 +897,7 @@ RTCPSender::BuildPLI(uint8_t* rtcpbuffer, int& pos) } int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer, - int& pos, + uint32_t& pos, bool repeat) { // sanity if(pos + 20 >= IP_PACKET_SIZE) { @@ -964,7 +946,7 @@ int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer, +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ int32_t -RTCPSender::BuildSLI(uint8_t* rtcpbuffer, int& pos, const uint8_t pictureID) +RTCPSender::BuildSLI(uint8_t* rtcpbuffer, uint32_t& pos, const uint8_t pictureID) { // sanity if(pos + 16 >= IP_PACKET_SIZE) @@ -1011,7 +993,7 @@ RTCPSender::BuildSLI(uint8_t* rtcpbuffer, int& pos, const uint8_t pictureID) */ int32_t RTCPSender::BuildRPSI(uint8_t* rtcpbuffer, - int& pos, + uint32_t& pos, const uint64_t pictureID, const uint8_t payloadType) { @@ -1087,7 +1069,7 @@ RTCPSender::BuildRPSI(uint8_t* rtcpbuffer, } int32_t -RTCPSender::BuildREMB(uint8_t* rtcpbuffer, int& pos) +RTCPSender::BuildREMB(uint8_t* rtcpbuffer, uint32_t& pos) { // sanity if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE) @@ -1148,7 +1130,7 @@ RTCPSender::SetTargetBitrate(unsigned int target_bitrate) } int32_t -RTCPSender::BuildTMMBR(uint8_t* rtcpbuffer, int& pos) +RTCPSender::BuildTMMBR(uint8_t* rtcpbuffer, uint32_t& pos) { // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate // If the sender is an owner of the TMMBN -> send TMMBR @@ -1254,7 +1236,7 @@ RTCPSender::BuildTMMBR(uint8_t* rtcpbuffer, int& pos) } int32_t -RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, int& pos) +RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, uint32_t& pos) { TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend(); if(boundingSet == NULL) @@ -1326,7 +1308,7 @@ RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, int& pos) } int32_t -RTCPSender::BuildAPP(uint8_t* rtcpbuffer, int& pos) +RTCPSender::BuildAPP(uint8_t* rtcpbuffer, uint32_t& pos) { // sanity if(_appData == NULL) @@ -1364,7 +1346,7 @@ RTCPSender::BuildAPP(uint8_t* rtcpbuffer, int& pos) int32_t RTCPSender::BuildNACK(uint8_t* rtcpbuffer, - int& pos, + uint32_t& pos, const int32_t nackSize, const uint16_t* nackList, std::string* nackString) @@ -1434,7 +1416,7 @@ RTCPSender::BuildNACK(uint8_t* rtcpbuffer, } int32_t -RTCPSender::BuildBYE(uint8_t* rtcpbuffer, int& pos) +RTCPSender::BuildBYE(uint8_t* rtcpbuffer, uint32_t& pos) { // sanity if(pos + 8 >= IP_PACKET_SIZE) @@ -1479,7 +1461,7 @@ RTCPSender::BuildBYE(uint8_t* rtcpbuffer, int& pos) } int32_t -RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos) +RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, uint32_t& pos) { // sanity if(pos + 44 >= IP_PACKET_SIZE) @@ -1554,378 +1536,414 @@ RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos) int32_t RTCPSender::SendRTCP( uint32_t packetTypeFlags, + const ReceiveStatistics::RtpReceiveStatistics* receive_stats, int32_t nackSize, const uint16_t* nackList, bool repeat, uint64_t pictureID) { - { - CriticalSectionScoped lock(_criticalSectionRTCPSender); - if(_method == kRtcpOff) + uint32_t rtcpPacketTypeFlags = packetTypeFlags; + uint32_t pos = 0; + uint8_t rtcpbuffer[IP_PACKET_SIZE]; + + do // only to be able to use break :) (and the critsect must be inside its own scope) { - WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, - "%s invalid state", __FUNCTION__); - return -1; - } - } - uint8_t rtcp_buffer[IP_PACKET_SIZE]; - int rtcp_length = PrepareRTCP(packetTypeFlags, nackSize, nackList, repeat, - pictureID, rtcp_buffer, IP_PACKET_SIZE); - if (rtcp_length < 0) { - return -1; - } - // Sanity don't send empty packets. - if (rtcp_length == 0) - { - return -1; - } - return SendToNetwork(rtcp_buffer, static_cast<uint16_t>(rtcp_length)); -} + // collect the received information + RTCPReportBlock received; + bool hasReceived = false; + uint32_t NTPsec = 0; + uint32_t NTPfrac = 0; + bool rtcpCompound = false; + uint32_t jitterTransmissionOffset = 0; -int RTCPSender::PrepareRTCP( - uint32_t packetTypeFlags, - int32_t nackSize, - const uint16_t* nackList, - bool repeat, - uint64_t pictureID, - uint8_t* rtcp_buffer, - int buffer_size) { - uint32_t rtcpPacketTypeFlags = packetTypeFlags; - // Collect the received information. - uint32_t NTPsec = 0; - uint32_t NTPfrac = 0; - uint32_t jitterTransmissionOffset = 0; - int position = 0; + { + CriticalSectionScoped lock(_criticalSectionRTCPSender); + if(_method == kRtcpOff) + { + WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, + "%s invalid state", __FUNCTION__); + return -1; + } + rtcpCompound = (_method == kRtcpCompound) ? true : false; + } - CriticalSectionScoped lock(_criticalSectionRTCPSender); + if (rtcpCompound || + rtcpPacketTypeFlags & kRtcpReport || + rtcpPacketTypeFlags & kRtcpSr || + rtcpPacketTypeFlags & kRtcpRr) + { + // Do we have receive statistics to send? + if (receive_stats) + { + received.fractionLost = receive_stats->fraction_lost; + received.cumulativeLost = receive_stats->cumulative_lost; + received.extendedHighSeqNum = + receive_stats->extended_max_sequence_number; + received.jitter = receive_stats->jitter; + jitterTransmissionOffset = 0; + hasReceived = true; + + uint32_t lastReceivedRRNTPsecs = 0; + uint32_t lastReceivedRRNTPfrac = 0; + uint32_t remoteSR = 0; + + // ok even if we have not received a SR, we will send 0 in that case + _rtpRtcp.LastReceivedNTP(lastReceivedRRNTPsecs, + lastReceivedRRNTPfrac, + remoteSR); + + // get our NTP as late as possible to avoid a race + _clock->CurrentNtp(NTPsec, NTPfrac); + + // Delay since last received report + uint32_t delaySinceLastReceivedSR = 0; + if((lastReceivedRRNTPsecs !=0) || (lastReceivedRRNTPfrac !=0)) + { + // get the 16 lowest bits of seconds and the 16 higest bits of fractions + uint32_t now=NTPsec&0x0000FFFF; + now <<=16; + now += (NTPfrac&0xffff0000)>>16; - if(_TMMBR ) // Attach TMMBR to send and receive reports. - { - rtcpPacketTypeFlags |= kRtcpTmmbr; - } - if(_appSend) - { - rtcpPacketTypeFlags |= kRtcpApp; - _appSend = false; - } - if(_REMB && _sendREMB) - { - // Always attach REMB to SR if that is configured. Note that REMB is - // only sent on one of the RTP modules in the REMB group. - rtcpPacketTypeFlags |= kRtcpRemb; - } - if(_xrSendVoIPMetric) - { - rtcpPacketTypeFlags |= kRtcpXrVoipMetric; - _xrSendVoIPMetric = false; - } - if(_sendTMMBN) // Set when having received a TMMBR. - { - rtcpPacketTypeFlags |= kRtcpTmmbn; - _sendTMMBN = false; - } + uint32_t receiveTime = lastReceivedRRNTPsecs&0x0000FFFF; + receiveTime <<=16; + receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16; - if(_method == kRtcpCompound) - { - if(_sending) - { - rtcpPacketTypeFlags |= kRtcpSr; - } else - { - rtcpPacketTypeFlags |= kRtcpRr; - } - } else if(_method == kRtcpNonCompound) - { - if(rtcpPacketTypeFlags & kRtcpReport) - { - if(_sending) - { - rtcpPacketTypeFlags |= kRtcpSr; - } else - { - rtcpPacketTypeFlags |= kRtcpRr; - } - } - } - if( rtcpPacketTypeFlags & kRtcpRr || - rtcpPacketTypeFlags & kRtcpSr) - { - // generate next time to send a RTCP report - // seeded from RTP constructor - int32_t random = rand() % 1000; - int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS; - - if(_audio) - { - timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) + - (RTCP_INTERVAL_AUDIO_MS*random/1000); - }else - { - uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS; - if(_sending) - { - // Calculate bandwidth for video; 360 / send bandwidth in kbit/s. - uint32_t sendBitrateKbit = 0; - uint32_t videoRate = 0; - uint32_t fecRate = 0; - uint32_t nackRate = 0; - _rtpRtcp.BitrateSent(&sendBitrateKbit, - &videoRate, - &fecRate, - &nackRate); - sendBitrateKbit /= 1000; - if(sendBitrateKbit != 0) - { - minIntervalMs = 360000/sendBitrateKbit; - } - } - if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS) - { - minIntervalMs = RTCP_INTERVAL_VIDEO_MS; - } - timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000); - } - _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext; - } + delaySinceLastReceivedSR = now-receiveTime; + } + received.delaySinceLastSR = delaySinceLastReceivedSR; + received.lastSR = remoteSR; + } else + { + // we need to send our NTP even if we dont have received any reports + _clock->CurrentNtp(NTPsec, NTPfrac); + } + } - // If the data does not fit in the packet we fill it as much as possible. - int32_t buildVal = 0; - - // We need to send our NTP even if we haven't received any reports. - _clock->CurrentNtp(NTPsec, NTPfrac); - if (ShouldSendReportBlocks(rtcpPacketTypeFlags)) { - StatisticianMap statisticians = - receive_statistics_->GetActiveStatisticians(); - if (!statisticians.empty()) { - StatisticianMap::const_iterator it; - int i; - for (it = statisticians.begin(), i = 0; it != statisticians.end(); - ++it, ++i) { - RTCPReportBlock report_block; - if (PrepareReport(it->second, &report_block, &NTPsec, &NTPfrac)) - AddReportBlock(it->first, &internal_report_blocks_, &report_block); - } - if (_IJ && !statisticians.empty()) { - rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset; - } - _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac); - } - } + CriticalSectionScoped lock(_criticalSectionRTCPSender); - if(rtcpPacketTypeFlags & kRtcpSr) - { - buildVal = BuildSR(rtcp_buffer, position, NTPsec, NTPfrac); - if (buildVal == -1) { - return -1; - } else if (buildVal == -2) { - return position; - } - buildVal = BuildSDEC(rtcp_buffer, position); - if (buildVal == -1) { - return -1; - } else if (buildVal == -2) { - return position; - } - }else if(rtcpPacketTypeFlags & kRtcpRr) - { - buildVal = BuildRR(rtcp_buffer, position, NTPsec, NTPfrac); - if (buildVal == -1) { - return -1; - } else if (buildVal == -2) { - return position; - } - // only of set - if(_CNAME[0] != 0) - { - buildVal = BuildSDEC(rtcp_buffer, position); - if (buildVal == -1) { - return -1; - } - } - } - if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset) - { - // If present, this RTCP packet must be placed after a - // receiver report. - buildVal = BuildExtendedJitterReport(rtcp_buffer, - position, - jitterTransmissionOffset); - if (buildVal == -1) { - return -1; - } else if (buildVal == -2) { - return position; - } - } - if(rtcpPacketTypeFlags & kRtcpPli) - { - buildVal = BuildPLI(rtcp_buffer, position); - if (buildVal == -1) { - return -1; - } else if (buildVal == -2) { - return position; - } - TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI"); - _pliCount++; - TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC, _pliCount); - } - if(rtcpPacketTypeFlags & kRtcpFir) - { - buildVal = BuildFIR(rtcp_buffer, position, repeat); - if (buildVal == -1) { - return -1; - } else if (buildVal == -2) { - return position; - } - TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR"); - _fullIntraRequestCount++; - TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC, - _fullIntraRequestCount); - } - if(rtcpPacketTypeFlags & kRtcpSli) - { - buildVal = BuildSLI(rtcp_buffer, position, (uint8_t)pictureID); - if (buildVal == -1) { - return -1; - } else if (buildVal == -2) { - return position; - } - } - if(rtcpPacketTypeFlags & kRtcpRpsi) - { - const int8_t payloadType = _rtpRtcp.SendPayloadType(); - if (payloadType == -1) { - return -1; - } - buildVal = BuildRPSI(rtcp_buffer, position, pictureID, - (uint8_t)payloadType); - if (buildVal == -1) { - return -1; - } else if (buildVal == -2) { - return position; - } - } - if(rtcpPacketTypeFlags & kRtcpRemb) - { - buildVal = BuildREMB(rtcp_buffer, position); - if (buildVal == -1) { - return -1; - } else if (buildVal == -2) { - return position; - } - TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB"); - } - if(rtcpPacketTypeFlags & kRtcpBye) - { - buildVal = BuildBYE(rtcp_buffer, position); - if (buildVal == -1) { - return -1; - } else if (buildVal == -2) { - return position; - } - } - if(rtcpPacketTypeFlags & kRtcpApp) - { - buildVal = BuildAPP(rtcp_buffer, position); - if (buildVal == -1) { - return -1; - } else if (buildVal == -2) { - return position; - } - } - if(rtcpPacketTypeFlags & kRtcpTmmbr) - { - buildVal = BuildTMMBR(rtcp_buffer, position); - if (buildVal == -1) { - return -1; - } else if (buildVal == -2) { - return position; - } - } - if(rtcpPacketTypeFlags & kRtcpTmmbn) - { - buildVal = BuildTMMBN(rtcp_buffer, position); - if (buildVal == -1) { - return -1; - } else if (buildVal == -2) { - return position; - } - } - if(rtcpPacketTypeFlags & kRtcpNack) - { - std::string nackString; - buildVal = BuildNACK(rtcp_buffer, position, nackSize, nackList, - &nackString); - if (buildVal == -1) { - return -1; - } else if (buildVal == -2) { - return position; - } - TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK", - "nacks", TRACE_STR_COPY(nackString.c_str())); - _nackCount++; - TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC, _nackCount); - } - if(rtcpPacketTypeFlags & kRtcpXrVoipMetric) - { - buildVal = BuildVoIPMetric(rtcp_buffer, position); - if (buildVal == -1) { - return -1; - } else if (buildVal == -2) { - return position; - } - } - return position; -} + if(_TMMBR ) // attach TMMBR to send and receive reports + { + rtcpPacketTypeFlags |= kRtcpTmmbr; + } + if(_appSend) + { + rtcpPacketTypeFlags |= kRtcpApp; + _appSend = false; + } + if(_REMB && _sendREMB) + { + // Always attach REMB to SR if that is configured. Note that REMB is + // only sent on one of the RTP modules in the REMB group. + rtcpPacketTypeFlags |= kRtcpRemb; + } + if(_xrSendVoIPMetric) + { + rtcpPacketTypeFlags |= kRtcpXrVoipMetric; + _xrSendVoIPMetric = false; + } + if(_sendTMMBN) // set when having received a TMMBR + { + rtcpPacketTypeFlags |= kRtcpTmmbn; + _sendTMMBN = false; + } -bool RTCPSender::ShouldSendReportBlocks(uint32_t rtcp_packet_type) const { - return Status() == kRtcpCompound || - (rtcp_packet_type & kRtcpReport) || - (rtcp_packet_type & kRtcpSr) || - (rtcp_packet_type & kRtcpRr); -} + if(_method == kRtcpCompound) + { + if(_sending) + { + rtcpPacketTypeFlags |= kRtcpSr; + } else + { + rtcpPacketTypeFlags |= kRtcpRr; + } + if (_IJ && hasReceived) + { + rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset; + } + } else if(_method == kRtcpNonCompound) + { + if(rtcpPacketTypeFlags & kRtcpReport) + { + if(_sending) + { + rtcpPacketTypeFlags |= kRtcpSr; + } else + { + rtcpPacketTypeFlags |= kRtcpRr; + } + } + } + if( rtcpPacketTypeFlags & kRtcpRr || + rtcpPacketTypeFlags & kRtcpSr) + { + // generate next time to send a RTCP report + // seeded from RTP constructor + int32_t random = rand() % 1000; + int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS; -bool RTCPSender::PrepareReport(StreamStatistician* statistician, - RTCPReportBlock* report_block, - uint32_t* ntp_secs, uint32_t* ntp_frac) { - // Do we have receive statistics to send? - StreamStatistician::Statistics stats; - if (!statistician->GetStatistics(&stats, true)) - return false; - report_block->fractionLost = stats.fraction_lost; - report_block->cumulativeLost = stats.cumulative_lost; - report_block->extendedHighSeqNum = - stats.extended_max_sequence_number; - report_block->jitter = stats.jitter; - - uint32_t lastReceivedRRNTPsecs = 0; - uint32_t lastReceivedRRNTPfrac = 0; - uint32_t remoteSR = 0; - - // ok even if we have not received a SR, we will send 0 in that case - _rtpRtcp.LastReceivedNTP(lastReceivedRRNTPsecs, - lastReceivedRRNTPfrac, - remoteSR); - - // get our NTP as late as possible to avoid a race - _clock->CurrentNtp(*ntp_secs, *ntp_frac); - - // Delay since last received report - uint32_t delaySinceLastReceivedSR = 0; - if((lastReceivedRRNTPsecs !=0) || (lastReceivedRRNTPfrac !=0)) { - // get the 16 lowest bits of seconds and the 16 higest bits of fractions - uint32_t now=*ntp_secs&0x0000FFFF; - now <<=16; - now += (*ntp_frac&0xffff0000)>>16; - - uint32_t receiveTime = lastReceivedRRNTPsecs&0x0000FFFF; - receiveTime <<=16; - receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16; - - delaySinceLastReceivedSR = now-receiveTime; - } - report_block->delaySinceLastSR = delaySinceLastReceivedSR; - report_block->lastSR = remoteSR; - return true; + if(_audio) + { + timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) + (RTCP_INTERVAL_AUDIO_MS*random/1000); + }else + { + uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS; + if(_sending) + { + // calc bw for video 360/sendBW in kbit/s + uint32_t sendBitrateKbit = 0; + uint32_t videoRate = 0; + uint32_t fecRate = 0; + uint32_t nackRate = 0; + _rtpRtcp.BitrateSent(&sendBitrateKbit, + &videoRate, + &fecRate, + &nackRate); + sendBitrateKbit /= 1000; + if(sendBitrateKbit != 0) + { + minIntervalMs = 360000/sendBitrateKbit; + } + } + if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS) + { + minIntervalMs = RTCP_INTERVAL_VIDEO_MS; + } + timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000); + } + _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext; + } + + // if the data does not fitt in the packet we fill it as much as possible + int32_t buildVal = 0; + + if(rtcpPacketTypeFlags & kRtcpSr) + { + if(hasReceived) + { + buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac, &received); + } else + { + buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac); + } + if(buildVal == -1) + { + return -1; // error + + }else if(buildVal == -2) + { + break; // out of buffer + } + buildVal = BuildSDEC(rtcpbuffer, pos); + if(buildVal == -1) + { + return -1; // error + + }else if(buildVal == -2) + { + break; // out of buffer + } + + }else if(rtcpPacketTypeFlags & kRtcpRr) + { + if(hasReceived) + { + buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac,&received); + }else + { + buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac); + } + if(buildVal == -1) + { + return -1; // error + + }else if(buildVal == -2) + { + break; // out of buffer + } + // only of set + if(_CNAME[0] != 0) + { + buildVal = BuildSDEC(rtcpbuffer, pos); + if(buildVal == -1) + { + return -1; // error + } + } + } + if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset) + { + // If present, this RTCP packet must be placed after a + // receiver report. + buildVal = BuildExtendedJitterReport(rtcpbuffer, + pos, + jitterTransmissionOffset); + if(buildVal == -1) + { + return -1; // error + } + else if(buildVal == -2) + { + break; // out of buffer + } + } + if(rtcpPacketTypeFlags & kRtcpPli) + { + buildVal = BuildPLI(rtcpbuffer, pos); + if(buildVal == -1) + { + return -1; // error + + }else if(buildVal == -2) + { + break; // out of buffer + } + TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI"); + _pliCount++; + TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC, _pliCount); + } + if(rtcpPacketTypeFlags & kRtcpFir) + { + buildVal = BuildFIR(rtcpbuffer, pos, repeat); + if(buildVal == -1) + { + return -1; // error + + }else if(buildVal == -2) + { + break; // out of buffer + } + TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR"); + _fullIntraRequestCount++; + TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC, + _fullIntraRequestCount); + } + if(rtcpPacketTypeFlags & kRtcpSli) + { + buildVal = BuildSLI(rtcpbuffer, pos, (uint8_t)pictureID); + if(buildVal == -1) + { + return -1; // error + + }else if(buildVal == -2) + { + break; // out of buffer + } + } + if(rtcpPacketTypeFlags & kRtcpRpsi) + { + const int8_t payloadType = _rtpRtcp.SendPayloadType(); + if(payloadType == -1) + { + return -1; + } + buildVal = BuildRPSI(rtcpbuffer, pos, pictureID, (uint8_t)payloadType); + if(buildVal == -1) + { + return -1; // error + + }else if(buildVal == -2) + { + break; // out of buffer + } + } + if(rtcpPacketTypeFlags & kRtcpRemb) + { + buildVal = BuildREMB(rtcpbuffer, pos); + if(buildVal == -1) + { + return -1; // error + + }else if(buildVal == -2) + { + break; // out of buffer + } + TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB"); + } + if(rtcpPacketTypeFlags & kRtcpBye) + { + buildVal = BuildBYE(rtcpbuffer, pos); + if(buildVal == -1) + { + return -1; // error + + }else if(buildVal == -2) + { + break; // out of buffer + } + } + if(rtcpPacketTypeFlags & kRtcpApp) + { + buildVal = BuildAPP(rtcpbuffer, pos); + if(buildVal == -1) + { + return -1; // error + + }else if(buildVal == -2) + { + break; // out of buffer + } + } + if(rtcpPacketTypeFlags & kRtcpTmmbr) + { + buildVal = BuildTMMBR(rtcpbuffer, pos); + if(buildVal == -1) + { + return -1; // error + + }else if(buildVal == -2) + { + break; // out of buffer + } + } + if(rtcpPacketTypeFlags & kRtcpTmmbn) + { + buildVal = BuildTMMBN(rtcpbuffer, pos); + if(buildVal == -1) + { + return -1; // error + + }else if(buildVal == -2) + { + break; // out of buffer + } + } + if(rtcpPacketTypeFlags & kRtcpNack) + { + std::string nackString; + buildVal = BuildNACK(rtcpbuffer, pos, nackSize, nackList, + &nackString); + if(buildVal == -1) + { + return -1; // error + + }else if(buildVal == -2) + { + break; // out of buffer + } + TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK", + "nacks", TRACE_STR_COPY(nackString.c_str())); + _nackCount++; + TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC, _nackCount); + } + if(rtcpPacketTypeFlags & kRtcpXrVoipMetric) + { + buildVal = BuildVoIPMetric(rtcpbuffer, pos); + if(buildVal == -1) + { + return -1; // error + + }else if(buildVal == -2) + { + break; // out of buffer + } + } + }while (false); + // Sanity don't send empty packets. + if (pos == 0) + { + return -1; + } + return SendToNetwork(rtcpbuffer, (uint16_t)pos); } int32_t @@ -2009,76 +2027,103 @@ RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) } // called under critsect _criticalSectionRTCPSender -int32_t RTCPSender::WriteAllReportBlocksToBuffer( - uint8_t* rtcpbuffer, - int pos, - uint8_t& numberOfReportBlocks, - const uint32_t NTPsec, - const uint32_t NTPfrac) { +int32_t RTCPSender::AddReportBlocks(uint8_t* rtcpbuffer, + uint32_t& pos, + uint8_t& numberOfReportBlocks, + const RTCPReportBlock* received, + const uint32_t NTPsec, + const uint32_t NTPfrac) { // sanity one block if(pos + 24 >= IP_PACKET_SIZE) { WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__); return -1; } - numberOfReportBlocks = external_report_blocks_.size(); - numberOfReportBlocks += internal_report_blocks_.size(); - if ((pos + numberOfReportBlocks * 24) >= IP_PACKET_SIZE) { + numberOfReportBlocks = _reportBlocks.size(); + if (received) { + // add our multiple RR to numberOfReportBlocks + numberOfReportBlocks++; + } + if (received) { + // answer to the one that sends to me + _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac); + + // Remote SSRC + ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC); + pos += 4; + + // fraction lost + rtcpbuffer[pos++]=received->fractionLost; + + // cumulative loss + ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos, + received->cumulativeLost); + pos += 3; + // extended highest seq_no, contain the highest sequence number received + ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, + received->extendedHighSeqNum); + pos += 4; + + //Jitter + ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->jitter); + pos += 4; + + // Last SR timestamp, our NTP time when we received the last report + // This is the value that we read from the send report packet not when we + // received it... + ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->lastSR); + pos += 4; + + // Delay since last received report,time since we received the report + ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, + received->delaySinceLastSR); + pos += 4; + } + if ((pos + _reportBlocks.size() * 24) >= IP_PACKET_SIZE) { WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__); return -1; } - pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, internal_report_blocks_); - while (!internal_report_blocks_.empty()) { - delete internal_report_blocks_.begin()->second; - internal_report_blocks_.erase(internal_report_blocks_.begin()); - } - pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, external_report_blocks_); - return pos; -} + std::map<uint32_t, RTCPReportBlock*>::iterator it = + _reportBlocks.begin(); -int32_t RTCPSender::WriteReportBlocksToBuffer( - uint8_t* rtcpbuffer, - int32_t position, - const std::map<uint32_t, RTCPReportBlock*>& report_blocks) { - std::map<uint32_t, RTCPReportBlock*>::const_iterator it = - report_blocks.begin(); - for (; it != report_blocks.end(); it++) { + for (; it != _reportBlocks.end(); it++) { + // we can have multiple report block in a conference uint32_t remoteSSRC = it->first; RTCPReportBlock* reportBlock = it->second; if (reportBlock) { // Remote SSRC - ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position, remoteSSRC); - position += 4; + ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, remoteSSRC); + pos += 4; // fraction lost - rtcpbuffer[position++] = reportBlock->fractionLost; + rtcpbuffer[pos++] = reportBlock->fractionLost; // cumulative loss - ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+position, + ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos, reportBlock->cumulativeLost); - position += 3; + pos += 3; // extended highest seq_no, contain the highest sequence number received - ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position, + ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, reportBlock->extendedHighSeqNum); - position += 4; + pos += 4; - // Jitter - ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position, + //Jitter + ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, reportBlock->jitter); - position += 4; + pos += 4; - ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position, + ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, reportBlock->lastSR); - position += 4; + pos += 4; - ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position, + ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, reportBlock->delaySinceLastSR); - position += 4; + pos += 4; } } - return position; + return pos; } // no callbacks allowed inside this function diff --git a/modules/rtp_rtcp/source/rtcp_sender.h b/modules/rtp_rtcp/source/rtcp_sender.h index 06c14ce0..3b679778 100644 --- a/modules/rtp_rtcp/source/rtcp_sender.h +++ b/modules/rtp_rtcp/source/rtcp_sender.h @@ -49,8 +49,7 @@ class RTCPSender { public: RTCPSender(const int32_t id, const bool audio, - Clock* clock, ModuleRtpRtcpImpl* owner, - ReceiveStatistics* receive_statistics); + Clock* clock, ModuleRtpRtcpImpl* owner); virtual ~RTCPSender(); void ChangeUniqueId(const int32_t id); @@ -94,16 +93,16 @@ public: int32_t SendRTCP( uint32_t rtcpPacketTypeFlags, + const ReceiveStatistics::RtpReceiveStatistics* receive_stats, int32_t nackSize = 0, const uint16_t* nackList = 0, bool repeat = false, uint64_t pictureID = 0); - int32_t AddExternalReportBlock( - uint32_t SSRC, - const RTCPReportBlock* receiveBlock); + int32_t AddReportBlock(const uint32_t SSRC, + const RTCPReportBlock* receiveBlock); - int32_t RemoveExternalReportBlock(uint32_t SSRC); + int32_t RemoveReportBlock(const uint32_t SSRC); /* * REMB @@ -156,71 +155,49 @@ private: void UpdatePacketRate(); - int32_t WriteAllReportBlocksToBuffer(uint8_t* rtcpbuffer, - int pos, + int32_t AddReportBlocks(uint8_t* rtcpbuffer, + uint32_t& pos, uint8_t& numberOfReportBlocks, + const RTCPReportBlock* received, const uint32_t NTPsec, const uint32_t NTPfrac); - int32_t WriteReportBlocksToBuffer( - uint8_t* rtcpbuffer, - int32_t position, - const std::map<uint32_t, RTCPReportBlock*>& report_blocks); - - int32_t AddReportBlock( - uint32_t SSRC, - std::map<uint32_t, RTCPReportBlock*>* report_blocks, - const RTCPReportBlock* receiveBlock); - - bool PrepareReport(StreamStatistician* statistician, - RTCPReportBlock* report_block, - uint32_t* ntp_secs, uint32_t* ntp_frac); - int32_t BuildSR(uint8_t* rtcpbuffer, - int& pos, + uint32_t& pos, const uint32_t NTPsec, - const uint32_t NTPfrac); + const uint32_t NTPfrac, + const RTCPReportBlock* received = NULL); int32_t BuildRR(uint8_t* rtcpbuffer, - int& pos, + uint32_t& pos, const uint32_t NTPsec, - const uint32_t NTPfrac); - - int PrepareRTCP( - uint32_t packetTypeFlags, - int32_t nackSize, - const uint16_t* nackList, - bool repeat, - uint64_t pictureID, - uint8_t* rtcp_buffer, - int buffer_size); - - bool ShouldSendReportBlocks(uint32_t rtcp_packet_type) const; + const uint32_t NTPfrac, + const RTCPReportBlock* received = NULL); int32_t BuildExtendedJitterReport( uint8_t* rtcpbuffer, - int& pos, + uint32_t& pos, const uint32_t jitterTransmissionTimeOffset); - int32_t BuildSDEC(uint8_t* rtcpbuffer, int& pos); - int32_t BuildPLI(uint8_t* rtcpbuffer, int& pos); - int32_t BuildREMB(uint8_t* rtcpbuffer, int& pos); - int32_t BuildTMMBR(uint8_t* rtcpbuffer, int& pos); - int32_t BuildTMMBN(uint8_t* rtcpbuffer, int& pos); - int32_t BuildAPP(uint8_t* rtcpbuffer, int& pos); - int32_t BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos); - int32_t BuildBYE(uint8_t* rtcpbuffer, int& pos); - int32_t BuildFIR(uint8_t* rtcpbuffer, int& pos, bool repeat); + int32_t BuildSDEC(uint8_t* rtcpbuffer, uint32_t& pos); + int32_t BuildPLI(uint8_t* rtcpbuffer, uint32_t& pos); + int32_t BuildREMB(uint8_t* rtcpbuffer, uint32_t& pos); + int32_t BuildTMMBR(uint8_t* rtcpbuffer, uint32_t& pos); + int32_t BuildTMMBN(uint8_t* rtcpbuffer, uint32_t& pos); + int32_t BuildAPP(uint8_t* rtcpbuffer, uint32_t& pos); + int32_t BuildVoIPMetric(uint8_t* rtcpbuffer, uint32_t& pos); + int32_t BuildBYE(uint8_t* rtcpbuffer, uint32_t& pos); + int32_t BuildFIR(uint8_t* rtcpbuffer, uint32_t& pos, bool repeat); int32_t BuildSLI(uint8_t* rtcpbuffer, - int& pos, + uint32_t& pos, const uint8_t pictureID); int32_t BuildRPSI(uint8_t* rtcpbuffer, - int& pos, + uint32_t& pos, const uint64_t pictureID, const uint8_t payloadType); int32_t BuildNACK(uint8_t* rtcpbuffer, - int& pos, + uint32_t& pos, const int32_t nackSize, const uint16_t* nackList, std::string* nackString); @@ -254,10 +231,7 @@ private: uint32_t _remoteSSRC; // SSRC that we receive on our RTP channel char _CNAME[RTCP_CNAME_SIZE]; - - ReceiveStatistics* receive_statistics_; - std::map<uint32_t, RTCPReportBlock*> internal_report_blocks_; - std::map<uint32_t, RTCPReportBlock*> external_report_blocks_; + std::map<uint32_t, RTCPReportBlock*> _reportBlocks; std::map<uint32_t, RTCPUtility::RTCPCnameInformation*> _csrcCNAMEs; int32_t _cameraDelayMS; diff --git a/modules/rtp_rtcp/source/rtcp_sender_unittest.cc b/modules/rtp_rtcp/source/rtcp_sender_unittest.cc index 6e05fd12..855f418c 100644 --- a/modules/rtp_rtcp/source/rtcp_sender_unittest.cc +++ b/modules/rtp_rtcp/source/rtcp_sender_unittest.cc @@ -285,8 +285,7 @@ class RtcpSenderTest : public ::testing::Test { remote_bitrate_estimator_( RemoteBitrateEstimatorFactory().Create( &remote_bitrate_observer_, - system_clock_)), - receive_statistics_(ReceiveStatistics::Create(system_clock_)) { + system_clock_)) { test_transport_ = new TestTransport(); RtpRtcp::Configuration configuration; @@ -299,8 +298,7 @@ class RtcpSenderTest : public ::testing::Test { rtp_rtcp_impl_ = new ModuleRtpRtcpImpl(configuration); rtp_receiver_.reset(RtpReceiver::CreateVideoReceiver( 0, system_clock_, test_transport_, NULL, rtp_payload_registry_.get())); - rtcp_sender_ = new RTCPSender(0, false, system_clock_, rtp_rtcp_impl_, - receive_statistics_.get()); + rtcp_sender_ = new RTCPSender(0, false, system_clock_, rtp_rtcp_impl_); rtcp_receiver_ = new RTCPReceiver(0, system_clock_, rtp_rtcp_impl_); test_transport_->SetRTCPReceiver(rtcp_receiver_); // Initialize @@ -330,7 +328,6 @@ class RtcpSenderTest : public ::testing::Test { TestTransport* test_transport_; MockRemoteBitrateObserver remote_bitrate_observer_; scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_; - scoped_ptr<ReceiveStatistics> receive_statistics_; enum {kMaxPacketLength = 1500}; uint8_t packet_[kMaxPacketLength]; @@ -338,7 +335,7 @@ class RtcpSenderTest : public ::testing::Test { TEST_F(RtcpSenderTest, RtcpOff) { EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpOff)); - EXPECT_EQ(-1, rtcp_sender_->SendRTCP(kRtcpSr)); + EXPECT_EQ(-1, rtcp_sender_->SendRTCP(kRtcpSr, NULL)); } TEST_F(RtcpSenderTest, IJStatus) { @@ -375,13 +372,14 @@ TEST_F(RtcpSenderTest, TestCompound) { PayloadUnion payload_specific; EXPECT_TRUE(rtp_payload_registry_->GetPayloadSpecifics(header.payloadType, &payload_specific)); - receive_statistics_->IncomingPacket(header, packet_length, false, true); EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(&header, packet_, packet_length, payload_specific, true)); EXPECT_EQ(0, rtcp_sender_->SetIJStatus(true)); EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpCompound)); - EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRr)); + ReceiveStatistics::RtpReceiveStatistics receive_stats; + memset(&receive_stats, 0, sizeof(receive_stats)); + EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRr, &receive_stats)); // Transmission time offset packet should be received. ASSERT_TRUE(test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags & @@ -391,7 +389,9 @@ TEST_F(RtcpSenderTest, TestCompound) { TEST_F(RtcpSenderTest, TestCompound_NoRtpReceived) { EXPECT_EQ(0, rtcp_sender_->SetIJStatus(true)); EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpCompound)); - EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRr)); + // |receive_stats| is NULL since no data has been received. + ReceiveStatistics::RtpReceiveStatistics* receive_stats = NULL; + EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRr, receive_stats)); // Transmission time offset packet should not be received. ASSERT_FALSE(test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags & @@ -409,7 +409,9 @@ TEST_F(RtcpSenderTest, SendsTmmbnIfSetAndEmpty) { TMMBRSet bounding_set; EXPECT_EQ(0, rtcp_sender_->SetTMMBN(&bounding_set, 3)); ASSERT_EQ(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags); - EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpSr)); + ReceiveStatistics::RtpReceiveStatistics receive_stats; + memset(&receive_stats, 0, sizeof(receive_stats)); + EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpSr, &receive_stats)); // We now expect the packet to show up in the rtcp_packet_info_ of // test_transport_. ASSERT_NE(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags); @@ -431,7 +433,9 @@ TEST_F(RtcpSenderTest, SendsTmmbnIfSetAndValid) { EXPECT_EQ(0, rtcp_sender_->SetTMMBN(&bounding_set, 3)); ASSERT_EQ(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags); - EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpSr)); + ReceiveStatistics::RtpReceiveStatistics receive_stats; + memset(&receive_stats, 0, sizeof(receive_stats)); + EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpSr, &receive_stats)); // We now expect the packet to show up in the rtcp_packet_info_ of // test_transport_. ASSERT_NE(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags); diff --git a/modules/rtp_rtcp/source/rtp_receiver_impl.cc b/modules/rtp_rtcp/source/rtp_receiver_impl.cc index c3d1039f..b50b348a 100644 --- a/modules/rtp_rtcp/source/rtp_receiver_impl.cc +++ b/modules/rtp_rtcp/source/rtp_receiver_impl.cc @@ -283,7 +283,7 @@ bool RtpReceiverImpl::IncomingRtpPacket( } if (should_reset_statistics) { - cb_rtp_feedback_->ResetStatistics(ssrc_); + cb_rtp_feedback_->ResetStatistics(); } WebRtcRTPHeader webrtc_rtp_header; @@ -418,7 +418,7 @@ void RtpReceiverImpl::CheckSSRCChanged(const RTPHeader* rtp_header) { // We need the payload_type_ to make the call if the remote SSRC is 0. new_ssrc = true; - cb_rtp_feedback_->ResetStatistics(ssrc_); + cb_rtp_feedback_->ResetStatistics(); last_received_timestamp_ = 0; last_received_sequence_number_ = 0; diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc index 1dd7cd05..145c89b6 100644 --- a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc +++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc @@ -41,7 +41,7 @@ RtpRtcp::Configuration::Configuration() audio(false), clock(NULL), default_module(NULL), - receive_statistics(NullObjectReceiveStatistics()), + receive_statistics(NULL), outgoing_transport(NULL), rtcp_feedback(NULL), intra_frame_callback(NULL), @@ -74,9 +74,10 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const Configuration& configuration) configuration.audio_messages, configuration.paced_sender), rtcp_sender_(configuration.id, configuration.audio, configuration.clock, - this, configuration.receive_statistics), + this), rtcp_receiver_(configuration.id, configuration.clock, this), clock_(configuration.clock), + receive_statistics_(configuration.receive_statistics), id_(configuration.id), audio_(configuration.audio), collision_detected_(false), @@ -241,7 +242,13 @@ int32_t ModuleRtpRtcpImpl::Process() { } } if (rtcp_sender_.TimeToSendRTCPReport()) { - rtcp_sender_.SendRTCP(kRtcpReport); + ReceiveStatistics::RtpReceiveStatistics receive_stats; + if (receive_statistics_ && + receive_statistics_->Statistics(&receive_stats, true)) { + rtcp_sender_.SendRTCP(kRtcpReport, &receive_stats); + } else { + rtcp_sender_.SendRTCP(kRtcpReport, NULL); + } } } @@ -570,7 +577,13 @@ int32_t ModuleRtpRtcpImpl::SendOutgoingData( if (!have_child_modules) { // Don't send RTCP from default module. if (rtcp_sender_.TimeToSendRTCPReport(kVideoFrameKey == frame_type)) { - rtcp_sender_.SendRTCP(kRtcpReport); + ReceiveStatistics::RtpReceiveStatistics receive_stats; + if (receive_statistics_ && + receive_statistics_->Statistics(&receive_stats, true)) { + rtcp_sender_.SendRTCP(kRtcpReport, &receive_stats); + } else { + rtcp_sender_.SendRTCP(kRtcpReport, NULL); + } } return rtp_sender_.SendOutgoingData(frame_type, payload_type, @@ -912,7 +925,19 @@ int32_t ModuleRtpRtcpImpl::ResetSendDataCountersRTP() { int32_t ModuleRtpRtcpImpl::SendRTCP(uint32_t rtcp_packet_type) { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id_, "SendRTCP(0x%x)", rtcp_packet_type); - return rtcp_sender_.SendRTCP(kRtcpReport); + ReceiveStatistics::RtpReceiveStatistics receive_stats; + if (rtcp_sender_.Status() == kRtcpCompound || + (rtcp_packet_type & kRtcpReport) || + (rtcp_packet_type & kRtcpSr) || + (rtcp_packet_type & kRtcpRr)) { + if (receive_statistics_ && + receive_statistics_->Statistics(&receive_stats, true)) { + return rtcp_sender_.SendRTCP(rtcp_packet_type, &receive_stats); + } else { + return rtcp_sender_.SendRTCP(rtcp_packet_type, NULL); + } + } + return rtcp_sender_.SendRTCP(rtcp_packet_type, NULL); } int32_t ModuleRtpRtcpImpl::SetRTCPApplicationSpecificData( @@ -968,14 +993,14 @@ int32_t ModuleRtpRtcpImpl::AddRTCPReportBlock( const RTCPReportBlock* report_block) { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id_, "AddRTCPReportBlock()"); - return rtcp_sender_.AddExternalReportBlock(ssrc, report_block); + return rtcp_sender_.AddReportBlock(ssrc, report_block); } int32_t ModuleRtpRtcpImpl::RemoveRTCPReportBlock( const uint32_t ssrc) { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id_, "RemoveRTCPReportBlock()"); - return rtcp_sender_.RemoveExternalReportBlock(ssrc); + return rtcp_sender_.RemoveReportBlock(ssrc); } // (REMB) Receiver Estimated Max Bitrate. @@ -1129,7 +1154,15 @@ int32_t ModuleRtpRtcpImpl::SendNACK(const uint16_t* nack_list, } nack_last_seq_number_sent_ = nack_list[start_id + nackLength - 1]; - return rtcp_sender_.SendRTCP(kRtcpNack, nackLength, &nack_list[start_id]); + ReceiveStatistics::RtpReceiveStatistics receive_stats; + if (rtcp_sender_.Status() == kRtcpCompound && receive_statistics_ && + receive_statistics_->Statistics(&receive_stats, true)) { + return rtcp_sender_.SendRTCP(kRtcpNack, &receive_stats, nackLength, + &nack_list[start_id]); + } else { + return rtcp_sender_.SendRTCP(kRtcpNack, NULL, nackLength, + &nack_list[start_id]); + } } // Store the sent packets, needed to answer to a Negative acknowledgment @@ -1324,8 +1357,14 @@ int32_t ModuleRtpRtcpImpl::SendRTCPSliceLossIndication( id_, "SendRTCPSliceLossIndication (picture_id:%d)", picture_id); - - return rtcp_sender_.SendRTCP(kRtcpSli, 0, 0, false, picture_id); + ReceiveStatistics::RtpReceiveStatistics receive_stats; + if (rtcp_sender_.Status() == kRtcpCompound && receive_statistics_ && + receive_statistics_->Statistics(&receive_stats, true)) { + return rtcp_sender_.SendRTCP(kRtcpSli, &receive_stats, 0, 0, false, + picture_id); + } else { + return rtcp_sender_.SendRTCP(kRtcpSli, NULL, 0, 0, false, picture_id); + } } int32_t ModuleRtpRtcpImpl::SetCameraDelay(const int32_t delay_ms) { @@ -1523,7 +1562,14 @@ void ModuleRtpRtcpImpl::OnRequestSendReport() { int32_t ModuleRtpRtcpImpl::SendRTCPReferencePictureSelection( const uint64_t picture_id) { - return rtcp_sender_.SendRTCP(kRtcpRpsi, 0, 0, false, picture_id); + ReceiveStatistics::RtpReceiveStatistics receive_stats; + if (rtcp_sender_.Status() == kRtcpCompound && receive_statistics_ && + receive_statistics_->Statistics(&receive_stats, true)) { + return rtcp_sender_.SendRTCP(kRtcpRpsi, &receive_stats, 0, 0, false, + picture_id); + } else { + return rtcp_sender_.SendRTCP(kRtcpRpsi, NULL, 0, 0, false, picture_id); + } } uint32_t ModuleRtpRtcpImpl::SendTimeOfSendReport( diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.h b/modules/rtp_rtcp/source/rtp_rtcp_impl.h index 11340c26..76862884 100644 --- a/modules/rtp_rtcp/source/rtp_rtcp_impl.h +++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.h @@ -377,6 +377,8 @@ class ModuleRtpRtcpImpl : public RtpRtcp { private: int64_t RtcpReportInterval(); + ReceiveStatistics* receive_statistics_; + int32_t id_; const bool audio_; bool collision_detected_; diff --git a/modules/rtp_rtcp/source/rtp_utility.cc b/modules/rtp_rtcp/source/rtp_utility.cc index 409a1773..dd626044 100644 --- a/modules/rtp_rtcp/source/rtp_utility.cc +++ b/modules/rtp_rtcp/source/rtp_utility.cc @@ -61,11 +61,6 @@ RtpAudioFeedback* NullObjectRtpAudioFeedback() { return &null_rtp_audio_feedback; } -ReceiveStatistics* NullObjectReceiveStatistics() { - static NullReceiveStatistics null_receive_statistics; - return &null_receive_statistics; -} - namespace ModuleRTPUtility { enum { diff --git a/modules/rtp_rtcp/source/rtp_utility.h b/modules/rtp_rtcp/source/rtp_utility.h index 72bbfa0e..e2706f2f 100644 --- a/modules/rtp_rtcp/source/rtp_utility.h +++ b/modules/rtp_rtcp/source/rtp_utility.h @@ -14,7 +14,6 @@ #include <stddef.h> // size_t, ptrdiff_t #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" -#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h" #include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h" #include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h" #include "webrtc/typedefs.h" @@ -26,7 +25,6 @@ const uint8_t kRtpMarkerBitMask = 0x80; RtpData* NullObjectRtpData(); RtpFeedback* NullObjectRtpFeedback(); RtpAudioFeedback* NullObjectRtpAudioFeedback(); -ReceiveStatistics* NullObjectReceiveStatistics(); namespace ModuleRTPUtility { diff --git a/modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc b/modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc index 3df06a21..66026b05 100644 --- a/modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc +++ b/modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc @@ -76,8 +76,8 @@ class TestRtpFeedback : public NullRtpFeedback { virtual ~TestRtpFeedback() {} virtual void OnIncomingSSRCChanged(const int32_t id, - const uint32_t ssrc) { - rtp_rtcp_->SetRemoteSSRC(ssrc); + const uint32_t SSRC) { + rtp_rtcp_->SetRemoteSSRC(SSRC); } private: @@ -334,10 +334,8 @@ TEST_F(RtpRtcpRtcpTest, RTCP) { EXPECT_EQ(static_cast<uint32_t>(0), reportBlockReceived.cumulativeLost); - StreamStatistician *statistician = - receive_statistics2_->GetStatistician(reportBlockReceived.sourceSSRC); - StreamStatistician::Statistics stats; - EXPECT_TRUE(statistician->GetStatistics(&stats, true)); + ReceiveStatistics::RtpReceiveStatistics stats; + EXPECT_TRUE(receive_statistics2_->Statistics(&stats, true)); EXPECT_EQ(0, stats.fraction_lost); EXPECT_EQ((uint32_t)0, stats.cumulative_lost); EXPECT_EQ(test_sequence_number, stats.extended_max_sequence_number); diff --git a/video_engine/vie_channel.cc b/video_engine/vie_channel.cc index 2a00c210..851d1c05 100644 --- a/video_engine/vie_channel.cc +++ b/video_engine/vie_channel.cc @@ -324,7 +324,6 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec, WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_), "%s: RTP::SetRTCPStatus failure", __FUNCTION__); } - if (rtp_rtcp_->StorePackets()) { rtp_rtcp->SetStorePacketsStatus(true, nack_history_size_sender_); } else if (paced_sender_) { @@ -1273,12 +1272,10 @@ int32_t ViEChannel::GetReceivedRtcpStatistics(uint16_t* fraction_lost, WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s", __FUNCTION__); - uint32_t remote_ssrc = vie_receiver_.GetRemoteSsrc(); uint8_t frac_lost = 0; - StreamStatistician* statistician = - vie_receiver_.GetReceiveStatistics()->GetStatistician(remote_ssrc); - StreamStatistician::Statistics receive_stats; - if (!statistician || !statistician->GetStatistics( + ReceiveStatistics* receive_statistics = vie_receiver_.GetReceiveStatistics(); + ReceiveStatistics::RtpReceiveStatistics receive_stats; + if (!receive_statistics || !receive_statistics->Statistics( &receive_stats, rtp_rtcp_->RTCP() == kRtcpOff)) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), "%s: Could not get received RTP statistics", __FUNCTION__); @@ -1290,6 +1287,7 @@ int32_t ViEChannel::GetReceivedRtcpStatistics(uint16_t* fraction_lost, *jitter_samples = receive_stats.jitter; *fraction_lost = frac_lost; + uint32_t remote_ssrc = vie_receiver_.GetRemoteSsrc(); uint16_t dummy = 0; uint16_t rtt = 0; if (rtp_rtcp_->RTT(remote_ssrc, &rtt, &dummy, &dummy, &dummy) != 0) { @@ -1307,12 +1305,8 @@ int32_t ViEChannel::GetRtpStatistics(uint32_t* bytes_sent, WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s", __FUNCTION__); - StreamStatistician* statistician = vie_receiver_.GetReceiveStatistics()-> - GetStatistician(vie_receiver_.GetRemoteSsrc()); - *bytes_received = 0; - *packets_received = 0; - if (statistician) - statistician->GetDataCounters(bytes_received, packets_received); + ReceiveStatistics* receive_statistics = vie_receiver_.GetReceiveStatistics(); + receive_statistics->GetDataCounters(bytes_received, packets_received); if (rtp_rtcp_->DataCountersRTP(bytes_sent, packets_sent) != 0) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), "%s: Could not get counters", __FUNCTION__); @@ -1894,7 +1888,8 @@ int32_t ViEChannel::OnInitializeDecoder( return 0; } -void ViEChannel::OnIncomingSSRCChanged(const int32_t id, const uint32_t ssrc) { +void ViEChannel::OnIncomingSSRCChanged(const int32_t id, + const uint32_t SSRC) { if (channel_id_ != ChannelId(id)) { assert(false); WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), @@ -1903,14 +1898,14 @@ void ViEChannel::OnIncomingSSRCChanged(const int32_t id, const uint32_t ssrc) { } WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), - "%s: %u", __FUNCTION__, ssrc); + "%s: %u", __FUNCTION__, SSRC); - rtp_rtcp_->SetRemoteSSRC(ssrc); + rtp_rtcp_->SetRemoteSSRC(SSRC); CriticalSectionScoped cs(callback_cs_.get()); { if (rtp_observer_) { - rtp_observer_->IncomingSSRCChanged(channel_id_, ssrc); + rtp_observer_->IncomingSSRCChanged(channel_id_, SSRC); } } } @@ -1939,11 +1934,8 @@ void ViEChannel::OnIncomingCSRCChanged(const int32_t id, } } -void ViEChannel::ResetStatistics(uint32_t ssrc) { - StreamStatistician* statistician = - vie_receiver_.GetReceiveStatistics()->GetStatistician(ssrc); - if (statistician) - statistician->ResetStatistics(); +void ViEChannel::ResetStatistics() { + vie_receiver_.GetReceiveStatistics()->ResetStatistics(); } } // namespace webrtc diff --git a/video_engine/vie_channel.h b/video_engine/vie_channel.h index 322ec952..0d2e64b4 100644 --- a/video_engine/vie_channel.h +++ b/video_engine/vie_channel.h @@ -212,11 +212,11 @@ class ViEChannel const uint8_t channels, const uint32_t rate); virtual void OnIncomingSSRCChanged(const int32_t id, - const uint32_t ssrc); + const uint32_t SSRC); virtual void OnIncomingCSRCChanged(const int32_t id, const uint32_t CSRC, const bool added); - virtual void ResetStatistics(uint32_t); + virtual void ResetStatistics(); int32_t SetLocalReceiver(const uint16_t rtp_port, const uint16_t rtcp_port, diff --git a/video_engine/vie_receiver.cc b/video_engine/vie_receiver.cc index cc50b9ac..2edf68b7 100644 --- a/video_engine/vie_receiver.cc +++ b/video_engine/vie_receiver.cc @@ -404,10 +404,8 @@ bool ViEReceiver::IsPacketRetransmitted(const RTPHeader& header) const { rtp_receiver_->RTXStatus(&rtx_enabled, &rtx_ssrc, &rtx_payload_type); if (!rtx_enabled) { // Check if this is a retransmission. - StreamStatistician::Statistics stats; - StreamStatistician* statistician = - rtp_receive_statistics_->GetStatistician(header.ssrc); - if (statistician && statistician->GetStatistics(&stats, false)) { + ReceiveStatistics::RtpReceiveStatistics stats; + if (rtp_receive_statistics_->Statistics(&stats, false)) { uint16_t min_rtt = 0; rtp_rtcp_->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL); return rtp_receiver_->RetransmitOfOldPacket(header, stats.jitter, diff --git a/voice_engine/channel.cc b/voice_engine/channel.cc index 4671b6fd..f8f8bd2c 100644 --- a/voice_engine/channel.cc +++ b/voice_engine/channel.cc @@ -360,15 +360,20 @@ Channel::OnPlayTelephoneEvent(int32_t id, } void -Channel::OnIncomingSSRCChanged(int32_t id, uint32_t ssrc) +Channel::OnIncomingSSRCChanged(int32_t id, + uint32_t SSRC) { WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), "Channel::OnIncomingSSRCChanged(id=%d, SSRC=%d)", - id, ssrc); + id, SSRC); int32_t channel = VoEChannelId(id); assert(channel == _channelId); + // Reset RTP-module counters since a new incoming RTP stream is detected + rtp_receive_statistics_->ResetDataCounters(); + rtp_receive_statistics_->ResetStatistics(); + if (_rtpObserver) { CriticalSectionScoped cs(&_callbackCritSect); @@ -376,7 +381,7 @@ Channel::OnIncomingSSRCChanged(int32_t id, uint32_t ssrc) if (_rtpObserverPtr) { // Send new SSRC to registered observer using callback - _rtpObserverPtr->OnIncomingSSRCChanged(channel, ssrc); + _rtpObserverPtr->OnIncomingSSRCChanged(channel, SSRC); } } } @@ -403,12 +408,8 @@ void Channel::OnIncomingCSRCChanged(int32_t id, } } -void Channel::ResetStatistics(uint32_t ssrc) { - StreamStatistician* statistician = - rtp_receive_statistics_->GetStatistician(ssrc); - if (statistician) { - statistician->ResetStatistics(); - } +void Channel::ResetStatistics() { + rtp_receive_statistics_->ResetStatistics(); } void @@ -2230,10 +2231,8 @@ bool Channel::IsPacketRetransmitted(const RTPHeader& header) const { rtp_receiver_->RTXStatus(&rtx_enabled, &rtx_ssrc, &rtx_payload_type); if (!rtx_enabled) { // Check if this is a retransmission. - StreamStatistician::Statistics stats; - StreamStatistician* statistician = - rtp_receive_statistics_->GetStatistician(header.ssrc); - if (statistician && statistician->GetStatistics(&stats, false)) { + ReceiveStatistics::RtpReceiveStatistics stats; + if (rtp_receive_statistics_->Statistics(&stats, false)) { uint16_t min_rtt = 0; _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL); return rtp_receiver_->RetransmitOfOldPacket(header, stats.jitter, @@ -3922,10 +3921,8 @@ 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( + ReceiveStatistics::RtpReceiveStatistics statistics; + if (!rtp_receive_statistics_->Statistics( &statistics, _rtpRtcpModule->RTCP() == kRtcpOff)) { _engineStatisticsPtr->SetLastError( VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning, @@ -4019,10 +4016,8 @@ Channel::GetRTPStatistics(CallStatistics& stats) // 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( + ReceiveStatistics::RtpReceiveStatistics statistics; + if (!rtp_receive_statistics_->Statistics( &statistics, _rtpRtcpModule->RTCP() == kRtcpOff)) { _engineStatisticsPtr->SetLastError( VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning, @@ -4092,9 +4087,7 @@ Channel::GetRTPStatistics(CallStatistics& stats) uint32_t bytesReceived(0); uint32_t packetsReceived(0); - if (statistician) { - statistician->GetDataCounters(&bytesReceived, &packetsReceived); - } + rtp_receive_statistics_->GetDataCounters(&bytesReceived, &packetsReceived); if (_rtpRtcpModule->DataCountersRTP(&bytesSent, &packetsSent) != 0) diff --git a/voice_engine/channel.h b/voice_engine/channel.h index 34013069..f88dca47 100644 --- a/voice_engine/channel.h +++ b/voice_engine/channel.h @@ -329,12 +329,12 @@ public: RTPAliveType alive); void OnIncomingSSRCChanged(int32_t id, - uint32_t ssrc); + uint32_t SSRC); void OnIncomingCSRCChanged(int32_t id, uint32_t CSRC, bool added); - void ResetStatistics(uint32_t ssrc); + void ResetStatistics(); public: // From RtcpFeedback in the RTP/RTCP module |