| OLD | NEW |
| (Empty) |
| 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 "webrtc/base/bind.h" | |
| 44 #include "webrtc/media/webrtc/webrtcmediaengine.h" | |
| 45 #include "webrtc/media/webrtc/webrtcvideodecoderfactory.h" | |
| 46 #include "webrtc/media/webrtc/webrtcvideoencoderfactory.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 int64_t max_size_bytes) { | |
| 230 RTC_DCHECK(signaling_thread_->IsCurrent()); | |
| 231 return channel_manager_->StartAecDump(file, max_size_bytes); | |
| 232 } | |
| 233 | |
| 234 void PeerConnectionFactory::StopAecDump() { | |
| 235 RTC_DCHECK(signaling_thread_->IsCurrent()); | |
| 236 channel_manager_->StopAecDump(); | |
| 237 } | |
| 238 | |
| 239 bool PeerConnectionFactory::StartRtcEventLog(rtc::PlatformFile file) { | |
| 240 RTC_DCHECK(signaling_thread_->IsCurrent()); | |
| 241 return channel_manager_->StartRtcEventLog(file); | |
| 242 } | |
| 243 | |
| 244 void PeerConnectionFactory::StopRtcEventLog() { | |
| 245 RTC_DCHECK(signaling_thread_->IsCurrent()); | |
| 246 channel_manager_->StopRtcEventLog(); | |
| 247 } | |
| 248 | |
| 249 rtc::scoped_refptr<PeerConnectionInterface> | |
| 250 PeerConnectionFactory::CreatePeerConnection( | |
| 251 const PeerConnectionInterface::RTCConfiguration& configuration, | |
| 252 const MediaConstraintsInterface* constraints, | |
| 253 rtc::scoped_ptr<cricket::PortAllocator> allocator, | |
| 254 rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store, | |
| 255 PeerConnectionObserver* observer) { | |
| 256 RTC_DCHECK(signaling_thread_->IsCurrent()); | |
| 257 | |
| 258 if (!dtls_identity_store.get()) { | |
| 259 // Because |pc|->Initialize takes ownership of the store we need a new | |
| 260 // wrapper object that can be deleted without deleting the underlying | |
| 261 // |dtls_identity_store_|, protecting it from being deleted multiple times. | |
| 262 dtls_identity_store.reset( | |
| 263 new DtlsIdentityStoreWrapper(dtls_identity_store_)); | |
| 264 } | |
| 265 | |
| 266 if (!allocator) { | |
| 267 allocator.reset(new cricket::BasicPortAllocator( | |
| 268 default_network_manager_.get(), default_socket_factory_.get())); | |
| 269 } | |
| 270 allocator->SetNetworkIgnoreMask(options_.network_ignore_mask); | |
| 271 | |
| 272 rtc::scoped_refptr<PeerConnection> pc( | |
| 273 new rtc::RefCountedObject<PeerConnection>(this)); | |
| 274 if (!pc->Initialize(configuration, constraints, std::move(allocator), | |
| 275 std::move(dtls_identity_store), observer)) { | |
| 276 return nullptr; | |
| 277 } | |
| 278 return PeerConnectionProxy::Create(signaling_thread(), pc); | |
| 279 } | |
| 280 | |
| 281 rtc::scoped_refptr<MediaStreamInterface> | |
| 282 PeerConnectionFactory::CreateLocalMediaStream(const std::string& label) { | |
| 283 RTC_DCHECK(signaling_thread_->IsCurrent()); | |
| 284 return MediaStreamProxy::Create(signaling_thread_, | |
| 285 MediaStream::Create(label)); | |
| 286 } | |
| 287 | |
| 288 rtc::scoped_refptr<VideoTrackInterface> | |
| 289 PeerConnectionFactory::CreateVideoTrack( | |
| 290 const std::string& id, | |
| 291 VideoSourceInterface* source) { | |
| 292 RTC_DCHECK(signaling_thread_->IsCurrent()); | |
| 293 rtc::scoped_refptr<VideoTrackInterface> track( | |
| 294 VideoTrack::Create(id, source)); | |
| 295 return VideoTrackProxy::Create(signaling_thread_, track); | |
| 296 } | |
| 297 | |
| 298 rtc::scoped_refptr<AudioTrackInterface> | |
| 299 PeerConnectionFactory::CreateAudioTrack(const std::string& id, | |
| 300 AudioSourceInterface* source) { | |
| 301 RTC_DCHECK(signaling_thread_->IsCurrent()); | |
| 302 rtc::scoped_refptr<AudioTrackInterface> track(AudioTrack::Create(id, source)); | |
| 303 return AudioTrackProxy::Create(signaling_thread_, track); | |
| 304 } | |
| 305 | |
| 306 webrtc::MediaControllerInterface* PeerConnectionFactory::CreateMediaController() | |
| 307 const { | |
| 308 RTC_DCHECK(signaling_thread_->IsCurrent()); | |
| 309 return MediaControllerInterface::Create(worker_thread_, | |
| 310 channel_manager_.get()); | |
| 311 } | |
| 312 | |
| 313 rtc::Thread* PeerConnectionFactory::signaling_thread() { | |
| 314 // This method can be called on a different thread when the factory is | |
| 315 // created in CreatePeerConnectionFactory(). | |
| 316 return signaling_thread_; | |
| 317 } | |
| 318 | |
| 319 rtc::Thread* PeerConnectionFactory::worker_thread() { | |
| 320 RTC_DCHECK(signaling_thread_->IsCurrent()); | |
| 321 return worker_thread_; | |
| 322 } | |
| 323 | |
| 324 cricket::MediaEngineInterface* PeerConnectionFactory::CreateMediaEngine_w() { | |
| 325 ASSERT(worker_thread_ == rtc::Thread::Current()); | |
| 326 return cricket::WebRtcMediaEngineFactory::Create( | |
| 327 default_adm_.get(), video_encoder_factory_.get(), | |
| 328 video_decoder_factory_.get()); | |
| 329 } | |
| 330 | |
| 331 } // namespace webrtc | |
| OLD | NEW |