Signal threads for faster receiver destruction.

Unblocks pending threads (render thread + decoder thread) when
destroying renderers and shutting down decoders.

Speeds up SetLocalDescription significantly (10x or so) under
WebRtcVideoEngine2 but also shutdown times in ~ViEChannel and
~ViEReceiver in general.

BUG=1788
R=mflodman@webrtc.org, stefan@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/41959004

Cr-Commit-Position: refs/heads/master@{#8387}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8387 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/video_coding/main/interface/video_coding.h b/webrtc/modules/video_coding/main/interface/video_coding.h
index f1ce2ec..02b36b1 100644
--- a/webrtc/modules/video_coding/main/interface/video_coding.h
+++ b/webrtc/modules/video_coding/main/interface/video_coding.h
@@ -582,6 +582,8 @@
         EncodedImageCallback* observer) = 0;
     virtual void RegisterPostEncodeImageCallback(
         EncodedImageCallback* post_encode_callback) = 0;
+    // Releases pending decode calls, permitting faster thread shutdown.
+    virtual void TriggerDecoderShutdown() = 0;
 };
 
 }  // namespace webrtc
diff --git a/webrtc/modules/video_coding/main/source/receiver.cc b/webrtc/modules/video_coding/main/source/receiver.cc
index dad2b6f..6ab9e29 100644
--- a/webrtc/modules/video_coding/main/source/receiver.cc
+++ b/webrtc/modules/video_coding/main/source/receiver.cc
@@ -54,7 +54,6 @@
 
 int32_t VCMReceiver::Initialize() {
   Reset();
-  CriticalSectionScoped cs(crit_sect_);
   return VCM_OK;
 }
 
@@ -86,6 +85,11 @@
   return VCM_OK;
 }
 
+void VCMReceiver::TriggerDecoderShutdown() {
+  jitter_buffer_.Stop();
+  render_wait_event_->Set();
+}
+
 VCMEncodedFrame* VCMReceiver::FrameForDecoding(uint16_t max_wait_time_ms,
                                                int64_t& next_render_time_ms,
                                                bool render_timing) {
diff --git a/webrtc/modules/video_coding/main/source/receiver.h b/webrtc/modules/video_coding/main/source/receiver.h
index f531ac8..0e1f01a 100644
--- a/webrtc/modules/video_coding/main/source/receiver.h
+++ b/webrtc/modules/video_coding/main/source/receiver.h
@@ -81,11 +81,13 @@
 
   void RegisterStatsCallback(VCMReceiveStatisticsCallback* callback);
 
+  void TriggerDecoderShutdown();
+
  private:
   static int32_t GenerateReceiverId();
 
   CriticalSectionWrapper* crit_sect_;
-  Clock* clock_;
+  Clock* const clock_;
   VCMJitterBuffer jitter_buffer_;
   VCMTiming* timing_;
   scoped_ptr<EventWrapper> render_wait_event_;
diff --git a/webrtc/modules/video_coding/main/source/video_coding_impl.cc b/webrtc/modules/video_coding/main/source/video_coding_impl.cc
index 7289e2f..a90ab07 100644
--- a/webrtc/modules/video_coding/main/source/video_coding_impl.cc
+++ b/webrtc/modules/video_coding/main/source/video_coding_impl.cc
@@ -345,6 +345,10 @@
     post_encode_callback_.Register(observer);
   }
 
+  void TriggerDecoderShutdown() override {
+    receiver_->TriggerDecoderShutdown();
+  }
+
  private:
   EncodedImageCallbackWrapper post_encode_callback_;
   scoped_ptr<vcm::VideoSender> sender_;
diff --git a/webrtc/modules/video_coding/main/source/video_coding_impl.h b/webrtc/modules/video_coding/main/source/video_coding_impl.h
index cf4a986..39e763f 100644
--- a/webrtc/modules/video_coding/main/source/video_coding_impl.h
+++ b/webrtc/modules/video_coding/main/source/video_coding_impl.h
@@ -182,6 +182,7 @@
   int32_t Process();
 
   void RegisterPreDecodeImageCallback(EncodedImageCallback* observer);
+  void TriggerDecoderShutdown();
 
  protected:
   int32_t Decode(const webrtc::VCMEncodedFrame& frame)
diff --git a/webrtc/modules/video_coding/main/source/video_receiver.cc b/webrtc/modules/video_coding/main/source/video_receiver.cc
index 46fa399..3e20ed3 100644
--- a/webrtc/modules/video_coding/main/source/video_receiver.cc
+++ b/webrtc/modules/video_coding/main/source/video_receiver.cc
@@ -335,6 +335,10 @@
   return VCM_OK;
 }
 
+void VideoReceiver::TriggerDecoderShutdown() {
+  _receiver.TriggerDecoderShutdown();
+}
+
 // Decode next frame, blocking.
 // Should be called as often as possible to get the most out of the decoder.
 int32_t VideoReceiver::Decode(uint16_t maxWaitTimeMs) {
diff --git a/webrtc/modules/video_render/incoming_video_stream.cc b/webrtc/modules/video_render/incoming_video_stream.cc
index 4a95622..256c21c 100644
--- a/webrtc/modules/video_render/incoming_video_stream.cc
+++ b/webrtc/modules/video_render/incoming_video_stream.cc
@@ -246,14 +246,21 @@
     return 0;
   }
 
-  thread_critsect_.Enter();
-  if (incoming_render_thread_) {
-    ThreadWrapper* thread = incoming_render_thread_;
-    incoming_render_thread_ = NULL;
-#ifndef WIN32_
-    deliver_buffer_event_.StopTimer();
-#endif
-    thread_critsect_.Leave();
+  ThreadWrapper* thread = NULL;
+  {
+    CriticalSectionScoped cs_thread(&thread_critsect_);
+    if (incoming_render_thread_ != NULL) {
+      thread = incoming_render_thread_;
+      // Setting the incoming render thread to NULL marks that we're performing
+      // a shutdown and will make IncomingVideoStreamProcess abort after wakeup.
+      incoming_render_thread_ = NULL;
+      deliver_buffer_event_.StopTimer();
+      // Set the event to allow the thread to wake up and shut down without
+      // waiting for a timeout.
+      deliver_buffer_event_.Set();
+    }
+  }
+  if (thread) {
     if (thread->Stop()) {
       delete thread;
     } else {
@@ -261,8 +268,6 @@
       WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, module_id_,
                    "%s: Not able to stop thread, leaking", __FUNCTION__);
     }
-  } else {
-    thread_critsect_.Leave();
   }
   running_ = false;
   return 0;
diff --git a/webrtc/video_engine/vie_channel.cc b/webrtc/video_engine/vie_channel.cc
index 0278fe3..dcb9596 100644
--- a/webrtc/video_engine/vie_channel.cc
+++ b/webrtc/video_engine/vie_channel.cc
@@ -1733,6 +1733,8 @@
     return 0;
   }
 
+  vcm_->TriggerDecoderShutdown();
+
   if (decode_thread_->Stop()) {
     delete decode_thread_;
   } else {