In ReportBlockData expose RTCP report block properties directly

These accessors would allow to deprecated report_block() accessor and
then would allow to remove redundant RTCPReportBlock and ReportBlock types converging on single
ReportBlockData type to pass that information across WebRTC components

helpers like fraction_lost() and jitter() would also allow to unify conversion of the rtp specific format into more common way of represent such information

Bug: None
Change-Id: I3c97f96affcf83b529095899bd63af007f8b4014
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/303880
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#39975}
diff --git a/modules/rtp_rtcp/include/report_block_data.cc b/modules/rtp_rtcp/include/report_block_data.cc
index c2a3713..42a8e75 100644
--- a/modules/rtp_rtcp/include/report_block_data.cc
+++ b/modules/rtp_rtcp/include/report_block_data.cc
@@ -10,10 +10,15 @@
 
 #include "modules/rtp_rtcp/include/report_block_data.h"
 
+#include "rtc_base/checks.h"
+
 namespace webrtc {
 
-TimeDelta ReportBlockData::AvgRtt() const {
-  return num_rtts_ > 0 ? sum_rtt_ / num_rtts_ : TimeDelta::Zero();
+TimeDelta ReportBlockData::jitter(int rtp_clock_rate_hz) const {
+  RTC_DCHECK_GT(rtp_clock_rate_hz, 0);
+  // Conversion to TimeDelta and division are swapped to avoid conversion
+  // to/from floating point types.
+  return TimeDelta::Seconds(jitter()) / rtp_clock_rate_hz;
 }
 
 void ReportBlockData::SetReportBlock(uint32_t sender_ssrc,
diff --git a/modules/rtp_rtcp/include/report_block_data.h b/modules/rtp_rtcp/include/report_block_data.h
index fa556cf..48a4d93 100644
--- a/modules/rtp_rtcp/include/report_block_data.h
+++ b/modules/rtp_rtcp/include/report_block_data.h
@@ -18,6 +18,9 @@
 
 namespace webrtc {
 
+// Represents fields and derived information received in RTCP report block
+// attached to RTCP sender report or RTCP receiver report, as described in
+// https://www.rfc-editor.org/rfc/rfc3550#section-6.4.1
 class ReportBlockData {
  public:
   ReportBlockData() = default;
@@ -25,6 +28,50 @@
   ReportBlockData(const ReportBlockData&) = default;
   ReportBlockData& operator=(const ReportBlockData&) = default;
 
+  // The SSRC identifier for the originator of this report block,
+  // i.e. remote receiver of the RTP stream.
+  uint32_t sender_ssrc() const { return report_block_.sender_ssrc; }
+
+  // The SSRC identifier of the source to which the information in this
+  // reception report block pertains, i.e. local sender of the RTP stream.
+  uint32_t source_ssrc() const { return report_block_.source_ssrc; }
+
+  // The fraction of RTP data packets from 'source_ssrc()' lost since the
+  // previous report block was sent.
+  // Fraction loss in range [0.0, 1.0].
+  float fraction_lost() const { return fraction_lost_raw() / 256.0; }
+
+  // Fraction loss as was written in the raw packet: range is [0, 255] where 0
+  // represents no loss, and 255 represents 99.6% loss (255/256 * 100%).
+  uint8_t fraction_lost_raw() const { return report_block_.fraction_lost; }
+
+  // The total number of RTP data packets from 'source_ssrc()' that have been
+  // lost since the beginning of reception.  This number is defined to be the
+  // number of packets expected less the number of packets actually received,
+  // where the number of packets received includes any which are late or
+  // duplicates. Thus, packets that arrive late are not counted as lost, and the
+  // loss may be negative if there are duplicates.
+  int cumulative_lost() const { return report_block_.packets_lost; }
+
+  // The low 16 bits contain the highest sequence number received in an RTP data
+  // packet from 'source_ssrc()', and the most significant 16 bits extend that
+  // sequence number with the corresponding count of sequence number cycles.
+  uint32_t extended_highest_sequence_number() const {
+    return report_block_.extended_highest_sequence_number;
+  }
+
+  // An estimate of the statistical variance of the RTP data packet interarrival
+  // time, measured in RTP timestamp units. The interarrival jitter J is defined
+  // to be the mean deviation (smoothed absolute value) of the difference D in
+  // packet spacing at the receiver compared to the sender for a pair of
+  // packets.
+  uint32_t jitter() const { return report_block_.jitter; }
+
+  // Jitter converted to common time units.
+  TimeDelta jitter(int rtp_clock_rate_hz) const;
+
+  // TODO(danilchap): Deprecate in favor of using ReportBlockData accessors
+  // directly.
   const RTCPReportBlock& report_block() const { return report_block_; }
 
   [[deprecated]] int64_t report_block_timestamp_utc_us() const {
@@ -34,11 +81,14 @@
   [[deprecated]] int64_t min_rtt_ms() const { return min_rtt_.ms(); }
   [[deprecated]] int64_t max_rtt_ms() const { return max_rtt_.ms(); }
   [[deprecated]] int64_t sum_rtt_ms() const { return sum_rtt_.ms(); }
-  [[deprecated]] double AvgRttMs() const { return AvgRtt().ms<double>(); }
 
+  // Time in utc epoch (Jan 1st, 1970) the report block was received.
   Timestamp report_block_timestamp_utc() const {
     return report_block_timestamp_utc_;
   }
+
+  // Round Trip Time measurments for given (sender_ssrc, source_ssrc) pair.
+  // Min, max, sum, number of measurements are since beginning of the call.
   TimeDelta last_rtt() const { return last_rtt_; }
   TimeDelta min_rtt() const { return min_rtt_; }
   TimeDelta max_rtt() const { return max_rtt_; }
@@ -46,11 +96,9 @@
   size_t num_rtts() const { return num_rtts_; }
   bool has_rtt() const { return num_rtts_ != 0; }
 
-  TimeDelta AvgRtt() const;
-
   void SetReportBlock(uint32_t sender_ssrc,
                       const rtcp::ReportBlock& report_block,
-                      Timestamp report_block_timestamp_utc_us);
+                      Timestamp report_block_timestamp_utc);
   void AddRoundTripTimeSample(TimeDelta rtt);
 
  private:
diff --git a/modules/rtp_rtcp/source/rtcp_receiver.cc b/modules/rtp_rtcp/source/rtcp_receiver.cc
index 5f53c58..9a0effc 100644
--- a/modules/rtp_rtcp/source/rtcp_receiver.cc
+++ b/modules/rtp_rtcp/source/rtcp_receiver.cc
@@ -612,7 +612,7 @@
   ReportBlockData* report_block_data =
       &received_report_blocks_[report_block.source_ssrc()];
   if (report_block.extended_high_seq_num() >
-      report_block_data->report_block().extended_highest_sequence_number) {
+      report_block_data->extended_highest_sequence_number()) {
     // We have successfully delivered new RTP packets to the remote side after
     // the last RR was sent from the remote side.
     last_increased_sequence_number_ = last_received_rb_;
@@ -806,7 +806,7 @@
   // Clear our lists.
   rtts_.erase(bye.sender_ssrc());
   EraseIf(received_report_blocks_, [&](const auto& elem) {
-    return elem.second.report_block().sender_ssrc == bye.sender_ssrc();
+    return elem.second.sender_ssrc() == bye.sender_ssrc();
   });
 
   TmmbrInformation* tmmbr_info = GetTmmbrInformation(bye.sender_ssrc());
diff --git a/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc b/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
index 979609a..b1a5667 100644
--- a/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
+++ b/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
@@ -441,12 +441,10 @@
   receiver.IncomingPacket(rr1.Build());
 
   EXPECT_EQ(now, receiver.LastReceivedReportBlockMs());
-  EXPECT_THAT(receiver.GetLatestReportBlockData(),
-              UnorderedElementsAre(
-                  Property(&ReportBlockData::report_block,
-                           Field(&RTCPReportBlock::fraction_lost, 0)),
-                  Property(&ReportBlockData::report_block,
-                           Field(&RTCPReportBlock::fraction_lost, 10))));
+  EXPECT_THAT(
+      receiver.GetLatestReportBlockData(),
+      UnorderedElementsAre(Property(&ReportBlockData::fraction_lost_raw, 0),
+                           Property(&ReportBlockData::fraction_lost_raw, 10)));
 
   // Insert next receiver report with same ssrc but new values.
   rtcp::ReportBlock rb3;
@@ -478,20 +476,16 @@
   EXPECT_THAT(
       receiver.GetLatestReportBlockData(),
       UnorderedElementsAre(
-          Property(
-              &ReportBlockData::report_block,
-              AllOf(Field(&RTCPReportBlock::source_ssrc, kReceiverMainSsrc),
-                    Field(&RTCPReportBlock::fraction_lost, kFracLost[0]),
-                    Field(&RTCPReportBlock::packets_lost, kCumLost[0]),
-                    Field(&RTCPReportBlock::extended_highest_sequence_number,
-                          kSequenceNumbers[0]))),
-          Property(
-              &ReportBlockData::report_block,
-              AllOf(Field(&RTCPReportBlock::source_ssrc, kReceiverExtraSsrc),
-                    Field(&RTCPReportBlock::fraction_lost, kFracLost[1]),
-                    Field(&RTCPReportBlock::packets_lost, kCumLost[1]),
-                    Field(&RTCPReportBlock::extended_highest_sequence_number,
-                          kSequenceNumbers[1])))));
+          AllOf(Property(&ReportBlockData::source_ssrc, kReceiverMainSsrc),
+                Property(&ReportBlockData::fraction_lost_raw, kFracLost[0]),
+                Property(&ReportBlockData::cumulative_lost, kCumLost[0]),
+                Property(&ReportBlockData::extended_highest_sequence_number,
+                         kSequenceNumbers[0])),
+          AllOf(Property(&ReportBlockData::source_ssrc, kReceiverExtraSsrc),
+                Property(&ReportBlockData::fraction_lost_raw, kFracLost[1]),
+                Property(&ReportBlockData::cumulative_lost, kCumLost[1]),
+                Property(&ReportBlockData::extended_highest_sequence_number,
+                         kSequenceNumbers[1]))));
 }
 
 TEST(RtcpReceiverTest,
@@ -522,16 +516,14 @@
 
   EXPECT_EQ(now, receiver.LastReceivedReportBlockMs());
 
-  EXPECT_THAT(
-      receiver.GetLatestReportBlockData(),
-      ElementsAre(Property(
-          &ReportBlockData::report_block,
-          AllOf(Field(&RTCPReportBlock::source_ssrc, kReceiverMainSsrc),
-                Field(&RTCPReportBlock::sender_ssrc, kSenderSsrc),
-                Field(&RTCPReportBlock::fraction_lost, kFracLost[0]),
-                Field(&RTCPReportBlock::packets_lost, kCumLost[0]),
-                Field(&RTCPReportBlock::extended_highest_sequence_number,
-                      kSequenceNumbers[0])))));
+  EXPECT_THAT(receiver.GetLatestReportBlockData(),
+              ElementsAre(AllOf(
+                  Property(&ReportBlockData::source_ssrc, kReceiverMainSsrc),
+                  Property(&ReportBlockData::sender_ssrc, kSenderSsrc),
+                  Property(&ReportBlockData::fraction_lost_raw, kFracLost[0]),
+                  Property(&ReportBlockData::cumulative_lost, kCumLost[0]),
+                  Property(&ReportBlockData::extended_highest_sequence_number,
+                           kSequenceNumbers[0]))));
 
   rtcp::ReportBlock rb2;
   rb2.SetMediaSsrc(kReceiverMainSsrc);
@@ -547,16 +539,14 @@
               OnReceivedRtcpReceiverReport(SizeIs(1), _, now));
   receiver.IncomingPacket(rr2.Build());
 
-  EXPECT_THAT(
-      receiver.GetLatestReportBlockData(),
-      UnorderedElementsAre(Property(
-          &ReportBlockData::report_block,
-          AllOf(Field(&RTCPReportBlock::source_ssrc, kReceiverMainSsrc),
-                Field(&RTCPReportBlock::sender_ssrc, kSenderSsrc2),
-                Field(&RTCPReportBlock::fraction_lost, kFracLost[1]),
-                Field(&RTCPReportBlock::packets_lost, kCumLost[1]),
-                Field(&RTCPReportBlock::extended_highest_sequence_number,
-                      kSequenceNumbers[1])))));
+  EXPECT_THAT(receiver.GetLatestReportBlockData(),
+              UnorderedElementsAre(AllOf(
+                  Property(&ReportBlockData::source_ssrc, kReceiverMainSsrc),
+                  Property(&ReportBlockData::sender_ssrc, kSenderSsrc2),
+                  Property(&ReportBlockData::fraction_lost_raw, kFracLost[1]),
+                  Property(&ReportBlockData::cumulative_lost, kCumLost[1]),
+                  Property(&ReportBlockData::extended_highest_sequence_number,
+                           kSequenceNumbers[1]))));
 }
 
 TEST(RtcpReceiverTest, GetRtt) {
@@ -1573,19 +1563,18 @@
   rtcp_report.SetSenderSsrc(kSenderSsrc);
   rtcp_report.AddReportBlock(rtcp_block);
   EXPECT_CALL(observer, OnReportBlockDataUpdated)
-      .WillOnce([&](ReportBlockData report_block_data) {
-        const auto& report_block = report_block_data.report_block();
-        EXPECT_EQ(rtcp_block.source_ssrc(), report_block.source_ssrc);
-        EXPECT_EQ(kSenderSsrc, report_block.sender_ssrc);
-        EXPECT_EQ(rtcp_block.fraction_lost(), report_block.fraction_lost);
-        EXPECT_EQ(rtcp_block.cumulative_lost(), report_block.packets_lost);
+      .WillOnce([&](ReportBlockData report_block) {
+        EXPECT_EQ(rtcp_block.source_ssrc(), report_block.source_ssrc());
+        EXPECT_EQ(kSenderSsrc, report_block.sender_ssrc());
+        EXPECT_EQ(rtcp_block.fraction_lost(), report_block.fraction_lost_raw());
+        EXPECT_EQ(rtcp_block.cumulative_lost(), report_block.cumulative_lost());
         EXPECT_EQ(rtcp_block.extended_high_seq_num(),
-                  report_block.extended_highest_sequence_number);
-        EXPECT_EQ(rtcp_block.jitter(), report_block.jitter);
-        EXPECT_EQ(report_block_data.report_block_timestamp_utc(),
+                  report_block.extended_highest_sequence_number());
+        EXPECT_EQ(rtcp_block.jitter(), report_block.jitter());
+        EXPECT_EQ(report_block.report_block_timestamp_utc(),
                   Timestamp::Millis(kNtpNowMs));
         // No RTT is calculated in this test.
-        EXPECT_EQ(0u, report_block_data.num_rtts());
+        EXPECT_EQ(0u, report_block.num_rtts());
       });
   EXPECT_CALL(mocks.rtp_rtcp_impl, OnReceivedRtcpReportBlocks);
   EXPECT_CALL(mocks.bandwidth_observer, OnReceivedRtcpReceiverReport);
@@ -1627,8 +1616,7 @@
   InSequence sequence;
   EXPECT_CALL(observer, OnReportBlockDataUpdated)
       .WillOnce([&](ReportBlockData report_block_data) {
-        EXPECT_EQ(kReceiverMainSsrc,
-                  report_block_data.report_block().source_ssrc);
+        EXPECT_EQ(kReceiverMainSsrc, report_block_data.source_ssrc());
         EXPECT_EQ(1u, report_block_data.num_rtts());
         EXPECT_EQ(kRtt, report_block_data.min_rtt());
         EXPECT_EQ(kRtt, report_block_data.max_rtt());
@@ -1637,8 +1625,7 @@
       });
   EXPECT_CALL(observer, OnReportBlockDataUpdated)
       .WillOnce([](ReportBlockData report_block_data) {
-        EXPECT_EQ(kReceiverExtraSsrc,
-                  report_block_data.report_block().source_ssrc);
+        EXPECT_EQ(kReceiverExtraSsrc, report_block_data.source_ssrc());
         EXPECT_EQ(0u, report_block_data.num_rtts());
       });
   receiver.IncomingPacket(sr.Build());
@@ -1664,11 +1651,9 @@
 
   auto report_block_datas = receiver.GetLatestReportBlockData();
   ASSERT_THAT(report_block_datas, SizeIs(1));
-  EXPECT_EQ(kReceiverMainSsrc,
-            report_block_datas[0].report_block().source_ssrc);
-  EXPECT_EQ(
-      kSequenceNumber,
-      report_block_datas[0].report_block().extended_highest_sequence_number);
+  EXPECT_EQ(kReceiverMainSsrc, report_block_datas[0].source_ssrc());
+  EXPECT_EQ(kSequenceNumber,
+            report_block_datas[0].extended_highest_sequence_number());
 }
 
 TEST(RtcpReceiverTest, GetReportBlockDataAfterTwoReportBlocksOfSameSsrc) {
@@ -1706,11 +1691,9 @@
   // Only the latest block should be returned.
   auto report_block_datas = receiver.GetLatestReportBlockData();
   ASSERT_THAT(report_block_datas, SizeIs(1));
-  EXPECT_EQ(kReceiverMainSsrc,
-            report_block_datas[0].report_block().source_ssrc);
-  EXPECT_EQ(
-      kSequenceNumber2,
-      report_block_datas[0].report_block().extended_highest_sequence_number);
+  EXPECT_EQ(kReceiverMainSsrc, report_block_datas[0].source_ssrc());
+  EXPECT_EQ(kSequenceNumber2,
+            report_block_datas[0].extended_highest_sequence_number());
 }
 
 TEST(RtcpReceiverTest, GetReportBlockDataAfterTwoReportBlocksOfDifferentSsrcs) {
@@ -1747,16 +1730,12 @@
   // Both report blocks should be returned.
   auto report_block_datas = receiver.GetLatestReportBlockData();
   ASSERT_THAT(report_block_datas, SizeIs(2));
-  EXPECT_EQ(kReceiverMainSsrc,
-            report_block_datas[0].report_block().source_ssrc);
-  EXPECT_EQ(
-      kSequenceNumber1,
-      report_block_datas[0].report_block().extended_highest_sequence_number);
-  EXPECT_EQ(kReceiverExtraSsrc,
-            report_block_datas[1].report_block().source_ssrc);
-  EXPECT_EQ(
-      kSequenceNumber2,
-      report_block_datas[1].report_block().extended_highest_sequence_number);
+  EXPECT_EQ(kReceiverMainSsrc, report_block_datas[0].source_ssrc());
+  EXPECT_EQ(kSequenceNumber1,
+            report_block_datas[0].extended_highest_sequence_number());
+  EXPECT_EQ(kReceiverExtraSsrc, report_block_datas[1].source_ssrc());
+  EXPECT_EQ(kSequenceNumber2,
+            report_block_datas[1].extended_highest_sequence_number());
 }
 
 TEST(RtcpReceiverTest, ReceivesTransportFeedback) {