New const method StreamStatistician::GetStats

And a corresponding struct RtpReceiveStats. This is intended
to hold the information exposed via GetStats, which is quite
different from the stats reported to the peer via RTCP.

This is a preparation for moving ReceiveStatistics out of the
individual receive stream objects, and instead have a shared instance
owned by RtpStreamReceiverController or maybe Call.

Bug: webrtc:10679,chromium:677543
Change-Id: Ibb52ee769516ddc51da109b7f2319405693be5d5
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/148982
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Commit-Queue: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28943}
diff --git a/audio/channel_receive.cc b/audio/channel_receive.cc
index d2d3188..20cd0db 100644
--- a/audio/channel_receive.cc
+++ b/audio/channel_receive.cc
@@ -724,34 +724,29 @@
 
   // The jitter statistics is updated for each received RTP packet and is
   // based on received packets.
-  RtcpStatistics statistics;
+  RtpReceiveStats rtp_stats;
   StreamStatistician* statistician =
       rtp_receive_statistics_->GetStatistician(remote_ssrc_);
   if (statistician) {
-    statistician->GetStatistics(&statistics,
-                                _rtpRtcpModule->RTCP() == RtcpMode::kOff);
+    rtp_stats = statistician->GetStats();
   }
 
-  stats.cumulativeLost = statistics.packets_lost;
-  stats.jitterSamples = statistics.jitter;
+  stats.cumulativeLost = rtp_stats.packets_lost;
+  stats.jitterSamples = rtp_stats.jitter;
 
   // --- RTT
   stats.rttMs = GetRTT();
 
   // --- Data counters
   if (statistician) {
-    StreamDataCounters data_counters =
-        statistician->GetReceiveStreamDataCounters();
     if (use_standard_bytes_stats_) {
-      stats.bytesReceived = data_counters.transmitted.payload_bytes;
+      stats.bytesReceived = rtp_stats.packet_counter.payload_bytes;
     } else {
-      stats.bytesReceived = data_counters.transmitted.payload_bytes +
-                            data_counters.transmitted.header_bytes +
-                            data_counters.transmitted.padding_bytes;
+      stats.bytesReceived = rtp_stats.packet_counter.TotalBytes();
     }
-    stats.packetsReceived = data_counters.transmitted.packets;
+    stats.packetsReceived = rtp_stats.packet_counter.packets;
     stats.last_packet_received_timestamp_ms =
-        data_counters.last_packet_received_timestamp_ms;
+        rtp_stats.last_packet_received_timestamp_ms;
   } else {
     stats.bytesReceived = 0;
     stats.packetsReceived = 0;
diff --git a/call/video_receive_stream.cc b/call/video_receive_stream.cc
index 9f737e2..ed830bc 100644
--- a/call/video_receive_stream.cc
+++ b/call/video_receive_stream.cc
@@ -58,8 +58,7 @@
   ss << "jb_emitted_count: " << jitter_buffer_emitted_count << ", ";
   ss << "min_playout_delay_ms: " << min_playout_delay_ms << ", ";
   ss << "sync_offset_ms: " << sync_offset_ms << ", ";
-  ss << "cum_loss: " << rtcp_stats.packets_lost << ", ";
-  ss << "max_ext_seq: " << rtcp_stats.extended_highest_sequence_number << ", ";
+  ss << "cum_loss: " << rtp_stats.packets_lost << ", ";
   ss << "nack: " << rtcp_packet_type_counts.nack_packets << ", ";
   ss << "fir: " << rtcp_packet_type_counts.fir_packets << ", ";
   ss << "pli: " << rtcp_packet_type_counts.pli_packets;
diff --git a/call/video_receive_stream.h b/call/video_receive_stream.h
index 4bc9b28..ad702e6 100644
--- a/call/video_receive_stream.h
+++ b/call/video_receive_stream.h
@@ -110,9 +110,8 @@
 
     uint32_t ssrc = 0;
     std::string c_name;
-    StreamDataCounters rtp_stats;
+    RtpReceiveStats rtp_stats;
     RtcpPacketTypeCounter rtcp_packet_type_counts;
-    RtcpStatistics rtcp_stats;
 
     // Timing frame info: all important timestamps for a full lifetime of a
     // single 'timing frame'.
diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc
index 586d356..a3e48d9 100644
--- a/media/engine/webrtc_video_engine.cc
+++ b/media/engine/webrtc_video_engine.cc
@@ -2795,14 +2795,12 @@
     info.codec_payload_type = stats.current_payload_type;
   }
   if (use_standard_bytes_stats_) {
-    info.bytes_rcvd = stats.rtp_stats.transmitted.payload_bytes;
+    info.bytes_rcvd = stats.rtp_stats.packet_counter.payload_bytes;
   } else {
-    info.bytes_rcvd = stats.rtp_stats.transmitted.payload_bytes +
-                      stats.rtp_stats.transmitted.header_bytes +
-                      stats.rtp_stats.transmitted.padding_bytes;
+    info.bytes_rcvd = stats.rtp_stats.packet_counter.TotalBytes();
   }
