Revert r4322 "Support sending multiple report blocks and keeping track of statistics on
several SSRCs"

R=pwestin@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/1774006

git-svn-id: http://webrtc.googlecode.com/svn/trunk@4344 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp
index be6c909..3ea1515 100644
--- a/webrtc/modules/modules.gyp
+++ b/webrtc/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/webrtc/modules/rtp_rtcp/interface/receive_statistics.h b/webrtc/modules/rtp_rtcp/interface/receive_statistics.h
index 4cc069a..fc47bf8 100644
--- a/webrtc/modules/rtp_rtcp/interface/receive_statistics.h
+++ b/webrtc/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 @@
 
 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,36 +29,26 @@
     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;
-};
-
-class ReceiveStatistics : public Module {
- public:
-  typedef std::map<uint32_t, StreamStatistician*> StatisticianMap;
-
   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 void GetActiveStatisticians(
-      StatisticianMap* statisticians) 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;
+
+  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/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h b/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h
index aa7f4e8..9754203 100644
--- a/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h
+++ b/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h
@@ -205,13 +205,13 @@
         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 OnResetStatistics(uint32_t ssrc) = 0;
+    virtual void OnResetStatistics() = 0;
 
 protected:
     virtual ~RtpFeedback() {}
@@ -281,13 +281,13 @@
  }
 
   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 OnResetStatistics(uint32_t ssrc) {}
+ virtual void OnResetStatistics() {}
 };
 
 // Null object version of RtpData.
diff --git a/webrtc/modules/rtp_rtcp/source/nack_rtx_unittest.cc b/webrtc/modules/rtp_rtcp/source/nack_rtx_unittest.cc
index 56b49cc..ecf4a07 100644
--- a/webrtc/modules/rtp_rtcp/source/nack_rtx_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/nack_rtx_unittest.cc
@@ -56,8 +56,8 @@
   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/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc b/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc
index 1c28fa6..afeafbc 100644
--- a/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc
+++ b/webrtc/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_oh_(12),
+
+      received_packet_oh_(12),  // RTP header.
       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,33 +66,33 @@
   received_byte_count_ = 0;
   received_retransmitted_packets_ = 0;
   received_inorder_packet_count_ = 0;
-  first_packet_ = true;
 }
 
-void StreamStatisticianImpl::ResetDataCounters() {
-  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 StreamStatisticianImpl::IncomingPacket(const RTPHeader& header,
-                                            size_t bytes,
-                                            bool retransmitted,
-                                            bool in_order) {
-  CriticalSectionScoped cs(crit_sect_.get());
+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;
   }
 
@@ -98,9 +100,8 @@
   // 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.
@@ -115,12 +116,8 @@
 
     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);
@@ -137,7 +134,7 @@
       // 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_ +
@@ -153,8 +150,7 @@
       }
     }
     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_++;
@@ -170,8 +166,19 @@
   received_packet_oh_ = (15 * received_packet_oh_ + 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());
+
+  if (missing == NULL) {
+    return false;
+  }
   if (received_seq_first_ == 0 && received_byte_count_ == 0) {
     // We have not received anything.
     return false;
@@ -216,19 +223,19 @@
       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 = (uint8_t)((255 * (missing)) / exp_since_last);
+    local_fraction_lost = (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_;
@@ -251,9 +258,10 @@
   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_;
   }
@@ -263,105 +271,19 @@
   }
 }
 
-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);
-}
-
-void ReceiveStatisticsImpl::GetActiveStatisticians(
-    StatisticianMap* statisticians) const {
-  CriticalSectionScoped cs(crit_sect_.get());
-  statisticians->clear();
-  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) {
-      (*statisticians)[it->first] = it->second;
-    }
-  }
-}
-
-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::TimeUntilNextProcess() {
+  int time_since_last_update = clock_->TimeInMilliseconds() -
+      incoming_bitrate_.time_last_rate_update();
+  return std::max(kRateUpdateIntervalMs - time_since_last_update, 0);
 }
 
 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();
+  incoming_bitrate_.Process();
   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);
-}
-
 }  // namespace webrtc
diff --git a/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h b/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h
index d61c0f0..1207606 100644
--- a/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h
+++ b/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h
@@ -23,43 +23,43 @@
 
 class CriticalSectionWrapper;
 
