1 /* 2 * libjingle 3 * Copyright 2004--2011 Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "talk/app/webrtc/peerconnectionfactory.h" 29 30 #include <utility> 31 32 #include "talk/app/webrtc/audiotrack.h" 33 #include "talk/app/webrtc/localaudiosource.h" 34 #include "talk/app/webrtc/mediastream.h" 35 #include "talk/app/webrtc/mediastreamproxy.h" 36 #include "talk/app/webrtc/mediastreamtrackproxy.h" 37 #include "talk/app/webrtc/peerconnection.h" 38 #include "talk/app/webrtc/peerconnectionfactoryproxy.h" 39 #include "talk/app/webrtc/peerconnectionproxy.h" 40 #include "talk/app/webrtc/videosource.h" 41 #include "talk/app/webrtc/videosourceproxy.h" 42 #include "talk/app/webrtc/videotrack.h" 43 #include "talk/media/webrtc/webrtcmediaengine.h" 44 #include "talk/media/webrtc/webrtcvideodecoderfactory.h" 45 #include "talk/media/webrtc/webrtcvideoencoderfactory.h" 46 #include "webrtc/base/bind.h" 47 #include "webrtc/modules/audio_device/include/audio_device.h" 48 #include "webrtc/p2p/base/basicpacketsocketfactory.h" 49 #include "webrtc/p2p/client/basicportallocator.h" 50 51 namespace webrtc { 52 53 namespace { 54 55 // Passes down the calls to |store_|. See usage in CreatePeerConnection. 56 class DtlsIdentityStoreWrapper : public DtlsIdentityStoreInterface { 57 public: 58 DtlsIdentityStoreWrapper( 59 const rtc::scoped_refptr<RefCountedDtlsIdentityStore>& store) 60 : store_(store) { 61 RTC_DCHECK(store_); 62 } 63 64 void RequestIdentity( 65 rtc::KeyType key_type, 66 const rtc::scoped_refptr<webrtc::DtlsIdentityRequestObserver>& 67 observer) override { 68 store_->RequestIdentity(key_type, observer); 69 } 70 71 private: 72 rtc::scoped_refptr<RefCountedDtlsIdentityStore> store_; 73 }; 74 75 } // anonymous namespace 76 77 rtc::scoped_refptr<PeerConnectionFactoryInterface> 78 CreatePeerConnectionFactory() { 79 rtc::scoped_refptr<PeerConnectionFactory> pc_factory( 80 new rtc::RefCountedObject<PeerConnectionFactory>()); 81 82 83 // Call Initialize synchronously but make sure its executed on 84 // |signaling_thread|. 85 MethodCall0<PeerConnectionFactory, bool> call( 86 pc_factory.get(), 87 &PeerConnectionFactory::Initialize); 88 bool result = call.Marshal(pc_factory->signaling_thread()); 89 90 if (!result) { 91 return NULL; 92 } 93 return PeerConnectionFactoryProxy::Create(pc_factory->signaling_thread(), 94 pc_factory); 95 } 96 97 rtc::scoped_refptr<PeerConnectionFactoryInterface> 98 CreatePeerConnectionFactory( 99 rtc::Thread* worker_thread, 100 rtc::Thread* signaling_thread, 101 AudioDeviceModule* default_adm, 102 cricket::WebRtcVideoEncoderFactory* encoder_factory, 103 cricket::WebRtcVideoDecoderFactory* decoder_factory) { 104 rtc::scoped_refptr<PeerConnectionFactory> pc_factory( 105 new rtc::RefCountedObject<PeerConnectionFactory>(worker_thread, 106 signaling_thread, 107 default_adm, 108 encoder_factory, 109 decoder_factory)); 110 111 // Call Initialize synchronously but make sure its executed on 112 // |signaling_thread|. 113 MethodCall0<PeerConnectionFactory, bool> call( 114 pc_factory.get(), 115 &PeerConnectionFactory::Initialize); 116 bool result = call.Marshal(signaling_thread); 117 118 if (!result) { 119 return NULL; 120 } 121 return PeerConnectionFactoryProxy::Create(signaling_thread, pc_factory); 122 } 123 124 PeerConnectionFactory::PeerConnectionFactory() 125 : owns_ptrs_(true), 126 wraps_current_thread_(false), 127 signaling_thread_(rtc::ThreadManager::Instance()->CurrentThread()), 128 worker_thread_(new rtc::Thread) { 129 if (!signaling_thread_) { 130 signaling_thread_ = rtc::ThreadManager::Instance()->WrapCurrentThread(); 131 wraps_current_thread_ = true; 132 } 133 worker_thread_->Start(); 134 } 135 136 PeerConnectionFactory::PeerConnectionFactory( 137 rtc::Thread* worker_thread, 138 rtc::Thread* signaling_thread, 139 AudioDeviceModule* default_adm, 140 cricket::WebRtcVideoEncoderFactory* video_encoder_factory, 141 cricket::WebRtcVideoDecoderFactory* video_decoder_factory) 142 : owns_ptrs_(false), 143 wraps_current_thread_(false), 144 signaling_thread_(signaling_thread), 145 worker_thread_(worker_thread), 146 default_adm_(default_adm), 147 video_encoder_factory_(video_encoder_factory), 148 video_decoder_factory_(video_decoder_factory) { 149 ASSERT(worker_thread != NULL); 150 ASSERT(signaling_thread != NULL); 151 // TODO: Currently there is no way creating an external adm in 152 // libjingle source tree. So we can 't currently assert if this is NULL. 153 // ASSERT(default_adm != NULL); 154 } 155 156 PeerConnectionFactory::~PeerConnectionFactory() { 157 RTC_DCHECK(signaling_thread_->IsCurrent()); 158 channel_manager_.reset(nullptr); 159 160 // Make sure |worker_thread_| and |signaling_thread_| outlive 161 // |dtls_identity_store_|, |default_socket_factory_| and 162 // |default_network_manager_|. 163 dtls_identity_store_ = nullptr; 164 default_socket_factory_ = nullptr; 165 default_network_manager_ = nullptr; 166 167 if (owns_ptrs_) { 168 if (wraps_current_thread_) 169 rtc::ThreadManager::Instance()->UnwrapCurrentThread(); 170 delete worker_thread_; 171 } 172 } 173 174 bool PeerConnectionFactory::Initialize() { 175 RTC_DCHECK(signaling_thread_->IsCurrent()); 176 rtc::InitRandom(rtc::Time()); 177 178 default_network_manager_.reset(new rtc::BasicNetworkManager()); 179 if (!default_network_manager_) { 180 return false; 181 } 182 183 default_socket_factory_.reset( 184 new rtc::BasicPacketSocketFactory(worker_thread_)); 185 if (!default_socket_factory_) { 186 return false; 187 } 188 189 // TODO: Need to make sure only one VoE is created inside 190 // WebRtcMediaEngine. 191 cricket::MediaEngineInterface* media_engine = 192 worker_thread_->Invoke<cricket::MediaEngineInterface*>(rtc::Bind( 193 &PeerConnectionFactory::CreateMediaEngine_w, this)); 194 195 channel_manager_.reset( 196 new cricket::ChannelManager(media_engine, worker_thread_)); 197 198 channel_manager_->SetVideoRtxEnabled(true); 199 if (!channel_manager_->Init()) { 200 return false; 201 } 202 203 dtls_identity_store_ = new RefCountedDtlsIdentityStore( 204 signaling_thread_, worker_thread_); 205 206 return true; 207 } 208 209 rtc::scoped_refptr<AudioSourceInterface> 210 PeerConnectionFactory::CreateAudioSource( 211 const MediaConstraintsInterface* constraints) { 212 RTC_DCHECK(signaling_thread_->IsCurrent()); 213 rtc::scoped_refptr<LocalAudioSource> source( 214 LocalAudioSource::Create(options_, constraints)); 215 return source; 216 } 217 218 rtc::scoped_refptr<VideoSourceInterface> 219 PeerConnectionFactory::CreateVideoSource( 220 cricket::VideoCapturer* capturer, 221 const MediaConstraintsInterface* constraints) { 222 RTC_DCHECK(signaling_thread_->IsCurrent()); 223 rtc::scoped_refptr<VideoSource> source(VideoSource::Create( 224 channel_manager_.get(), capturer, constraints, false)); 225 return VideoSourceProxy::Create(signaling_thread_, source); 226 } 227 228 bool PeerConnectionFactory::StartAecDump(rtc::PlatformFile file) { 229 RTC_DCHECK(signaling_thread_->IsCurrent()); 230 return channel_manager_->StartAecDump(file); 231 } 232 233 void PeerConnectionFactory::StopAecDump() { 234 RTC_DCHECK(signaling_thread_->IsCurrent()); 235 channel_manager_->StopAecDump(); 236 } 237 238 bool PeerConnectionFactory::StartRtcEventLog(rtc::PlatformFile file) { 239 RTC_DCHECK(signaling_thread_->IsCurrent()); 240 return channel_manager_->StartRtcEventLog(file); 241 } 242 243 void PeerConnectionFactory::StopRtcEventLog() { 244 RTC_DCHECK(signaling_thread_->IsCurrent()); 245 channel_manager_->StopRtcEventLog(); 246 } 247 248 rtc::scoped_refptr<PeerConnectionInterface> 249 PeerConnectionFactory::CreatePeerConnection( 250 const PeerConnectionInterface::RTCConfiguration& configuration, 251 const MediaConstraintsInterface* constraints, 252 rtc::scoped_ptr<cricket::PortAllocator> allocator, 253 rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store, 254 PeerConnectionObserver* observer) { 255 RTC_DCHECK(signaling_thread_->IsCurrent()); 256 257 if (!dtls_identity_store.get()) { 258 // Because |pc|->Initialize takes ownership of the store we need a new 259 // wrapper object that can be deleted without deleting the underlying 260 // |dtls_identity_store_|, protecting it from being deleted multiple times. 261 dtls_identity_store.reset( 262 new DtlsIdentityStoreWrapper(dtls_identity_store_)); 263 } 264 265 if (!allocator) { 266 allocator.reset(new cricket::BasicPortAllocator( 267 default_network_manager_.get(), default_socket_factory_.get())); 268 } 269 allocator->SetNetworkIgnoreMask(options_.network_ignore_mask); 270 271 rtc::scoped_refptr<PeerConnection> pc( 272 new rtc::RefCountedObject<PeerConnection>(this)); 273 if (!pc->Initialize(configuration, constraints, std::move(allocator), 274 std::move(dtls_identity_store), observer)) { 275 return nullptr; 276 } 277 return PeerConnectionProxy::Create(signaling_thread(), pc); 278 } 279 280 rtc::scoped_refptr<MediaStreamInterface> 281 PeerConnectionFactory::CreateLocalMediaStream(const std::string& label) { 282 RTC_DCHECK(signaling_thread_->IsCurrent()); 283 return MediaStreamProxy::Create(signaling_thread_, 284 MediaStream::Create(label)); 285 } 286 287 rtc::scoped_refptr<VideoTrackInterface> 288 PeerConnectionFactory::CreateVideoTrack( 289 const std::string& id, 290 VideoSourceInterface* source) { 291 RTC_DCHECK(signaling_thread_->IsCurrent()); 292 rtc::scoped_refptr<VideoTrackInterface> track( 293 VideoTrack::Create(id, source)); 294 return VideoTrackProxy::Create(signaling_thread_, track); 295 } 296 297 rtc::scoped_refptr<AudioTrackInterface> 298 PeerConnectionFactory::CreateAudioTrack(const std::string& id, 299 AudioSourceInterface* source) { 300 RTC_DCHECK(signaling_thread_->IsCurrent()); 301 rtc::scoped_refptr<AudioTrackInterface> track(AudioTrack::Create(id, source)); 302 return AudioTrackProxy::Create(signaling_thread_, track); 303 } 304 305 webrtc::MediaControllerInterface* PeerConnectionFactory::CreateMediaController() 306 const { 307 RTC_DCHECK(signaling_thread_->IsCurrent()); 308 return MediaControllerInterface::Create(worker_thread_, 309 channel_manager_.get()); 310 } 311 312 rtc::Thread* PeerConnectionFactory::signaling_thread() { 313 // This method can be called on a different thread when the factory is 314 // created in CreatePeerConnectionFactory(). 315 return signaling_thread_; 316 } 317 318 rtc::Thread* PeerConnectionFactory::worker_thread() { 319 RTC_DCHECK(signaling_thread_->IsCurrent()); 320 return worker_thread_; 321 } 322 323 cricket::MediaEngineInterface* PeerConnectionFactory::CreateMediaEngine_w() { 324 ASSERT(worker_thread_ == rtc::Thread::Current()); 325 return cricket::WebRtcMediaEngineFactory::Create( 326 default_adm_.get(), video_encoder_factory_.get(), 327 video_decoder_factory_.get()); 328 } 329 330 } // namespace webrtc 331