Stop decoders in VideoReceiveStream destructor.

Prevents use-after-free from decoder threads since the VCM outlives
ViEChannel.

BUG=webrtc:5494
R=danilchap@webrtc.org

Review URL: https://codereview.webrtc.org/1699893002 .

Cr-Commit-Position: refs/heads/master@{#11628}
diff --git a/webrtc/video/video_receive_stream.cc b/webrtc/video/video_receive_stream.cc
index 9046cc6..4546ab7 100644
--- a/webrtc/video/video_receive_stream.cc
+++ b/webrtc/video/video_receive_stream.cc
@@ -278,8 +278,7 @@
 
   RTC_DCHECK(!config_.decoders.empty());
   std::set<int> decoder_payload_types;
-  for (size_t i = 0; i < config_.decoders.size(); ++i) {
-    const Decoder& decoder = config_.decoders[i];
+  for (const Decoder& decoder : config_.decoders) {
     RTC_CHECK(decoder.decoder);
     RTC_CHECK(decoder_payload_types.find(decoder.payload_type) ==
               decoder_payload_types.end())
@@ -310,6 +309,14 @@
   Stop();
 
   process_thread_->DeRegisterModule(vcm_.get());
+
+  // Deregister external decoders so that they are no longer running during
+  // destruction. This effectively stops the VCM since the decoder thread is
+  // stopped, the VCM is deregistered and no asynchronous decoder threads are
+  // running.
+  for (const Decoder& decoder : config_.decoders)
+    vcm_->RegisterExternalDecoder(nullptr, decoder.payload_type);
+
   vie_channel_.RegisterPreRenderCallback(nullptr);
   vcm_->RegisterPreDecodeImageCallback(nullptr);