• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &params);
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, &params);
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, &params);
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