Reland "Fix threading model of video quality test with audio enabled"

This is a reland of f537da6c194d2c021709a255563c27b261e92488

Original change's description:
> Fix threading model of video quality test with audio enabled
> 
> Bug: None
> Change-Id: Ifb7fc57df54ec4d0a6f8c7f0504f3c06de6ac756
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/130514
> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
> Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org>
> Commit-Queue: Artem Titov <titovartem@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#27413}

Bug: None
Change-Id: I4fb793a5a5f636103159ed537847d6f2deb60108
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/132797
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27621}
diff --git a/video/video_analyzer.cc b/video/video_analyzer.cc
index 11d2c7b..d74b79a 100644
--- a/video/video_analyzer.cc
+++ b/video/video_analyzer.cc
@@ -49,21 +49,23 @@
 }
 }  // namespace
 
-VideoAnalyzer::VideoAnalyzer(test::LayerFilteringTransport* transport,
-                             const std::string& test_label,
-                             double avg_psnr_threshold,
-                             double avg_ssim_threshold,
-                             int duration_frames,
-                             FILE* graph_data_output_file,
-                             const std::string& graph_title,
-                             uint32_t ssrc_to_analyze,
-                             uint32_t rtx_ssrc_to_analyze,
-                             size_t selected_stream,
-                             int selected_sl,
-                             int selected_tl,
-                             bool is_quick_test_enabled,
-                             Clock* clock,
-                             std::string rtp_dump_name)
+VideoAnalyzer::VideoAnalyzer(
+    test::LayerFilteringTransport* transport,
+    const std::string& test_label,
+    double avg_psnr_threshold,
+    double avg_ssim_threshold,
+    int duration_frames,
+    FILE* graph_data_output_file,
+    const std::string& graph_title,
+    uint32_t ssrc_to_analyze,
+    uint32_t rtx_ssrc_to_analyze,
+    size_t selected_stream,
+    int selected_sl,
+    int selected_tl,
+    bool is_quick_test_enabled,
+    Clock* clock,
+    std::string rtp_dump_name,
+    test::SingleThreadedTaskQueueForTesting* task_queue)
     : transport_(transport),
       receiver_(nullptr),
       call_(nullptr),
@@ -99,10 +101,10 @@
       avg_psnr_threshold_(avg_psnr_threshold),
       avg_ssim_threshold_(avg_ssim_threshold),
       is_quick_test_enabled_(is_quick_test_enabled),
-      stats_polling_thread_(&PollStatsThread, this, "StatsPoller"),
       done_(true, false),
       clock_(clock),
-      start_ms_(clock->TimeInMilliseconds()) {
+      start_ms_(clock->TimeInMilliseconds()),
+      task_queue_(task_queue) {
   // Create thread pool for CPU-expensive PSNR/SSIM calculations.
 
   // Try to use about as many threads as cores, but leave kMinCoresLeft alone,
@@ -336,7 +338,12 @@
   // at time-out check if frames_processed is going up. If so, give it more
   // time, otherwise fail. Hopefully this will reduce test flakiness.
 
-  stats_polling_thread_.Start();
+  {
+    rtc::CritScope lock(&comparison_lock_);
+    stop_stats_poller_ = false;
+    stats_polling_task_id_ = task_queue_->PostDelayedTask(
+        [this]() { PollStats(); }, kSendStatsPollingIntervalMs);
+  }
 
   int last_frames_processed = -1;
   int last_frames_captured = -1;
@@ -381,11 +388,15 @@
   if (iteration > 0)
     printf("- Farewell, sweet Concorde!\n");
 
+  {
+    rtc::CritScope lock(&comparison_lock_);
+    stop_stats_poller_ = true;
+    task_queue_->CancelTask(stats_polling_task_id_);
+  }
+
   PrintResults();
   if (graph_data_output_file_)
     PrintSamplesToFile();
-
-  stats_polling_thread_.Stop();
 }
 
 void VideoAnalyzer::StartMeasuringCpuProcessTime() {
@@ -456,57 +467,56 @@
   }
 }
 
