Add a mutex free implementation of webrtc::ReceiveStatistics

The mutex is removed from the old existing implementation and instead a wrapper is implemented that ensure thread-safety.
Both the thread-safe and unsafe version share the same implementation of the logic.

There are two ways of construction:
webrtc::ReceiveStatistics::Create - thread-safe version.
webrtc::ReceiveStatistics::CreateUnLocked -thread-unsafe

Bug: none
Change-Id: Ica375919fda70180335c8f9ea666497811daf866
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/211240
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Per Kjellander <perkj@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33419}
diff --git a/modules/rtp_rtcp/include/receive_statistics.h b/modules/rtp_rtcp/include/receive_statistics.h
index 2cc3fea..ce87b99 100644
--- a/modules/rtp_rtcp/include/receive_statistics.h
+++ b/modules/rtp_rtcp/include/receive_statistics.h
@@ -55,7 +55,12 @@
  public:
   ~ReceiveStatistics() override = default;
 
+  // Returns a thread-safe instance of ReceiveStatistics.
+  // https://chromium.googlesource.com/chromium/src/+/lkgr/docs/threading_and_tasks.md#threading-lexicon
   static std::unique_ptr<ReceiveStatistics> Create(Clock* clock);
+  // Returns a thread-compatible instance of ReceiveStatistics.
+  static std::unique_ptr<ReceiveStatistics> CreateThreadCompatible(
+      Clock* clock);
 
   // Returns a pointer to the statistician of an ssrc.
   virtual StreamStatistician* GetStatistician(uint32_t ssrc) const = 0;
diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.cc b/modules/rtp_rtcp/source/receive_statistics_impl.cc
index 6ec41a1..4c399a1 100644
--- a/modules/rtp_rtcp/source/receive_statistics_impl.cc
+++ b/modules/rtp_rtcp/source/receive_statistics_impl.cc
@@ -13,6 +13,7 @@
 #include <cmath>
 #include <cstdlib>
 #include <memory>
+#include <utility>
 #include <vector>
 
 #include "modules/remote_bitrate_estimator/test/bwe_test_logging.h"
