Fix processing of dropped frame for runtime added participant

Bug: webrtc:12247
Change-Id: I0fe5cad8f755bda899e81b31e255f24816bf33bc
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/215061
Commit-Queue: Andrey Logvin <landrey@webrtc.org>
Reviewed-by: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33698}
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 9b18f6f..7d52389 100644
--- a/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc
+++ b/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc
@@ -466,7 +466,7 @@
                                   frame_in_flight->rendered_time(peer_index));
   {
     MutexLock cr(&comparison_lock_);
-    stream_stats_[stats_key].skipped_between_rendered.AddSample(
+    stream_stats_.at(stats_key).skipped_between_rendered.AddSample(
         StatsSample(dropped_count, Now()));
   }
 
@@ -519,6 +519,7 @@
     counters.encoded = frames_count;
     stream_frame_counters_.insert({key, std::move(counters)});
 
+    stream_stats_.insert({key, StreamStats()});
     stream_last_freeze_end_time_.insert({key, start_time_});
   }
   // Ensure, that frames states are handled correctly
diff --git a/test/pc/e2e/analyzer/video/default_video_quality_analyzer_test.cc b/test/pc/e2e/analyzer/video/default_video_quality_analyzer_test.cc
index a8b5d9f..4cdc681 100644
--- a/test/pc/e2e/analyzer/video/default_video_quality_analyzer_test.cc
+++ b/test/pc/e2e/analyzer/video/default_video_quality_analyzer_test.cc
@@ -760,6 +760,11 @@
   constexpr char kAlice[] = "alice";
   constexpr char kBob[] = "bob";
   constexpr char kCharlie[] = "charlie";
+  constexpr char kKatie[] = "katie";
+
+  constexpr int kFramesCount = 9;
+  constexpr int kOneThirdFrames = kFramesCount / 3;
+  constexpr int kTwoThirdFrames = 2 * kOneThirdFrames;
 
   DefaultVideoQualityAnalyzer analyzer(Clock::GetRealTimeClock(),
                                        AnalyzerOptionsForTest());
@@ -769,7 +774,9 @@
   std::vector<uint16_t> frames_order;
   analyzer.RegisterParticipantInCall(kAlice);
   analyzer.RegisterParticipantInCall(kBob);
-  for (int i = 0; i < kMaxFramesInFlightPerStream; ++i) {
+
+  // Alice is sending frames.
+  for (int i = 0; i < kFramesCount; ++i) {
     VideoFrame frame = NextFrame(frame_generator.get(), i);
     frame.set_id(analyzer.OnFrameCaptured(kAlice, kStreamLabel, frame));
     frames_order.push_back(frame.id());
@@ -779,7 +786,8 @@
                             VideoQualityAnalyzerInterface::EncoderStats());
   }
 