-void VideoAnalyzer::PollStatsThread(void* obj) {
-  static_cast<VideoAnalyzer*>(obj)->PollStats();
-}
-
 void VideoAnalyzer::PollStats() {
-  while (!done_.Wait(kSendStatsPollingIntervalMs)) {
-    rtc::CritScope crit(&comparison_lock_);
-
-    Call::Stats call_stats = call_->GetStats();
-    send_bandwidth_bps_.AddSample(call_stats.send_bandwidth_bps);
-
-    VideoSendStream::Stats send_stats = send_stream_->GetStats();
-    // It's not certain that we yet have estimates for any of these stats.
-    // Check that they are positive before mixing them in.
-    if (send_stats.encode_frame_rate > 0)
-      encode_frame_rate_.AddSample(send_stats.encode_frame_rate);
-    if (send_stats.avg_encode_time_ms > 0)
-      encode_time_ms_.AddSample(send_stats.avg_encode_time_ms);
-    if (send_stats.encode_usage_percent > 0)
-      encode_usage_percent_.AddSample(send_stats.encode_usage_percent);
-    if (send_stats.media_bitrate_bps > 0)
-      media_bitrate_bps_.AddSample(send_stats.media_bitrate_bps);
-    size_t fec_bytes = 0;
-    for (const auto& kv : send_stats.substreams) {
-      fec_bytes += kv.second.rtp_stats.fec.payload_bytes +
-                   kv.second.rtp_stats.fec.padding_bytes;
-    }
-    fec_bitrate_bps_.AddSample((fec_bytes - last_fec_bytes_) * 8);
-    last_fec_bytes_ = fec_bytes;
-
-    if (receive_stream_ != nullptr) {
-      VideoReceiveStream::Stats receive_stats = receive_stream_->GetStats();
-      if (receive_stats.decode_ms > 0)
-        decode_time_ms_.AddSample(receive_stats.decode_ms);
-      if (receive_stats.max_decode_ms > 0)
-        decode_time_max_ms_.AddSample(receive_stats.max_decode_ms);
-      if (receive_stats.width > 0 && receive_stats.height > 0) {
-        pixels_.AddSample(receive_stats.width * receive_stats.height);
-      }
-    }
-
-    if (audio_receive_stream_ != nullptr) {
-      AudioReceiveStream::Stats receive_stats =
-          audio_receive_stream_->GetStats();
-      audio_expand_rate_.AddSample(receive_stats.expand_rate);
-      audio_accelerate_rate_.AddSample(receive_stats.accelerate_rate);
-      audio_jitter_buffer_ms_.AddSample(receive_stats.jitter_buffer_ms);
-    }
-
-    memory_usage_.AddSample(rtc::GetProcessResidentSizeBytes());
+  rtc::CritScope crit(&comparison_lock_);
+  if (stop_stats_poller_) {
+    return;
   }
+
+  Call::Stats call_stats = call_->GetStats();
+  send_bandwidth_bps_.AddSample(call_stats.send_bandwidth_bps);
+
+  VideoSendStream::Stats send_stats = send_stream_->GetStats();
+  // It's not certain that we yet have estimates for any of these stats.
+  // Check that they are positive before mixing them in.
+  if (send_stats.encode_frame_rate > 0)
+    encode_frame_rate_.AddSample(send_stats.encode_frame_rate);
+  if (send_stats.avg_encode_time_ms > 0)
+    encode_time_ms_.AddSample(send_stats.avg_encode_time_ms);
+  if (send_stats.encode_usage_percent > 0)
+    encode_usage_percent_.AddSample(send_stats.encode_usage_percent);
+  if (send_stats.media_bitrate_bps > 0)
+    media_bitrate_bps_.AddSample(send_stats.media_bitrate_bps);
+  size_t fec_bytes = 0;
+  for (const auto& kv : send_stats.substreams) {
+    fec_bytes += kv.second.rtp_stats.fec.payload_bytes +
+                 kv.second.rtp_stats.fec.padding_bytes;
+  }
+  fec_bitrate_bps_.AddSample((fec_bytes - last_fec_bytes_) * 8);
+  last_fec_bytes_ = fec_bytes;
+
+  if (receive_stream_ != nullptr) {
+    VideoReceiveStream::Stats receive_stats = receive_stream_->GetStats();
+    if (receive_stats.decode_ms > 0)
+      decode_time_ms_.AddSample(receive_stats.decode_ms);
+    if (receive_stats.max_decode_ms > 0)
+      decode_time_max_ms_.AddSample(receive_stats.max_decode_ms);
+    if (receive_stats.width > 0 && receive_stats.height > 0) {
+      pixels_.AddSample(receive_stats.width * receive_stats.height);
+    }
+  }
+
+  if (audio_receive_stream_ != nullptr) {
+    AudioReceiveStream::Stats receive_stats = audio_receive_stream_->GetStats();
+    audio_expand_rate_.AddSample(receive_stats.expand_rate);
+    audio_accelerate_rate_.AddSample(receive_stats.accelerate_rate);
+    audio_jitter_buffer_ms_.AddSample(receive_stats.jitter_buffer_ms);
+  }
+
+  memory_usage_.AddSample(rtc::GetProcessResidentSizeBytes());
+
+  stats_polling_task_id_ = task_queue_->PostDelayedTask(
+      [this]() { PollStats(); }, kSendStatsPollingIntervalMs);
 }
 
 bool VideoAnalyzer::FrameComparisonThread(void* obj) {
diff --git a/video/video_analyzer.h b/video/video_analyzer.h
index 36ed03e..8550345 100644
--- a/video/video_analyzer.h
+++ b/video/video_analyzer.h
@@ -44,7 +44,8 @@
                 int selected_tl,
                 bool is_quick_test_enabled,
                 Clock* clock,
-                std::string rtp_dump_name);
+                std::string rtp_dump_name,
+                test::SingleThreadedTaskQueueForTesting* task_queue);
   ~VideoAnalyzer();
 
   virtual void SetReceiver(PacketReceiver* receiver);
