Remove playout delay lock.
Now update the playout delay and related stats on the worker thread.

This was previously reviewed here:
https://webrtc-review.googlesource.com/c/src/+/172929/

With the exception of reducing unnecessarily broad
lock scope in one function in rtp_rtcp_impl.cc
and added comments in rtp_streams_synchronizer.h

Bug: webrtc:11489
Change-Id: I77807b5da2accfe774255d9409542d358f288993
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/174200
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31193}
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
index 1cb61f5..4f84b02 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
+++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
@@ -774,8 +774,10 @@
 }
 
 void ModuleRtpRtcpImpl::set_rtt_ms(int64_t rtt_ms) {
-  rtc::CritScope cs(&critical_section_rtt_);
-  rtt_ms_ = rtt_ms;
+  {
+    rtc::CritScope cs(&critical_section_rtt_);
+    rtt_ms_ = rtt_ms;
+  }
   if (rtp_sender_) {
     rtp_sender_->packet_history.SetRtt(rtt_ms);
   }
diff --git a/video/rtp_streams_synchronizer.h b/video/rtp_streams_synchronizer.h
index 60e2c8e..00ef526 100644
--- a/video/rtp_streams_synchronizer.h
+++ b/video/rtp_streams_synchronizer.h
@@ -25,6 +25,11 @@
 
 class Syncable;
 
+// TODO(bugs.webrtc.org/11489): Remove dependency on ProcessThread/Module.
+// Instead make this a single threaded class, constructed on a TQ and
+// post a 1 sec timer there. There shouldn't be a need for locking internally
+// and the callback from this class, should occur on the construction TQ
+// which in turn means that the callback doesn't need locking either.
 class RtpStreamsSynchronizer : public Module {
  public:
   explicit RtpStreamsSynchronizer(Syncable* syncable_video);
diff --git a/video/video_receive_stream2.cc b/video/video_receive_stream2.cc
index 0af17d5..19ca958 100644
--- a/video/video_receive_stream2.cc
+++ b/video/video_receive_stream2.cc
@@ -274,6 +274,7 @@
   RTC_LOG(LS_INFO) << "~VideoReceiveStream2: " << config_.ToString();
   Stop();
   process_thread_->DeRegisterModule(&rtp_stream_sync_);
+  task_safety_flag_->SetNotAlive();
 }
 
 void VideoReceiveStream2::SignalNetworkState(NetworkState state) {
@@ -477,8 +478,6 @@
     return false;
   }
 
-  // TODO(bugs.webrtc.org/11489): Consider posting to worker.
-  rtc::CritScope cs(&playout_delay_lock_);
   base_minimum_playout_delay_ms_ = delay_ms;
   UpdatePlayoutDelays();
   return true;
@@ -486,8 +485,6 @@
 
 int VideoReceiveStream2::GetBaseMinimumPlayoutDelayMs() const {
   RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
-
-  rtc::CritScope cs(&playout_delay_lock_);
   return base_minimum_playout_delay_ms_;
 }
 
@@ -549,21 +546,18 @@
   }
   last_complete_frame_time_ms_ = time_now_ms;
 
-  // TODO(bugs.webrtc.org/11489): We grab the playout_delay_lock_ lock
-  // potentially twice. Consider checking both min/max and posting to worker if
-  // there's a change. If we always update playout delays on the worker, we
-  // don't need a lock.
   const PlayoutDelay& playout_delay = frame->EncodedImage().playout_delay_;
-  if (playout_delay.min_ms >= 0) {
-    rtc::CritScope cs(&playout_delay_lock_);
-    frame_minimum_playout_delay_ms_ = playout_delay.min_ms;
-    UpdatePlayoutDelays();
-  }
-
-  if (playout_delay.max_ms >= 0) {
-    rtc::CritScope cs(&playout_delay_lock_);
-    frame_maximum_playout_delay_ms_ = playout_delay.max_ms;
-    UpdatePlayoutDelays();
+  if (playout_delay.min_ms >= 0 || playout_delay.max_ms >= 0) {
+    worker_thread_->PostTask(ToQueuedTask(
+        task_safety_flag_,
+        [min_ms = playout_delay.min_ms, max_ms = playout_delay.max_ms, this]() {
+          RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
+          if (min_ms >= 0)
+            frame_minimum_playout_delay_ms_ = min_ms;
+          if (max_ms >= 0)
+            frame_maximum_playout_delay_ms_ = max_ms;
+          UpdatePlayoutDelays();
+        }));
   }
 
   int64_t last_continuous_pid = frame_buffer_->InsertFrame(std::move(frame));
@@ -607,9 +601,21 @@
 }
 
 void VideoReceiveStream2::SetMinimumPlayoutDelay(int delay_ms) {
-  RTC_DCHECK_RUN_ON(&module_process_sequence_checker_);
-  // TODO(bugs.webrtc.org/11489): Consider posting to worker.
-  rtc::CritScope cs(&playout_delay_lock_);
+  // TODO(bugs.webrtc.org/11489): Currently called back on the module process
+  // thread because of RtpStreamsSynchronizer or |rtp_stream_sync_|. Once we
+  // change RtpStreamsSynchronizer to be single threaded, this call should
+  // always occur on the worker thread. Use of |rtp_stream_sync_| should all
+  // move to the worker thread, which will remove a lot of locks and take
+  // blocking work off of the decoder thread.
+  if (!worker_thread_->IsCurrent()) {
+    RTC_DCHECK_RUN_ON(&module_process_sequence_checker_);
+    worker_thread_->PostTask(
+        ToQueuedTask(task_safety_flag_,
+                     [delay_ms, this]() { SetMinimumPlayoutDelay(delay_ms); }));
+    return;
+  }
+
+  RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
   syncable_minimum_playout_delay_ms_ = delay_ms;
   UpdatePlayoutDelays();
 }