-  info.packets_rcvd = stats.rtp_stats.transmitted.packets;
-  info.packets_lost = stats.rtcp_stats.packets_lost;
+  info.packets_rcvd = stats.rtp_stats.packet_counter.packets;
+  info.packets_lost = stats.rtp_stats.packets_lost;
 
   info.framerate_rcvd = stats.network_frame_rate;
   info.framerate_decoded = stats.decode_frame_rate;
diff --git a/media/engine/webrtc_video_engine_unittest.cc b/media/engine/webrtc_video_engine_unittest.cc
index 92ffc5c..48e90f5 100644
--- a/media/engine/webrtc_video_engine_unittest.cc
+++ b/media/engine/webrtc_video_engine_unittest.cc
@@ -5233,21 +5233,20 @@
 
   FakeVideoReceiveStream* stream = AddRecvStream();
   webrtc::VideoReceiveStream::Stats stats;
-  stats.rtp_stats.transmitted.payload_bytes = 2;
-  stats.rtp_stats.transmitted.header_bytes = 3;
-  stats.rtp_stats.transmitted.padding_bytes = 4;
-  stats.rtp_stats.transmitted.packets = 5;
-  stats.rtcp_stats.packets_lost = 6;
-  stats.rtcp_stats.fraction_lost = 7;
+  stats.rtp_stats.packet_counter.payload_bytes = 2;
+  stats.rtp_stats.packet_counter.header_bytes = 3;
+  stats.rtp_stats.packet_counter.padding_bytes = 4;
+  stats.rtp_stats.packet_counter.packets = 5;
+  stats.rtp_stats.packets_lost = 6;
   stream->SetStats(stats);
 
   cricket::VideoMediaInfo info;
   ASSERT_TRUE(channel_->GetStats(&info));