-class StreamStatisticianImpl : public StreamStatistician {
+class ReceiveStatisticsImpl : public ReceiveStatistics {
  public:
-  explicit StreamStatisticianImpl(Clock* clock);
+  explicit ReceiveStatisticsImpl(Clock* clock);
 
-  virtual ~StreamStatisticianImpl() {}
-
-  void IncomingPacket(const RTPHeader& rtp_header, size_t bytes,
-                      bool retransmitted, bool in_order);
-  bool GetStatistics(Statistics* statistics, bool reset);
+  // 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;
-  void ProcessBitrate();
-  uint32_t BitrateReceived() const;
+  uint32_t BitrateReceived();
   void ResetStatistics();
   void ResetDataCounters();
-  void LastReceiveTimeNtp(uint32_t* secs, uint32_t* frac) const;
+
+  // 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_oh_;
@@ -71,35 +71,7 @@
   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.
-  void IncomingPacket(const RTPHeader& header, size_t bytes,
-                      bool old_packet, bool in_order);
-  void ChangeSsrc(uint32_t from_ssrc, uint32_t to_ssrc);
-  void GetActiveStatisticians(StatisticianMap* statisticians) const;
-  StreamStatistician* GetStatistician(uint32_t ssrc) const;
-  void ResetStatistics(uint32_t ssrc);
-  void ResetDataCounters(uint32_t ssrc);
-
-  // Implement Module.
-  int32_t Process();
-  int32_t TimeUntilNextProcess();
-
- 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/webrtc/modules/rtp_rtcp/source/receive_statistics_unittest.cc b/webrtc/modules/rtp_rtcp/source/receive_statistics_unittest.cc
deleted file mode 100644
index b6ddf73..0000000
--- a/webrtc/modules/rtp_rtcp/source/receive_statistics_unittest.cc
+++ /dev/null
@@ -1,137 +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);
-
-  ReceiveStatistics::StatisticianMap statisticians;
-  receive_statistics_->GetActiveStatisticians(&statisticians);
-  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;
-  ReceiveStatistics::StatisticianMap statisticians;
-  receive_statistics_->GetActiveStatisticians(&statisticians);
-  // 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.
-  receive_statistics_->GetActiveStatisticians(&statisticians);
-  EXPECT_EQ(1u, statisticians.size());
-
-  clock_.AdvanceTimeMilliseconds(1000);
-  // kSsrc2 should have timed out.
-  receive_statistics_->GetActiveStatisticians(&statisticians);
-  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.
-  receive_statistics_->GetActiveStatisticians(&statisticians);
-  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/webrtc/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc
index 2a7902f..e7c7bcb 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc
@@ -61,7 +61,6 @@
   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 @@
   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 @@
   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 @@
   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/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc b/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc
index 3470481..8b2fb0c 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc
@@ -406,6 +406,7 @@
         TRACE_EVENT_INSTANT2("webrtc_rtp", "SR",
                              "remote_ssrc", remoteSSRC,
                              "ssrc", _SSRC);
+
         if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
         {
             // only signal that we have received a SR when we accept one
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc
index c3bc8f5..71c47b9 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc
@@ -65,8 +65,7 @@
 RTCPSender::RTCPSender(const int32_t id,
                        const bool audio,
                        Clock* clock,
-                       ModuleRtpRtcpImpl* owner,
-                       ReceiveStatistics* receive_statistics) :
+                       ModuleRtpRtcpImpl* owner) :
     _id(id),
     _audio(audio),
     _clock(clock),
@@ -90,9 +89,7 @@
     _SSRC(0),
     _remoteSSRC(0),
     _CNAME(),
-    receive_statistics_(receive_statistics),
-    internal_report_blocks_(),
-    external_report_blocks_(),
+    _reportBlocks(),
     _csrcCNAMEs(),
 
     _cameraDelayMS(0),
@@ -137,15 +134,11 @@
   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 =
@@ -275,7 +268,7 @@
     }
     if(sendRTCPBye)
     {
-        return SendRTCP(kRtcpBye);
+        return SendRTCP(kRtcpBye, NULL);
     }
     return 0;
 }
@@ -563,59 +556,52 @@
     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)
