[DVQA] Tolerate receiving frames which were considerer as dropped before

It can happen that SFU will resend the frame which was before
considered as dropped during stream switching.

Bug: b/197740434
Change-Id: I95a67e6e637f6005a24df15875b50133a6e8eaaf
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/230423
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#34865}
diff --git a/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc b/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc
index b8c8a67..da4a81a 100644
--- a/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc
+++ b/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc
@@ -33,6 +33,10 @@
 
 constexpr int kMicrosPerSecond = 1000000;
 constexpr int kBitsInByte = 8;
+constexpr absl::string_view kSkipRenderedFrameReasonProcessed = "processed";
+constexpr absl::string_view kSkipRenderedFrameReasonRendered = "rendered";
+constexpr absl::string_view kSkipRenderedFrameReasonDropped =
+    "considered dropped";
 
 void LogFrameCounters(const std::string& name, const FrameCounters& counters) {
   RTC_LOG(INFO) << "[" << name << "] Captured    : " << counters.captured;
@@ -387,12 +391,25 @@
 
   auto frame_it = captured_frames_in_flight_.find(frame.id());
   if (frame_it == captured_frames_in_flight_.end() ||
-      frame_it->second.HasRenderedTime(peer_index)) {
-    // It means this frame was rendered before, so we can skip it. It may happen
-    // when we have multiple simulcast streams in one track and received
-    // the same picture from two different streams because SFU can't reliably
-    // correlate two simulcast streams and started relaying the second stream
-    // from the same frame it has relayed right before for the first stream.
+      frame_it->second.HasRenderedTime(peer_index) ||
+      frame_it->second.IsDropped(peer_index)) {
+    // It means this frame was rendered or dropped before, so we can skip it.
+    // It may happen when we have multiple simulcast streams in one track and
+    // received the same frame from two different streams because SFU can't
+    // reliably correlate two simulcast streams and started relaying the second
+    // stream from the same frame it has relayed right before for the first
+    // stream.
+    absl::string_view reason = kSkipRenderedFrameReasonProcessed;
+    if (frame_it != captured_frames_in_flight_.end()) {
+      if (frame_it->second.HasRenderedTime(peer_index)) {
+        reason = kSkipRenderedFrameReasonRendered;
+      } else if (frame_it->second.IsDropped(peer_index)) {
+        reason = kSkipRenderedFrameReasonDropped;
+      }
+    }
+    RTC_LOG(WARNING) << "Peer " << peer_name
+                     << "; Received frame out of order: received frame with id "
+                     << frame.id() << " which was " << reason << " before";
     return;
   }
 
@@ -1030,6 +1047,14 @@
   return it->second.rendered_time.IsFinite();
 }
 
+bool DefaultVideoQualityAnalyzer::FrameInFlight::IsDropped(size_t peer) const {
+  auto it = receiver_stats_.find(peer);
+  if (it == receiver_stats_.end()) {
+    return false;
+  }
+  return it->second.dropped;
+}
+
 FrameStats DefaultVideoQualityAnalyzer::FrameInFlight::GetStatsForPeer(
     size_t peer) const {
   FrameStats stats(captured_time_);
diff --git a/test/pc/e2e/analyzer/video/default_video_quality_analyzer.h b/test/pc/e2e/analyzer/video/default_video_quality_analyzer.h
index 2091edf..d7365cb 100644
--- a/test/pc/e2e/analyzer/video/default_video_quality_analyzer.h
+++ b/test/pc/e2e/analyzer/video/default_video_quality_analyzer.h
@@ -243,6 +243,7 @@
     }
 
     void MarkDropped(size_t peer) { receiver_stats_[peer].dropped = true; }
+    bool IsDropped(size_t peer) const;
 
     void SetPrevFrameRenderedTime(size_t peer, webrtc::Timestamp time) {
       receiver_stats_[peer].prev_frame_rendered_time = time;