@@ -731,6 +737,7 @@
 }
 
 void VideoReceiveStream2::UpdatePlayoutDelays() const {
+  RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
   const int minimum_delay_ms =
       std::max({frame_minimum_playout_delay_ms_, base_minimum_playout_delay_ms_,
                 syncable_minimum_playout_delay_ms_});
diff --git a/video/video_receive_stream2.h b/video/video_receive_stream2.h
index 2a0c07c..22a2469 100644
--- a/video/video_receive_stream2.h
+++ b/video/video_receive_stream2.h
@@ -26,6 +26,7 @@
 #include "modules/video_coding/video_receiver2.h"
 #include "rtc_base/synchronization/sequence_checker.h"
 #include "rtc_base/task_queue.h"
+#include "rtc_base/task_utils/pending_task_safety_flag.h"
 #include "system_wrappers/include/clock.h"
 #include "video/receive_statistics_proxy2.h"
 #include "video/rtp_streams_synchronizer.h"
@@ -134,8 +135,7 @@
   void HandleEncodedFrame(std::unique_ptr<video_coding::EncodedFrame> frame)
       RTC_RUN_ON(decode_queue_);
   void HandleFrameBufferTimeout() RTC_RUN_ON(decode_queue_);
-  void UpdatePlayoutDelays() const
-      RTC_EXCLUSIVE_LOCKS_REQUIRED(playout_delay_lock_);
+  void UpdatePlayoutDelays() const;
   void RequestKeyFrame(int64_t timestamp_ms) RTC_RUN_ON(decode_queue_);
   void HandleKeyFrameGeneration(bool received_frame_is_keyframe, int64_t now_ms)
       RTC_RUN_ON(decode_queue_);
@@ -200,22 +200,23 @@
   const int max_wait_for_keyframe_ms_;
   const int max_wait_for_frame_ms_;
 
-  rtc::CriticalSection playout_delay_lock_;
-
   // All of them tries to change current min_playout_delay on |timing_| but
   // source of the change request is different in each case. Among them the
   // biggest delay is used. -1 means use default value from the |timing_|.
   //
   // Minimum delay as decided by the RTP playout delay extension.
-  int frame_minimum_playout_delay_ms_ RTC_GUARDED_BY(playout_delay_lock_) = -1;
-  // Minimum delay as decided by the setLatency function in "webrtc/api".
-  int base_minimum_playout_delay_ms_ RTC_GUARDED_BY(playout_delay_lock_) = -1;
-  // Minimum delay as decided by the A/V synchronization feature.
-  int syncable_minimum_playout_delay_ms_ RTC_GUARDED_BY(playout_delay_lock_) =
+  int frame_minimum_playout_delay_ms_ RTC_GUARDED_BY(worker_sequence_checker_) =
       -1;
+  // Minimum delay as decided by the setLatency function in "webrtc/api".
+  int base_minimum_playout_delay_ms_ RTC_GUARDED_BY(worker_sequence_checker_) =
+      -1;
+  // Minimum delay as decided by the A/V synchronization feature.
+  int syncable_minimum_playout_delay_ms_
+      RTC_GUARDED_BY(worker_sequence_checker_) = -1;
 
   // Maximum delay as decided by the RTP playout delay extension.
-  int frame_maximum_playout_delay_ms_ RTC_GUARDED_BY(playout_delay_lock_) = -1;
+  int frame_maximum_playout_delay_ms_ RTC_GUARDED_BY(worker_sequence_checker_) =
+      -1;
 
   // Function that is triggered with encoded frames, if not empty.
   std::function<void(const RecordableEncodedFrame&)>
@@ -225,6 +226,10 @@
 
   // Defined last so they are destroyed before all other members.
   rtc::TaskQueue decode_queue_;
+
+  // Used to signal destruction to potentially pending tasks.
+  PendingTaskSafetyFlag::Pointer task_safety_flag_ =
+      PendingTaskSafetyFlag::Create();
 };
 }  // namespace internal
 }  // namespace webrtc