-  EXPECT_EQ(stats.rtp_stats.transmitted.payload_bytes,
+  EXPECT_EQ(stats.rtp_stats.packet_counter.payload_bytes,
             rtc::checked_cast<size_t>(info.receivers[0].bytes_rcvd));
-  EXPECT_EQ(stats.rtp_stats.transmitted.packets,
+  EXPECT_EQ(stats.rtp_stats.packet_counter.packets,
             rtc::checked_cast<unsigned int>(info.receivers[0].packets_rcvd));
-  EXPECT_EQ(stats.rtcp_stats.packets_lost, info.receivers[0].packets_lost);
+  EXPECT_EQ(stats.rtp_stats.packets_lost, info.receivers[0].packets_lost);
 }
 
 TEST_F(WebRtcVideoChannelTest, TranslatesCallStatsCorrectly) {
diff --git a/modules/rtp_rtcp/include/receive_statistics.h b/modules/rtp_rtcp/include/receive_statistics.h
index 959e3cd..7f185a8 100644
--- a/modules/rtp_rtcp/include/receive_statistics.h
+++ b/modules/rtp_rtcp/include/receive_statistics.h
@@ -22,6 +22,7 @@
 #include "modules/rtp_rtcp/include/rtcp_statistics.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/report_block.h"
+#include "rtc_base/deprecation.h"
 
 namespace webrtc {
 
@@ -40,11 +41,16 @@
  public:
   virtual ~StreamStatistician();
 
+  virtual RtpReceiveStats GetStats() const = 0;
+
+  // TODO(nisse): Delete, migrate users to the above the GetStats method.
+  RTC_DEPRECATED
   virtual bool GetStatistics(RtcpStatistics* statistics, bool reset) = 0;
 
   // Returns average over the stream life time.
   virtual absl::optional<int> GetFractionLostInPercent() const = 0;
 
+  // TODO(nisse): Delete, migrate users to the above the GetStats method.
   // Gets received stream data counters (includes reset counter values).
   virtual StreamDataCounters GetReceiveStreamDataCounters() const = 0;
 
diff --git a/modules/rtp_rtcp/include/rtp_rtcp_defines.h b/modules/rtp_rtcp/include/rtp_rtcp_defines.h
index dd2ddae..d343516 100644
--- a/modules/rtp_rtcp/include/rtp_rtcp_defines.h
+++ b/modules/rtp_rtcp/include/rtp_rtcp_defines.h
@@ -444,6 +444,20 @@
                                    uint32_t ssrc) = 0;
 };
 
+// Information exposed through the GetStats api.
+struct RtpReceiveStats {
+  // |packets_lost| and |jitter| are defined by RFC 3550, and exposed in the
+  // RTCReceivedRtpStreamStats dictionary, see
+  // https://w3c.github.io/webrtc-stats/#receivedrtpstats-dict*
+  int32_t packets_lost = 0;
+  uint32_t jitter = 0;
+
+  // Timestamp and counters exposed in RTCInboundRtpStreamStats, see
+  // https://w3c.github.io/webrtc-stats/#inboundrtpstats-dict*
+  absl::optional<int64_t> last_packet_received_timestamp_ms;
+  RtpPacketCounter packet_counter;
+};
+
 class RtcpAckObserver {
  public:
   // This method is called on received report blocks matching the sender ssrc.
diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.cc b/modules/rtp_rtcp/source/receive_statistics_impl.cc
index ab896cb..f4ea2a0 100644
--- a/modules/rtp_rtcp/source/receive_statistics_impl.cc
+++ b/modules/rtp_rtcp/source/receive_statistics_impl.cc
@@ -166,6 +166,19 @@
   enable_retransmit_detection_ = enable;
 }
 
+RtpReceiveStats StreamStatisticianImpl::GetStats() const {
+  rtc::CritScope cs(&stream_lock_);
+  RtpReceiveStats stats;
+  stats.packets_lost = cumulative_loss_;
+  // TODO(nisse): Can we return a float instead?
+  // Note: internal jitter value is in Q4 and needs to be scaled by 1/16.
+  stats.jitter = jitter_q4_ >> 4;
+  stats.last_packet_received_timestamp_ms =
+      receive_counters_.last_packet_received_timestamp_ms;
+  stats.packet_counter = receive_counters_.transmitted;
+  return stats;
+}
+
 bool StreamStatisticianImpl::GetStatistics(RtcpStatistics* statistics,
                                            bool reset) {
   rtc::CritScope cs(&stream_lock_);
diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.h b/modules/rtp_rtcp/source/receive_statistics_impl.h
index 04030d4..d76e431 100644
--- a/modules/rtp_rtcp/source/receive_statistics_impl.h
+++ b/modules/rtp_rtcp/source/receive_statistics_impl.h
@@ -32,6 +32,8 @@
                          int max_reordering_threshold);
   ~StreamStatisticianImpl() override;
 
+  RtpReceiveStats GetStats() const override;
+
   // |reset| here and in next method restarts calculation of fraction_lost stat.
   bool GetStatistics(RtcpStatistics* statistics, bool reset) override;
   bool GetActiveStatisticsAndReset(RtcpStatistics* statistics);
diff --git a/modules/rtp_rtcp/source/receive_statistics_unittest.cc b/modules/rtp_rtcp/source/receive_statistics_unittest.cc
index 44e53cf..81e66b6 100644
--- a/modules/rtp_rtcp/source/receive_statistics_unittest.cc
+++ b/modules/rtp_rtcp/source/receive_statistics_unittest.cc
@@ -243,13 +243,16 @@
   packet1_.SetSequenceNumber(5);
   receive_statistics_->OnRtpPacket(packet1_);
 
+  std::vector<rtcp::ReportBlock> report_blocks =
+      receive_statistics_->RtcpReportBlocks(1);
+  ASSERT_THAT(report_blocks, SizeIs(1));
+  EXPECT_EQ(kSsrc1, report_blocks[0].source_ssrc());
+
+  // 20% = 51/255.
+  EXPECT_EQ(51u, report_blocks[0].fraction_lost());
+  EXPECT_EQ(1, report_blocks[0].cumulative_lost_signed());
   StreamStatistician* statistician =
       receive_statistics_->GetStatistician(kSsrc1);
-  RtcpStatistics statistics;
-  statistician->GetStatistics(&statistics, true);
-  // 20% = 51/255.
-  EXPECT_EQ(51u, statistics.fraction_lost);
-  EXPECT_EQ(1, statistics.packets_lost);
   EXPECT_EQ(20, statistician->GetFractionLostInPercent());
 }
 
