Allow WebRtcMediaEngine to be created from any thread.

This eliminates a thread hop in PeerConnectionFactory initialization,
and will allow some code to be simplified.

BUG=None

Review-Url: https://codereview.webrtc.org/2934103002
Cr-Commit-Position: refs/heads/master@{#18613}
diff --git a/webrtc/media/base/fakemediaengine.h b/webrtc/media/base/fakemediaengine.h
index 4984d1b..12cd4cb 100644
--- a/webrtc/media/base/fakemediaengine.h
+++ b/webrtc/media/base/fakemediaengine.h
@@ -775,6 +775,7 @@
     // sanity checks against that.
     codecs_.push_back(AudioCodec(101, "fake_audio_codec", 0, 0, 1));
   }
+  void Init() {}
   rtc::scoped_refptr<webrtc::AudioState> GetAudioState() const {
     return rtc::scoped_refptr<webrtc::AudioState>();
   }
diff --git a/webrtc/media/base/mediaengine.h b/webrtc/media/base/mediaengine.h
index 2b9e790..ca704ce 100644
--- a/webrtc/media/base/mediaengine.h
+++ b/webrtc/media/base/mediaengine.h
@@ -122,6 +122,7 @@
   }
   virtual ~CompositeMediaEngine() {}
   virtual bool Init() {
+    voice_.Init();
     video_.Init();
     return true;
   }
diff --git a/webrtc/media/engine/webrtcmediaengine.h b/webrtc/media/engine/webrtcmediaengine.h
index 1fc988d..db955d0 100644
--- a/webrtc/media/engine/webrtcmediaengine.h
+++ b/webrtc/media/engine/webrtcmediaengine.h
@@ -32,6 +32,10 @@
 
 class WebRtcMediaEngineFactory {
  public:
+  // These Create methods may be called on any thread, though the engine is
+  // only expected to be used on one thread, internally called the "worker
+  // thread". This is the thread Init must be called on.
+
   // TODO(ossu): Backwards-compatible interface. Will be deprecated once the
   // audio decoder factory is fully plumbed and used throughout WebRTC.
   // See: crbug.com/webrtc/6000
diff --git a/webrtc/media/engine/webrtcvoiceengine.cc b/webrtc/media/engine/webrtcvoiceengine.cc
index 0fef4fd..b39be5b 100644
--- a/webrtc/media/engine/webrtcvoiceengine.cc
+++ b/webrtc/media/engine/webrtcvoiceengine.cc
@@ -219,10 +219,7 @@
                         encoder_factory,
                         decoder_factory,
                         audio_mixer,
-                        new VoEWrapper()) {
-  audio_state_ =
-      webrtc::AudioState::Create(MakeAudioStateConfig(voe(), audio_mixer));
-}
+                        nullptr) {}
 
 WebRtcVoiceEngine::WebRtcVoiceEngine(
     webrtc::AudioDeviceModule* adm,
@@ -230,17 +227,43 @@
     const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
     rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer,
     VoEWrapper* voe_wrapper)
-    : low_priority_worker_queue_("rtc-low-prio", rtc::TaskQueue::Priority::LOW),
-      adm_(adm),
+    : adm_(adm),
       encoder_factory_(encoder_factory),
       decoder_factory_(decoder_factory),
+      audio_mixer_(audio_mixer),
       voe_wrapper_(voe_wrapper) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  LOG(LS_INFO) << "WebRtcVoiceEngine::WebRtcVoiceEngine";
-  RTC_DCHECK(voe_wrapper);
-  RTC_DCHECK(decoder_factory);
-
+  // This may be called from any thread, so detach thread checkers.
+  worker_thread_checker_.DetachFromThread();
   signal_thread_checker_.DetachFromThread();
+  LOG(LS_INFO) << "WebRtcVoiceEngine::WebRtcVoiceEngine";
+  RTC_DCHECK(decoder_factory);
+  RTC_DCHECK(encoder_factory);
+  // The rest of our initialization will happen in Init.
+}
+
+WebRtcVoiceEngine::~WebRtcVoiceEngine() {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  LOG(LS_INFO) << "WebRtcVoiceEngine::~WebRtcVoiceEngine";
+  if (initialized_) {
+    StopAecDump();
+    voe_wrapper_->base()->Terminate();
+    webrtc::Trace::SetTraceCallback(nullptr);
+  }
+}
+
+void WebRtcVoiceEngine::Init() {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  LOG(LS_INFO) << "WebRtcVoiceEngine::Init";
+
+  // TaskQueue expects to be created/destroyed on the same thread.
+  low_priority_worker_queue_.reset(
+      new rtc::TaskQueue("rtc-low-prio", rtc::TaskQueue::Priority::LOW));
+
+  // VoEWrapper needs to be created on the worker thread. It's expected to be
+  // null here unless it's being injected for testing.
+  if (!voe_wrapper_) {
+    voe_wrapper_.reset(new VoEWrapper());
+  }
 
   // Load our audio codec lists.
   LOG(LS_INFO) << "Supported send codecs in order of preference:";
@@ -310,14 +333,14 @@
   apm()->Initialize();
   webrtc::adm_helpers::SetPlayoutDevice(adm_);
 #endif  // !WEBRTC_IOS
-}
 
