Implement support for RFC8888 in  ParsedRtcEventLog::GetPacketInfos

This allow plotting per packet delay if RFC8888 feedback is utilized

Bug: webrtc:436707095
Change-Id: I1769fa25fd200b80009d36158858a82b01264696
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/403380
Reviewed-by: Björn Terelius <terelius@webrtc.org>
Commit-Queue: Björn Terelius <terelius@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#45302}
diff --git a/logging/BUILD.gn b/logging/BUILD.gn
index 85d3db5..1870196 100644
--- a/logging/BUILD.gn
+++ b/logging/BUILD.gn
@@ -535,6 +535,7 @@
       "../api/video:video_frame",
       "../modules:module_api_public",
       "../modules/audio_coding:audio_network_adaptor",
+      "../modules/rtp_rtcp:ntp_time_util",
       "../modules/rtp_rtcp:rtp_rtcp_format",
       "../rtc_base:checks",
       "../rtc_base:copy_on_write_buffer",
diff --git a/logging/rtc_event_log/rtc_event_log_parser.cc b/logging/rtc_event_log/rtc_event_log_parser.cc
index 35492d1..cb5ca71 100644
--- a/logging/rtc_event_log/rtc_event_log_parser.cc
+++ b/logging/rtc_event_log/rtc_event_log_parser.cc
@@ -76,6 +76,7 @@
 #include "modules/rtp_rtcp/include/rtp_cvo.h"
 #include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "modules/rtp_rtcp/source/ntp_time_util.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/bye.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/congestion_control_feedback.h"
@@ -2397,10 +2398,36 @@
       GetOverheadChangingEvents(GetRouteChanges(), direction);
   auto overhead_iter = overheads.begin();
   std::vector<LoggedPacketInfo> packets;
-  std::map<int64_t, size_t> indices;
+  std::map</*unwrapped transport sequence number*/ int64_t,
+           /*index into packets*/ size_t>
+      twcc_indices;
+  RtpSequenceNumberUnwrapper transport_seq_num_unwrapper;
+
+  class PerSSRCInfo {
+   public:
+    void AddPacketIndex(uint16_t rtp_sequence_number, size_t index) {
+      packet_indices_[rtp_seq_num_unwrapper_.Unwrap(rtp_sequence_number)] =
+          index;
+    }
+    std::optional<size_t> FindPacketIndex(uint16_t rtp_sequence_number) {
+      auto it = packet_indices_.find(
+          rtp_seq_num_unwrapper_.Unwrap(rtp_sequence_number));
+      if (it == packet_indices_.end()) {
+        return std::nullopt;
+      }
+      return it->second;
+    }
+
+   private:
+    RtpSequenceNumberUnwrapper rtp_seq_num_unwrapper_;
+    std::map</*unwrapped rtp sequence number*/ int64_t,
+             /*index into packets*/ size_t>
+        packet_indices_;
+  };
+  std::map</*ssrc*/ uint32_t, PerSSRCInfo> ccfb_indices;
+
   uint16_t current_overhead = kDefaultOverhead;
   Timestamp last_log_time = Timestamp::Zero();