@@ -263,13 +266,16 @@
   packet1_.SetSequenceNumber(5);
   receive_statistics_->OnRtpPacket(packet1_);
 
+  std::vector<rtcp::ReportBlock> report_blocks =
+      receive_statistics_->RtcpReportBlocks(1);
+  ASSERT_THAT(report_blocks, SizeIs(1));
+  EXPECT_EQ(kSsrc1, report_blocks[0].source_ssrc());
+
+  // 20% = 51/255.
+  EXPECT_EQ(51u, report_blocks[0].fraction_lost());
+  EXPECT_EQ(1, report_blocks[0].cumulative_lost_signed());
   StreamStatistician* statistician =
       receive_statistics_->GetStatistician(kSsrc1);
-  RtcpStatistics statistics;
-  statistician->GetStatistics(&statistics, true);
-  // 20% = 51/255.
-  EXPECT_EQ(51u, statistics.fraction_lost);
-  EXPECT_EQ(1, statistics.packets_lost);
   EXPECT_EQ(20, statistician->GetFractionLostInPercent());
 }
 
@@ -285,13 +291,16 @@
   packet1_.SetSequenceNumber(5);
   receive_statistics_->OnRtpPacket(packet1_);
 
+  std::vector<rtcp::ReportBlock> report_blocks =
+      receive_statistics_->RtcpReportBlocks(1);
+  ASSERT_THAT(report_blocks, SizeIs(1));
+  EXPECT_EQ(kSsrc1, report_blocks[0].source_ssrc());
+
+  // 20% = 51/255.
+  EXPECT_EQ(51u, report_blocks[0].fraction_lost());
+  EXPECT_EQ(1, report_blocks[0].cumulative_lost_signed());
   StreamStatistician* statistician =
       receive_statistics_->GetStatistician(kSsrc1);
-  RtcpStatistics statistics;
-  statistician->GetStatistics(&statistics, true);
-  // 20% = 51/255.
-  EXPECT_EQ(51u, statistics.fraction_lost);
-  EXPECT_EQ(1, statistics.packets_lost);
   EXPECT_EQ(20, statistician->GetFractionLostInPercent());
 }
 
@@ -308,28 +317,34 @@
   receive_statistics_->OnRtpPacket(packet1_);
 
   // Only one packet was actually lost, 0xffff.
+  std::vector<rtcp::ReportBlock> report_blocks =
+      receive_statistics_->RtcpReportBlocks(1);
+  ASSERT_THAT(report_blocks, SizeIs(1));
+  EXPECT_EQ(kSsrc1, report_blocks[0].source_ssrc());
+
+  // 20% = 51/255.
+  EXPECT_EQ(51u, report_blocks[0].fraction_lost());
+  EXPECT_EQ(1, report_blocks[0].cumulative_lost_signed());
   StreamStatistician* statistician =
       receive_statistics_->GetStatistician(kSsrc1);
