summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhenrike@webrtc.org <henrike@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d>2013-08-21 19:44:13 +0000
committerhenrike@webrtc.org <henrike@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d>2013-08-21 19:44:13 +0000
commitc0976d247fedbe48d703f1ef3d5fb0fd70fdab93 (patch)
tree8b1e0d2a2f9b8fb2102334113ad42e892f5cd4d7
parentefe1f0f566a6a102bce8d961a1135b987b41d36d (diff)
downloadwebrtc-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
-rw-r--r--modules/modules.gyp1
-rw-r--r--modules/rtp_rtcp/interface/receive_statistics.h54
-rw-r--r--modules/rtp_rtcp/interface/rtp_rtcp_defines.h8
-rw-r--r--modules/rtp_rtcp/source/nack_rtx_unittest.cc4
-rw-r--r--modules/rtp_rtcp/source/receive_statistics_impl.cc212
-rw-r--r--modules/rtp_rtcp/source/receive_statistics_impl.h67
-rw-r--r--modules/rtp_rtcp/source/receive_statistics_unittest.cc135
-rw-r--r--modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc11
-rw-r--r--modules/rtp_rtcp/source/rtcp_sender.cc959
-rw-r--r--modules/rtp_rtcp/source/rtcp_sender.h82
-rw-r--r--modules/rtp_rtcp/source/rtcp_sender_unittest.cc26
-rw-r--r--modules/rtp_rtcp/source/rtp_receiver_impl.cc4
-rw-r--r--modules/rtp_rtcp/source/rtp_rtcp_impl.cc68
-rw-r--r--modules/rtp_rtcp/source/rtp_rtcp_impl.h2
-rw-r--r--modules/rtp_rtcp/source/rtp_utility.cc5
-rw-r--r--modules/rtp_rtcp/source/rtp_utility.h2
-rw-r--r--modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc10
-rw-r--r--video_engine/vie_channel.cc34
-rw-r--r--video_engine/vie_channel.h4
-rw-r--r--video_engine/vie_receiver.cc6
-rw-r--r--voice_engine/channel.cc41
-rw-r--r--voice_engine/channel.h4
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