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 "talk/app/webrtc/audiotrack.h"
31 #include "talk/app/webrtc/localaudiosource.h"
32 #include "talk/app/webrtc/mediastreamproxy.h"
33 #include "talk/app/webrtc/mediastreamtrackproxy.h"
34 #include "talk/app/webrtc/peerconnection.h"
35 #include "talk/app/webrtc/peerconnectionproxy.h"
36 #include "talk/app/webrtc/portallocatorfactory.h"
37 #include "talk/app/webrtc/videosource.h"
38 #include "talk/app/webrtc/videosourceproxy.h"
39 #include "talk/app/webrtc/videotrack.h"
40 #include "talk/media/devices/dummydevicemanager.h"
41 #include "talk/media/webrtc/webrtcmediaengine.h"
42 #include "talk/media/webrtc/webrtcvideodecoderfactory.h"
43 #include "talk/media/webrtc/webrtcvideoencoderfactory.h"
44 #include "webrtc/modules/audio_device/include/audio_device.h"
45
46 using talk_base::scoped_refptr;
47
48 namespace {
49
50 typedef talk_base::TypedMessageData<bool> InitMessageData;
51
52 struct CreatePeerConnectionParams : public talk_base::MessageData {
CreatePeerConnectionParams__anone0c4fcd60111::CreatePeerConnectionParams53 CreatePeerConnectionParams(
54 const webrtc::PeerConnectionInterface::IceServers& configuration,
55 const webrtc::MediaConstraintsInterface* constraints,
56 webrtc::PortAllocatorFactoryInterface* allocator_factory,
57 webrtc::DTLSIdentityServiceInterface* dtls_identity_service,
58 webrtc::PeerConnectionObserver* observer)
59 : configuration(configuration),
60 constraints(constraints),
61 allocator_factory(allocator_factory),
62 dtls_identity_service(dtls_identity_service),
63 observer(observer) {
64 }
65 scoped_refptr<webrtc::PeerConnectionInterface> peerconnection;
66 const webrtc::PeerConnectionInterface::IceServers& configuration;
67 const webrtc::MediaConstraintsInterface* constraints;
68 scoped_refptr<webrtc::PortAllocatorFactoryInterface> allocator_factory;
69 webrtc::DTLSIdentityServiceInterface* dtls_identity_service;
70 webrtc::PeerConnectionObserver* observer;
71 };
72
73 struct CreatePeerConnectionParamsDeprecated : public talk_base::MessageData {
CreatePeerConnectionParamsDeprecated__anone0c4fcd60111::CreatePeerConnectionParamsDeprecated74 CreatePeerConnectionParamsDeprecated(
75 const std::string& configuration,
76 webrtc::PortAllocatorFactoryInterface* allocator_factory,
77 webrtc::PeerConnectionObserver* observer)
78 : configuration(configuration),
79 allocator_factory(allocator_factory),
80 observer(observer) {
81 }
82 scoped_refptr<webrtc::PeerConnectionInterface> peerconnection;
83 const std::string& configuration;
84 scoped_refptr<webrtc::PortAllocatorFactoryInterface> allocator_factory;
85 webrtc::PeerConnectionObserver* observer;
86 };
87
88 struct CreateAudioSourceParams : public talk_base::MessageData {
CreateAudioSourceParams__anone0c4fcd60111::CreateAudioSourceParams89 explicit CreateAudioSourceParams(
90 const webrtc::MediaConstraintsInterface* constraints)
91 : constraints(constraints) {
92 }
93 const webrtc::MediaConstraintsInterface* constraints;
94 scoped_refptr<webrtc::AudioSourceInterface> source;
95 };
96
97 struct CreateVideoSourceParams : public talk_base::MessageData {
CreateVideoSourceParams__anone0c4fcd60111::CreateVideoSourceParams98 CreateVideoSourceParams(cricket::VideoCapturer* capturer,
99 const webrtc::MediaConstraintsInterface* constraints)
100 : capturer(capturer),
101 constraints(constraints) {
102 }
103 cricket::VideoCapturer* capturer;
104 const webrtc::MediaConstraintsInterface* constraints;
105 scoped_refptr<webrtc::VideoSourceInterface> source;
106 };
107
108 enum {
109 MSG_INIT_FACTORY = 1,
110 MSG_TERMINATE_FACTORY,
111 MSG_CREATE_PEERCONNECTION,
112 MSG_CREATE_AUDIOSOURCE,
113 MSG_CREATE_VIDEOSOURCE,
114 };
115
116 } // namespace
117
118 namespace webrtc {
119
120 scoped_refptr<PeerConnectionFactoryInterface>
CreatePeerConnectionFactory()121 CreatePeerConnectionFactory() {
122 scoped_refptr<PeerConnectionFactory> pc_factory(
123 new talk_base::RefCountedObject<PeerConnectionFactory>());
124
125 if (!pc_factory->Initialize()) {
126 return NULL;
127 }
128 return pc_factory;
129 }
130
131 scoped_refptr<PeerConnectionFactoryInterface>
CreatePeerConnectionFactory(talk_base::Thread * worker_thread,talk_base::Thread * signaling_thread,AudioDeviceModule * default_adm,cricket::WebRtcVideoEncoderFactory * encoder_factory,cricket::WebRtcVideoDecoderFactory * decoder_factory)132 CreatePeerConnectionFactory(
133 talk_base::Thread* worker_thread,
134 talk_base::Thread* signaling_thread,
135 AudioDeviceModule* default_adm,
136 cricket::WebRtcVideoEncoderFactory* encoder_factory,
137 cricket::WebRtcVideoDecoderFactory* decoder_factory) {
138 scoped_refptr<PeerConnectionFactory> pc_factory(
139 new talk_base::RefCountedObject<PeerConnectionFactory>(
140 worker_thread, signaling_thread, default_adm,
141 encoder_factory, decoder_factory));
142 if (!pc_factory->Initialize()) {
143 return NULL;
144 }
145 return pc_factory;
146 }
147
PeerConnectionFactory()148 PeerConnectionFactory::PeerConnectionFactory()
149 : owns_ptrs_(true),
150 signaling_thread_(new talk_base::Thread),
151 worker_thread_(new talk_base::Thread) {
152 bool result = signaling_thread_->Start();
153 ASSERT(result);
154 result = worker_thread_->Start();
155 ASSERT(result);
156 }
157
PeerConnectionFactory(talk_base::Thread * worker_thread,talk_base::Thread * signaling_thread,AudioDeviceModule * default_adm,cricket::WebRtcVideoEncoderFactory * video_encoder_factory,cricket::WebRtcVideoDecoderFactory * video_decoder_factory)158 PeerConnectionFactory::PeerConnectionFactory(
159 talk_base::Thread* worker_thread,
160 talk_base::Thread* signaling_thread,
161 AudioDeviceModule* default_adm,
162 cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
163 cricket::WebRtcVideoDecoderFactory* video_decoder_factory)
164 : owns_ptrs_(false),
165 signaling_thread_(signaling_thread),
166 worker_thread_(worker_thread),
167 default_adm_(default_adm),
168 video_encoder_factory_(video_encoder_factory),
169 video_decoder_factory_(video_decoder_factory) {
170 ASSERT(worker_thread != NULL);
171 ASSERT(signaling_thread != NULL);
172 // TODO: Currently there is no way creating an external adm in
173 // libjingle source tree. So we can 't currently assert if this is NULL.
174 // ASSERT(default_adm != NULL);
175 }
176
~PeerConnectionFactory()177 PeerConnectionFactory::~PeerConnectionFactory() {
178 signaling_thread_->Clear(this);
179 signaling_thread_->Send(this, MSG_TERMINATE_FACTORY);
180 if (owns_ptrs_) {
181 delete signaling_thread_;
182 delete worker_thread_;
183 }
184 }
185
Initialize()186 bool PeerConnectionFactory::Initialize() {
187 InitMessageData result(false);
188 signaling_thread_->Send(this, MSG_INIT_FACTORY, &result);
189 return result.data();
190 }
191
OnMessage(talk_base::Message * msg)192 void PeerConnectionFactory::OnMessage(talk_base::Message* msg) {
193 switch (msg->message_id) {
194 case MSG_INIT_FACTORY: {
195 InitMessageData* pdata = static_cast<InitMessageData*>(msg->pdata);
196 pdata->data() = Initialize_s();
197 break;
198 }
199 case MSG_TERMINATE_FACTORY: {
200 Terminate_s();
201 break;
202 }
203 case MSG_CREATE_PEERCONNECTION: {
204 CreatePeerConnectionParams* pdata =
205 static_cast<CreatePeerConnectionParams*> (msg->pdata);
206 pdata->peerconnection = CreatePeerConnection_s(
207 pdata->configuration,
208 pdata->constraints,
209 pdata->allocator_factory,
210 pdata->dtls_identity_service,
211 pdata->observer);
212 break;
213 }
214 case MSG_CREATE_AUDIOSOURCE: {
215 CreateAudioSourceParams* pdata =
216 static_cast<CreateAudioSourceParams*>(msg->pdata);
217 pdata->source = CreateAudioSource_s(pdata->constraints);
218 break;
219 }
220 case MSG_CREATE_VIDEOSOURCE: {
221 CreateVideoSourceParams* pdata =
222 static_cast<CreateVideoSourceParams*>(msg->pdata);
223 pdata->source = CreateVideoSource_s(pdata->capturer, pdata->constraints);
224 break;
225 }
226 }
227 }
228
Initialize_s()229 bool PeerConnectionFactory::Initialize_s() {
230 talk_base::InitRandom(talk_base::Time());
231
232 allocator_factory_ = PortAllocatorFactory::Create(worker_thread_);
233 if (!allocator_factory_)
234 return false;
235
236 cricket::DummyDeviceManager* device_manager(
237 new cricket::DummyDeviceManager());
238 // TODO: Need to make sure only one VoE is created inside
239 // WebRtcMediaEngine.
240 cricket::WebRtcMediaEngine* webrtc_media_engine(
241 new cricket::WebRtcMediaEngine(default_adm_.get(),
242 NULL, // No secondary adm.
243 video_encoder_factory_.get(),
244 video_decoder_factory_.get()));
245
246 channel_manager_.reset(new cricket::ChannelManager(
247 webrtc_media_engine, device_manager, worker_thread_));
248 if (!channel_manager_->Init()) {
249 return false;
250 }
251 return true;
252 }
253
254 // Terminate what we created on the signaling thread.
Terminate_s()255 void PeerConnectionFactory::Terminate_s() {
256 channel_manager_.reset(NULL);
257 allocator_factory_ = NULL;
258 }
259
260 talk_base::scoped_refptr<AudioSourceInterface>
CreateAudioSource_s(const MediaConstraintsInterface * constraints)261 PeerConnectionFactory::CreateAudioSource_s(
262 const MediaConstraintsInterface* constraints) {
263 talk_base::scoped_refptr<LocalAudioSource> source(
264 LocalAudioSource::Create(options_, constraints));
265 return source;
266 }
267
268 talk_base::scoped_refptr<VideoSourceInterface>
CreateVideoSource_s(cricket::VideoCapturer * capturer,const MediaConstraintsInterface * constraints)269 PeerConnectionFactory::CreateVideoSource_s(
270 cricket::VideoCapturer* capturer,
271 const MediaConstraintsInterface* constraints) {
272 talk_base::scoped_refptr<VideoSource> source(
273 VideoSource::Create(channel_manager_.get(), capturer, constraints));
274 return VideoSourceProxy::Create(signaling_thread_, source);
275 }
276
277 scoped_refptr<PeerConnectionInterface>
CreatePeerConnection(const PeerConnectionInterface::IceServers & configuration,const MediaConstraintsInterface * constraints,PortAllocatorFactoryInterface * allocator_factory,DTLSIdentityServiceInterface * dtls_identity_service,PeerConnectionObserver * observer)278 PeerConnectionFactory::CreatePeerConnection(
279 const PeerConnectionInterface::IceServers& configuration,
280 const MediaConstraintsInterface* constraints,
281 PortAllocatorFactoryInterface* allocator_factory,
282 DTLSIdentityServiceInterface* dtls_identity_service,
283 PeerConnectionObserver* observer) {
284 CreatePeerConnectionParams params(configuration, constraints,
285 allocator_factory, dtls_identity_service,
286 observer);
287 signaling_thread_->Send(this, MSG_CREATE_PEERCONNECTION, ¶ms);
288 return params.peerconnection;
289 }
290
291 scoped_refptr<PeerConnectionInterface>
CreatePeerConnection(const PeerConnectionInterface::IceServers & configuration,const MediaConstraintsInterface * constraints,DTLSIdentityServiceInterface * dtls_identity_service,PeerConnectionObserver * observer)292 PeerConnectionFactory::CreatePeerConnection(
293 const PeerConnectionInterface::IceServers& configuration,
294 const MediaConstraintsInterface* constraints,
295 DTLSIdentityServiceInterface* dtls_identity_service,
296 PeerConnectionObserver* observer) {
297 return CreatePeerConnection(
298 configuration, constraints, NULL, dtls_identity_service, observer);
299 }
300
301 talk_base::scoped_refptr<PeerConnectionInterface>
CreatePeerConnection_s(const PeerConnectionInterface::IceServers & configuration,const MediaConstraintsInterface * constraints,PortAllocatorFactoryInterface * allocator_factory,DTLSIdentityServiceInterface * dtls_identity_service,PeerConnectionObserver * observer)302 PeerConnectionFactory::CreatePeerConnection_s(
303 const PeerConnectionInterface::IceServers& configuration,
304 const MediaConstraintsInterface* constraints,
305 PortAllocatorFactoryInterface* allocator_factory,
306 DTLSIdentityServiceInterface* dtls_identity_service,
307 PeerConnectionObserver* observer) {
308 ASSERT(allocator_factory || allocator_factory_);
309 talk_base::scoped_refptr<PeerConnection> pc(
310 new talk_base::RefCountedObject<PeerConnection>(this));
311 if (!pc->Initialize(
312 configuration,
313 constraints,
314 allocator_factory ? allocator_factory : allocator_factory_.get(),
315 dtls_identity_service,
316 observer)) {
317 return NULL;
318 }
319 return PeerConnectionProxy::Create(signaling_thread(), pc);
320 }
321
322 scoped_refptr<MediaStreamInterface>
CreateLocalMediaStream(const std::string & label)323 PeerConnectionFactory::CreateLocalMediaStream(const std::string& label) {
324 return MediaStreamProxy::Create(signaling_thread_,
325 MediaStream::Create(label));
326 }
327
328 talk_base::scoped_refptr<AudioSourceInterface>
CreateAudioSource(const MediaConstraintsInterface * constraints)329 PeerConnectionFactory::CreateAudioSource(
330 const MediaConstraintsInterface* constraints) {
331 CreateAudioSourceParams params(constraints);
332 signaling_thread_->Send(this, MSG_CREATE_AUDIOSOURCE, ¶ms);
333 return params.source;
334 }
335
336 talk_base::scoped_refptr<VideoSourceInterface>
CreateVideoSource(cricket::VideoCapturer * capturer,const MediaConstraintsInterface * constraints)337 PeerConnectionFactory::CreateVideoSource(
338 cricket::VideoCapturer* capturer,
339 const MediaConstraintsInterface* constraints) {
340
341 CreateVideoSourceParams params(capturer,
342 constraints);
343 signaling_thread_->Send(this, MSG_CREATE_VIDEOSOURCE, ¶ms);
344 return params.source;
345 }
346
347 talk_base::scoped_refptr<VideoTrackInterface>
CreateVideoTrack(const std::string & id,VideoSourceInterface * source)348 PeerConnectionFactory::CreateVideoTrack(
349 const std::string& id,
350 VideoSourceInterface* source) {
351 talk_base::scoped_refptr<VideoTrackInterface> track(
352 VideoTrack::Create(id, source));
353 return VideoTrackProxy::Create(signaling_thread_, track);
354 }
355
CreateAudioTrack(const std::string & id,AudioSourceInterface * source)356 scoped_refptr<AudioTrackInterface> PeerConnectionFactory::CreateAudioTrack(
357 const std::string& id,
358 AudioSourceInterface* source) {
359 talk_base::scoped_refptr<AudioTrackInterface> track(
360 AudioTrack::Create(id, source));
361 return AudioTrackProxy::Create(signaling_thread_, track);
362 }
363
channel_manager()364 cricket::ChannelManager* PeerConnectionFactory::channel_manager() {
365 return channel_manager_.get();
366 }
367
signaling_thread()368 talk_base::Thread* PeerConnectionFactory::signaling_thread() {
369 return signaling_thread_;
370 }
371
worker_thread()372 talk_base::Thread* PeerConnectionFactory::worker_thread() {
373 return worker_thread_;
374 }
375
376 } // namespace webrtc
377