diff --git a/webrtc/api/peerconnectionfactory.cc b/webrtc/api/peerconnectionfactory.cc index e76701e486..9da6e57f94 100644 --- a/webrtc/api/peerconnectionfactory.cc +++ b/webrtc/api/peerconnectionfactory.cc @@ -57,27 +57,9 @@ rtc::scoped_refptr CreatePeerConnectionFactory( AudioDeviceModule* default_adm, cricket::WebRtcVideoEncoderFactory* encoder_factory, cricket::WebRtcVideoDecoderFactory* decoder_factory) { - rtc::scoped_refptr pc_factory( - new rtc::RefCountedObject( - network_thread, - worker_thread, - signaling_thread, - default_adm, - CreateBuiltinAudioDecoderFactory(), - encoder_factory, - decoder_factory)); - - // Call Initialize synchronously but make sure its executed on - // |signaling_thread|. - MethodCall0 call( - pc_factory.get(), - &PeerConnectionFactory::Initialize); - bool result = call.Marshal(RTC_FROM_HERE, signaling_thread); - - if (!result) { - return nullptr; - } - return PeerConnectionFactoryProxy::Create(signaling_thread, pc_factory); + return CreatePeerConnectionFactoryWithAudioMixer( + network_thread, worker_thread, signaling_thread, default_adm, + encoder_factory, decoder_factory, nullptr); } PeerConnectionFactory::PeerConnectionFactory() @@ -95,6 +77,33 @@ PeerConnectionFactory::PeerConnectionFactory() worker_thread_->Start(); } +rtc::scoped_refptr +CreatePeerConnectionFactoryWithAudioMixer( + rtc::Thread* network_thread, + rtc::Thread* worker_thread, + rtc::Thread* signaling_thread, + AudioDeviceModule* default_adm, + cricket::WebRtcVideoEncoderFactory* encoder_factory, + cricket::WebRtcVideoDecoderFactory* decoder_factory, + rtc::scoped_refptr audio_mixer) { + rtc::scoped_refptr pc_factory( + new rtc::RefCountedObject( + network_thread, worker_thread, signaling_thread, default_adm, + CreateBuiltinAudioDecoderFactory(), encoder_factory, decoder_factory, + audio_mixer)); + + // Call Initialize synchronously but make sure it is executed on + // |signaling_thread|. + MethodCall0 call( + pc_factory.get(), &PeerConnectionFactory::Initialize); + bool result = call.Marshal(RTC_FROM_HERE, signaling_thread); + + if (!result) { + return nullptr; + } + return PeerConnectionFactoryProxy::Create(signaling_thread, pc_factory); +} + PeerConnectionFactory::PeerConnectionFactory( rtc::Thread* network_thread, rtc::Thread* worker_thread, @@ -103,7 +112,8 @@ PeerConnectionFactory::PeerConnectionFactory( const rtc::scoped_refptr& audio_decoder_factory, cricket::WebRtcVideoEncoderFactory* video_encoder_factory, - cricket::WebRtcVideoDecoderFactory* video_decoder_factory) + cricket::WebRtcVideoDecoderFactory* video_decoder_factory, + rtc::scoped_refptr audio_mixer) : owns_ptrs_(false), wraps_current_thread_(false), network_thread_(network_thread), @@ -112,7 +122,8 @@ PeerConnectionFactory::PeerConnectionFactory( default_adm_(default_adm), audio_decoder_factory_(audio_decoder_factory), video_encoder_factory_(video_encoder_factory), - video_decoder_factory_(video_decoder_factory) { + video_decoder_factory_(video_decoder_factory), + external_audio_mixer_(audio_mixer) { RTC_DCHECK(network_thread); RTC_DCHECK(worker_thread); RTC_DCHECK(signaling_thread); @@ -336,10 +347,8 @@ rtc::Thread* PeerConnectionFactory::network_thread() { cricket::MediaEngineInterface* PeerConnectionFactory::CreateMediaEngine_w() { ASSERT(worker_thread_ == rtc::Thread::Current()); return cricket::WebRtcMediaEngineFactory::Create( - default_adm_.get(), - audio_decoder_factory_, - video_encoder_factory_.get(), - video_decoder_factory_.get()); + default_adm_.get(), audio_decoder_factory_, video_encoder_factory_.get(), + video_decoder_factory_.get(), external_audio_mixer_); } } // namespace webrtc diff --git a/webrtc/api/peerconnectionfactory.h b/webrtc/api/peerconnectionfactory.h index 7a30ab4569..4b412bacb9 100644 --- a/webrtc/api/peerconnectionfactory.h +++ b/webrtc/api/peerconnectionfactory.h @@ -111,7 +111,8 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface { const rtc::scoped_refptr& audio_decoder_factory, cricket::WebRtcVideoEncoderFactory* video_encoder_factory, - cricket::WebRtcVideoDecoderFactory* video_decoder_factory); + cricket::WebRtcVideoDecoderFactory* video_decoder_factory, + rtc::scoped_refptr audio_mixer); virtual ~PeerConnectionFactory(); private: @@ -135,6 +136,9 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface { std::unique_ptr video_decoder_factory_; std::unique_ptr default_network_manager_; std::unique_ptr default_socket_factory_; + // External audio mixer. This can be NULL. In that case, internal audio mixer + // will be created and used. + rtc::scoped_refptr external_audio_mixer_; }; } // namespace webrtc diff --git a/webrtc/api/peerconnectioninterface.h b/webrtc/api/peerconnectioninterface.h index 29badbd8bb..d4daf2435e 100644 --- a/webrtc/api/peerconnectioninterface.h +++ b/webrtc/api/peerconnectioninterface.h @@ -87,6 +87,7 @@ class WebRtcVideoEncoderFactory; namespace webrtc { class AudioDeviceModule; +class AudioMixer; class MediaConstraintsInterface; // MediaStream container interface. @@ -803,6 +804,20 @@ rtc::scoped_refptr CreatePeerConnectionFactory( cricket::WebRtcVideoEncoderFactory* encoder_factory, cricket::WebRtcVideoDecoderFactory* decoder_factory); +// Create a new instance of PeerConnectionFactoryInterface with external audio +// mixer. +// +// If |audio_mixer| is null, an internal audio mixer will be created and used. +rtc::scoped_refptr +CreatePeerConnectionFactoryWithAudioMixer( + rtc::Thread* network_thread, + rtc::Thread* worker_thread, + rtc::Thread* signaling_thread, + AudioDeviceModule* default_adm, + cricket::WebRtcVideoEncoderFactory* encoder_factory, + cricket::WebRtcVideoDecoderFactory* decoder_factory, + rtc::scoped_refptr audio_mixer); + // Create a new instance of PeerConnectionFactoryInterface. // Same thread is used as worker and network thread. inline rtc::scoped_refptr diff --git a/webrtc/audio/audio_receive_stream.cc b/webrtc/audio/audio_receive_stream.cc index 8da0616f1d..f46337afd1 100644 --- a/webrtc/audio/audio_receive_stream.cc +++ b/webrtc/audio/audio_receive_stream.cc @@ -293,7 +293,7 @@ int AudioReceiveStream::PreferredSampleRate() const { } int AudioReceiveStream::Ssrc() const { - return config_.rtp.local_ssrc; + return config_.rtp.remote_ssrc; } internal::AudioState* AudioReceiveStream::audio_state() const { diff --git a/webrtc/media/base/fakemediaengine.h b/webrtc/media/base/fakemediaengine.h index dc547f8f10..932427b9b4 100644 --- a/webrtc/media/base/fakemediaengine.h +++ b/webrtc/media/base/fakemediaengine.h @@ -753,10 +753,10 @@ class FakeBaseEngine { class FakeVoiceEngine : public FakeBaseEngine { public: - FakeVoiceEngine( - webrtc::AudioDeviceModule* adm, - const rtc::scoped_refptr& - audio_decoder_factory) { + FakeVoiceEngine(webrtc::AudioDeviceModule* adm, + const rtc::scoped_refptr& + audio_decoder_factory, + rtc::scoped_refptr audio_mixer) { // Add a fake audio codec. Note that the name must not be "" as there are // sanity checks against that. codecs_.push_back(AudioCodec(101, "fake_audio_codec", 0, 0, 1)); @@ -864,6 +864,7 @@ class FakeMediaEngine : public: FakeMediaEngine() : CompositeMediaEngine(nullptr, + nullptr, nullptr) {} virtual ~FakeMediaEngine() {} diff --git a/webrtc/media/base/mediaengine.h b/webrtc/media/base/mediaengine.h index 5b7443b6f3..debc171360 100644 --- a/webrtc/media/base/mediaengine.h +++ b/webrtc/media/base/mediaengine.h @@ -33,6 +33,7 @@ namespace webrtc { class AudioDeviceModule; +class AudioMixer; class Call; } @@ -110,11 +111,11 @@ class MediaEngineFactory { template class CompositeMediaEngine : public MediaEngineInterface { public: - CompositeMediaEngine( - webrtc::AudioDeviceModule* adm, - const rtc::scoped_refptr& - audio_decoder_factory) - : voice_(adm, audio_decoder_factory) {} + CompositeMediaEngine(webrtc::AudioDeviceModule* adm, + const rtc::scoped_refptr& + audio_decoder_factory, + rtc::scoped_refptr audio_mixer) + : voice_(adm, audio_decoder_factory, audio_mixer) {} virtual ~CompositeMediaEngine() {} virtual bool Init() { video_.Init(); diff --git a/webrtc/media/engine/nullwebrtcvideoengine_unittest.cc b/webrtc/media/engine/nullwebrtcvideoengine_unittest.cc index c63dbfb010..a8f2421610 100644 --- a/webrtc/media/engine/nullwebrtcvideoengine_unittest.cc +++ b/webrtc/media/engine/nullwebrtcvideoengine_unittest.cc @@ -25,7 +25,9 @@ class WebRtcMediaEngineNullVideo WebRtcVideoEncoderFactory* video_encoder_factory, WebRtcVideoDecoderFactory* video_decoder_factory) : CompositeMediaEngine( - adm, audio_decoder_factory) { + adm, + audio_decoder_factory, + nullptr) { video_.SetExternalDecoderFactory(video_decoder_factory); video_.SetExternalEncoderFactory(video_encoder_factory); } diff --git a/webrtc/media/engine/webrtcmediaengine.cc b/webrtc/media/engine/webrtcmediaengine.cc index 1531be36b5..c76840cf0d 100644 --- a/webrtc/media/engine/webrtcmediaengine.cc +++ b/webrtc/media/engine/webrtcmediaengine.cc @@ -33,13 +33,18 @@ class WebRtcMediaEngine2 const rtc::scoped_refptr& audio_decoder_factory, WebRtcVideoEncoderFactory* video_encoder_factory, - WebRtcVideoDecoderFactory* video_decoder_factory) + WebRtcVideoDecoderFactory* video_decoder_factory, + rtc::scoped_refptr audio_mixer) #ifdef HAVE_WEBRTC_VIDEO : CompositeMediaEngine( - adm, audio_decoder_factory){ + adm, + audio_decoder_factory, + audio_mixer){ #else : CompositeMediaEngine( - adm, audio_decoder_factory) { + adm, + audio_decoder_factory, + audio_mixer) { #endif video_.SetExternalDecoderFactory(video_decoder_factory); video_.SetExternalEncoderFactory(video_encoder_factory); @@ -53,9 +58,11 @@ cricket::MediaEngineInterface* CreateWebRtcMediaEngine( const rtc::scoped_refptr& audio_decoder_factory, cricket::WebRtcVideoEncoderFactory* video_encoder_factory, - cricket::WebRtcVideoDecoderFactory* video_decoder_factory) { - return new cricket::WebRtcMediaEngine2( - adm, audio_decoder_factory, video_encoder_factory, video_decoder_factory); + cricket::WebRtcVideoDecoderFactory* video_decoder_factory, + rtc::scoped_refptr audio_mixer) { + return new cricket::WebRtcMediaEngine2(adm, audio_decoder_factory, + video_encoder_factory, + video_decoder_factory, audio_mixer); } void DestroyWebRtcMediaEngine(cricket::MediaEngineInterface* media_engine) { @@ -71,9 +78,9 @@ MediaEngineInterface* WebRtcMediaEngineFactory::Create( webrtc::AudioDeviceModule* adm, WebRtcVideoEncoderFactory* video_encoder_factory, WebRtcVideoDecoderFactory* video_decoder_factory) { - return CreateWebRtcMediaEngine(adm, - webrtc::CreateBuiltinAudioDecoderFactory(), - video_encoder_factory, video_decoder_factory); + return CreateWebRtcMediaEngine( + adm, webrtc::CreateBuiltinAudioDecoderFactory(), video_encoder_factory, + video_decoder_factory, nullptr); } // Used by PeerConnectionFactory to create a media engine passed into @@ -83,9 +90,11 @@ MediaEngineInterface* WebRtcMediaEngineFactory::Create( const rtc::scoped_refptr& audio_decoder_factory, WebRtcVideoEncoderFactory* video_encoder_factory, - WebRtcVideoDecoderFactory* video_decoder_factory) { + WebRtcVideoDecoderFactory* video_decoder_factory, + rtc::scoped_refptr audio_mixer) { return CreateWebRtcMediaEngine(adm, audio_decoder_factory, - video_encoder_factory, video_decoder_factory); + video_encoder_factory, video_decoder_factory, + audio_mixer); } namespace { diff --git a/webrtc/media/engine/webrtcmediaengine.h b/webrtc/media/engine/webrtcmediaengine.h index 49b050c593..3cca48f39c 100644 --- a/webrtc/media/engine/webrtcmediaengine.h +++ b/webrtc/media/engine/webrtcmediaengine.h @@ -21,6 +21,7 @@ namespace webrtc { class AudioDecoderFactory; class AudioDeviceModule; +class AudioMixer; } namespace cricket { class WebRtcVideoDecoderFactory; @@ -44,7 +45,8 @@ class WebRtcMediaEngineFactory { const rtc::scoped_refptr& audio_decoder_factory, WebRtcVideoEncoderFactory* video_encoder_factory, - WebRtcVideoDecoderFactory* video_decoder_factory); + WebRtcVideoDecoderFactory* video_decoder_factory, + rtc::scoped_refptr audio_mixer); }; // Verify that extension IDs are within 1-byte extension range and are not diff --git a/webrtc/media/engine/webrtcmediaengine_unittest.cc b/webrtc/media/engine/webrtcmediaengine_unittest.cc index 03e50a18c9..77fbc87beb 100644 --- a/webrtc/media/engine/webrtcmediaengine_unittest.cc +++ b/webrtc/media/engine/webrtcmediaengine_unittest.cc @@ -188,7 +188,8 @@ TEST(WebRtcMediaEngineFactoryTest, CreateOldApi) { TEST(WebRtcMediaEngineFactoryTest, CreateWithBuiltinDecoders) { std::unique_ptr engine(WebRtcMediaEngineFactory::Create( - nullptr, webrtc::CreateBuiltinAudioDecoderFactory(), nullptr, nullptr)); + nullptr, webrtc::CreateBuiltinAudioDecoderFactory(), nullptr, nullptr, + nullptr)); EXPECT_TRUE(engine); } diff --git a/webrtc/media/engine/webrtcvoiceengine.cc b/webrtc/media/engine/webrtcvoiceengine.cc index 2a0583c909..a36f328705 100644 --- a/webrtc/media/engine/webrtcvoiceengine.cc +++ b/webrtc/media/engine/webrtcvoiceengine.cc @@ -277,10 +277,16 @@ void GetOpusConfig(const AudioCodec& codec, voe_codec->rate = GetOpusBitrate(codec, *max_playback_rate); } -webrtc::AudioState::Config MakeAudioStateConfig(VoEWrapper* voe_wrapper) { +webrtc::AudioState::Config MakeAudioStateConfig( + VoEWrapper* voe_wrapper, + rtc::scoped_refptr audio_mixer) { webrtc::AudioState::Config config; config.voice_engine = voe_wrapper->engine(); - config.audio_mixer = webrtc::AudioMixerImpl::Create(); + if (audio_mixer) { + config.audio_mixer = audio_mixer; + } else { + config.audio_mixer = webrtc::AudioMixerImpl::Create(); + } return config; } @@ -540,14 +546,17 @@ bool WebRtcVoiceEngine::ToCodecInst(const AudioCodec& in, WebRtcVoiceEngine::WebRtcVoiceEngine( webrtc::AudioDeviceModule* adm, - const rtc::scoped_refptr& decoder_factory) - : WebRtcVoiceEngine(adm, decoder_factory, new VoEWrapper()) { - audio_state_ = webrtc::AudioState::Create(MakeAudioStateConfig(voe())); + const rtc::scoped_refptr& decoder_factory, + rtc::scoped_refptr audio_mixer) + : WebRtcVoiceEngine(adm, decoder_factory, audio_mixer, new VoEWrapper()) { + audio_state_ = + webrtc::AudioState::Create(MakeAudioStateConfig(voe(), audio_mixer)); } WebRtcVoiceEngine::WebRtcVoiceEngine( webrtc::AudioDeviceModule* adm, const rtc::scoped_refptr& decoder_factory, + rtc::scoped_refptr audio_mixer, VoEWrapper* voe_wrapper) : adm_(adm), decoder_factory_(decoder_factory), voe_wrapper_(voe_wrapper) { RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); diff --git a/webrtc/media/engine/webrtcvoiceengine.h b/webrtc/media/engine/webrtcvoiceengine.h index 633e7d3e95..224fcb20b6 100644 --- a/webrtc/media/engine/webrtcvoiceengine.h +++ b/webrtc/media/engine/webrtcvoiceengine.h @@ -34,6 +34,7 @@ namespace cricket { class AudioDeviceModule; +class AudioMixer; class AudioSource; class VoEWrapper; class WebRtcVoiceMediaChannel; @@ -48,11 +49,13 @@ class WebRtcVoiceEngine final : public webrtc::TraceCallback { WebRtcVoiceEngine( webrtc::AudioDeviceModule* adm, - const rtc::scoped_refptr& decoder_factory); + const rtc::scoped_refptr& decoder_factory, + rtc::scoped_refptr audio_mixer); // Dependency injection for testing. WebRtcVoiceEngine( webrtc::AudioDeviceModule* adm, const rtc::scoped_refptr& decoder_factory, + rtc::scoped_refptr audio_mixer, VoEWrapper* voe_wrapper); ~WebRtcVoiceEngine() override; diff --git a/webrtc/media/engine/webrtcvoiceengine_unittest.cc b/webrtc/media/engine/webrtcvoiceengine_unittest.cc index bddefdd145..3ca7ec8b05 100644 --- a/webrtc/media/engine/webrtcvoiceengine_unittest.cc +++ b/webrtc/media/engine/webrtcvoiceengine_unittest.cc @@ -84,7 +84,7 @@ TEST(WebRtcVoiceEngineTestStubLibrary, StartupShutdown) { EXPECT_FALSE(voe.IsInited()); { cricket::WebRtcVoiceEngine engine( - &adm, webrtc::MockAudioDecoderFactory::CreateUnusedFactory(), + &adm, webrtc::MockAudioDecoderFactory::CreateUnusedFactory(), nullptr, new FakeVoEWrapper(&voe)); EXPECT_TRUE(voe.IsInited()); } @@ -116,7 +116,7 @@ class WebRtcVoiceEngineTestFake : public testing::Test { EXPECT_CALL(apm_, ApplyConfig(testing::_)); EXPECT_CALL(apm_, SetExtraOptions(testing::_)); EXPECT_CALL(apm_, Initialize()).WillOnce(Return(0)); - engine_.reset(new cricket::WebRtcVoiceEngine(&adm_, factory, + engine_.reset(new cricket::WebRtcVoiceEngine(&adm_, factory, nullptr, new FakeVoEWrapper(&voe_))); send_parameters_.codecs.push_back(kPcmuCodec); recv_parameters_.codecs.push_back(kPcmuCodec); @@ -3466,7 +3466,7 @@ TEST(WebRtcVoiceEngineTest, StartupShutdown) { // If the VoiceEngine wants to gather available codecs early, that's fine but // we never want it to create a decoder at this stage. cricket::WebRtcVoiceEngine engine( - nullptr, webrtc::MockAudioDecoderFactory::CreateUnusedFactory()); + nullptr, webrtc::MockAudioDecoderFactory::CreateUnusedFactory(), nullptr); webrtc::RtcEventLogNullImpl event_log; std::unique_ptr call( webrtc::Call::Create(webrtc::Call::Config(&event_log))); @@ -3483,7 +3483,7 @@ TEST(WebRtcVoiceEngineTest, StartupShutdownWithExternalADM) { EXPECT_CALL(adm, Release()).Times(3).WillRepeatedly(Return(0)); { cricket::WebRtcVoiceEngine engine( - &adm, webrtc::MockAudioDecoderFactory::CreateUnusedFactory()); + &adm, webrtc::MockAudioDecoderFactory::CreateUnusedFactory(), nullptr); webrtc::RtcEventLogNullImpl event_log; std::unique_ptr call( webrtc::Call::Create(webrtc::Call::Config(&event_log))); @@ -3551,7 +3551,7 @@ TEST(WebRtcVoiceEngineTest, HasCorrectCodecs) { // TODO(ossu): Why are the payload types of codecs with non-static payload // type assignments checked here? It shouldn't really matter. cricket::WebRtcVoiceEngine engine( - nullptr, webrtc::MockAudioDecoderFactory::CreateUnusedFactory()); + nullptr, webrtc::MockAudioDecoderFactory::CreateUnusedFactory(), nullptr); for (const cricket::AudioCodec& codec : engine.send_codecs()) { if (codec.name == "CN" && codec.clockrate == 16000) { EXPECT_EQ(105, codec.id); @@ -3587,7 +3587,7 @@ TEST(WebRtcVoiceEngineTest, HasCorrectCodecs) { // Tests that VoE supports at least 32 channels TEST(WebRtcVoiceEngineTest, Has32Channels) { cricket::WebRtcVoiceEngine engine( - nullptr, webrtc::MockAudioDecoderFactory::CreateUnusedFactory()); + nullptr, webrtc::MockAudioDecoderFactory::CreateUnusedFactory(), nullptr); webrtc::RtcEventLogNullImpl event_log; std::unique_ptr call( webrtc::Call::Create(webrtc::Call::Config(&event_log))); @@ -3620,7 +3620,7 @@ TEST(WebRtcVoiceEngineTest, SetRecvCodecs) { // SetRecvParameters returns true. // I think it will become clear once audio decoder injection is completed. cricket::WebRtcVoiceEngine engine( - nullptr, webrtc::CreateBuiltinAudioDecoderFactory()); + nullptr, webrtc::CreateBuiltinAudioDecoderFactory(), nullptr); webrtc::RtcEventLogNullImpl event_log; std::unique_ptr call( webrtc::Call::Create(webrtc::Call::Config(&event_log)));