Use SeqNumUnwapper to handle reordering of first packets

Fixed todo by replacing SequenceNumberUnwrapper with updated class
SeqNumUnwrapper that correctly handles reordering of early packets.

Bug: webrtc:10263
Change-Id: Iffd93db924fee132d35752996b8d29acbb315d24
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/130498
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Commit-Queue: Johannes Kron <kron@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27417}
diff --git a/modules/remote_bitrate_estimator/BUILD.gn b/modules/remote_bitrate_estimator/BUILD.gn
index 055ae68..91e8a77 100644
--- a/modules/remote_bitrate_estimator/BUILD.gn
+++ b/modules/remote_bitrate_estimator/BUILD.gn
@@ -50,6 +50,7 @@
     "../../modules/rtp_rtcp:rtp_rtcp_format",
     "../../rtc_base:checks",
     "../../rtc_base:rtc_base_approved",
+    "../../rtc_base:rtc_numerics",
     "../../rtc_base:safe_minmax",
     "../../rtc_base/experiments:field_trial_parser",
     "../../system_wrappers",
diff --git a/modules/remote_bitrate_estimator/remote_estimator_proxy.cc b/modules/remote_bitrate_estimator/remote_estimator_proxy.cc
index 70eef90..009f867 100644
--- a/modules/remote_bitrate_estimator/remote_estimator_proxy.cc
+++ b/modules/remote_bitrate_estimator/remote_estimator_proxy.cc
@@ -42,7 +42,6 @@
       last_process_time_ms_(-1),
       media_ssrc_(0),
       feedback_packet_count_(0),
-      window_start_seq_(-1),
       send_interval_ms_(kDefaultSendIntervalMs),
       send_feedback_on_request_only_(false) {}
 
@@ -125,40 +124,27 @@
     return;
   }
 
-  // TODO(holmer): We should handle a backwards wrap here if the first
-  // sequence number was small and the new sequence number is large. The
-  // SequenceNumberUnwrapper doesn't do this, so we should replace this with
-  // calls to IsNewerSequenceNumber instead.
   int64_t seq = unwrapper_.Unwrap(sequence_number);