@@ -683,15 +669,12 @@
     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);
@@ -701,7 +684,7 @@
 
 
 int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer,
-                              int& pos) {
+                              uint32_t& pos) {
   size_t lengthCname = strlen(_CNAME);
   assert(lengthCname < RTCP_CNAME_SIZE);
 
@@ -796,9 +779,10 @@
 
 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)
@@ -819,14 +803,11 @@
     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 retVal;
     }
-    pos = retVal;
     rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
 
     uint16_t len = uint16_t((pos)/4 -1);
@@ -855,10 +836,10 @@
 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;
@@ -886,7 +867,7 @@
 }
 
 int32_t
-RTCPSender::BuildPLI(uint8_t* rtcpbuffer, int& pos)
+RTCPSender::BuildPLI(uint8_t* rtcpbuffer, uint32_t& pos)
 {
     // sanity
     if(pos + 12 >= IP_PACKET_SIZE)
@@ -913,7 +894,7 @@
 }
 
 int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
-                             int& pos,
+                             uint32_t& pos,
                              bool repeat) {
   // sanity
   if(pos + 20 >= IP_PACKET_SIZE)  {
@@ -962,7 +943,7 @@
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 */
 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)
@@ -1009,7 +990,7 @@
 */
 int32_t
 RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
-                     int& pos,
+                     uint32_t& pos,
                      const uint64_t pictureID,
                      const uint8_t payloadType)
 {
@@ -1085,7 +1066,7 @@
 }
 
 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)
@@ -1146,7 +1127,7 @@
 }
 
 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
@@ -1252,7 +1233,7 @@
 }
 
 int32_t
-RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, int& pos)
+RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, uint32_t& pos)
 {
     TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
     if(boundingSet == NULL)
@@ -1324,7 +1305,7 @@
 }
 
 int32_t
-RTCPSender::BuildAPP(uint8_t* rtcpbuffer, int& pos)
+RTCPSender::BuildAPP(uint8_t* rtcpbuffer, uint32_t& pos)
 {
     // sanity
     if(_appData == NULL)
@@ -1362,7 +1343,7 @@
 
 int32_t
 RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
-                      int& pos,
+                      uint32_t& pos,
                       const int32_t nackSize,
                       const uint16_t* nackList,
                       std::string* nackString)
@@ -1432,7 +1413,7 @@
 }
 
 int32_t
-RTCPSender::BuildBYE(uint8_t* rtcpbuffer, int& pos)
+RTCPSender::BuildBYE(uint8_t* rtcpbuffer, uint32_t& pos)
 {
     // sanity
     if(pos + 8 >= IP_PACKET_SIZE)
@@ -1477,7 +1458,7 @@
 }
 
 int32_t
-RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos)
+RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, uint32_t& pos)
 {
     // sanity
     if(pos + 44 >= IP_PACKET_SIZE)
@@ -1552,381 +1533,414 @@
 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__);
+        // collect the received information
+        RTCPReportBlock received;
+        bool hasReceived = false;
+        uint32_t NTPsec = 0;
+        uint32_t NTPfrac = 0;
+        bool rtcpCompound = false;
+        uint32_t jitterTransmissionOffset = 0;
+
+        {
+          CriticalSectionScoped lock(_criticalSectionRTCPSender);
+          if(_method == kRtcpOff)
+          {
+              WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
+                           "%s invalid state", __FUNCTION__);
+              return -1;
+          }
+          rtcpCompound = (_method == kRtcpCompound) ? true : false;
+        }
+
+        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;
+
+                    uint32_t receiveTime = lastReceivedRRNTPsecs&0x0000FFFF;
+                    receiveTime <<=16;
+                    receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16;
+
+                    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);
+            }
+        }
+
+        CriticalSectionScoped lock(_criticalSectionRTCPSender);
+
+        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;
+        }
+
+        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;
+
+            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;
     }
