Home | History | Annotate | Download | only in webrtc
      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 {
     53   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 {
     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 
     88 struct 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 
     97 struct 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 
    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>
    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>
    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 
    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 
    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 
    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 
    186 bool PeerConnectionFactory::Initialize() {
    187   InitMessageData result(false);
    188   signaling_thread_->Send(this, MSG_INIT_FACTORY, &result);
    189   return result.data();
    190 }
    191 
    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 
    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.
    255 void PeerConnectionFactory::Terminate_s() {
    256   channel_manager_.reset(NULL);
    257   allocator_factory_ = NULL;
    258 }
    259 
    260 talk_base::scoped_refptr<AudioSourceInterface>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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 
    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 
    364 cricket::ChannelManager* PeerConnectionFactory::channel_manager() {
    365   return channel_manager_.get();
    366 }
    367 
    368 talk_base::Thread* PeerConnectionFactory::signaling_thread() {
    369   return signaling_thread_;
    370 }
    371 
    372 talk_base::Thread* PeerConnectionFactory::worker_thread() {
    373   return worker_thread_;
    374 }
    375 
    376 }  // namespace webrtc
    377