-  RtpSequenceNumberUnwrapper seq_num_unwrapper;
 
   auto advance_time = [&](Timestamp new_log_time) {
     if (overhead_iter != overheads.end() &&
@@ -2412,8 +2439,9 @@
     // therefore we don't want to match up sequence numbers as we might have had
     // a wraparound.
     if (new_log_time - last_log_time > TimeDelta::Seconds(30)) {
-      seq_num_unwrapper.Reset();
-      indices.clear();
+      transport_seq_num_unwrapper.Reset();
+      twcc_indices.clear();
+      ccfb_indices.clear();
     }
     RTC_DCHECK_GE(new_log_time, last_log_time);
     last_log_time = new_log_time;
@@ -2444,25 +2472,28 @@
     if (logged.has_transport_seq_no) {
       logged.log_feedback_time = Timestamp::PlusInfinity();
       int64_t unwrapped_seq_num =
-          seq_num_unwrapper.Unwrap(logged.transport_seq_no);
-      if (indices.find(unwrapped_seq_num) != indices.end()) {
+          transport_seq_num_unwrapper.Unwrap(logged.transport_seq_no);
+      if (twcc_indices.find(unwrapped_seq_num) != twcc_indices.end()) {
         Timestamp prev_log_packet_time =
-            packets[indices[unwrapped_seq_num]].log_packet_time;
+            packets[twcc_indices[unwrapped_seq_num]].log_packet_time;
         RTC_LOG(LS_WARNING)
             << "Repeated sent packet sequence number: " << unwrapped_seq_num
             << " Packet time:" << prev_log_packet_time.seconds() << "s vs "
             << logged.log_packet_time.seconds()
             << "s at:" << rtp.log_time_ms() / 1000;
       }
-      indices[unwrapped_seq_num] = packets.size();
+      twcc_indices[unwrapped_seq_num] = packets.size();
+    } else {
+      ccfb_indices[rtp.header.ssrc].AddPacketIndex(rtp.header.sequenceNumber,
+                                                   packets.size());
     }
     packets.push_back(logged);
   };
 
-  Timestamp feedback_base_time = Timestamp::MinusInfinity();
-  Timestamp last_feedback_base_time = Timestamp::MinusInfinity();
+  Timestamp twcc_feedback_base_time = Timestamp::MinusInfinity();
+  Timestamp twcc_last_feedback_base_time = Timestamp::MinusInfinity();
 
-  auto feedback_handler =
+  auto twcc_feedback_handler =
       [&](const LoggedRtcpPacketTransportFeedback& logged_rtcp) {
         auto log_feedback_time = logged_rtcp.log_time();
         advance_time(log_feedback_time);
@@ -2470,21 +2501,23 @@
         // Add timestamp deltas to a local time base selected on first packet
         // arrival. This won't be the true time base, but makes it easier to
         // manually inspect time stamps.
-        if (!last_feedback_base_time.IsFinite()) {
-          feedback_base_time = log_feedback_time;
+        if (!twcc_last_feedback_base_time.IsFinite()) {
+          twcc_feedback_base_time = log_feedback_time;
         } else {
-          feedback_base_time += feedback.GetBaseDelta(last_feedback_base_time);
+          twcc_feedback_base_time +=
+              feedback.GetBaseDelta(twcc_last_feedback_base_time);
         }
-        last_feedback_base_time = feedback.BaseTime();
+        twcc_last_feedback_base_time = feedback.BaseTime();
 
         std::vector<LoggedPacketInfo*> packet_feedbacks;
         packet_feedbacks.reserve(feedback.GetPacketStatusCount());
         std::vector<int64_t> unknown_seq_nums;
         feedback.ForAllPackets([&](uint16_t sequence_number,
                                    TimeDelta delta_since_base) {
-          int64_t unwrapped_seq_num = seq_num_unwrapper.Unwrap(sequence_number);
-          auto it = indices.find(unwrapped_seq_num);
-          if (it == indices.end()) {
+          int64_t unwrapped_seq_num =
+              transport_seq_num_unwrapper.Unwrap(sequence_number);
+          auto it = twcc_indices.find(unwrapped_seq_num);
+          if (it == twcc_indices.end()) {
             unknown_seq_nums.push_back(unwrapped_seq_num);
             return;
           }
@@ -2497,7 +2530,8 @@
           }
           if (delta_since_base.IsFinite()) {
             if (sent->reported_recv_time.IsInfinite()) {
-              sent->reported_recv_time = feedback_base_time + delta_since_base;
+              sent->reported_recv_time =
+                  twcc_feedback_base_time + delta_since_base;
               sent->log_feedback_time = log_feedback_time;
             }
           } else {
@@ -2532,15 +2566,81 @@
         }
       };
 
+  Timestamp ccfb_feedback_offset = Timestamp::MinusInfinity();
+  std::optional<uint32_t> last_feedback_compact_ntp_time_;
+  auto ccfb_feedback_handler =
+      [&](const LoggedRtcpCongestionControlFeedback& logged_rtcp) {
+        Timestamp log_feedback_time = logged_rtcp.log_time();
+        advance_time(log_feedback_time);
+        const rtcp::CongestionControlFeedback& feedback =
+            logged_rtcp.congestion_feedback;
+
+        if (ccfb_feedback_offset.IsInfinite()) {
+          ccfb_feedback_offset = log_feedback_time;
+        }
+        TimeDelta feedback_delta =
+            last_feedback_compact_ntp_time_.has_value()
+                ? CompactNtpIntervalToTimeDelta(
+                      feedback.report_timestamp_compact_ntp() -
+                      *last_feedback_compact_ntp_time_)
+                : TimeDelta::Zero();
+        last_feedback_compact_ntp_time_ =
+            feedback.report_timestamp_compact_ntp();
+        if (feedback_delta < TimeDelta::Zero()) {
+          RTC_LOG(LS_WARNING)
+              << "Unexpected feedback ntp time delta " << feedback_delta << ".";
+          ccfb_feedback_offset = log_feedback_time;
+        } else {
+          ccfb_feedback_offset += feedback_delta;
+        }
+        for (const rtcp::CongestionControlFeedback::PacketInfo& packet :
+             feedback.packets()) {
+          std::optional<size_t> packets_index =
+              ccfb_indices[packet.ssrc].FindPacketIndex(packet.sequence_number);
+          if (!packets_index.has_value()) {
+            RTC_LOG(LS_WARNING)
+                << " Got feedback for unknown packet, ssrc: " << packet.ssrc
+                << " rtp seqno:" << packet.sequence_number;
+            continue;
+          }
+          LoggedPacketInfo* sent = &packets[*packets_index];
+          RTC_DCHECK_EQ(packet.ssrc, sent->ssrc);
+          RTC_DCHECK_EQ(packet.sequence_number, sent->stream_seq_no);
+          if (log_feedback_time - sent->log_packet_time >
+              TimeDelta::Seconds(60)) {
+            RTC_LOG(LS_WARNING)
+                << "Received very late feedback, possibly due to wraparound.";
+            return;
+          }
+          if (packet.arrival_time_offset.IsFinite()) {
+            if (sent->reported_recv_time.IsInfinite()) {
+              sent->log_feedback_time = log_feedback_time;
+              sent->feedback_hold_duration = packet.arrival_time_offset;
+              sent->reported_recv_time =
+                  ccfb_feedback_offset - packet.arrival_time_offset;
+            }
+          } else {
+            if (sent->log_feedback_time.IsInfinite()) {
+              sent->log_feedback_time = log_feedback_time;
+              sent->reported_recv_time = Timestamp::PlusInfinity();
+            }
+          }
+        }
+      };
+
   RtcEventProcessor process;
   for (const auto& rtp_packets : rtp_packets_by_ssrc(direction)) {
     process.AddEvents(rtp_packets.packet_view, rtp_handler, direction);
   }
   if (direction == PacketDirection::kOutgoingPacket) {
-    process.AddEvents(incoming_transport_feedback_, feedback_handler,
+    process.AddEvents(incoming_transport_feedback_, twcc_feedback_handler,
+                      PacketDirection::kIncomingPacket);
+    process.AddEvents(incoming_congestion_feedback_, ccfb_feedback_handler,
                       PacketDirection::kIncomingPacket);
   } else {
-    process.AddEvents(outgoing_transport_feedback_, feedback_handler,
+    process.AddEvents(outgoing_transport_feedback_, twcc_feedback_handler,
+                      PacketDirection::kOutgoingPacket);
+    process.AddEvents(outgoing_congestion_feedback_, ccfb_feedback_handler,
                       PacketDirection::kOutgoingPacket);
   }
   process.ProcessEventsInOrder();
diff --git a/logging/rtc_event_log/rtc_event_processor_order.h b/logging/rtc_event_log/rtc_event_processor_order.h
index 7c2c7e8..a9a4750 100644
--- a/logging/rtc_event_log/rtc_event_processor_order.h
+++ b/logging/rtc_event_log/rtc_event_processor_order.h
@@ -439,6 +439,20 @@
 };
 
 template <>
+class TieBreaker<LoggedRtcpCongestionControlFeedback> {
+ public:
+  static constexpr int type_order(PacketDirection direction) {
+    return static_cast<int>(direction == PacketDirection::kIncomingPacket
+                                ? TypeOrder::RtcpIn
+                                : TypeOrder::RtcpOut);
+  }
+  static std::optional<uint16_t> transport_seq_num_accessor(
+      const LoggedRtcpCongestionControlFeedback&) {
+    return std::optional<uint16_t>();
+  }
+};
+
+template <>
 class TieBreaker<LoggedRtcpPacketSenderReport> {
  public:
   static constexpr int type_order(PacketDirection direction) {