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