-  RtcpStatistics statistics;
-  statistician->GetStatistics(&statistics, true);
-  // 20% = 51/255.
-  EXPECT_EQ(51u, statistics.fraction_lost);
-  EXPECT_EQ(1, statistics.packets_lost);
   EXPECT_EQ(20, statistician->GetFractionLostInPercent());
 
   // Now test losing one packet *after* the rollover.
   packet1_.SetSequenceNumber(3);
   receive_statistics_->OnRtpPacket(packet1_);
-  statistician->GetStatistics(&statistics, true);
+
+  report_blocks = receive_statistics_->RtcpReportBlocks(1);
+  ASSERT_THAT(report_blocks, SizeIs(1));
+  EXPECT_EQ(kSsrc1, report_blocks[0].source_ssrc());
+
   // 50% = 127/255.
-  EXPECT_EQ(127u, statistics.fraction_lost);
-  EXPECT_EQ(2, statistics.packets_lost);
+  EXPECT_EQ(127u, report_blocks[0].fraction_lost());
+  EXPECT_EQ(2, report_blocks[0].cumulative_lost_signed());
   // 2 packets lost, 7 expected
   EXPECT_EQ(28, statistician->GetFractionLostInPercent());
 }
 
 TEST_F(ReceiveStatisticsTest, StreamRestartDoesntCountAsLoss) {
-  RtcpStatistics statistics;
   receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
 
   packet1_.SetSequenceNumber(0);
@@ -339,23 +354,30 @@
 
   packet1_.SetSequenceNumber(400);
   receive_statistics_->OnRtpPacket(packet1_);
+
+  std::vector<rtcp::ReportBlock> report_blocks =
+      receive_statistics_->RtcpReportBlocks(1);
+  ASSERT_THAT(report_blocks, SizeIs(1));
+  EXPECT_EQ(kSsrc1, report_blocks[0].source_ssrc());
+
+  EXPECT_EQ(0, report_blocks[0].fraction_lost());
+  EXPECT_EQ(0, report_blocks[0].cumulative_lost_signed());
   StreamStatistician* statistician =
       receive_statistics_->GetStatistician(kSsrc1);
-  statistician->GetStatistics(&statistics, true);
-  EXPECT_EQ(0, statistics.fraction_lost);
-  EXPECT_EQ(0, statistics.packets_lost);
   EXPECT_EQ(0, statistician->GetFractionLostInPercent());
 
   packet1_.SetSequenceNumber(401);
   receive_statistics_->OnRtpPacket(packet1_);
-  statistician->GetStatistics(&statistics, true);
-  EXPECT_EQ(0, statistics.fraction_lost);
-  EXPECT_EQ(0, statistics.packets_lost);
+  report_blocks = receive_statistics_->RtcpReportBlocks(1);
+  ASSERT_THAT(report_blocks, SizeIs(1));
+  EXPECT_EQ(kSsrc1, report_blocks[0].source_ssrc());
+
+  EXPECT_EQ(0, report_blocks[0].fraction_lost());
+  EXPECT_EQ(0, report_blocks[0].cumulative_lost_signed());
   EXPECT_EQ(0, statistician->GetFractionLostInPercent());
 }
 
 TEST_F(ReceiveStatisticsTest, CountsLossAfterStreamRestart) {
-  RtcpStatistics statistics;
   receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
 
   packet1_.SetSequenceNumber(0);
@@ -370,17 +392,20 @@
   packet1_.SetSequenceNumber(403);
   receive_statistics_->OnRtpPacket(packet1_);
 
+  std::vector<rtcp::ReportBlock> report_blocks =
+      receive_statistics_->RtcpReportBlocks(1);
+  ASSERT_THAT(report_blocks, SizeIs(1));
+  EXPECT_EQ(kSsrc1, report_blocks[0].source_ssrc());
+
+  EXPECT_EQ(1, report_blocks[0].cumulative_lost_signed());
+
   StreamStatistician* statistician =
       receive_statistics_->GetStatistician(kSsrc1);
-
-  statistician->GetStatistics(&statistics, true);
-  EXPECT_EQ(1, statistics.packets_lost);
   // Is this reasonable? */
   EXPECT_EQ(0, statistician->GetFractionLostInPercent());
 }
 
 TEST_F(ReceiveStatisticsTest, StreamCanRestartAtSequenceNumberWrapAround) {
-  RtcpStatistics statistics;
   receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
 
   packet1_.SetSequenceNumber(0xffff - 401);
@@ -395,13 +420,15 @@
   packet1_.SetSequenceNumber(2);
   receive_statistics_->OnRtpPacket(packet1_);
 
-  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
-                                                              true);
-  EXPECT_EQ(1, statistics.packets_lost);
+  std::vector<rtcp::ReportBlock> report_blocks =
+      receive_statistics_->RtcpReportBlocks(1);
+  ASSERT_THAT(report_blocks, SizeIs(1));
+  EXPECT_EQ(kSsrc1, report_blocks[0].source_ssrc());
+
+  EXPECT_EQ(1, report_blocks[0].cumulative_lost_signed());
 }
 
 TEST_F(ReceiveStatisticsTest, StreamRestartNeedsTwoConsecutivePackets) {
-  RtcpStatistics statistics;
   receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
 
   packet1_.SetSequenceNumber(400);
@@ -413,38 +440,53 @@
   receive_statistics_->OnRtpPacket(packet1_);
   packet1_.SetSequenceNumber(3);
   receive_statistics_->OnRtpPacket(packet1_);
-  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
-                                                              true);
-  EXPECT_EQ(401u, statistics.extended_highest_sequence_number);
+
+  std::vector<rtcp::ReportBlock> report_blocks =
+      receive_statistics_->RtcpReportBlocks(1);
+  ASSERT_THAT(report_blocks, SizeIs(1));
+  EXPECT_EQ(kSsrc1, report_blocks[0].source_ssrc());
+
+  EXPECT_EQ(401u, report_blocks[0].extended_high_seq_num());
 
   packet1_.SetSequenceNumber(4);
   receive_statistics_->OnRtpPacket(packet1_);
