diff --git a/talk/app/webrtc/peerconnectionfactory.cc b/talk/app/webrtc/peerconnectionfactory.cc index 862ceda96..5e3bf42f0 100644 --- a/talk/app/webrtc/peerconnectionfactory.cc +++ b/talk/app/webrtc/peerconnectionfactory.cc @@ -32,6 +32,7 @@ #include "talk/app/webrtc/mediastreamproxy.h" #include "talk/app/webrtc/mediastreamtrackproxy.h" #include "talk/app/webrtc/peerconnection.h" +#include "talk/app/webrtc/peerconnectionfactoryproxy.h" #include "talk/app/webrtc/peerconnectionproxy.h" #include "talk/app/webrtc/portallocatorfactory.h" #include "talk/app/webrtc/videosource.h" @@ -44,72 +45,6 @@ #include "webrtc/base/bind.h" #include "webrtc/modules/audio_device/include/audio_device.h" -using rtc::scoped_refptr; - -namespace { - -typedef rtc::TypedMessageData InitMessageData; - -struct CreatePeerConnectionParams : public rtc::MessageData { - CreatePeerConnectionParams( - const webrtc::PeerConnectionInterface::RTCConfiguration& configuration, - const webrtc::MediaConstraintsInterface* constraints, - webrtc::PortAllocatorFactoryInterface* allocator_factory, - webrtc::DTLSIdentityServiceInterface* dtls_identity_service, - webrtc::PeerConnectionObserver* observer) - : configuration(configuration), - constraints(constraints), - allocator_factory(allocator_factory), - dtls_identity_service(dtls_identity_service), - observer(observer) { - } - scoped_refptr peerconnection; - const webrtc::PeerConnectionInterface::RTCConfiguration& configuration; - const webrtc::MediaConstraintsInterface* constraints; - scoped_refptr allocator_factory; - webrtc::DTLSIdentityServiceInterface* dtls_identity_service; - webrtc::PeerConnectionObserver* observer; -}; - -struct CreateAudioSourceParams : public rtc::MessageData { - explicit CreateAudioSourceParams( - const webrtc::MediaConstraintsInterface* constraints) - : constraints(constraints) { - } - const webrtc::MediaConstraintsInterface* constraints; - scoped_refptr source; -}; - -struct CreateVideoSourceParams : public rtc::MessageData { - CreateVideoSourceParams(cricket::VideoCapturer* capturer, - const webrtc::MediaConstraintsInterface* constraints) - : capturer(capturer), - constraints(constraints) { - } - cricket::VideoCapturer* capturer; - const webrtc::MediaConstraintsInterface* constraints; - scoped_refptr source; -}; - -struct StartAecDumpParams : public rtc::MessageData { - explicit StartAecDumpParams(rtc::PlatformFile aec_dump_file) - : aec_dump_file(aec_dump_file) { - } - rtc::PlatformFile aec_dump_file; - bool result; -}; - -enum { - MSG_INIT_FACTORY = 1, - MSG_TERMINATE_FACTORY, - MSG_CREATE_PEERCONNECTION, - MSG_CREATE_AUDIOSOURCE, - MSG_CREATE_VIDEOSOURCE, - MSG_START_AEC_DUMP, -}; - -} // namespace - namespace webrtc { rtc::scoped_refptr @@ -117,10 +52,19 @@ CreatePeerConnectionFactory() { rtc::scoped_refptr pc_factory( new rtc::RefCountedObject()); - if (!pc_factory->Initialize()) { + + // Call Initialize synchronously but make sure its executed on + // |signaling_thread|. + MethodCall0 call( + pc_factory.get(), + &PeerConnectionFactory::Initialize); + bool result = call.Marshal(pc_factory->signaling_thread()); + + if (!result) { return NULL; } - return pc_factory; + return PeerConnectionFactoryProxy::Create(pc_factory->signaling_thread(), + pc_factory); } rtc::scoped_refptr @@ -132,24 +76,34 @@ CreatePeerConnectionFactory( cricket::WebRtcVideoDecoderFactory* decoder_factory) { rtc::scoped_refptr pc_factory( new rtc::RefCountedObject(worker_thread, - signaling_thread, - default_adm, - encoder_factory, - decoder_factory)); - if (!pc_factory->Initialize()) { + signaling_thread, + default_adm, + 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(signaling_thread); + + if (!result) { return NULL; } - return pc_factory; + return PeerConnectionFactoryProxy::Create(signaling_thread, pc_factory); } PeerConnectionFactory::PeerConnectionFactory() : owns_ptrs_(true), - signaling_thread_(new rtc::Thread), + wraps_current_thread_(false), + signaling_thread_(rtc::ThreadManager::Instance()->CurrentThread()), worker_thread_(new rtc::Thread) { - bool result = signaling_thread_->Start(); - ASSERT(result); - result = worker_thread_->Start(); - ASSERT(result); + if (!signaling_thread_) { + signaling_thread_ = rtc::ThreadManager::Instance()->WrapCurrentThread(); + wraps_current_thread_ = true; + } + worker_thread_->Start(); } PeerConnectionFactory::PeerConnectionFactory( @@ -159,6 +113,7 @@ PeerConnectionFactory::PeerConnectionFactory( cricket::WebRtcVideoEncoderFactory* video_encoder_factory, cricket::WebRtcVideoDecoderFactory* video_decoder_factory) : owns_ptrs_(false), + wraps_current_thread_(false), signaling_thread_(signaling_thread), worker_thread_(worker_thread), default_adm_(default_adm), @@ -172,64 +127,18 @@ PeerConnectionFactory::PeerConnectionFactory( } PeerConnectionFactory::~PeerConnectionFactory() { - signaling_thread_->Clear(this); - signaling_thread_->Send(this, MSG_TERMINATE_FACTORY); + DCHECK(signaling_thread_->IsCurrent()); + channel_manager_.reset(NULL); + allocator_factory_ = NULL; if (owns_ptrs_) { - delete signaling_thread_; + if (wraps_current_thread_) + rtc::ThreadManager::Instance()->UnwrapCurrentThread(); delete worker_thread_; } } bool PeerConnectionFactory::Initialize() { - InitMessageData result(false); - signaling_thread_->Send(this, MSG_INIT_FACTORY, &result); - return result.data(); -} - -void PeerConnectionFactory::OnMessage(rtc::Message* msg) { - switch (msg->message_id) { - case MSG_INIT_FACTORY: { - InitMessageData* pdata = static_cast(msg->pdata); - pdata->data() = Initialize_s(); - break; - } - case MSG_TERMINATE_FACTORY: { - Terminate_s(); - break; - } - case MSG_CREATE_PEERCONNECTION: { - CreatePeerConnectionParams* pdata = - static_cast (msg->pdata); - pdata->peerconnection = CreatePeerConnection_s( - pdata->configuration, - pdata->constraints, - pdata->allocator_factory, - pdata->dtls_identity_service, - pdata->observer); - break; - } - case MSG_CREATE_AUDIOSOURCE: { - CreateAudioSourceParams* pdata = - static_cast(msg->pdata); - pdata->source = CreateAudioSource_s(pdata->constraints); - break; - } - case MSG_CREATE_VIDEOSOURCE: { - CreateVideoSourceParams* pdata = - static_cast(msg->pdata); - pdata->source = CreateVideoSource_s(pdata->capturer, pdata->constraints); - break; - } - case MSG_START_AEC_DUMP: { - StartAecDumpParams* pdata = - static_cast(msg->pdata); - pdata->result = StartAecDump_s(pdata->aec_dump_file); - break; - } - } -} - -bool PeerConnectionFactory::Initialize_s() { + DCHECK(signaling_thread_->IsCurrent()); rtc::InitRandom(rtc::Time()); allocator_factory_ = PortAllocatorFactory::Create(worker_thread_); @@ -255,30 +164,27 @@ bool PeerConnectionFactory::Initialize_s() { return true; } -// Terminate what we created on the signaling thread. -void PeerConnectionFactory::Terminate_s() { - channel_manager_.reset(NULL); - allocator_factory_ = NULL; -} - rtc::scoped_refptr -PeerConnectionFactory::CreateAudioSource_s( +PeerConnectionFactory::CreateAudioSource( const MediaConstraintsInterface* constraints) { + DCHECK(signaling_thread_->IsCurrent()); rtc::scoped_refptr source( LocalAudioSource::Create(options_, constraints)); return source; } rtc::scoped_refptr -PeerConnectionFactory::CreateVideoSource_s( +PeerConnectionFactory::CreateVideoSource( cricket::VideoCapturer* capturer, const MediaConstraintsInterface* constraints) { + DCHECK(signaling_thread_->IsCurrent()); rtc::scoped_refptr source( VideoSource::Create(channel_manager_.get(), capturer, constraints)); return VideoSourceProxy::Create(signaling_thread_, source); } -bool PeerConnectionFactory::StartAecDump_s(rtc::PlatformFile file) { +bool PeerConnectionFactory::StartAecDump(rtc::PlatformFile file) { + DCHECK(signaling_thread_->IsCurrent()); return channel_manager_->StartAecDump(file); } @@ -289,22 +195,8 @@ PeerConnectionFactory::CreatePeerConnection( PortAllocatorFactoryInterface* allocator_factory, DTLSIdentityServiceInterface* dtls_identity_service, PeerConnectionObserver* observer) { - CreatePeerConnectionParams params(configuration, constraints, - allocator_factory, dtls_identity_service, - observer); - signaling_thread_->Send( - this, MSG_CREATE_PEERCONNECTION, ¶ms); - return params.peerconnection; -} - -rtc::scoped_refptr -PeerConnectionFactory::CreatePeerConnection_s( - const PeerConnectionInterface::RTCConfiguration& configuration, - const MediaConstraintsInterface* constraints, - PortAllocatorFactoryInterface* allocator_factory, - DTLSIdentityServiceInterface* dtls_identity_service, - PeerConnectionObserver* observer) { - ASSERT(allocator_factory || allocator_factory_); + DCHECK(signaling_thread_->IsCurrent()); + DCHECK(allocator_factory || allocator_factory_); rtc::scoped_refptr pc( new rtc::RefCountedObject(this)); if (!pc->Initialize( @@ -320,33 +212,16 @@ PeerConnectionFactory::CreatePeerConnection_s( rtc::scoped_refptr PeerConnectionFactory::CreateLocalMediaStream(const std::string& label) { + DCHECK(signaling_thread_->IsCurrent()); return MediaStreamProxy::Create(signaling_thread_, MediaStream::Create(label)); } -rtc::scoped_refptr -PeerConnectionFactory::CreateAudioSource( - const MediaConstraintsInterface* constraints) { - CreateAudioSourceParams params(constraints); - signaling_thread_->Send(this, MSG_CREATE_AUDIOSOURCE, ¶ms); - return params.source; -} - -rtc::scoped_refptr -PeerConnectionFactory::CreateVideoSource( - cricket::VideoCapturer* capturer, - const MediaConstraintsInterface* constraints) { - - CreateVideoSourceParams params(capturer, - constraints); - signaling_thread_->Send(this, MSG_CREATE_VIDEOSOURCE, ¶ms); - return params.source; -} - rtc::scoped_refptr PeerConnectionFactory::CreateVideoTrack( const std::string& id, VideoSourceInterface* source) { + DCHECK(signaling_thread_->IsCurrent()); rtc::scoped_refptr track( VideoTrack::Create(id, source)); return VideoTrackProxy::Create(signaling_thread_, track); @@ -355,26 +230,25 @@ PeerConnectionFactory::CreateVideoTrack( rtc::scoped_refptr PeerConnectionFactory::CreateAudioTrack(const std::string& id, AudioSourceInterface* source) { + DCHECK(signaling_thread_->IsCurrent()); rtc::scoped_refptr track( AudioTrack::Create(id, source)); return AudioTrackProxy::Create(signaling_thread_, track); } -bool PeerConnectionFactory::StartAecDump(rtc::PlatformFile file) { - StartAecDumpParams params(file); - signaling_thread_->Send(this, MSG_START_AEC_DUMP, ¶ms); - return params.result; -} - cricket::ChannelManager* PeerConnectionFactory::channel_manager() { + DCHECK(signaling_thread_->IsCurrent()); return channel_manager_.get(); } rtc::Thread* PeerConnectionFactory::signaling_thread() { + // This method can be called on a different thread when the factory is + // created in CreatePeerConnectionFactory(). return signaling_thread_; } rtc::Thread* PeerConnectionFactory::worker_thread() { + DCHECK(signaling_thread_->IsCurrent()); return worker_thread_; } diff --git a/talk/app/webrtc/peerconnectionfactory.h b/talk/app/webrtc/peerconnectionfactory.h index 119b7cd12..1b734d6a9 100644 --- a/talk/app/webrtc/peerconnectionfactory.h +++ b/talk/app/webrtc/peerconnectionfactory.h @@ -37,8 +37,7 @@ namespace webrtc { -class PeerConnectionFactory : public PeerConnectionFactoryInterface, - public rtc::MessageHandler { +class PeerConnectionFactory : public PeerConnectionFactoryInterface { public: virtual void SetOptions(const Options& options) { options_ = options; @@ -54,25 +53,25 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface, bool Initialize(); - virtual rtc::scoped_refptr - CreateLocalMediaStream(const std::string& label); + rtc::scoped_refptr + CreateLocalMediaStream(const std::string& label) override; - virtual rtc::scoped_refptr CreateAudioSource( - const MediaConstraintsInterface* constraints); + rtc::scoped_refptr CreateAudioSource( + const MediaConstraintsInterface* constraints) override; - virtual rtc::scoped_refptr CreateVideoSource( + rtc::scoped_refptr CreateVideoSource( cricket::VideoCapturer* capturer, - const MediaConstraintsInterface* constraints); + const MediaConstraintsInterface* constraints) override; - virtual rtc::scoped_refptr + rtc::scoped_refptr CreateVideoTrack(const std::string& id, - VideoSourceInterface* video_source); + VideoSourceInterface* video_source) override; - virtual rtc::scoped_refptr + rtc::scoped_refptr CreateAudioTrack(const std::string& id, - AudioSourceInterface* audio_source); + AudioSourceInterface* audio_source) override; - virtual bool StartAecDump(rtc::PlatformFile file); + bool StartAecDump(rtc::PlatformFile file) override; virtual cricket::ChannelManager* channel_manager(); virtual rtc::Thread* signaling_thread(); @@ -90,27 +89,8 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface, virtual ~PeerConnectionFactory(); private: - bool Initialize_s(); - void Terminate_s(); - rtc::scoped_refptr CreateAudioSource_s( - const MediaConstraintsInterface* constraints); - rtc::scoped_refptr CreateVideoSource_s( - cricket::VideoCapturer* capturer, - const MediaConstraintsInterface* constraints); - - rtc::scoped_refptr CreatePeerConnection_s( - const PeerConnectionInterface::RTCConfiguration& configuration, - const MediaConstraintsInterface* constraints, - PortAllocatorFactoryInterface* allocator_factory, - DTLSIdentityServiceInterface* dtls_identity_service, - PeerConnectionObserver* observer); - - bool StartAecDump_s(rtc::PlatformFile file); - - // Implements rtc::MessageHandler. - void OnMessage(rtc::Message* msg); - bool owns_ptrs_; + bool wraps_current_thread_; rtc::Thread* signaling_thread_; rtc::Thread* worker_thread_; Options options_; diff --git a/talk/app/webrtc/peerconnectionfactoryproxy.h b/talk/app/webrtc/peerconnectionfactoryproxy.h new file mode 100644 index 000000000..e37dcf980 --- /dev/null +++ b/talk/app/webrtc/peerconnectionfactoryproxy.h @@ -0,0 +1,62 @@ +/* + * libjingle + * Copyright 2014, Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TALK_APP_WEBRTC_PEERCONNECTIONFACTORYPROXY_H_ +#define TALK_APP_WEBRTC_PEERCONNECTIONFACTORYPROXY_H_ + +#include + +#include "talk/app/webrtc/peerconnectioninterface.h" +#include "talk/app/webrtc/proxy.h" + +namespace webrtc { + +BEGIN_PROXY_MAP(PeerConnectionFactory) + PROXY_METHOD1(void, SetOptions, const Options&) + PROXY_METHOD5(rtc::scoped_refptr, + CreatePeerConnection, + const PeerConnectionInterface::RTCConfiguration&, + const MediaConstraintsInterface*, + PortAllocatorFactoryInterface*, + DTLSIdentityServiceInterface*, + PeerConnectionObserver*) + PROXY_METHOD1(rtc::scoped_refptr, + CreateLocalMediaStream, const std::string&) + PROXY_METHOD1(rtc::scoped_refptr, + CreateAudioSource, const MediaConstraintsInterface*) + PROXY_METHOD2(rtc::scoped_refptr, + CreateVideoSource, cricket::VideoCapturer*, + const MediaConstraintsInterface*) + PROXY_METHOD2(rtc::scoped_refptr, + CreateVideoTrack, const std::string&, VideoSourceInterface*) + PROXY_METHOD2(rtc::scoped_refptr, + CreateAudioTrack, const std::string&, AudioSourceInterface*) + PROXY_METHOD1(bool, StartAecDump, rtc::PlatformFile) +END_PROXY() + +} // namespace webrtc + +#endif // TALK_APP_WEBRTC_PEERCONNECTIONFACTORYPROXY_H_ diff --git a/talk/app/webrtc/proxy.h b/talk/app/webrtc/proxy.h index 134f58001..707384246 100644 --- a/talk/app/webrtc/proxy.h +++ b/talk/app/webrtc/proxy.h @@ -71,6 +71,16 @@ class ReturnType { void Invoke(C* c, M m, T1 a1, T2 a2) { r_ = (c->*m)(a1, a2); } template void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) { r_ = (c->*m)(a1, a2, a3); } + template + void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3, T4 a4) { + r_ = (c->*m)(a1, a2, a3, a4); + } + template + void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) { + r_ = (c->*m)(a1, a2, a3, a4, a5); + } R value() { return r_; } @@ -99,7 +109,7 @@ class SynchronousMethodCall : public rtc::MessageData, public rtc::MessageHandler { public: - SynchronousMethodCall(rtc::MessageHandler* proxy) + explicit SynchronousMethodCall(rtc::MessageHandler* proxy) : e_(), proxy_(proxy) {} ~SynchronousMethodCall() {} @@ -119,7 +129,7 @@ class SynchronousMethodCall rtc::MessageHandler* proxy_; }; -} // internal +} // namespace internal template class MethodCall0 : public rtc::Message, @@ -249,6 +259,59 @@ class MethodCall3 : public rtc::Message, T3 a3_; }; +template +class MethodCall4 : public rtc::Message, + public rtc::MessageHandler { + public: + typedef R (C::*Method)(T1 a1, T2 a2, T3 a3, T4 a4); + MethodCall4(C* c, Method m, T1 a1, T2 a2, T3 a3, T4 a4) + : c_(c), m_(m), a1_(a1), a2_(a2), a3_(a3), a4_(a4) {} + + R Marshal(rtc::Thread* t) { + internal::SynchronousMethodCall(this).Invoke(t); + return r_.value(); + } + + private: + void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_, a3_, a4_); } + + C* c_; + Method m_; + ReturnType r_; + T1 a1_; + T2 a2_; + T3 a3_; + T4 a4_; +}; + +template +class MethodCall5 : public rtc::Message, + public rtc::MessageHandler { + public: + typedef R (C::*Method)(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); + MethodCall5(C* c, Method m, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) + : c_(c), m_(m), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5) {} + + R Marshal(rtc::Thread* t) { + internal::SynchronousMethodCall(this).Invoke(t); + return r_.value(); + } + + private: + void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_, a3_, a4_, a5_); } + + C* c_; + Method m_; + ReturnType r_; + T1 a1_; + T2 a2_; + T3 a3_; + T4 a4_; + T5 a5_; +}; + #define BEGIN_PROXY_MAP(c) \ class c##Proxy : public c##Interface {\ protected:\ @@ -302,6 +365,20 @@ class MethodCall3 : public rtc::Message, return call.Marshal(owner_thread_);\ }\ +#define PROXY_METHOD4(r, method, t1, t2, t3, t4)\ + r method(t1 a1, t2 a2, t3 a3, t4 a4) OVERRIDE {\ + MethodCall4 call(\ + c_.get(), &C::method, a1, a2, a3, a4);\ + return call.Marshal(owner_thread_);\ + }\ + +#define PROXY_METHOD5(r, method, t1, t2, t3, t4, t5)\ + r method(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) OVERRIDE {\ + MethodCall5 call(\ + c_.get(), &C::method, a1, a2, a3, a4, a5);\ + return call.Marshal(owner_thread_);\ + }\ + #define END_PROXY() \ private:\ void Release_s() {\ diff --git a/talk/libjingle.gyp b/talk/libjingle.gyp index 29a23bd08..9d44b42d2 100755 --- a/talk/libjingle.gyp +++ b/talk/libjingle.gyp @@ -663,6 +663,7 @@ 'app/webrtc/peerconnection.h', 'app/webrtc/peerconnectionfactory.cc', 'app/webrtc/peerconnectionfactory.h', + 'app/webrtc/peerconnectionfactoryproxy.h', 'app/webrtc/peerconnectioninterface.h', 'app/webrtc/peerconnectionproxy.h', 'app/webrtc/portallocatorfactory.cc',