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 <utility>
     31 
     32 #include "talk/app/webrtc/audiotrack.h"
     33 #include "talk/app/webrtc/localaudiosource.h"
     34 #include "talk/app/webrtc/mediastream.h"
     35 #include "talk/app/webrtc/mediastreamproxy.h"
     36 #include "talk/app/webrtc/mediastreamtrackproxy.h"
     37 #include "talk/app/webrtc/peerconnection.h"
     38 #include "talk/app/webrtc/peerconnectionfactoryproxy.h"
     39 #include "talk/app/webrtc/peerconnectionproxy.h"
     40 #include "talk/app/webrtc/videosource.h"
     41 #include "talk/app/webrtc/videosourceproxy.h"
     42 #include "talk/app/webrtc/videotrack.h"
     43 #include "talk/media/webrtc/webrtcmediaengine.h"
     44 #include "talk/media/webrtc/webrtcvideodecoderfactory.h"
     45 #include "talk/media/webrtc/webrtcvideoencoderfactory.h"
     46 #include "webrtc/base/bind.h"
     47 #include "webrtc/modules/audio_device/include/audio_device.h"
     48 #include "webrtc/p2p/base/basicpacketsocketfactory.h"
     49 #include "webrtc/p2p/client/basicportallocator.h"
     50 
     51 namespace webrtc {
     52 
     53 namespace {
     54 
     55 // Passes down the calls to |store_|. See usage in CreatePeerConnection.
     56 class DtlsIdentityStoreWrapper : public DtlsIdentityStoreInterface {
     57  public:
     58   DtlsIdentityStoreWrapper(
     59       const rtc::scoped_refptr<RefCountedDtlsIdentityStore>& store)
     60       : store_(store) {
     61     RTC_DCHECK(store_);
     62   }
     63 
     64   void RequestIdentity(
     65       rtc::KeyType key_type,
     66       const rtc::scoped_refptr<webrtc::DtlsIdentityRequestObserver>&
     67           observer) override {
     68     store_->RequestIdentity(key_type, observer);
     69   }
     70 
     71  private:
     72   rtc::scoped_refptr<RefCountedDtlsIdentityStore> store_;
     73 };
     74 
     75 }  // anonymous namespace
     76 
     77 rtc::scoped_refptr<PeerConnectionFactoryInterface>
     78 CreatePeerConnectionFactory() {
     79   rtc::scoped_refptr<PeerConnectionFactory> pc_factory(
     80       new rtc::RefCountedObject<PeerConnectionFactory>());
     81 
     82 
     83   // Call Initialize synchronously but make sure its executed on
     84   // |signaling_thread|.
     85   MethodCall0<PeerConnectionFactory, bool> call(
     86       pc_factory.get(),
     87       &PeerConnectionFactory::Initialize);
     88   bool result =  call.Marshal(pc_factory->signaling_thread());
     89 
     90   if (!result) {
     91     return NULL;
     92   }
     93   return PeerConnectionFactoryProxy::Create(pc_factory->signaling_thread(),
     94                                             pc_factory);
     95 }
     96 
     97 rtc::scoped_refptr<PeerConnectionFactoryInterface>
     98 CreatePeerConnectionFactory(
     99     rtc::Thread* worker_thread,
    100     rtc::Thread* signaling_thread,
    101     AudioDeviceModule* default_adm,
    102     cricket::WebRtcVideoEncoderFactory* encoder_factory,
    103     cricket::WebRtcVideoDecoderFactory* decoder_factory) {
    104   rtc::scoped_refptr<PeerConnectionFactory> pc_factory(
    105       new rtc::RefCountedObject<PeerConnectionFactory>(worker_thread,
    106                                                        signaling_thread,
    107                                                        default_adm,
    108                                                        encoder_factory,
    109                                                        decoder_factory));
    110 
    111   // Call Initialize synchronously but make sure its executed on
    112   // |signaling_thread|.
    113   MethodCall0<PeerConnectionFactory, bool> call(
    114       pc_factory.get(),
    115       &PeerConnectionFactory::Initialize);
    116   bool result =  call.Marshal(signaling_thread);
    117 
    118   if (!result) {
    119     return NULL;
    120   }
    121   return PeerConnectionFactoryProxy::Create(signaling_thread, pc_factory);
    122 }
    123 
    124 PeerConnectionFactory::PeerConnectionFactory()
    125     : owns_ptrs_(true),
    126       wraps_current_thread_(false),
    127       signaling_thread_(rtc::ThreadManager::Instance()->CurrentThread()),
    128       worker_thread_(new rtc::Thread) {
    129   if (!signaling_thread_) {
    130     signaling_thread_ = rtc::ThreadManager::Instance()->WrapCurrentThread();
    131     wraps_current_thread_ = true;
    132   }
    133   worker_thread_->Start();
    134 }
    135 
    136 PeerConnectionFactory::PeerConnectionFactory(
    137     rtc::Thread* worker_thread,
    138     rtc::Thread* signaling_thread,
    139     AudioDeviceModule* default_adm,
    140     cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
    141     cricket::WebRtcVideoDecoderFactory* video_decoder_factory)
    142     : owns_ptrs_(false),
    143       wraps_current_thread_(false),
    144       signaling_thread_(signaling_thread),
    145       worker_thread_(worker_thread),
    146       default_adm_(default_adm),
    147       video_encoder_factory_(video_encoder_factory),
    148       video_decoder_factory_(video_decoder_factory) {
    149   ASSERT(worker_thread != NULL);
    150   ASSERT(signaling_thread != NULL);
    151   // TODO: Currently there is no way creating an external adm in
    152   // libjingle source tree. So we can 't currently assert if this is NULL.
    153   // ASSERT(default_adm != NULL);
    154 }
    155 
    156 PeerConnectionFactory::~PeerConnectionFactory() {
    157   RTC_DCHECK(signaling_thread_->IsCurrent());
    158   channel_manager_.reset(nullptr);
    159 
    160   // Make sure |worker_thread_| and |signaling_thread_| outlive
    161   // |dtls_identity_store_|, |default_socket_factory_| and
    162   // |default_network_manager_|.
    163   dtls_identity_store_ = nullptr;
    164   default_socket_factory_ = nullptr;
    165   default_network_manager_ = nullptr;
    166 
    167   if (owns_ptrs_) {
    168     if (wraps_current_thread_)
    169       rtc::ThreadManager::Instance()->UnwrapCurrentThread();
    170     delete worker_thread_;
    171   }
    172 }
    173 
    174 bool PeerConnectionFactory::Initialize() {
    175   RTC_DCHECK(signaling_thread_->IsCurrent());
    176   rtc::InitRandom(rtc::Time());
    177 
    178   default_network_manager_.reset(new rtc::BasicNetworkManager());
    179   if (!default_network_manager_) {
    180     return false;
    181   }
    182 
    183   default_socket_factory_.reset(
    184       new rtc::BasicPacketSocketFactory(worker_thread_));
    185   if (!default_socket_factory_) {
    186     return false;
    187   }
    188 
    189   // TODO:  Need to make sure only one VoE is created inside
    190   // WebRtcMediaEngine.
    191   cricket::MediaEngineInterface* media_engine =
    192       worker_thread_->Invoke<cricket::MediaEngineInterface*>(rtc::Bind(
    193       &PeerConnectionFactory::CreateMediaEngine_w, this));
    194 
    195   channel_manager_.reset(
    196       new cricket::ChannelManager(media_engine, worker_thread_));
    197 
    198   channel_manager_->SetVideoRtxEnabled(true);
    199   if (!channel_manager_->Init()) {
    200     return false;
    201   }
    202 
    203   dtls_identity_store_ = new RefCountedDtlsIdentityStore(
    204       signaling_thread_, worker_thread_);
    205 
    206   return true;
    207 }
    208 
    209 rtc::scoped_refptr<AudioSourceInterface>
    210 PeerConnectionFactory::CreateAudioSource(
    211     const MediaConstraintsInterface* constraints) {
    212   RTC_DCHECK(signaling_thread_->IsCurrent());
    213   rtc::scoped_refptr<LocalAudioSource> source(
    214       LocalAudioSource::Create(options_, constraints));
    215   return source;
    216 }
    217 
    218 rtc::scoped_refptr<VideoSourceInterface>
    219 PeerConnectionFactory::CreateVideoSource(
    220     cricket::VideoCapturer* capturer,
    221     const MediaConstraintsInterface* constraints) {
    222   RTC_DCHECK(signaling_thread_->IsCurrent());
    223   rtc::scoped_refptr<VideoSource> source(VideoSource::Create(
    224       channel_manager_.get(), capturer, constraints, false));
    225   return VideoSourceProxy::Create(signaling_thread_, source);
    226 }
    227 
    228 bool PeerConnectionFactory::StartAecDump(rtc::PlatformFile file) {
    229   RTC_DCHECK(signaling_thread_->IsCurrent());
    230   return channel_manager_->StartAecDump(file);
    231 }
    232 
    233 void PeerConnectionFactory::StopAecDump() {
    234   RTC_DCHECK(signaling_thread_->IsCurrent());
    235   channel_manager_->StopAecDump();
    236 }
    237 
    238 bool PeerConnectionFactory::StartRtcEventLog(rtc::PlatformFile file) {
    239   RTC_DCHECK(signaling_thread_->IsCurrent());
    240   return channel_manager_->StartRtcEventLog(file);
    241 }
    242 
    243 void PeerConnectionFactory::StopRtcEventLog() {
    244   RTC_DCHECK(signaling_thread_->IsCurrent());
    245   channel_manager_->StopRtcEventLog();
    246 }
    247 
    248 rtc::scoped_refptr<PeerConnectionInterface>
    249 PeerConnectionFactory::CreatePeerConnection(
    250     const PeerConnectionInterface::RTCConfiguration& configuration,
    251     const MediaConstraintsInterface* constraints,
    252     rtc::scoped_ptr<cricket::PortAllocator> allocator,
    253     rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store,
    254     PeerConnectionObserver* observer) {
    255   RTC_DCHECK(signaling_thread_->IsCurrent());
    256 
    257   if (!dtls_identity_store.get()) {
    258     // Because |pc|->Initialize takes ownership of the store we need a new
    259     // wrapper object that can be deleted without deleting the underlying
    260     // |dtls_identity_store_|, protecting it from being deleted multiple times.
    261     dtls_identity_store.reset(
    262         new DtlsIdentityStoreWrapper(dtls_identity_store_));
    263   }
    264 
    265   if (!allocator) {
    266     allocator.reset(new cricket::BasicPortAllocator(
    267         default_network_manager_.get(), default_socket_factory_.get()));
    268   }
    269   allocator->SetNetworkIgnoreMask(options_.network_ignore_mask);
    270 
    271   rtc::scoped_refptr<PeerConnection> pc(
    272       new rtc::RefCountedObject<PeerConnection>(this));
    273   if (!pc->Initialize(configuration, constraints, std::move(allocator),
    274                       std::move(dtls_identity_store), observer)) {
    275     return nullptr;
    276   }
    277   return PeerConnectionProxy::Create(signaling_thread(), pc);
    278 }
    279 
    280 rtc::scoped_refptr<MediaStreamInterface>
    281 PeerConnectionFactory::CreateLocalMediaStream(const std::string& label) {
    282   RTC_DCHECK(signaling_thread_->IsCurrent());
    283   return MediaStreamProxy::Create(signaling_thread_,
    284                                   MediaStream::Create(label));
    285 }
    286 
    287 rtc::scoped_refptr<VideoTrackInterface>
    288 PeerConnectionFactory::CreateVideoTrack(
    289     const std::string& id,
    290     VideoSourceInterface* source) {
    291   RTC_DCHECK(signaling_thread_->IsCurrent());
    292   rtc::scoped_refptr<VideoTrackInterface> track(
    293       VideoTrack::Create(id, source));
    294   return VideoTrackProxy::Create(signaling_thread_, track);
    295 }
    296 
    297 rtc::scoped_refptr<AudioTrackInterface>
    298 PeerConnectionFactory::CreateAudioTrack(const std::string& id,
    299                                         AudioSourceInterface* source) {
    300   RTC_DCHECK(signaling_thread_->IsCurrent());
    301   rtc::scoped_refptr<AudioTrackInterface> track(AudioTrack::Create(id, source));
    302   return AudioTrackProxy::Create(signaling_thread_, track);
    303 }
    304 
    305 webrtc::MediaControllerInterface* PeerConnectionFactory::CreateMediaController()
    306     const {
    307   RTC_DCHECK(signaling_thread_->IsCurrent());
    308   return MediaControllerInterface::Create(worker_thread_,
    309                                           channel_manager_.get());
    310 }
    311 
    312 rtc::Thread* PeerConnectionFactory::signaling_thread() {
    313   // This method can be called on a different thread when the factory is
    314   // created in CreatePeerConnectionFactory().
    315   return signaling_thread_;
    316 }
    317 
    318 rtc::Thread* PeerConnectionFactory::worker_thread() {
    319   RTC_DCHECK(signaling_thread_->IsCurrent());
    320   return worker_thread_;
    321 }
    322 
    323 cricket::MediaEngineInterface* PeerConnectionFactory::CreateMediaEngine_w() {
    324   ASSERT(worker_thread_ == rtc::Thread::Current());
    325   return cricket::WebRtcMediaEngineFactory::Create(
    326       default_adm_.get(), video_encoder_factory_.get(),
    327       video_decoder_factory_.get());
    328 }
    329 
    330 }  // namespace webrtc
    331