Home | History | Annotate | Download | only in video
      1 /*
      2  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include <assert.h>
     12 #include <string.h>
     13 
     14 #include <map>
     15 #include <vector>
     16 
     17 #include "webrtc/call.h"
     18 #include "webrtc/common.h"
     19 #include "webrtc/config.h"
     20 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
     21 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
     22 #include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
     23 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
     24 #include "webrtc/system_wrappers/interface/thread_annotations.h"
     25 #include "webrtc/system_wrappers/interface/trace.h"
     26 #include "webrtc/video/video_receive_stream.h"
     27 #include "webrtc/video/video_send_stream.h"
     28 #include "webrtc/video_engine/include/vie_base.h"
     29 #include "webrtc/video_engine/include/vie_codec.h"
     30 #include "webrtc/video_engine/include/vie_rtp_rtcp.h"
     31 
     32 namespace webrtc {
     33 const char* RtpExtension::kTOffset = "urn:ietf:params:rtp-hdrext:toffset";
     34 const char* RtpExtension::kAbsSendTime =
     35     "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time";
     36 namespace internal {
     37 
     38 class CpuOveruseObserverProxy : public webrtc::CpuOveruseObserver {
     39  public:
     40   CpuOveruseObserverProxy(OveruseCallback* overuse_callback)
     41       : crit_(CriticalSectionWrapper::CreateCriticalSection()),
     42         overuse_callback_(overuse_callback) {
     43     assert(overuse_callback != NULL);
     44   }
     45 
     46   virtual ~CpuOveruseObserverProxy() {}
     47 
     48   virtual void OveruseDetected() OVERRIDE {
     49     CriticalSectionScoped lock(crit_.get());
     50     overuse_callback_->OnOveruse();
     51   }
     52 
     53   virtual void NormalUsage() OVERRIDE {
     54     CriticalSectionScoped lock(crit_.get());
     55     overuse_callback_->OnNormalUse();
     56   }
     57 
     58  private:
     59   const scoped_ptr<CriticalSectionWrapper> crit_;
     60   OveruseCallback* overuse_callback_ GUARDED_BY(crit_);
     61 };
     62 
     63 class Call : public webrtc::Call, public PacketReceiver {
     64  public:
     65   Call(webrtc::VideoEngine* video_engine, const Call::Config& config);
     66   virtual ~Call();
     67 
     68   virtual PacketReceiver* Receiver() OVERRIDE;
     69 
     70   virtual VideoSendStream::Config GetDefaultSendConfig() OVERRIDE;
     71 
     72   virtual VideoSendStream* CreateVideoSendStream(
     73       const VideoSendStream::Config& config,
     74       const std::vector<VideoStream>& video_streams,
     75       const void* encoder_settings) OVERRIDE;
     76 
     77   virtual void DestroyVideoSendStream(webrtc::VideoSendStream* send_stream)
     78       OVERRIDE;
     79 
     80   virtual VideoReceiveStream::Config GetDefaultReceiveConfig() OVERRIDE;
     81 
     82   virtual VideoReceiveStream* CreateVideoReceiveStream(
     83       const VideoReceiveStream::Config& config) OVERRIDE;
     84 
     85   virtual void DestroyVideoReceiveStream(
     86       webrtc::VideoReceiveStream* receive_stream) OVERRIDE;
     87 
     88   virtual uint32_t SendBitrateEstimate() OVERRIDE;
     89   virtual uint32_t ReceiveBitrateEstimate() OVERRIDE;
     90 
     91   virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
     92                                        size_t length) OVERRIDE;
     93 
     94  private:
     95   DeliveryStatus DeliverRtcp(const uint8_t* packet, size_t length);
     96   DeliveryStatus DeliverRtp(const RTPHeader& header,
     97                             const uint8_t* packet,
     98                             size_t length);
     99 
    100   Call::Config config_;
    101 
    102   std::map<uint32_t, VideoReceiveStream*> receive_ssrcs_
    103       GUARDED_BY(receive_lock_);
    104   scoped_ptr<RWLockWrapper> receive_lock_;
    105 
    106   std::map<uint32_t, VideoSendStream*> send_ssrcs_ GUARDED_BY(send_lock_);
    107   scoped_ptr<RWLockWrapper> send_lock_;
    108 
    109   scoped_ptr<RtpHeaderParser> rtp_header_parser_;
    110 
    111   scoped_ptr<CpuOveruseObserverProxy> overuse_observer_proxy_;
    112 
    113   VideoEngine* video_engine_;
    114   ViERTP_RTCP* rtp_rtcp_;
    115   ViECodec* codec_;
    116   ViEBase* base_;
    117   int base_channel_id_;
    118 
    119   DISALLOW_COPY_AND_ASSIGN(Call);
    120 };
    121 }  // namespace internal
    122 
    123 Call* Call::Create(const Call::Config& config) {
    124   VideoEngine* video_engine = config.webrtc_config != NULL
    125                                   ? VideoEngine::Create(*config.webrtc_config)
    126                                   : VideoEngine::Create();
    127   assert(video_engine != NULL);
    128 
    129   return new internal::Call(video_engine, config);
    130 }
    131 
    132 namespace internal {
    133 
    134 const int kDefaultVideoStreamBitrateBps = 300000;
    135 
    136 Call::Call(webrtc::VideoEngine* video_engine, const Call::Config& config)
    137     : config_(config),
    138       receive_lock_(RWLockWrapper::CreateRWLock()),
    139       send_lock_(RWLockWrapper::CreateRWLock()),
    140       rtp_header_parser_(RtpHeaderParser::Create()),
    141       video_engine_(video_engine),
    142       base_channel_id_(-1) {
    143   assert(video_engine != NULL);
    144   assert(config.send_transport != NULL);
    145 
    146   if (config.overuse_callback) {
    147     overuse_observer_proxy_.reset(
    148         new CpuOveruseObserverProxy(config.overuse_callback));
    149   }
    150 
    151   rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine_);
    152   assert(rtp_rtcp_ != NULL);
    153 
    154   codec_ = ViECodec::GetInterface(video_engine_);
    155   assert(codec_ != NULL);
    156 
    157   // As a workaround for non-existing calls in the old API, create a base
    158   // channel used as default channel when creating send and receive streams.
    159   base_ = ViEBase::GetInterface(video_engine_);
    160   assert(base_ != NULL);
    161 
    162   base_->CreateChannel(base_channel_id_);
    163   assert(base_channel_id_ != -1);
    164 }
    165 
    166 Call::~Call() {
    167   base_->DeleteChannel(base_channel_id_);
    168   base_->Release();
    169   codec_->Release();
    170   rtp_rtcp_->Release();
    171   webrtc::VideoEngine::Delete(video_engine_);
    172 }
    173 
    174 PacketReceiver* Call::Receiver() { return this; }
    175 
    176 VideoSendStream::Config Call::GetDefaultSendConfig() {
    177   VideoSendStream::Config config;
    178   return config;
    179 }
    180 
    181 VideoSendStream* Call::CreateVideoSendStream(
    182     const VideoSendStream::Config& config,
    183     const std::vector<VideoStream>& video_streams,
    184     const void* encoder_settings) {
    185   assert(config.rtp.ssrcs.size() > 0);
    186 
    187   // TODO(mflodman): Base the start bitrate on a current bandwidth estimate, if
    188   // the call has already started.
    189   VideoSendStream* send_stream = new VideoSendStream(
    190       config_.send_transport,
    191       overuse_observer_proxy_.get(),
    192       video_engine_,
    193       config,
    194       video_streams,
    195       encoder_settings,
    196       base_channel_id_,
    197       config_.start_bitrate_bps != -1 ? config_.start_bitrate_bps
    198                                       : kDefaultVideoStreamBitrateBps);
    199 
    200   WriteLockScoped write_lock(*send_lock_);
    201   for (size_t i = 0; i < config.rtp.ssrcs.size(); ++i) {
    202     assert(send_ssrcs_.find(config.rtp.ssrcs[i]) == send_ssrcs_.end());
    203     send_ssrcs_[config.rtp.ssrcs[i]] = send_stream;
    204   }
    205   return send_stream;
    206 }
    207 
    208 void Call::DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) {
    209   assert(send_stream != NULL);
    210 
    211   VideoSendStream* send_stream_impl = NULL;
    212   {
    213     WriteLockScoped write_lock(*send_lock_);
    214     for (std::map<uint32_t, VideoSendStream*>::iterator it =
    215              send_ssrcs_.begin();
    216          it != send_ssrcs_.end();
    217          ++it) {
    218       if (it->second == static_cast<VideoSendStream*>(send_stream)) {
    219         send_stream_impl = it->second;
    220         send_ssrcs_.erase(it);
    221         break;
    222       }
    223     }
    224   }
    225 
    226   assert(send_stream_impl != NULL);
    227   delete send_stream_impl;
    228 }
    229 
    230 VideoReceiveStream::Config Call::GetDefaultReceiveConfig() {
    231   VideoReceiveStream::Config config;
    232   config.rtp.remb = true;
    233   return config;
    234 }
    235 
    236 VideoReceiveStream* Call::CreateVideoReceiveStream(
    237     const VideoReceiveStream::Config& config) {
    238   VideoReceiveStream* receive_stream =
    239       new VideoReceiveStream(video_engine_,
    240                              config,
    241                              config_.send_transport,
    242                              config_.voice_engine,
    243                              base_channel_id_);
    244 
    245   WriteLockScoped write_lock(*receive_lock_);
    246   assert(receive_ssrcs_.find(config.rtp.remote_ssrc) == receive_ssrcs_.end());
    247   receive_ssrcs_[config.rtp.remote_ssrc] = receive_stream;
    248   // TODO(pbos): Configure different RTX payloads per receive payload.
    249   VideoReceiveStream::Config::Rtp::RtxMap::const_iterator it =
    250       config.rtp.rtx.begin();
    251   if (it != config.rtp.rtx.end())
    252     receive_ssrcs_[it->second.ssrc] = receive_stream;
    253 
    254   return receive_stream;
    255 }
    256 
    257 void Call::DestroyVideoReceiveStream(
    258     webrtc::VideoReceiveStream* receive_stream) {
    259   assert(receive_stream != NULL);
    260 
    261   VideoReceiveStream* receive_stream_impl = NULL;
    262   {
    263     WriteLockScoped write_lock(*receive_lock_);
    264     // Remove all ssrcs pointing to a receive stream. As RTX retransmits on a
    265     // separate SSRC there can be either one or two.
    266     std::map<uint32_t, VideoReceiveStream*>::iterator it =
    267         receive_ssrcs_.begin();
    268     while (it != receive_ssrcs_.end()) {
    269       if (it->second == static_cast<VideoReceiveStream*>(receive_stream)) {
    270         assert(receive_stream_impl == NULL ||
    271             receive_stream_impl == it->second);
    272         receive_stream_impl = it->second;
    273         receive_ssrcs_.erase(it++);
    274       } else {
    275         ++it;
    276       }
    277     }
    278   }
    279 
    280   assert(receive_stream_impl != NULL);
    281   delete receive_stream_impl;
    282 }
    283 
    284 uint32_t Call::SendBitrateEstimate() {
    285   // TODO(pbos): Return send-bitrate estimate
    286   return 0;
    287 }
    288 
    289 uint32_t Call::ReceiveBitrateEstimate() {
    290   // TODO(pbos): Return receive-bitrate estimate
    291   return 0;
    292 }
    293 
    294 Call::PacketReceiver::DeliveryStatus Call::DeliverRtcp(const uint8_t* packet,
    295                                                        size_t length) {
    296   // TODO(pbos): Figure out what channel needs it actually.
    297   //             Do NOT broadcast! Also make sure it's a valid packet.
    298   //             Return DELIVERY_UNKNOWN_SSRC if it can be determined that
    299   //             there's no receiver of the packet.
    300   bool rtcp_delivered = false;
    301   {
    302     ReadLockScoped read_lock(*receive_lock_);
    303     for (std::map<uint32_t, VideoReceiveStream*>::iterator it =
    304              receive_ssrcs_.begin();
    305          it != receive_ssrcs_.end();
    306          ++it) {
    307       if (it->second->DeliverRtcp(packet, length))
    308         rtcp_delivered = true;
    309     }
    310   }
    311 
    312   {
    313     ReadLockScoped read_lock(*send_lock_);
    314     for (std::map<uint32_t, VideoSendStream*>::iterator it =
    315              send_ssrcs_.begin();
    316          it != send_ssrcs_.end();
    317          ++it) {
    318       if (it->second->DeliverRtcp(packet, length))
    319         rtcp_delivered = true;
    320     }
    321   }
    322   return rtcp_delivered ? DELIVERY_OK : DELIVERY_PACKET_ERROR;
    323 }
    324 
    325 Call::PacketReceiver::DeliveryStatus Call::DeliverRtp(const RTPHeader& header,
    326                                                       const uint8_t* packet,
    327                                                       size_t length) {
    328   ReadLockScoped read_lock(*receive_lock_);
    329   std::map<uint32_t, VideoReceiveStream*>::iterator it =
    330       receive_ssrcs_.find(header.ssrc);
    331 
    332   if (it == receive_ssrcs_.end())
    333     return DELIVERY_UNKNOWN_SSRC;
    334 
    335   return it->second->DeliverRtp(static_cast<const uint8_t*>(packet), length)
    336              ? DELIVERY_OK
    337              : DELIVERY_PACKET_ERROR;
    338 }
    339 
    340 Call::PacketReceiver::DeliveryStatus Call::DeliverPacket(const uint8_t* packet,
    341                                                          size_t length) {
    342   // TODO(pbos): ExtensionMap if there are extensions.
    343   if (RtpHeaderParser::IsRtcp(packet, static_cast<int>(length)))
    344     return DeliverRtcp(packet, length);
    345 
    346   RTPHeader rtp_header;
    347   if (!rtp_header_parser_->Parse(packet, static_cast<int>(length), &rtp_header))
    348     return DELIVERY_PACKET_ERROR;
    349 
    350   return DeliverRtp(rtp_header, packet, length);
    351 }
    352 
    353 }  // namespace internal
    354 }  // namespace webrtc
    355