• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/base/thread_annotations.h"
18 #include "webrtc/call.h"
19 #include "webrtc/common.h"
20 #include "webrtc/config.h"
21 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
22 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
23 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
24 #include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
25 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
26 #include "webrtc/system_wrappers/interface/trace.h"
27 #include "webrtc/video/video_receive_stream.h"
28 #include "webrtc/video/video_send_stream.h"
29 #include "webrtc/video_engine/include/vie_base.h"
30 #include "webrtc/video_engine/include/vie_codec.h"
31 #include "webrtc/video_engine/include/vie_rtp_rtcp.h"
32 #include "webrtc/video_engine/include/vie_network.h"
33 #include "webrtc/video_engine/include/vie_rtp_rtcp.h"
34 
35 namespace webrtc {
36 const char* RtpExtension::kTOffset = "urn:ietf:params:rtp-hdrext:toffset";
37 const char* RtpExtension::kAbsSendTime =
38     "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time";
39 
IsSupported(const std::string & name)40 bool RtpExtension::IsSupported(const std::string& name) {
41   return name == webrtc::RtpExtension::kTOffset ||
42          name == webrtc::RtpExtension::kAbsSendTime;
43 }
44 
Create(VideoEncoder::EncoderType codec_type)45 VideoEncoder* VideoEncoder::Create(VideoEncoder::EncoderType codec_type) {
46   switch (codec_type) {
47     case kVp8:
48       return VP8Encoder::Create();
49   }
50   assert(false);
51   return NULL;
52 }
53 
54 namespace internal {
55 
56 class CpuOveruseObserverProxy : public webrtc::CpuOveruseObserver {
57  public:
CpuOveruseObserverProxy(OveruseCallback * overuse_callback)58   explicit CpuOveruseObserverProxy(OveruseCallback* overuse_callback)
59       : crit_(CriticalSectionWrapper::CreateCriticalSection()),
60         overuse_callback_(overuse_callback) {
61     assert(overuse_callback != NULL);
62   }
63 
~CpuOveruseObserverProxy()64   virtual ~CpuOveruseObserverProxy() {}
65 
OveruseDetected()66   virtual void OveruseDetected() OVERRIDE {
67     CriticalSectionScoped lock(crit_.get());
68     overuse_callback_->OnOveruse();
69   }
70 
NormalUsage()71   virtual void NormalUsage() OVERRIDE {
72     CriticalSectionScoped lock(crit_.get());
73     overuse_callback_->OnNormalUse();
74   }
75 
76  private:
77   const scoped_ptr<CriticalSectionWrapper> crit_;
78   OveruseCallback* overuse_callback_ GUARDED_BY(crit_);
79 };
80 
81 class Call : public webrtc::Call, public PacketReceiver {
82  public:
83   Call(webrtc::VideoEngine* video_engine, const Call::Config& config);
84   virtual ~Call();
85 
86   virtual PacketReceiver* Receiver() OVERRIDE;
87 
88   virtual VideoSendStream* CreateVideoSendStream(
89       const VideoSendStream::Config& config,
90       const VideoEncoderConfig& encoder_config) OVERRIDE;
91 
92   virtual void DestroyVideoSendStream(webrtc::VideoSendStream* send_stream)
93       OVERRIDE;
94 
95   virtual VideoReceiveStream* CreateVideoReceiveStream(
96       const VideoReceiveStream::Config& config) OVERRIDE;
97 
98   virtual void DestroyVideoReceiveStream(
99       webrtc::VideoReceiveStream* receive_stream) OVERRIDE;
100 
101   virtual uint32_t SendBitrateEstimate() OVERRIDE;
102   virtual uint32_t ReceiveBitrateEstimate() OVERRIDE;
103 
104   virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
105                                        size_t length) OVERRIDE;
106 
107   virtual void SignalNetworkState(NetworkState state) OVERRIDE;
108 
109  private:
110   DeliveryStatus DeliverRtcp(const uint8_t* packet, size_t length);
111   DeliveryStatus DeliverRtp(const uint8_t* packet, size_t length);
112 
113   Call::Config config_;
114 
115   // Needs to be held while write-locking |receive_crit_| or |send_crit_|. This
116   // ensures that we have a consistent network state signalled to all senders
117   // and receivers.
118   scoped_ptr<CriticalSectionWrapper> network_enabled_crit_;
119   bool network_enabled_ GUARDED_BY(network_enabled_crit_);
120 
121   scoped_ptr<RWLockWrapper> receive_crit_;
122   std::map<uint32_t, VideoReceiveStream*> receive_ssrcs_
123       GUARDED_BY(receive_crit_);
124 
125   scoped_ptr<RWLockWrapper> send_crit_;
126   std::map<uint32_t, VideoSendStream*> send_ssrcs_ GUARDED_BY(send_crit_);
127 
128   scoped_ptr<CpuOveruseObserverProxy> overuse_observer_proxy_;
129 
130   VideoSendStream::RtpStateMap suspended_send_ssrcs_;
131 
132   VideoEngine* video_engine_;
133   ViERTP_RTCP* rtp_rtcp_;
134   ViECodec* codec_;
135   ViEBase* base_;
136   int base_channel_id_;
137 
138   DISALLOW_COPY_AND_ASSIGN(Call);
139 };
140 }  // namespace internal
141 
Create(const Call::Config & config)142 Call* Call::Create(const Call::Config& config) {
143   VideoEngine* video_engine = config.webrtc_config != NULL
144                                   ? VideoEngine::Create(*config.webrtc_config)
145                                   : VideoEngine::Create();
146   assert(video_engine != NULL);
147 
148   return new internal::Call(video_engine, config);
149 }
150 
151 namespace internal {
152 
153 const int kDefaultVideoStreamBitrateBps = 300000;
154 
Call(webrtc::VideoEngine * video_engine,const Call::Config & config)155 Call::Call(webrtc::VideoEngine* video_engine, const Call::Config& config)
156     : config_(config),
157       network_enabled_crit_(CriticalSectionWrapper::CreateCriticalSection()),
158       network_enabled_(true),
159       receive_crit_(RWLockWrapper::CreateRWLock()),
160       send_crit_(RWLockWrapper::CreateRWLock()),
161       video_engine_(video_engine),
162       base_channel_id_(-1) {
163   assert(video_engine != NULL);
164   assert(config.send_transport != NULL);
165 
166   if (config.overuse_callback) {
167     overuse_observer_proxy_.reset(
168         new CpuOveruseObserverProxy(config.overuse_callback));
169   }
170 
171   rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine_);
172   assert(rtp_rtcp_ != NULL);
173 
174   codec_ = ViECodec::GetInterface(video_engine_);
175   assert(codec_ != NULL);
176 
177   // As a workaround for non-existing calls in the old API, create a base
178   // channel used as default channel when creating send and receive streams.
179   base_ = ViEBase::GetInterface(video_engine_);
180   assert(base_ != NULL);
181 
182   base_->CreateChannel(base_channel_id_);
183   assert(base_channel_id_ != -1);
184 }
185 
~Call()186 Call::~Call() {
187   base_->DeleteChannel(base_channel_id_);
188   base_->Release();
189   codec_->Release();
190   rtp_rtcp_->Release();
191   webrtc::VideoEngine::Delete(video_engine_);
192 }
193 
Receiver()194 PacketReceiver* Call::Receiver() { return this; }
195 
CreateVideoSendStream(const VideoSendStream::Config & config,const VideoEncoderConfig & encoder_config)196 VideoSendStream* Call::CreateVideoSendStream(
197     const VideoSendStream::Config& config,
198     const VideoEncoderConfig& encoder_config) {
199   assert(config.rtp.ssrcs.size() > 0);
200 
201   // TODO(mflodman): Base the start bitrate on a current bandwidth estimate, if
202   // the call has already started.
203   VideoSendStream* send_stream = new VideoSendStream(
204       config_.send_transport,
205       overuse_observer_proxy_.get(),
206       video_engine_,
207       config,
208       encoder_config,
209       suspended_send_ssrcs_,
210       base_channel_id_,
211       config_.start_bitrate_bps != -1 ? config_.start_bitrate_bps
212                                       : kDefaultVideoStreamBitrateBps);
213 
214   // This needs to be taken before send_crit_ as both locks need to be held
215   // while changing network state.
216   CriticalSectionScoped lock(network_enabled_crit_.get());
217   WriteLockScoped write_lock(*send_crit_);
218   for (size_t i = 0; i < config.rtp.ssrcs.size(); ++i) {
219     assert(send_ssrcs_.find(config.rtp.ssrcs[i]) == send_ssrcs_.end());
220     send_ssrcs_[config.rtp.ssrcs[i]] = send_stream;
221   }
222   if (!network_enabled_)
223     send_stream->SignalNetworkState(kNetworkDown);
224   return send_stream;
225 }
226 
DestroyVideoSendStream(webrtc::VideoSendStream * send_stream)227 void Call::DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) {
228   assert(send_stream != NULL);
229 
230   send_stream->Stop();
231 
232   VideoSendStream* send_stream_impl = NULL;
233   {
234     WriteLockScoped write_lock(*send_crit_);
235     std::map<uint32_t, VideoSendStream*>::iterator it = send_ssrcs_.begin();
236     while (it != send_ssrcs_.end()) {
237       if (it->second == static_cast<VideoSendStream*>(send_stream)) {
238         send_stream_impl = it->second;
239         send_ssrcs_.erase(it++);
240       } else {
241         ++it;
242       }
243     }
244   }
245 
246   VideoSendStream::RtpStateMap rtp_state = send_stream_impl->GetRtpStates();
247 
248   for (VideoSendStream::RtpStateMap::iterator it = rtp_state.begin();
249        it != rtp_state.end();
250        ++it) {
251     suspended_send_ssrcs_[it->first] = it->second;
252   }
253 
254   assert(send_stream_impl != NULL);
255   delete send_stream_impl;
256 }
257 
CreateVideoReceiveStream(const VideoReceiveStream::Config & config)258 VideoReceiveStream* Call::CreateVideoReceiveStream(
259     const VideoReceiveStream::Config& config) {
260   VideoReceiveStream* receive_stream =
261       new VideoReceiveStream(video_engine_,
262                              config,
263                              config_.send_transport,
264                              config_.voice_engine,
265                              base_channel_id_);
266 
267   // This needs to be taken before receive_crit_ as both locks need to be held
268   // while changing network state.
269   CriticalSectionScoped lock(network_enabled_crit_.get());
270   WriteLockScoped write_lock(*receive_crit_);
271   assert(receive_ssrcs_.find(config.rtp.remote_ssrc) == receive_ssrcs_.end());
272   receive_ssrcs_[config.rtp.remote_ssrc] = receive_stream;
273   // TODO(pbos): Configure different RTX payloads per receive payload.
274   VideoReceiveStream::Config::Rtp::RtxMap::const_iterator it =
275       config.rtp.rtx.begin();
276   if (it != config.rtp.rtx.end())
277     receive_ssrcs_[it->second.ssrc] = receive_stream;
278 
279   if (!network_enabled_)
280     receive_stream->SignalNetworkState(kNetworkDown);
281   return receive_stream;
282 }
283 
DestroyVideoReceiveStream(webrtc::VideoReceiveStream * receive_stream)284 void Call::DestroyVideoReceiveStream(
285     webrtc::VideoReceiveStream* receive_stream) {
286   assert(receive_stream != NULL);
287 
288   VideoReceiveStream* receive_stream_impl = NULL;
289   {
290     WriteLockScoped write_lock(*receive_crit_);
291     // Remove all ssrcs pointing to a receive stream. As RTX retransmits on a
292     // separate SSRC there can be either one or two.
293     std::map<uint32_t, VideoReceiveStream*>::iterator it =
294         receive_ssrcs_.begin();
295     while (it != receive_ssrcs_.end()) {
296       if (it->second == static_cast<VideoReceiveStream*>(receive_stream)) {
297         assert(receive_stream_impl == NULL ||
298             receive_stream_impl == it->second);
299         receive_stream_impl = it->second;
300         receive_ssrcs_.erase(it++);
301       } else {
302         ++it;
303       }
304     }
305   }
306 
307   assert(receive_stream_impl != NULL);
308   delete receive_stream_impl;
309 }
310 
SendBitrateEstimate()311 uint32_t Call::SendBitrateEstimate() {
312   // TODO(pbos): Return send-bitrate estimate
313   return 0;
314 }
315 
ReceiveBitrateEstimate()316 uint32_t Call::ReceiveBitrateEstimate() {
317   // TODO(pbos): Return receive-bitrate estimate
318   return 0;
319 }
320 
SignalNetworkState(NetworkState state)321 void Call::SignalNetworkState(NetworkState state) {
322   // Take crit for entire function, it needs to be held while updating streams
323   // to guarantee a consistent state across streams.
324   CriticalSectionScoped lock(network_enabled_crit_.get());
325   network_enabled_ = state == kNetworkUp;
326   {
327     ReadLockScoped write_lock(*send_crit_);
328     for (std::map<uint32_t, VideoSendStream*>::iterator it =
329              send_ssrcs_.begin();
330          it != send_ssrcs_.end();
331          ++it) {
332       it->second->SignalNetworkState(state);
333     }
334   }
335   {
336     ReadLockScoped write_lock(*receive_crit_);
337     for (std::map<uint32_t, VideoReceiveStream*>::iterator it =
338              receive_ssrcs_.begin();
339          it != receive_ssrcs_.end();
340          ++it) {
341       it->second->SignalNetworkState(state);
342     }
343   }
344 }
345 
DeliverRtcp(const uint8_t * packet,size_t length)346 PacketReceiver::DeliveryStatus Call::DeliverRtcp(const uint8_t* packet,
347                                                        size_t length) {
348   // TODO(pbos): Figure out what channel needs it actually.
349   //             Do NOT broadcast! Also make sure it's a valid packet.
350   //             Return DELIVERY_UNKNOWN_SSRC if it can be determined that
351   //             there's no receiver of the packet.
352   bool rtcp_delivered = false;
353   {
354     ReadLockScoped read_lock(*receive_crit_);
355     for (std::map<uint32_t, VideoReceiveStream*>::iterator it =
356              receive_ssrcs_.begin();
357          it != receive_ssrcs_.end();
358          ++it) {
359       if (it->second->DeliverRtcp(packet, length))
360         rtcp_delivered = true;
361     }
362   }
363 
364   {
365     ReadLockScoped read_lock(*send_crit_);
366     for (std::map<uint32_t, VideoSendStream*>::iterator it =
367              send_ssrcs_.begin();
368          it != send_ssrcs_.end();
369          ++it) {
370       if (it->second->DeliverRtcp(packet, length))
371         rtcp_delivered = true;
372     }
373   }
374   return rtcp_delivered ? DELIVERY_OK : DELIVERY_PACKET_ERROR;
375 }
376 
DeliverRtp(const uint8_t * packet,size_t length)377 PacketReceiver::DeliveryStatus Call::DeliverRtp(const uint8_t* packet,
378                                                 size_t length) {
379   // Minimum RTP header size.
380   if (length < 12)
381     return DELIVERY_PACKET_ERROR;
382 
383   const uint8_t* ptr = &packet[8];
384   uint32_t ssrc = ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3];
385 
386   ReadLockScoped read_lock(*receive_crit_);
387   std::map<uint32_t, VideoReceiveStream*>::iterator it =
388       receive_ssrcs_.find(ssrc);
389 
390   if (it == receive_ssrcs_.end())
391     return DELIVERY_UNKNOWN_SSRC;
392 
393   return it->second->DeliverRtp(packet, length) ? DELIVERY_OK
394                                                 : DELIVERY_PACKET_ERROR;
395 }
396 
DeliverPacket(const uint8_t * packet,size_t length)397 PacketReceiver::DeliveryStatus Call::DeliverPacket(const uint8_t* packet,
398                                                    size_t length) {
399   if (RtpHeaderParser::IsRtcp(packet, length))
400     return DeliverRtcp(packet, length);
401 
402   return DeliverRtp(packet, length);
403 }
404 
405 }  // namespace internal
406 }  // namespace webrtc
407