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_;