-  }
-  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));
-}
-
-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(_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;
-  }
-
-  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;
-  }
-
-  // If the data does not fit in the packet we fill it as much as possible.
-  int32_t buildVal = 0;
-
-  if (ShouldSendReportBlocks(rtcpPacketTypeFlags)) {
-    ReceiveStatistics::StatisticianMap statisticians;
-    receive_statistics_->GetActiveStatisticians(&statisticians);
-    if (statisticians.empty()) {
-      // We need to send our NTP even if we dont have received any
-      // reports.
-      _clock->CurrentNtp(NTPsec, NTPfrac);
-    } else {
-      ReceiveStatistics::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);
-    }
-  }
-
-  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;
-}
-
-bool RTCPSender::ShouldSendReportBlocks(uint32_t rtcp_packet_type) const {
-  return Status() == kRtcpCompound ||
-      (rtcp_packet_type & kRtcpReport) ||
-      (rtcp_packet_type & kRtcpSr) ||
-      (rtcp_packet_type & kRtcpRr);
-}
-
-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;
+    return SendToNetwork(rtcpbuffer, (uint16_t)pos);
 }
 
 int32_t
@@ -2010,76 +2024,103 @@
 }
 
 // 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/webrtc/modules/rtp_rtcp/source/rtcp_sender.h b/webrtc/modules/rtp_rtcp/source/rtcp_sender.h
index b2c71ea..06c07f4 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_sender.h
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_sender.h
@@ -47,8 +47,7 @@
 {
 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);
@@ -92,16 +91,16 @@
 
     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
@@ -154,71 +153,49 @@
 
     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);
@@ -252,10 +229,7 @@
     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/webrtc/modules/rtp_rtcp/source/rtcp_sender_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_sender_unittest.cc
index 6e05fd1..855f418 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_sender_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_sender_unittest.cc
@@ -285,8 +285,7 @@
         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 @@
     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 @@
   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 @@
 
 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 @@
   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_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 @@
   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 @@
 
   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/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc b/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc
index ce0ad1a..8a3a37d 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc
@@ -282,7 +282,7 @@
     return false;
   }
   if (should_reset_statistics) {
-    cb_rtp_feedback_->OnResetStatistics(ssrc_);
+    cb_rtp_feedback_->OnResetStatistics();
   }
   WebRtcRTPHeader webrtc_rtp_header;
   memset(&webrtc_rtp_header, 0, sizeof(webrtc_rtp_header));
@@ -413,7 +413,7 @@
       // We need the payload_type_ to make the call if the remote SSRC is 0.
       new_ssrc = true;
 
-      cb_rtp_feedback_->OnResetStatistics(ssrc_);
+      cb_rtp_feedback_->OnResetStatistics();
 
       last_received_timestamp_      = 0;
       last_received_sequence_number_ = 0;
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
index 2a1c3d5..0a29904 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
@@ -41,7 +41,7 @@
       audio(false),
       clock(NULL),
       default_module(NULL),
-      receive_statistics(),
+      receive_statistics(NULL),
       outgoing_transport(NULL),
       rtcp_feedback(NULL),
       intra_frame_callback(NULL),
@@ -74,9 +74,10 @@
                   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,12 @@
       }
     }
     if (rtcp_sender_.TimeToSendRTCPReport()) {
-      rtcp_sender_.SendRTCP(kRtcpReport);
+      ReceiveStatistics::RtpReceiveStatistics receive_stats;
+      if (receive_statistics_->Statistics(&receive_stats, true)) {
+        rtcp_sender_.SendRTCP(kRtcpReport, &receive_stats);
+      } else {
+        rtcp_sender_.SendRTCP(kRtcpReport, NULL);
+      }
     }
   }
 
@@ -570,7 +576,12 @@
   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_->Statistics(&receive_stats, true)) {
+        rtcp_sender_.SendRTCP(kRtcpReport, &receive_stats);
+      } else {
+        rtcp_sender_.SendRTCP(kRtcpReport, NULL);
+      }
     }
     return rtp_sender_.SendOutgoingData(frame_type,
                                         payload_type,
@@ -926,7 +937,18 @@
 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_->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(
@@ -982,14 +1004,14 @@
     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.
@@ -1143,7 +1165,15 @@
   }
   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_->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
@@ -1334,8 +1364,14 @@
                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_->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) {
@@ -1533,7 +1569,14 @@
 
 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_->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/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h
index 6eef950..fd70751 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h
+++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h
@@ -374,6 +374,8 @@
  private:
   int64_t RtcpReportInterval();
 
+  ReceiveStatistics* receive_statistics_;
+
   int32_t             id_;
   const bool                audio_;
   bool                      collision_detected_;
diff --git a/webrtc/modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc b/webrtc/modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc
index 3df06a2..66026b0 100644
--- a/webrtc/modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc
+++ b/webrtc/modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc
@@ -76,8 +76,8 @@
   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 @@
   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/webrtc/video_engine/vie_channel.cc b/webrtc/video_engine/vie_channel.cc
index 4b05603..77c3c26 100644
--- a/webrtc/video_engine/vie_channel.cc
+++ b/webrtc/video_engine/vie_channel.cc
@@ -1247,12 +1247,10 @@
   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__);