-WebRtcVoiceEngine::~WebRtcVoiceEngine() {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  LOG(LS_INFO) << "WebRtcVoiceEngine::~WebRtcVoiceEngine";
-  StopAecDump();
-  voe_wrapper_->base()->Terminate();
-  webrtc::Trace::SetTraceCallback(nullptr);
+  // May be null for VoE injected for testing.
+  if (voe()->engine()) {
+    audio_state_ =
+        webrtc::AudioState::Create(MakeAudioStateConfig(voe(), audio_mixer_));
+  }
+
+  initialized_ = true;
 }
 
 rtc::scoped_refptr<webrtc::AudioState>
@@ -690,8 +713,8 @@
 bool WebRtcVoiceEngine::StartAecDump(rtc::PlatformFile file,
                                      int64_t max_size_bytes) {
   RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  auto aec_dump = webrtc::AecDumpFactory::Create(file, max_size_bytes,
-                                                 &low_priority_worker_queue_);
+  auto aec_dump = webrtc::AecDumpFactory::Create(
+      file, max_size_bytes, low_priority_worker_queue_.get());
   if (!aec_dump) {
     return false;
   }
@@ -702,8 +725,8 @@
 void WebRtcVoiceEngine::StartAecDump(const std::string& filename) {
   RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
 
-  auto aec_dump =
-      webrtc::AecDumpFactory::Create(filename, -1, &low_priority_worker_queue_);
+  auto aec_dump = webrtc::AecDumpFactory::Create(
+      filename, -1, low_priority_worker_queue_.get());
   if (aec_dump) {
     apm()->AttachAecDump(std::move(aec_dump));
   }
diff --git a/webrtc/media/engine/webrtcvoiceengine.h b/webrtc/media/engine/webrtcvoiceengine.h
index bbfec88..3aba581 100644
--- a/webrtc/media/engine/webrtcvoiceengine.h
+++ b/webrtc/media/engine/webrtcvoiceengine.h
@@ -67,6 +67,9 @@
       VoEWrapper* voe_wrapper);
   ~WebRtcVoiceEngine() override;
 
+  // Does initialization that needs to occur on the worker thread.
+  void Init();
+
   rtc::scoped_refptr<webrtc::AudioState> GetAudioState() const;
   VoiceMediaChannel* CreateChannel(webrtc::Call* call,
                                    const MediaConfig& config,
@@ -112,7 +115,7 @@
   void StartAecDump(const std::string& filename);
   int CreateVoEChannel();
 
-  rtc::TaskQueue low_priority_worker_queue_;
+  std::unique_ptr<rtc::TaskQueue> low_priority_worker_queue_;
 
   webrtc::AudioDeviceModule* adm();
   webrtc::AudioProcessing* apm();
@@ -128,6 +131,7 @@
   rtc::scoped_refptr<webrtc::AudioDeviceModule> adm_;
   rtc::scoped_refptr<webrtc::AudioEncoderFactory> encoder_factory_;
   rtc::scoped_refptr<webrtc::AudioDecoderFactory> decoder_factory_;
+  rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer_;
   // Reference to the APM, owned by VoE.
   webrtc::AudioProcessing* apm_ = nullptr;
   // Reference to the TransmitMixer, owned by VoE.
@@ -140,6 +144,7 @@
   std::vector<WebRtcVoiceMediaChannel*> channels_;
   webrtc::VoEBase::ChannelConfig channel_config_;
   bool is_dumping_aec_ = false;
+  bool initialized_ = false;
 
   webrtc::AgcConfig default_agc_config_;
   // Cache received extended_filter_aec, delay_agnostic_aec, experimental_ns
diff --git a/webrtc/media/engine/webrtcvoiceengine_unittest.cc b/webrtc/media/engine/webrtcvoiceengine_unittest.cc
index f96bf71..dbee6d3 100644
--- a/webrtc/media/engine/webrtcvoiceengine_unittest.cc
+++ b/webrtc/media/engine/webrtcvoiceengine_unittest.cc
@@ -135,6 +135,7 @@
         &adm, webrtc::MockAudioEncoderFactory::CreateUnusedFactory(),
         webrtc::MockAudioDecoderFactory::CreateUnusedFactory(), nullptr,
         new FakeVoEWrapper(&voe));
+    engine.Init();
     EXPECT_TRUE(voe.IsInited());
   }
   EXPECT_FALSE(voe.IsInited());
@@ -187,6 +188,7 @@
     engine_.reset(new cricket::WebRtcVoiceEngine(&adm_, encoder_factory,
                                                  decoder_factory, nullptr,
                                                  new FakeVoEWrapper(&voe_)));
+    engine_->Init();
     send_parameters_.codecs.push_back(kPcmuCodec);
     recv_parameters_.codecs.push_back(kPcmuCodec);
     // Default Options.