-  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
-                                                              true);
-  EXPECT_EQ(4u, statistics.extended_highest_sequence_number);
+
+  report_blocks = receive_statistics_->RtcpReportBlocks(1);
+  ASSERT_THAT(report_blocks, SizeIs(1));
+  EXPECT_EQ(kSsrc1, report_blocks[0].source_ssrc());
+
+  EXPECT_EQ(4u, report_blocks[0].extended_high_seq_num());
 }
 
 TEST_F(ReceiveStatisticsTest, WrapsAroundExtendedHighestSequenceNumber) {
-  RtcpStatistics statistics;
   packet1_.SetSequenceNumber(0xffff);
   receive_statistics_->OnRtpPacket(packet1_);
-  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
-                                                              true);
-  EXPECT_EQ(0xffffu, statistics.extended_highest_sequence_number);
+
+  std::vector<rtcp::ReportBlock> report_blocks =
+      receive_statistics_->RtcpReportBlocks(1);
+  ASSERT_THAT(report_blocks, SizeIs(1));
+  EXPECT_EQ(kSsrc1, report_blocks[0].source_ssrc());
+
+  EXPECT_EQ(0xffffu, report_blocks[0].extended_high_seq_num());
 
   // Wrap around.
   packet1_.SetSequenceNumber(1);
   receive_statistics_->OnRtpPacket(packet1_);
-  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
-                                                              true);
-  EXPECT_EQ(0x10001u, statistics.extended_highest_sequence_number);
+
+  report_blocks = receive_statistics_->RtcpReportBlocks(1);
+  ASSERT_THAT(report_blocks, SizeIs(1));
+  EXPECT_EQ(kSsrc1, report_blocks[0].source_ssrc());
+
+  EXPECT_EQ(0x10001u, report_blocks[0].extended_high_seq_num());
 
   // Should be treated as out of order; shouldn't increment highest extended
   // sequence number.
   packet1_.SetSequenceNumber(0x10000 - 6);