@@ -100,7 +101,6 @@
 }
 
 void StreamStatisticianImpl::UpdateCounters(const RtpPacketReceived& packet) {
-  MutexLock lock(&stream_lock_);
   RTC_DCHECK_EQ(ssrc_, packet.Ssrc());
   int64_t now_ms = clock_->TimeInMilliseconds();
 
@@ -159,17 +159,14 @@
 
 void StreamStatisticianImpl::SetMaxReorderingThreshold(
     int max_reordering_threshold) {
-  MutexLock lock(&stream_lock_);
   max_reordering_threshold_ = max_reordering_threshold;
 }
 
 void StreamStatisticianImpl::EnableRetransmitDetection(bool enable) {
-  MutexLock lock(&stream_lock_);
   enable_retransmit_detection_ = enable;
 }
 
 RtpReceiveStats StreamStatisticianImpl::GetStats() const {
-  MutexLock lock(&stream_lock_);
   RtpReceiveStats stats;
   stats.packets_lost = cumulative_loss_;
   // TODO(nisse): Can we return a float instead?
@@ -183,7 +180,6 @@
 
 bool StreamStatisticianImpl::GetActiveStatisticsAndReset(
     RtcpStatistics* statistics) {
-  MutexLock lock(&stream_lock_);
   if (clock_->TimeInMilliseconds() - last_receive_time_ms_ >=
       kStatisticsTimeoutMs) {
     // Not active.
@@ -192,9 +188,7 @@
   if (!ReceivedRtpPacket()) {
     return false;
   }
-
   *statistics = CalculateRtcpStatistics();
-
   return true;
 }
 
@@ -241,7 +235,6 @@
 }
 
 absl::optional<int> StreamStatisticianImpl::GetFractionLostInPercent() const {
-  MutexLock lock(&stream_lock_);
   if (!ReceivedRtpPacket()) {
     return absl::nullopt;
   }
@@ -257,12 +250,10 @@
 
 StreamDataCounters StreamStatisticianImpl::GetReceiveStreamDataCounters()
     const {
-  MutexLock lock(&stream_lock_);
   return receive_counters_;
 }
 
 uint32_t StreamStatisticianImpl::BitrateReceived() const {
-  MutexLock lock(&stream_lock_);
   return incoming_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0);
 }
 
@@ -295,21 +286,33 @@
 }
 
 std::unique_ptr<ReceiveStatistics> ReceiveStatistics::Create(Clock* clock) {
-  return std::make_unique<ReceiveStatisticsImpl>(clock);
+  return std::make_unique<ReceiveStatisticsLocked>(
+      clock, [](uint32_t ssrc, Clock* clock, int max_reordering_threshold) {
+        return std::make_unique<StreamStatisticianLocked>(
+            ssrc, clock, max_reordering_threshold);
+      });
 }
 
-ReceiveStatisticsImpl::ReceiveStatisticsImpl(Clock* clock)
+std::unique_ptr<ReceiveStatistics> ReceiveStatistics::CreateThreadCompatible(
+    Clock* clock) {
+  return std::make_unique<ReceiveStatisticsImpl>(
+      clock, [](uint32_t ssrc, Clock* clock, int max_reordering_threshold) {
+        return std::make_unique<StreamStatisticianImpl>(
+            ssrc, clock, max_reordering_threshold);
+      });
+}
+
+ReceiveStatisticsImpl::ReceiveStatisticsImpl(
+    Clock* clock,
+    std::function<std::unique_ptr<StreamStatisticianImplInterface>(
+        uint32_t ssrc,
+        Clock* clock,
+        int max_reordering_threshold)> stream_statistician_factory)
     : clock_(clock),
+      stream_statistician_factory_(std::move(stream_statistician_factory)),
       last_returned_ssrc_(0),
       max_reordering_threshold_(kDefaultMaxReorderingThreshold) {}
 
-ReceiveStatisticsImpl::~ReceiveStatisticsImpl() {
-  while (!statisticians_.empty()) {
-    delete statisticians_.begin()->second;
-    statisticians_.erase(statisticians_.begin());
-  }
-}
-
 void ReceiveStatisticsImpl::OnRtpPacket(const RtpPacketReceived& packet) {
   // StreamStatisticianImpl instance is created once and only destroyed when
   // this whole ReceiveStatisticsImpl is destroyed. StreamStatisticianImpl has
@@ -318,34 +321,28 @@
   GetOrCreateStatistician(packet.Ssrc())->UpdateCounters(packet);
 }
 
-StreamStatisticianImpl* ReceiveStatisticsImpl::GetStatistician(
+StreamStatistician* ReceiveStatisticsImpl::GetStatistician(
     uint32_t ssrc) const {
-  MutexLock lock(&receive_statistics_lock_);
   const auto& it = statisticians_.find(ssrc);
   if (it == statisticians_.end())
-    return NULL;
-  return it->second;
+    return nullptr;
+  return it->second.get();
 }
 
-StreamStatisticianImpl* ReceiveStatisticsImpl::GetOrCreateStatistician(
+StreamStatisticianImplInterface* ReceiveStatisticsImpl::GetOrCreateStatistician(
     uint32_t ssrc) {
-  MutexLock lock(&receive_statistics_lock_);
-  StreamStatisticianImpl*& impl = statisticians_[ssrc];
+  std::unique_ptr<StreamStatisticianImplInterface>& impl = statisticians_[ssrc];
   if (impl == nullptr) {  // new element
-    impl = new StreamStatisticianImpl(ssrc, clock_, max_reordering_threshold_);
+    impl =
+        stream_statistician_factory_(ssrc, clock_, max_reordering_threshold_);
   }
-  return impl;
+  return impl.get();
 }
 
 void ReceiveStatisticsImpl::SetMaxReorderingThreshold(
     int max_reordering_threshold) {
-  std::map<uint32_t, StreamStatisticianImpl*> statisticians;
-  {
-    MutexLock lock(&receive_statistics_lock_);
-    max_reordering_threshold_ = max_reordering_threshold;
-    statisticians = statisticians_;
-  }
-  for (auto& statistician : statisticians) {
+  max_reordering_threshold_ = max_reordering_threshold;
+  for (auto& statistician : statisticians_) {
     statistician.second->SetMaxReorderingThreshold(max_reordering_threshold);
   }
 }
@@ -364,15 +361,11 @@
 
 std::vector<rtcp::ReportBlock> ReceiveStatisticsImpl::RtcpReportBlocks(
     size_t max_blocks) {
-  std::map<uint32_t, StreamStatisticianImpl*> statisticians;
-  {
-    MutexLock lock(&receive_statistics_lock_);
-    statisticians = statisticians_;
-  }
   std::vector<rtcp::ReportBlock> result;
-  result.reserve(std::min(max_blocks, statisticians.size()));
-  auto add_report_block = [&result](uint32_t media_ssrc,
-                                    StreamStatisticianImpl* statistician) {
+  result.reserve(std::min(max_blocks, statisticians_.size()));
+  auto add_report_block = [&result](
+                              uint32_t media_ssrc,
+                              StreamStatisticianImplInterface* statistician) {
     // Do we have receive statistics to send?
     RtcpStatistics stats;
     if (!statistician->GetActiveStatisticsAndReset(&stats))
@@ -390,13 +383,13 @@
     block.SetJitter(stats.jitter);
   };
 
-  const auto start_it = statisticians.upper_bound(last_returned_ssrc_);
+  const auto start_it = statisticians_.upper_bound(last_returned_ssrc_);
   for (auto it = start_it;
-       result.size() < max_blocks && it != statisticians.end(); ++it)
-    add_report_block(it->first, it->second);
-  for (auto it = statisticians.begin();
+       result.size() < max_blocks && it != statisticians_.end(); ++it)
+    add_report_block(it->first, it->second.get());
+  for (auto it = statisticians_.begin();
        result.size() < max_blocks && it != start_it; ++it)
-    add_report_block(it->first, it->second);
+    add_report_block(it->first, it->second.get());
 
   if (!result.empty())
     last_returned_ssrc_ = result.back().source_ssrc();
diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.h b/modules/rtp_rtcp/source/receive_statistics_impl.h
index 41830b0..2456f93 100644
--- a/modules/rtp_rtcp/source/receive_statistics_impl.h
+++ b/modules/rtp_rtcp/source/receive_statistics_impl.h
@@ -12,7 +12,10 @@
 #define MODULES_RTP_RTCP_SOURCE_RECEIVE_STATISTICS_IMPL_H_
 
 #include <algorithm>
+#include <functional>
 #include <map>
+#include <memory>
+#include <utility>
 #include <vector>
 
 #include "absl/types/optional.h"
@@ -24,86 +27,141 @@
 
 namespace webrtc {
 
-class StreamStatisticianImpl : public StreamStatistician {
+// Extends StreamStatistician with methods needed by the implementation.
+class StreamStatisticianImplInterface : public StreamStatistician {
+ public:
+  virtual ~StreamStatisticianImplInterface() = default;
+  virtual bool GetActiveStatisticsAndReset(RtcpStatistics* statistics) = 0;
+  virtual void SetMaxReorderingThreshold(int max_reordering_threshold) = 0;
+  virtual void EnableRetransmitDetection(bool enable) = 0;
+  virtual void UpdateCounters(const RtpPacketReceived& packet) = 0;
+};
+
+// Thread-compatible implementation of StreamStatisticianImplInterface.
+class StreamStatisticianImpl : public StreamStatisticianImplInterface {
  public:
   StreamStatisticianImpl(uint32_t ssrc,
                          Clock* clock,
                          int max_reordering_threshold);
   ~StreamStatisticianImpl() override;
 
+  // Implements StreamStatistician
   RtpReceiveStats GetStats() const override;
-
-  bool GetActiveStatisticsAndReset(RtcpStatistics* statistics);
   absl::optional<int> GetFractionLostInPercent() const override;
   StreamDataCounters GetReceiveStreamDataCounters() const override;
   uint32_t BitrateReceived() const override;
 
-  void SetMaxReorderingThreshold(int max_reordering_threshold);
-  void EnableRetransmitDetection(bool enable);
-
+  // Implements StreamStatisticianImplInterface
+  bool GetActiveStatisticsAndReset(RtcpStatistics* statistics) override;
+  void SetMaxReorderingThreshold(int max_reordering_threshold) override;
+  void EnableRetransmitDetection(bool enable) override;
   // Updates StreamStatistician for incoming packets.
-  void UpdateCounters(const RtpPacketReceived& packet);
+  void UpdateCounters(const RtpPacketReceived& packet) override;
 
  private:
   bool IsRetransmitOfOldPacket(const RtpPacketReceived& packet,
-                               int64_t now_ms) const
-      RTC_EXCLUSIVE_LOCKS_REQUIRED(stream_lock_);
-  RtcpStatistics CalculateRtcpStatistics()
-      RTC_EXCLUSIVE_LOCKS_REQUIRED(stream_lock_);
-  void UpdateJitter(const RtpPacketReceived& packet, int64_t receive_time_ms)
-      RTC_EXCLUSIVE_LOCKS_REQUIRED(stream_lock_);
+                               int64_t now_ms) const;
+  RtcpStatistics CalculateRtcpStatistics();
+  void UpdateJitter(const RtpPacketReceived& packet, int64_t receive_time_ms);
   // Updates StreamStatistician for out of order packets.
   // Returns true if packet considered to be out of order.
   bool UpdateOutOfOrder(const RtpPacketReceived& packet,
                         int64_t sequence_number,
-                        int64_t now_ms)
-      RTC_EXCLUSIVE_LOCKS_REQUIRED(stream_lock_);
+                        int64_t now_ms);
   // Checks if this StreamStatistician received any rtp packets.
-  bool ReceivedRtpPacket() const RTC_EXCLUSIVE_LOCKS_REQUIRED(stream_lock_) {
-    return received_seq_first_ >= 0;
-  }
+  bool ReceivedRtpPacket() const { return received_seq_first_ >= 0; }
 
   const uint32_t ssrc_;
   Clock* const clock_;
-  mutable Mutex stream_lock_;
-  RateStatistics incoming_bitrate_ RTC_GUARDED_BY(&stream_lock_);
+  RateStatistics incoming_bitrate_;
   // In number of packets or sequence numbers.
-  int max_reordering_threshold_ RTC_GUARDED_BY(&stream_lock_);
-  bool enable_retransmit_detection_ RTC_GUARDED_BY(&stream_lock_);
+  int max_reordering_threshold_;
+  bool enable_retransmit_detection_;
 
   // Stats on received RTP packets.
-  uint32_t jitter_q4_ RTC_GUARDED_BY(&stream_lock_);
+  uint32_t jitter_q4_;
   // Cumulative loss according to RFC 3550, which may be negative (and often is,
   // if packets are reordered and there are non-RTX retransmissions).
-  int32_t cumulative_loss_ RTC_GUARDED_BY(&stream_lock_);
+  int32_t cumulative_loss_;
   // Offset added to outgoing rtcp reports, to make ensure that the reported
   // cumulative loss is non-negative. Reports with negative values confuse some
   // senders, in particular, our own loss-based bandwidth estimator.
-  int32_t cumulative_loss_rtcp_offset_ RTC_GUARDED_BY(&stream_lock_);
+  int32_t cumulative_loss_rtcp_offset_;
 
-  int64_t last_receive_time_ms_ RTC_GUARDED_BY(&stream_lock_);
-  uint32_t last_received_timestamp_ RTC_GUARDED_BY(&stream_lock_);
-  SequenceNumberUnwrapper seq_unwrapper_ RTC_GUARDED_BY(&stream_lock_);
-  int64_t received_seq_first_ RTC_GUARDED_BY(&stream_lock_);
-  int64_t received_seq_max_ RTC_GUARDED_BY(&stream_lock_);
+  int64_t last_receive_time_ms_;
+  uint32_t last_received_timestamp_;
+  SequenceNumberUnwrapper seq_unwrapper_;
+  int64_t received_seq_first_;
+  int64_t received_seq_max_;
   // Assume that the other side restarted when there are two sequential packets
   // with large jump from received_seq_max_.
-  absl::optional<uint16_t> received_seq_out_of_order_
-      RTC_GUARDED_BY(&stream_lock_);
+  absl::optional<uint16_t> received_seq_out_of_order_;
 
   // Current counter values.
-  StreamDataCounters receive_counters_ RTC_GUARDED_BY(&stream_lock_);
+  StreamDataCounters receive_counters_;
 
   // Counter values when we sent the last report.
-  int32_t last_report_cumulative_loss_ RTC_GUARDED_BY(&stream_lock_);
-  int64_t last_report_seq_max_ RTC_GUARDED_BY(&stream_lock_);
+  int32_t last_report_cumulative_loss_;
+  int64_t last_report_seq_max_;
 };
 
+// Thread-safe implementation of StreamStatisticianImplInterface.
+class StreamStatisticianLocked : public StreamStatisticianImplInterface {
+ public:
+  StreamStatisticianLocked(uint32_t ssrc,
+                           Clock* clock,
+                           int max_reordering_threshold)
+      : impl_(ssrc, clock, max_reordering_threshold) {}
+  ~StreamStatisticianLocked() override = default;
+
+  RtpReceiveStats GetStats() const override {
+    MutexLock lock(&stream_lock_);
+    return impl_.GetStats();
+  }
+  absl::optional<int> GetFractionLostInPercent() const override {
+    MutexLock lock(&stream_lock_);
+    return impl_.GetFractionLostInPercent();
+  }
+  StreamDataCounters GetReceiveStreamDataCounters() const override {
+    MutexLock lock(&stream_lock_);
+    return impl_.GetReceiveStreamDataCounters();
+  }
+  uint32_t BitrateReceived() const override {
+    MutexLock lock(&stream_lock_);
+    return impl_.BitrateReceived();
+  }
+  bool GetActiveStatisticsAndReset(RtcpStatistics* statistics) override {
+    MutexLock lock(&stream_lock_);
+    return impl_.GetActiveStatisticsAndReset(statistics);
+  }
+  void SetMaxReorderingThreshold(int max_reordering_threshold) override {
+    MutexLock lock(&stream_lock_);
+    return impl_.SetMaxReorderingThreshold(max_reordering_threshold);
+  }
+  void EnableRetransmitDetection(bool enable) override {
+    MutexLock lock(&stream_lock_);
+    return impl_.EnableRetransmitDetection(enable);
+  }
+  void UpdateCounters(const RtpPacketReceived& packet) override {
+    MutexLock lock(&stream_lock_);
+    return impl_.UpdateCounters(packet);
+  }
+
+ private:
+  mutable Mutex stream_lock_;
+  StreamStatisticianImpl impl_ RTC_GUARDED_BY(&stream_lock_);
+};
+
+// Thread-compatible implementation.
 class ReceiveStatisticsImpl : public ReceiveStatistics {
  public:
-  explicit ReceiveStatisticsImpl(Clock* clock);
-
-  ~ReceiveStatisticsImpl() override;
+  ReceiveStatisticsImpl(
+      Clock* clock,
+      std::function<std::unique_ptr<StreamStatisticianImplInterface>(
+          uint32_t ssrc,
+          Clock* clock,
+          int max_reordering_threshold)> stream_statistician_factory);
+  ~ReceiveStatisticsImpl() override = default;
 
   // Implements ReceiveStatisticsProvider.
   std::vector<rtcp::ReportBlock> RtcpReportBlocks(size_t max_blocks) override;
@@ -112,22 +170,69 @@
   void OnRtpPacket(const RtpPacketReceived& packet) override;
 
   // Implements ReceiveStatistics.
-  // Note: More specific return type for use in the implementation.
-  StreamStatisticianImpl* GetStatistician(uint32_t ssrc) const override;
+  StreamStatistician* GetStatistician(uint32_t ssrc) const override;
   void SetMaxReorderingThreshold(int max_reordering_threshold) override;
   void SetMaxReorderingThreshold(uint32_t ssrc,
                                  int max_reordering_threshold) override;
   void EnableRetransmitDetection(uint32_t ssrc, bool enable) override;
 
  private:
-  StreamStatisticianImpl* GetOrCreateStatistician(uint32_t ssrc);
+  StreamStatisticianImplInterface* GetOrCreateStatistician(uint32_t ssrc);
 
   Clock* const clock_;
-  mutable Mutex receive_statistics_lock_;
+  std::function<std::unique_ptr<StreamStatisticianImplInterface>(
+      uint32_t ssrc,
+      Clock* clock,
+      int max_reordering_threshold)>
+      stream_statistician_factory_;
   uint32_t last_returned_ssrc_;
-  int max_reordering_threshold_ RTC_GUARDED_BY(receive_statistics_lock_);
-  std::map<uint32_t, StreamStatisticianImpl*> statisticians_
-      RTC_GUARDED_BY(receive_statistics_lock_);
+  int max_reordering_threshold_;
+  std::map<uint32_t, std::unique_ptr<StreamStatisticianImplInterface>>
+      statisticians_;
 };
+
+// Thread-safe implementation wrapping access to ReceiveStatisticsImpl with a
+// mutex.
+class ReceiveStatisticsLocked : public ReceiveStatistics {
+ public:
+  explicit ReceiveStatisticsLocked(
+      Clock* clock,
+      std::function<std::unique_ptr<StreamStatisticianImplInterface>(
+          uint32_t ssrc,
+          Clock* clock,
+          int max_reordering_threshold)> stream_statitician_factory)
+      : impl_(clock, std::move(stream_statitician_factory)) {}
+  ~ReceiveStatisticsLocked() override = default;
+  std::vector<rtcp::ReportBlock> RtcpReportBlocks(size_t max_blocks) override {
+    MutexLock lock(&receive_statistics_lock_);
+    return impl_.RtcpReportBlocks(max_blocks);
+  }
+  void OnRtpPacket(const RtpPacketReceived& packet) override {
+    MutexLock lock(&receive_statistics_lock_);
+    return impl_.OnRtpPacket(packet);
+  }
+  StreamStatistician* GetStatistician(uint32_t ssrc) const override {
+    MutexLock lock(&receive_statistics_lock_);
+    return impl_.GetStatistician(ssrc);
+  }
+  void SetMaxReorderingThreshold(int max_reordering_threshold) override {
+    MutexLock lock(&receive_statistics_lock_);
+    return impl_.SetMaxReorderingThreshold(max_reordering_threshold);
+  }
+  void SetMaxReorderingThreshold(uint32_t ssrc,
+                                 int max_reordering_threshold) override {
+    MutexLock lock(&receive_statistics_lock_);
+    return impl_.SetMaxReorderingThreshold(ssrc, max_reordering_threshold);
+  }
+  void EnableRetransmitDetection(uint32_t ssrc, bool enable) override {
+    MutexLock lock(&receive_statistics_lock_);
+    return impl_.EnableRetransmitDetection(ssrc, enable);
+  }
+
+ private:
+  mutable Mutex receive_statistics_lock_;
+  ReceiveStatisticsImpl impl_ RTC_GUARDED_BY(&receive_statistics_lock_);
+};
+
 }  // namespace webrtc
 #endif  // MODULES_RTP_RTCP_SOURCE_RECEIVE_STATISTICS_IMPL_H_
diff --git a/modules/rtp_rtcp/source/receive_statistics_unittest.cc b/modules/rtp_rtcp/source/receive_statistics_unittest.cc
index 053460e..d40a743 100644
--- a/modules/rtp_rtcp/source/receive_statistics_unittest.cc
+++ b/modules/rtp_rtcp/source/receive_statistics_unittest.cc
@@ -65,10 +65,13 @@
   IncrementSequenceNumber(packet, 1);
 }
 
-class ReceiveStatisticsTest : public ::testing::Test {
+class ReceiveStatisticsTest : public ::testing::TestWithParam<bool> {
  public:
   ReceiveStatisticsTest()
-      : clock_(0), receive_statistics_(ReceiveStatistics::Create(&clock_)) {
+      : clock_(0),
+        receive_statistics_(
+            GetParam() ? ReceiveStatistics::Create(&clock_)
+                       : ReceiveStatistics::CreateThreadCompatible(&clock_)) {
     packet1_ = CreateRtpPacket(kSsrc1, kPacketSize1);
     packet2_ = CreateRtpPacket(kSsrc2, kPacketSize2);
   }
@@ -80,7 +83,14 @@
   RtpPacketReceived packet2_;
 };
 
-TEST_F(ReceiveStatisticsTest, TwoIncomingSsrcs) {
+INSTANTIATE_TEST_SUITE_P(All,
+                         ReceiveStatisticsTest,
+                         ::testing::Bool(),
+                         [](::testing::TestParamInfo<bool> info) {
+                           return info.param ? "WithMutex" : "WithoutMutex";
+                         });
+
+TEST_P(ReceiveStatisticsTest, TwoIncomingSsrcs) {
   receive_statistics_->OnRtpPacket(packet1_);
   IncrementSequenceNumber(&packet1_);
   receive_statistics_->OnRtpPacket(packet2_);
@@ -133,7 +143,7 @@
   EXPECT_EQ(3u, counters.transmitted.packets);
 }
 
-TEST_F(ReceiveStatisticsTest,
+TEST_P(ReceiveStatisticsTest,
        RtcpReportBlocksReturnsMaxBlocksWhenThereAreMoreStatisticians) {
   RtpPacketReceived packet1 = CreateRtpPacket(kSsrc1, kPacketSize1);
   RtpPacketReceived packet2 = CreateRtpPacket(kSsrc2, kPacketSize1);
@@ -147,7 +157,7 @@
   EXPECT_THAT(receive_statistics_->RtcpReportBlocks(2), SizeIs(2));
 }
 
-TEST_F(ReceiveStatisticsTest,
+TEST_P(ReceiveStatisticsTest,
        RtcpReportBlocksReturnsAllObservedSsrcsWithMultipleCalls) {
   RtpPacketReceived packet1 = CreateRtpPacket(kSsrc1, kPacketSize1);
   RtpPacketReceived packet2 = CreateRtpPacket(kSsrc2, kPacketSize1);
@@ -174,7 +184,7 @@
               UnorderedElementsAre(kSsrc1, kSsrc2, kSsrc3, kSsrc4));
 }
 
-TEST_F(ReceiveStatisticsTest, ActiveStatisticians) {
+TEST_P(ReceiveStatisticsTest, ActiveStatisticians) {
   receive_statistics_->OnRtpPacket(packet1_);
   IncrementSequenceNumber(&packet1_);
   clock_.AdvanceTimeMilliseconds(1000);
@@ -206,7 +216,7 @@
   EXPECT_EQ(2u, counters.transmitted.packets);
 }
 
-TEST_F(ReceiveStatisticsTest,
+TEST_P(ReceiveStatisticsTest,
        DoesntCreateRtcpReportBlockUntilFirstReceivedPacketForSsrc) {
   // Creates a statistician object for the ssrc.
   receive_statistics_->EnableRetransmitDetection(kSsrc1, true);
@@ -217,7 +227,7 @@
   EXPECT_EQ(1u, receive_statistics_->RtcpReportBlocks(3).size());
 }
 
-TEST_F(ReceiveStatisticsTest, GetReceiveStreamDataCounters) {
+TEST_P(ReceiveStatisticsTest, GetReceiveStreamDataCounters) {
   receive_statistics_->OnRtpPacket(packet1_);
   StreamStatistician* statistician =
       receive_statistics_->GetStatistician(kSsrc1);
@@ -233,7 +243,7 @@
   EXPECT_EQ(2u, counters.transmitted.packets);
 }
 
-TEST_F(ReceiveStatisticsTest, SimpleLossComputation) {
+TEST_P(ReceiveStatisticsTest, SimpleLossComputation) {
   packet1_.SetSequenceNumber(1);
   receive_statistics_->OnRtpPacket(packet1_);
   packet1_.SetSequenceNumber(3);
@@ -256,7 +266,7 @@
   EXPECT_EQ(20, statistician->GetFractionLostInPercent());
 }
 
-TEST_F(ReceiveStatisticsTest, LossComputationWithReordering) {
+TEST_P(ReceiveStatisticsTest, LossComputationWithReordering) {
   packet1_.SetSequenceNumber(1);
   receive_statistics_->OnRtpPacket(packet1_);
   packet1_.SetSequenceNumber(3);
@@ -279,7 +289,7 @@
   EXPECT_EQ(20, statistician->GetFractionLostInPercent());
 }
 
-TEST_F(ReceiveStatisticsTest, LossComputationWithDuplicates) {
+TEST_P(ReceiveStatisticsTest, LossComputationWithDuplicates) {
   // Lose 2 packets, but also receive 1 duplicate. Should actually count as
   // only 1 packet being lost.
   packet1_.SetSequenceNumber(1);
@@ -304,7 +314,7 @@
   EXPECT_EQ(20, statistician->GetFractionLostInPercent());
 }
 
-TEST_F(ReceiveStatisticsTest, LossComputationWithSequenceNumberWrapping) {
+TEST_P(ReceiveStatisticsTest, LossComputationWithSequenceNumberWrapping) {
   // First, test loss computation over a period that included a sequence number
   // rollover.
   packet1_.SetSequenceNumber(0xfffd);
@@ -344,7 +354,7 @@
   EXPECT_EQ(28, statistician->GetFractionLostInPercent());
 }
 
-TEST_F(ReceiveStatisticsTest, StreamRestartDoesntCountAsLoss) {
+TEST_P(ReceiveStatisticsTest, StreamRestartDoesntCountAsLoss) {
   receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
 
   packet1_.SetSequenceNumber(0);
@@ -377,7 +387,7 @@
   EXPECT_EQ(0, statistician->GetFractionLostInPercent());
 }
 
-TEST_F(ReceiveStatisticsTest, CountsLossAfterStreamRestart) {
+TEST_P(ReceiveStatisticsTest, CountsLossAfterStreamRestart) {
   receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
 
   packet1_.SetSequenceNumber(0);
@@ -405,7 +415,7 @@
   EXPECT_EQ(0, statistician->GetFractionLostInPercent());
 }
 
-TEST_F(ReceiveStatisticsTest, StreamCanRestartAtSequenceNumberWrapAround) {
+TEST_P(ReceiveStatisticsTest, StreamCanRestartAtSequenceNumberWrapAround) {
   receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
 
   packet1_.SetSequenceNumber(0xffff - 401);
@@ -428,7 +438,7 @@
   EXPECT_EQ(1, report_blocks[0].cumulative_lost_signed());
 }
 
-TEST_F(ReceiveStatisticsTest, StreamRestartNeedsTwoConsecutivePackets) {
+TEST_P(ReceiveStatisticsTest, StreamRestartNeedsTwoConsecutivePackets) {
   receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
 
   packet1_.SetSequenceNumber(400);
@@ -458,7 +468,7 @@
   EXPECT_EQ(4u, report_blocks[0].extended_high_seq_num());
 }
 
-TEST_F(ReceiveStatisticsTest, WrapsAroundExtendedHighestSequenceNumber) {
+TEST_P(ReceiveStatisticsTest, WrapsAroundExtendedHighestSequenceNumber) {
   packet1_.SetSequenceNumber(0xffff);
   receive_statistics_->OnRtpPacket(packet1_);
 
@@ -503,8 +513,7 @@
   EXPECT_EQ(0x20001u, report_blocks[0].extended_high_seq_num());
 }
 
-TEST_F(ReceiveStatisticsTest, StreamDataCounters) {
-  receive_statistics_ = ReceiveStatistics::Create(&clock_);
+TEST_P(ReceiveStatisticsTest, StreamDataCounters) {
   receive_statistics_->EnableRetransmitDetection(kSsrc1, true);
 
   const size_t kHeaderLength = 20;
@@ -554,9 +563,7 @@
   EXPECT_EQ(counters.retransmitted.packets, 1u);
 }
 
-TEST_F(ReceiveStatisticsTest, LastPacketReceivedTimestamp) {
-  receive_statistics_ = ReceiveStatistics::Create(&clock_);
-
+TEST_P(ReceiveStatisticsTest, LastPacketReceivedTimestamp) {
   clock_.AdvanceTimeMilliseconds(42);
   receive_statistics_->OnRtpPacket(packet1_);
   StreamDataCounters counters = receive_statistics_->GetStatistician(kSsrc1)