@@ -3263,6 +3265,7 @@
   cricket::WebRtcVoiceEngine engine(
       nullptr, webrtc::MockAudioEncoderFactory::CreateUnusedFactory(),
       webrtc::MockAudioDecoderFactory::CreateUnusedFactory(), nullptr);
+  engine.Init();
   webrtc::RtcEventLogNullImpl event_log;
   std::unique_ptr<webrtc::Call> call(
       webrtc::Call::Create(webrtc::Call::Config(&event_log)));
@@ -3284,6 +3287,7 @@
     cricket::WebRtcVoiceEngine engine(
         &adm, webrtc::MockAudioEncoderFactory::CreateUnusedFactory(),
         webrtc::MockAudioDecoderFactory::CreateUnusedFactory(), nullptr);
+    engine.Init();
     webrtc::RtcEventLogNullImpl event_log;
     std::unique_ptr<webrtc::Call> call(
         webrtc::Call::Create(webrtc::Call::Config(&event_log)));
@@ -3301,6 +3305,7 @@
   cricket::WebRtcVoiceEngine engine(
       nullptr, webrtc::MockAudioEncoderFactory::CreateUnusedFactory(),
       webrtc::MockAudioDecoderFactory::CreateUnusedFactory(), nullptr);
+  engine.Init();
   for (const cricket::AudioCodec& codec : engine.send_codecs()) {
     auto is_codec = [&codec](const char* name, int clockrate = 0) {
       return STR_CASE_CMP(codec.name.c_str(), name) == 0 &&
@@ -3342,6 +3347,7 @@
   cricket::WebRtcVoiceEngine engine(
       nullptr, webrtc::MockAudioEncoderFactory::CreateUnusedFactory(),
       webrtc::MockAudioDecoderFactory::CreateUnusedFactory(), nullptr);
+  engine.Init();
   webrtc::RtcEventLogNullImpl event_log;
   std::unique_ptr<webrtc::Call> call(
       webrtc::Call::Create(webrtc::Call::Config(&event_log)));
@@ -3376,6 +3382,7 @@
   cricket::WebRtcVoiceEngine engine(
       nullptr, webrtc::MockAudioEncoderFactory::CreateUnusedFactory(),
       webrtc::CreateBuiltinAudioDecoderFactory(), nullptr);
+  engine.Init();
   webrtc::RtcEventLogNullImpl event_log;
   std::unique_ptr<webrtc::Call> call(
       webrtc::Call::Create(webrtc::Call::Config(&event_log)));
@@ -3413,6 +3420,7 @@
 
   cricket::WebRtcVoiceEngine engine(nullptr, unused_encoder_factory,
                                     mock_decoder_factory, nullptr);
+  engine.Init();
   auto codecs = engine.recv_codecs();
   EXPECT_EQ(11, codecs.size());
 
diff --git a/webrtc/pc/peerconnectionfactory.cc b/webrtc/pc/peerconnectionfactory.cc
index 77e6f2c..ff1e31d 100644
--- a/webrtc/pc/peerconnectionfactory.cc
+++ b/webrtc/pc/peerconnectionfactory.cc
@@ -210,10 +210,11 @@
     return false;
   }
 
-  std::unique_ptr<cricket::MediaEngineInterface> media_engine =
-      worker_thread_->Invoke<std::unique_ptr<cricket::MediaEngineInterface>>(
-          RTC_FROM_HERE,
-          rtc::Bind(&PeerConnectionFactory::CreateMediaEngine_w, this));
+  std::unique_ptr<cricket::MediaEngineInterface> media_engine(
+      cricket::WebRtcMediaEngineFactory::Create(
+          default_adm_.get(), audio_encoder_factory_, audio_decoder_factory_,
+          video_encoder_factory_.get(), video_decoder_factory_.get(),
+          external_audio_mixer_));
 
   channel_manager_.reset(new cricket::ChannelManager(
       std::move(media_engine), worker_thread_, network_thread_));
@@ -381,15 +382,4 @@
   return network_thread_;
 }
 
-std::unique_ptr<cricket::MediaEngineInterface>
-PeerConnectionFactory::CreateMediaEngine_w() {
-  RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
-  return std::unique_ptr<cricket::MediaEngineInterface>(
-      cricket::WebRtcMediaEngineFactory::Create(
-          default_adm_.get(), audio_encoder_factory_,
-          audio_decoder_factory_,
-          video_encoder_factory_.get(), video_decoder_factory_.get(),
-          external_audio_mixer_));
-}
-
 }  // namespace webrtc
diff --git a/webrtc/pc/peerconnectionfactory.h b/webrtc/pc/peerconnectionfactory.h
index 0bf05bd..58d3e7f 100644
--- a/webrtc/pc/peerconnectionfactory.h
+++ b/webrtc/pc/peerconnectionfactory.h
@@ -121,8 +121,6 @@
   virtual ~PeerConnectionFactory();
 
  private:
-  std::unique_ptr<cricket::MediaEngineInterface> CreateMediaEngine_w();
-
   bool owns_ptrs_;
   bool wraps_current_thread_;
   rtc::Thread* network_thread_;