blob: 9c5c126b1a604cbf28ffb86cf9dff1e58943b8f6 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
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/localvideosource.h"
33#include "talk/app/webrtc/mediastreamproxy.h"
34#include "talk/app/webrtc/mediastreamtrackproxy.h"
35#include "talk/app/webrtc/peerconnection.h"
36#include "talk/app/webrtc/peerconnectionproxy.h"
37#include "talk/app/webrtc/portallocatorfactory.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
46using talk_base::scoped_refptr;
47
48namespace {
49
50typedef talk_base::TypedMessageData<bool> InitMessageData;
51
52struct CreatePeerConnectionParams : public talk_base::MessageData {
53 CreatePeerConnectionParams(
54 const webrtc::PeerConnectionInterface::IceServers& configuration,
55 const webrtc::MediaConstraintsInterface* constraints,
56 webrtc::PortAllocatorFactoryInterface* allocator_factory,
wu@webrtc.org91053e72013-08-10 07:18:04 +000057 webrtc::DTLSIdentityServiceInterface* dtls_identity_service,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000058 webrtc::PeerConnectionObserver* observer)
59 : configuration(configuration),
60 constraints(constraints),
61 allocator_factory(allocator_factory),
wu@webrtc.org91053e72013-08-10 07:18:04 +000062 dtls_identity_service(dtls_identity_service),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000063 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;
wu@webrtc.org91053e72013-08-10 07:18:04 +000069 webrtc::DTLSIdentityServiceInterface* dtls_identity_service;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000070 webrtc::PeerConnectionObserver* observer;
71};
72
73struct CreatePeerConnectionParamsDeprecated : public talk_base::MessageData {
74 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
88struct CreateAudioSourceParams : public talk_base::MessageData {
89 explicit CreateAudioSourceParams(
90 const webrtc::MediaConstraintsInterface* constraints)
91 : constraints(constraints) {
92 }
93 const webrtc::MediaConstraintsInterface* constraints;
94 scoped_refptr<webrtc::AudioSourceInterface> source;
95};
96
97struct CreateVideoSourceParams : public talk_base::MessageData {
98 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
108enum {
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
118namespace webrtc {
119
120scoped_refptr<PeerConnectionFactoryInterface>
121CreatePeerConnectionFactory() {
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
131scoped_refptr<PeerConnectionFactoryInterface>
132CreatePeerConnectionFactory(
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
148PeerConnectionFactory::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
158PeerConnectionFactory::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
177PeerConnectionFactory::~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
186bool PeerConnectionFactory::Initialize() {
187 InitMessageData result(false);
188 signaling_thread_->Send(this, MSG_INIT_FACTORY, &result);
189 return result.data();
190}
191
192void PeerConnectionFactory::OnMessage(talk_base::Message* msg) {
193 switch (msg->message_id) {
194 case MSG_INIT_FACTORY: {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000195 InitMessageData* pdata = static_cast<InitMessageData*>(msg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000196 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 =
wu@webrtc.org91053e72013-08-10 07:18:04 +0000205 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);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000212 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 =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000222 static_cast<CreateVideoSourceParams*>(msg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000223 pdata->source = CreateVideoSource_s(pdata->capturer, pdata->constraints);
224 break;
225 }
226 }
227}
228
229bool 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.
255void PeerConnectionFactory::Terminate_s() {
256 channel_manager_.reset(NULL);
257 allocator_factory_ = NULL;
258}
259
260talk_base::scoped_refptr<AudioSourceInterface>
261PeerConnectionFactory::CreateAudioSource_s(
262 const MediaConstraintsInterface* constraints) {
263 talk_base::scoped_refptr<LocalAudioSource> source(
264 LocalAudioSource::Create(constraints));
265 return source;
266}
267
268talk_base::scoped_refptr<VideoSourceInterface>
269PeerConnectionFactory::CreateVideoSource_s(
270 cricket::VideoCapturer* capturer,
271 const MediaConstraintsInterface* constraints) {
272 talk_base::scoped_refptr<LocalVideoSource> source(
273 LocalVideoSource::Create(channel_manager_.get(), capturer,
274 constraints));
275 return VideoSourceProxy::Create(signaling_thread_, source);
276}
277
278scoped_refptr<PeerConnectionInterface>
279PeerConnectionFactory::CreatePeerConnection(
280 const PeerConnectionInterface::IceServers& configuration,
281 const MediaConstraintsInterface* constraints,
282 PortAllocatorFactoryInterface* allocator_factory,
283 DTLSIdentityServiceInterface* dtls_identity_service,
284 PeerConnectionObserver* observer) {
285 CreatePeerConnectionParams params(configuration, constraints,
wu@webrtc.org91053e72013-08-10 07:18:04 +0000286 allocator_factory, dtls_identity_service,
287 observer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000288 signaling_thread_->Send(this, MSG_CREATE_PEERCONNECTION, &params);
289 return params.peerconnection;
290}
291
292scoped_refptr<PeerConnectionInterface>
293PeerConnectionFactory::CreatePeerConnection(
294 const PeerConnectionInterface::IceServers& configuration,
295 const MediaConstraintsInterface* constraints,
296 DTLSIdentityServiceInterface* dtls_identity_service,
297 PeerConnectionObserver* observer) {
298 return CreatePeerConnection(
299 configuration, constraints, NULL, dtls_identity_service, observer);
300}
301
302talk_base::scoped_refptr<PeerConnectionInterface>
303PeerConnectionFactory::CreatePeerConnection_s(
304 const PeerConnectionInterface::IceServers& configuration,
305 const MediaConstraintsInterface* constraints,
306 PortAllocatorFactoryInterface* allocator_factory,
wu@webrtc.org91053e72013-08-10 07:18:04 +0000307 DTLSIdentityServiceInterface* dtls_identity_service,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000308 PeerConnectionObserver* observer) {
309 ASSERT(allocator_factory || allocator_factory_);
310 talk_base::scoped_refptr<PeerConnection> pc(
311 new talk_base::RefCountedObject<PeerConnection>(this));
312 if (!pc->Initialize(
313 configuration,
314 constraints,
315 allocator_factory ? allocator_factory : allocator_factory_.get(),
wu@webrtc.org91053e72013-08-10 07:18:04 +0000316 dtls_identity_service,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000317 observer)) {
318 return NULL;
319 }
320 return PeerConnectionProxy::Create(signaling_thread(), pc);
321}
322
323scoped_refptr<MediaStreamInterface>
324PeerConnectionFactory::CreateLocalMediaStream(const std::string& label) {
325 return MediaStreamProxy::Create(signaling_thread_,
326 MediaStream::Create(label));
327}
328
329talk_base::scoped_refptr<AudioSourceInterface>
330PeerConnectionFactory::CreateAudioSource(
331 const MediaConstraintsInterface* constraints) {
332 CreateAudioSourceParams params(constraints);
333 signaling_thread_->Send(this, MSG_CREATE_AUDIOSOURCE, &params);
334 return params.source;
335}
336
337talk_base::scoped_refptr<VideoSourceInterface>
338PeerConnectionFactory::CreateVideoSource(
339 cricket::VideoCapturer* capturer,
340 const MediaConstraintsInterface* constraints) {
341
342 CreateVideoSourceParams params(capturer,
343 constraints);
344 signaling_thread_->Send(this, MSG_CREATE_VIDEOSOURCE, &params);
345 return params.source;
346}
347
348talk_base::scoped_refptr<VideoTrackInterface>
349PeerConnectionFactory::CreateVideoTrack(
350 const std::string& id,
351 VideoSourceInterface* source) {
352 talk_base::scoped_refptr<VideoTrackInterface> track(
353 VideoTrack::Create(id, source));
354 return VideoTrackProxy::Create(signaling_thread_, track);
355}
356
357scoped_refptr<AudioTrackInterface> PeerConnectionFactory::CreateAudioTrack(
358 const std::string& id,
359 AudioSourceInterface* source) {
360 talk_base::scoped_refptr<AudioTrackInterface> track(
361 AudioTrack::Create(id, source));
362 return AudioTrackProxy::Create(signaling_thread_, track);
363}
364
365cricket::ChannelManager* PeerConnectionFactory::channel_manager() {
366 return channel_manager_.get();
367}
368
369talk_base::Thread* PeerConnectionFactory::signaling_thread() {
370 return signaling_thread_;
371}
372
373talk_base::Thread* PeerConnectionFactory::worker_thread() {
374 return worker_thread_;
375}
376
377} // namespace webrtc