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