-  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
-                                                              true);
-  EXPECT_EQ(0x10001u, statistics.extended_highest_sequence_number);
+  report_blocks = receive_statistics_->RtcpReportBlocks(1);
+  ASSERT_THAT(report_blocks, SizeIs(1));
+  EXPECT_EQ(kSsrc1, report_blocks[0].source_ssrc());
+
+  EXPECT_EQ(0x10001u, report_blocks[0].extended_high_seq_num());
 
   // Receive a couple packets then wrap around again.
   receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
@@ -454,9 +496,11 @@
   }
   packet1_.SetSequenceNumber(1);
   receive_statistics_->OnRtpPacket(packet1_);
-  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
-                                                              true);
-  EXPECT_EQ(0x20001u, statistics.extended_highest_sequence_number);
+  report_blocks = receive_statistics_->RtcpReportBlocks(1);
+  ASSERT_THAT(report_blocks, SizeIs(1));
+  EXPECT_EQ(kSsrc1, report_blocks[0].source_ssrc());
+
+  EXPECT_EQ(0x20001u, report_blocks[0].extended_high_seq_num());
 }
 
 TEST_F(ReceiveStatisticsTest, StreamDataCounters) {
diff --git a/video/end_to_end_tests/stats_tests.cc b/video/end_to_end_tests/stats_tests.cc
index 910064c..e3ba87a 100644
--- a/video/end_to_end_tests/stats_tests.cc
+++ b/video/end_to_end_tests/stats_tests.cc
@@ -115,17 +115,13 @@
         receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
 
         receive_stats_filled_["StatisticsUpdated"] |=
-            stats.rtcp_stats.packets_lost != 0 ||
-            stats.rtcp_stats.extended_highest_sequence_number != 0 ||
-            stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
+            stats.rtp_stats.packets_lost != 0 || stats.rtp_stats.jitter != 0;
 
         receive_stats_filled_["DataCountersUpdated"] |=
-            stats.rtp_stats.transmitted.payload_bytes != 0 ||
-            stats.rtp_stats.fec.packets != 0 ||
-            stats.rtp_stats.transmitted.header_bytes != 0 ||
-            stats.rtp_stats.transmitted.packets != 0 ||
-            stats.rtp_stats.transmitted.padding_bytes != 0 ||
-            stats.rtp_stats.retransmitted.packets != 0;
+            stats.rtp_stats.packet_counter.payload_bytes != 0 ||
+            stats.rtp_stats.packet_counter.header_bytes != 0 ||
+            stats.rtp_stats.packet_counter.packets != 0 ||
+            stats.rtp_stats.packet_counter.padding_bytes != 0;
 
         receive_stats_filled_["CodecStats"] |= stats.target_delay_ms != 0;
 
@@ -445,7 +441,7 @@
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
       if (sent_rtp_ >= kNumRtpPacketsToSend) {
         VideoReceiveStream::Stats stats = receive_stream_->GetStats();
-        if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
+        if (kNumRtpPacketsToSend == stats.rtp_stats.packet_counter.packets) {
           observation_complete_.Set();
         }
         return DROP_PACKET;
diff --git a/video/video_receive_stream.cc b/video/video_receive_stream.cc
index 3e26fa9..a52dac8 100644
--- a/video/video_receive_stream.cc
+++ b/video/video_receive_stream.cc
@@ -463,8 +463,7 @@
   StreamStatistician* statistician =
       rtp_receive_statistics_->GetStatistician(stats.ssrc);
   if (statistician) {
-    statistician->GetStatistics(&stats.rtcp_stats, /*reset=*/false);
-    stats.rtp_stats = statistician->GetReceiveStreamDataCounters();
+    stats.rtp_stats = statistician->GetStats();
     stats.total_bitrate_bps = statistician->BitrateReceived();
   }
   if (config_.rtp.rtx_ssrc) {