@@ -1264,6 +1262,7 @@
   *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) {
@@ -1281,12 +1280,8 @@
   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__);
@@ -1866,7 +1861,8 @@
   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_),
@@ -1875,14 +1871,14 @@
   }
 
   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);
     }
   }
 }
@@ -1911,11 +1907,8 @@
   }
 }
 
-void ViEChannel::OnResetStatistics(uint32_t ssrc) {
-  StreamStatistician* statistician =
-      vie_receiver_.GetReceiveStatistics()->GetStatistician(ssrc);
-  if (statistician)
-    statistician->ResetStatistics();
+void ViEChannel::OnResetStatistics() {
+  vie_receiver_.GetReceiveStatistics()->ResetStatistics();
 }
 
 }  // namespace webrtc
diff --git a/webrtc/video_engine/vie_channel.h b/webrtc/video_engine/vie_channel.h
index 47d6c2f..fc86dfc 100644
--- a/webrtc/video_engine/vie_channel.h
+++ b/webrtc/video_engine/vie_channel.h
@@ -209,11 +209,11 @@
       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 OnResetStatistics(uint32_t);
+  virtual void OnResetStatistics();
 
   int32_t SetLocalReceiver(const uint16_t rtp_port,
                            const uint16_t rtcp_port,
diff --git a/webrtc/video_engine/vie_receiver.cc b/webrtc/video_engine/vie_receiver.cc
index 7a805fe..fc986ea 100644
--- a/webrtc/video_engine/vie_receiver.cc
+++ b/webrtc/video_engine/vie_receiver.cc
@@ -412,10 +412,8 @@
   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/webrtc/voice_engine/channel.cc b/webrtc/voice_engine/channel.cc
index be42d51..3c0dd92 100644
--- a/webrtc/voice_engine/channel.cc
+++ b/webrtc/voice_engine/channel.cc
@@ -360,15 +360,20 @@
 }
 
 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 @@
         if (_rtpObserverPtr)
         {
             // Send new SSRC to registered observer using callback
-            _rtpObserverPtr->OnIncomingSSRCChanged(channel, ssrc);
+            _rtpObserverPtr->OnIncomingSSRCChanged(channel, SSRC);
         }
     }
 }
@@ -403,12 +408,8 @@
     }
 }
 
-void Channel::OnResetStatistics(uint32_t ssrc) {
-  StreamStatistician* statistician =
-      rtp_receive_statistics_->GetStatistician(ssrc);
-  if (statistician) {
-    statistician->ResetStatistics();
-  }
+void Channel::OnResetStatistics() {
+  rtp_receive_statistics_->ResetStatistics();
 }
 
 void
@@ -2216,10 +2217,8 @@
   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,
@@ -3908,10 +3907,8 @@
 {
     // 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,
@@ -4005,10 +4002,8 @@
 
     // 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,
@@ -4078,9 +4073,7 @@
     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/webrtc/voice_engine/channel.h b/webrtc/voice_engine/channel.h
index aa8ae35..756ac88 100644
--- a/webrtc/voice_engine/channel.h
+++ b/webrtc/voice_engine/channel.h
@@ -329,12 +329,12 @@
                                RTPAliveType alive);
 
     void OnIncomingSSRCChanged(int32_t id,
-                               uint32_t ssrc);
+                               uint32_t SSRC);
 
     void OnIncomingCSRCChanged(int32_t id,
                                uint32_t CSRC, bool added);
 
-    void OnResetStatistics(uint32_t ssrc);
+    void OnResetStatistics();
 
 public:
     // From RtcpFeedback in the RTP/RTCP module