@@ -178,7 +179,6 @@
                           int64_t render_time_ms)
       RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
 
-  static void PollStatsThread(void* obj);
   void PollStats();
   static bool FrameComparisonThread(void* obj);
   bool CompareFrames();
@@ -273,14 +273,17 @@
   bool is_quick_test_enabled_;
 
   std::vector<rtc::PlatformThread*> comparison_thread_pool_;
-  rtc::PlatformThread stats_polling_thread_;
   rtc::Event comparison_available_event_;
   std::deque<FrameComparison> comparisons_ RTC_GUARDED_BY(comparison_lock_);
   rtc::Event done_;
+  test::SingleThreadedTaskQueueForTesting::TaskId stats_polling_task_id_
+      RTC_GUARDED_BY(comparison_lock_);
+  bool stop_stats_poller_ RTC_GUARDED_BY(comparison_lock_);
 
   std::unique_ptr<test::RtpFileWriter> rtp_file_writer_;
   Clock* const clock_;
   const int64_t start_ms_;
+  test::SingleThreadedTaskQueueForTesting* task_queue_;
 };
 
 }  // namespace webrtc
diff --git a/video/video_quality_test.cc b/video/video_quality_test.cc
index 139be61..10f9699 100644
--- a/video/video_quality_test.cc
+++ b/video/video_quality_test.cc
@@ -1203,13 +1203,11 @@
     recv_event_log_ = RtcEventLog::CreateNull();
   }
 
-  Call::Config send_call_config(send_event_log_.get());
-  Call::Config recv_call_config(recv_event_log_.get());
-  send_call_config.bitrate_config = params.call.call_bitrate_config;
-  recv_call_config.bitrate_config = params.call.call_bitrate_config;
-
-  task_queue_.SendTask([this, &send_call_config, &recv_call_config,
-                        &send_transport, &recv_transport]() {
+  task_queue_.SendTask([this, &params, &send_transport, &recv_transport]() {
+    Call::Config send_call_config(send_event_log_.get());
+    Call::Config recv_call_config(recv_event_log_.get());
+    send_call_config.bitrate_config = params.call.call_bitrate_config;
+    recv_call_config.bitrate_config = params.call.call_bitrate_config;
     if (params_.audio.enabled)
       InitializeAudioDevice(&send_call_config, &recv_call_config,
                             params_.audio.use_real_adm);
@@ -1234,7 +1232,8 @@
       kSendRtxSsrcs[params_.ss[0].selected_stream],
       static_cast<size_t>(params_.ss[0].selected_stream),
       params.ss[0].selected_sl, params_.video[0].selected_tl,
-      is_quick_test_enabled, clock_, params_.logging.rtp_dump_name);
+      is_quick_test_enabled, clock_, params_.logging.rtp_dump_name,
+      &task_queue_);
 
   task_queue_.SendTask([&]() {
     analyzer_->SetCall(sender_call_.get());