-  if (window_start_seq_ != -1 && seq > window_start_seq_ + 0xFFFF / 2) {
-    RTC_LOG(LS_WARNING) << "Skipping this sequence number (" << sequence_number
-                        << ") since it likely is reordered, but the unwrapper"
-                           "failed to handle it. Feedback window starts at "
-                        << window_start_seq_ << ".";
-    return;
-  }
 
   if (send_feedback_on_request_only_) {
     // Remove old packet arrival times.
     auto clear_to_it =
         packet_arrival_times_.lower_bound(seq - kMaxNumberOfPackets);
     packet_arrival_times_.erase(packet_arrival_times_.begin(), clear_to_it);
-  } else if (packet_arrival_times_.lower_bound(window_start_seq_) ==
-             packet_arrival_times_.end()) {
-    // Start new feedback packet, cull old packets.
-    for (auto it = packet_arrival_times_.begin();
-         it != packet_arrival_times_.end() && it->first < seq &&
-         arrival_time - it->second >= kBackWindowMs;) {
-      auto delete_it = it;
-      ++it;
-      packet_arrival_times_.erase(delete_it);
+  } else {
+    if (periodic_window_start_seq_ &&
+        packet_arrival_times_.lower_bound(*periodic_window_start_seq_) ==
+            packet_arrival_times_.end()) {
+      // Start new feedback packet, cull old packets.
+      for (auto it = packet_arrival_times_.begin();
+           it != packet_arrival_times_.end() && it->first < seq &&
+           arrival_time - it->second >= kBackWindowMs;) {
+        it = packet_arrival_times_.erase(it);
+      }
     }
-  }
-
-  if (window_start_seq_ == -1) {
-    window_start_seq_ = sequence_number;
-  } else if (seq < window_start_seq_) {
-    window_start_seq_ = seq;
+    if (!periodic_window_start_seq_ || seq < *periodic_window_start_seq_) {
+      periodic_window_start_seq_ = seq;
+    }
   }
 
   // We are only interested in the first time a packet is received.
@@ -174,16 +160,20 @@
 }
 
 void RemoteEstimatorProxy::SendPeriodicFeedbacks() {
-  // |window_start_seq_| is the first sequence number to include in the current
-  // feedback packet. Some older may still be in the map, in case a reordering
-  // happens and we need to retransmit them.
+  // |periodic_window_start_seq_| is the first sequence number to include in the
+  // current feedback packet. Some older may still be in the map, in case a
+  // reordering happens and we need to retransmit them.
+  if (!periodic_window_start_seq_)
+    return;
+
   for (auto begin_iterator =
-           packet_arrival_times_.lower_bound(window_start_seq_);
+           packet_arrival_times_.lower_bound(*periodic_window_start_seq_);
        begin_iterator != packet_arrival_times_.cend();
-       begin_iterator = packet_arrival_times_.lower_bound(window_start_seq_)) {
+       begin_iterator =
+           packet_arrival_times_.lower_bound(*periodic_window_start_seq_)) {
     rtcp::TransportFeedback feedback_packet;
-    window_start_seq_ = BuildFeedbackPacket(
-        feedback_packet_count_++, media_ssrc_, window_start_seq_,
+    periodic_window_start_seq_ = BuildFeedbackPacket(
+        feedback_packet_count_++, media_ssrc_, *periodic_window_start_seq_,
         begin_iterator, packet_arrival_times_.cend(), &feedback_packet);
 
     RTC_DCHECK(feedback_sender_ != nullptr);
@@ -208,11 +198,9 @@
       packet_arrival_times_.lower_bound(first_sequence_number);
   auto end_iterator = packet_arrival_times_.upper_bound(sequence_number);
 
-  // window_start_seq must be updated to make sure that we detect incorrectly
-  // unwrapped sequence_numbers in OnPacketArrival().
-  window_start_seq_ = BuildFeedbackPacket(feedback_packet_count_++, media_ssrc_,
-                                          first_sequence_number, begin_iterator,
-                                          end_iterator, &feedback_packet);
+  BuildFeedbackPacket(feedback_packet_count_++, media_ssrc_,
+                      first_sequence_number, begin_iterator, end_iterator,
+                      &feedback_packet);
 
   // Clear up to the first packet that is included in this feedback packet.
   packet_arrival_times_.erase(packet_arrival_times_.begin(), begin_iterator);
diff --git a/modules/remote_bitrate_estimator/remote_estimator_proxy.h b/modules/remote_bitrate_estimator/remote_estimator_proxy.h
index 73d89c1..d13e1a1 100644
--- a/modules/remote_bitrate_estimator/remote_estimator_proxy.h
+++ b/modules/remote_bitrate_estimator/remote_estimator_proxy.h
@@ -14,9 +14,9 @@
 #include <map>
 #include <vector>
 
-#include "modules/include/module_common_types.h"
 #include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
 #include "rtc_base/critical_section.h"
+#include "rtc_base/numerics/sequence_number_util.h"
 
 namespace webrtc {
 
@@ -81,8 +81,8 @@
 
   uint32_t media_ssrc_ RTC_GUARDED_BY(&lock_);
   uint8_t feedback_packet_count_ RTC_GUARDED_BY(&lock_);
-  SequenceNumberUnwrapper unwrapper_ RTC_GUARDED_BY(&lock_);
-  int64_t window_start_seq_ RTC_GUARDED_BY(&lock_);
+  SeqNumUnwrapper<uint16_t> unwrapper_ RTC_GUARDED_BY(&lock_);
+  absl::optional<int64_t> periodic_window_start_seq_ RTC_GUARDED_BY(&lock_);
   // Map unwrapped seq -> time.
   std::map<int64_t, int64_t> packet_arrival_times_ RTC_GUARDED_BY(&lock_);
   int64_t send_interval_ms_ RTC_GUARDED_BY(&lock_);
diff --git a/modules/remote_bitrate_estimator/remote_estimator_proxy_unittest.cc b/modules/remote_bitrate_estimator/remote_estimator_proxy_unittest.cc
index 71b6659..ab20d5a 100644
--- a/modules/remote_bitrate_estimator/remote_estimator_proxy_unittest.cc
+++ b/modules/remote_bitrate_estimator/remote_estimator_proxy_unittest.cc
@@ -196,18 +196,19 @@
   Process();
 }
 
-TEST_F(RemoteEstimatorProxyTest, GracefullyHandlesReorderingAndWrap) {
+TEST_F(RemoteEstimatorProxyTest, HandlesReorderingAndWrap) {
   const int64_t kDeltaMs = 1000;
   const uint16_t kLargeSeq = 62762;
   IncomingPacket(kBaseSeq, kBaseTimeMs);
   IncomingPacket(kLargeSeq, kBaseTimeMs + kDeltaMs);
 
   EXPECT_CALL(router_, SendTransportFeedback(_))
-      .WillOnce(Invoke([](rtcp::TransportFeedback* feedback_packet) {
-        EXPECT_EQ(kBaseSeq, feedback_packet->GetBaseSequence());
+      .WillOnce(Invoke([&](rtcp::TransportFeedback* feedback_packet) {
+        EXPECT_EQ(kLargeSeq, feedback_packet->GetBaseSequence());
         EXPECT_EQ(kMediaSsrc, feedback_packet->media_ssrc());
 
-        EXPECT_THAT(TimestampsMs(*feedback_packet), ElementsAre(kBaseTimeMs));
+        EXPECT_THAT(TimestampsMs(*feedback_packet),
+                    ElementsAre(kBaseTimeMs + kDeltaMs, kBaseTimeMs));
         return true;
       }));