-  for (size_t i = 0; i < frames_order.size() / 2; ++i) {
+  // Bob receives one third of the sent frames.
+  for (int i = 0; i < kOneThirdFrames; ++i) {
     uint16_t frame_id = frames_order.at(i);
     VideoFrame received_frame = DeepCopy(captured_frames.at(frame_id));
     analyzer.OnFramePreDecode(kBob, received_frame.id(),
@@ -790,8 +798,11 @@
   }
 
   analyzer.RegisterParticipantInCall(kCharlie);
+  analyzer.RegisterParticipantInCall(kKatie);
 
-  for (size_t i = frames_order.size() / 2; i < frames_order.size(); ++i) {
+  // New participants were dynamically added. Bob and Charlie receive second
+  // third of the sent frames. Katie drops the frames.
+  for (int i = kOneThirdFrames; i < kTwoThirdFrames; ++i) {
     uint16_t frame_id = frames_order.at(i);
     VideoFrame bob_received_frame = DeepCopy(captured_frames.at(frame_id));
     analyzer.OnFramePreDecode(kBob, bob_received_frame.id(),
@@ -808,6 +819,31 @@
     analyzer.OnFrameRendered(kCharlie, charlie_received_frame);
   }
 
+  // Bob, Charlie and Katie receive the rest of the sent frames.
+  for (int i = kTwoThirdFrames; i < kFramesCount; ++i) {
+    uint16_t frame_id = frames_order.at(i);
+    VideoFrame bob_received_frame = DeepCopy(captured_frames.at(frame_id));
+    analyzer.OnFramePreDecode(kBob, bob_received_frame.id(),
+                              FakeEncode(bob_received_frame));
+    analyzer.OnFrameDecoded(kBob, bob_received_frame,
+                            VideoQualityAnalyzerInterface::DecoderStats());
+    analyzer.OnFrameRendered(kBob, bob_received_frame);
+
+    VideoFrame charlie_received_frame = DeepCopy(captured_frames.at(frame_id));
+    analyzer.OnFramePreDecode(kCharlie, charlie_received_frame.id(),
+                              FakeEncode(charlie_received_frame));
+    analyzer.OnFrameDecoded(kCharlie, charlie_received_frame,
+                            VideoQualityAnalyzerInterface::DecoderStats());
+    analyzer.OnFrameRendered(kCharlie, charlie_received_frame);
+
+    VideoFrame katie_received_frame = DeepCopy(captured_frames.at(frame_id));
+    analyzer.OnFramePreDecode(kKatie, katie_received_frame.id(),
+                              FakeEncode(katie_received_frame));
+    analyzer.OnFrameDecoded(kKatie, katie_received_frame,
+                            VideoQualityAnalyzerInterface::DecoderStats());
+    analyzer.OnFrameRendered(kKatie, katie_received_frame);
+  }
+
   // Give analyzer some time to process frames on async thread. The computations
   // have to be fast (heavy metrics are disabled!), so if doesn't fit 100ms it
   // means we have an issue!
@@ -816,8 +852,7 @@
 
   AnalyzerStats stats = analyzer.GetAnalyzerStats();
   EXPECT_EQ(stats.memory_overloaded_comparisons_done, 0);
-  EXPECT_EQ(stats.comparisons_done,
-            kMaxFramesInFlightPerStream + kMaxFramesInFlightPerStream / 2);
+  EXPECT_EQ(stats.comparisons_done, kFramesCount + 2 * kTwoThirdFrames);
 
   std::vector<StatsSample> frames_in_flight_sizes =
       GetSortedSamples(stats.frames_in_flight_left_count);
@@ -825,37 +860,45 @@
       << ToString(frames_in_flight_sizes);
 
   FrameCounters frame_counters = analyzer.GetGlobalCounters();
-  EXPECT_EQ(frame_counters.captured, kMaxFramesInFlightPerStream);
-  EXPECT_EQ(frame_counters.received,
-            kMaxFramesInFlightPerStream + kMaxFramesInFlightPerStream / 2);
-  EXPECT_EQ(frame_counters.decoded,
-            kMaxFramesInFlightPerStream + kMaxFramesInFlightPerStream / 2);
-  EXPECT_EQ(frame_counters.rendered,
-            kMaxFramesInFlightPerStream + kMaxFramesInFlightPerStream / 2);
-  EXPECT_EQ(frame_counters.dropped, 0);
+  EXPECT_EQ(frame_counters.captured, kFramesCount);
+  EXPECT_EQ(frame_counters.received, 2 * kFramesCount);
+  EXPECT_EQ(frame_counters.decoded, 2 * kFramesCount);
+  EXPECT_EQ(frame_counters.rendered, 2 * kFramesCount);
+  EXPECT_EQ(frame_counters.dropped, kOneThirdFrames);
 
-  EXPECT_EQ(analyzer.GetKnownVideoStreams().size(), 2lu);
+  EXPECT_EQ(analyzer.GetKnownVideoStreams().size(), 3lu);
   const StatsKey kAliceBobStats(kStreamLabel, kAlice, kBob);
   const StatsKey kAliceCharlieStats(kStreamLabel, kAlice, kCharlie);
+  const StatsKey kAliceKatieStats(kStreamLabel, kAlice, kKatie);
   {
     FrameCounters stream_conters =
         analyzer.GetPerStreamCounters().at(kAliceBobStats);
-    EXPECT_EQ(stream_conters.captured, 10);
-    EXPECT_EQ(stream_conters.pre_encoded, 10);
-    EXPECT_EQ(stream_conters.encoded, 10);
-    EXPECT_EQ(stream_conters.received, 10);
-    EXPECT_EQ(stream_conters.decoded, 10);
-    EXPECT_EQ(stream_conters.rendered, 10);
+    EXPECT_EQ(stream_conters.captured, kFramesCount);
+    EXPECT_EQ(stream_conters.pre_encoded, kFramesCount);
+    EXPECT_EQ(stream_conters.encoded, kFramesCount);
+    EXPECT_EQ(stream_conters.received, kFramesCount);
+    EXPECT_EQ(stream_conters.decoded, kFramesCount);
+    EXPECT_EQ(stream_conters.rendered, kFramesCount);
   }
   {
     FrameCounters stream_conters =
         analyzer.GetPerStreamCounters().at(kAliceCharlieStats);
-    EXPECT_EQ(stream_conters.captured, 5);
-    EXPECT_EQ(stream_conters.pre_encoded, 5);
-    EXPECT_EQ(stream_conters.encoded, 5);
-    EXPECT_EQ(stream_conters.received, 5);
-    EXPECT_EQ(stream_conters.decoded, 5);
-    EXPECT_EQ(stream_conters.rendered, 5);
+    EXPECT_EQ(stream_conters.captured, kTwoThirdFrames);
+    EXPECT_EQ(stream_conters.pre_encoded, kTwoThirdFrames);
+    EXPECT_EQ(stream_conters.encoded, kTwoThirdFrames);
+    EXPECT_EQ(stream_conters.received, kTwoThirdFrames);
+    EXPECT_EQ(stream_conters.decoded, kTwoThirdFrames);
+    EXPECT_EQ(stream_conters.rendered, kTwoThirdFrames);
+  }
+  {
+    FrameCounters stream_conters =
+        analyzer.GetPerStreamCounters().at(kAliceKatieStats);
+    EXPECT_EQ(stream_conters.captured, kTwoThirdFrames);
+    EXPECT_EQ(stream_conters.pre_encoded, kTwoThirdFrames);
+    EXPECT_EQ(stream_conters.encoded, kTwoThirdFrames);
+    EXPECT_EQ(stream_conters.received, kOneThirdFrames);
+    EXPECT_EQ(stream_conters.decoded, kOneThirdFrames);
+    EXPECT_EQ(stream_conters.rendered, kOneThirdFrames);
   }
 }