blob: 1f162b1f348e460e0be8fcbe1bbdbfe4f5db5715 [file] [log] [blame]
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001/*
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
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000011#include <string.h>
12
pbos@webrtc.org29d58392013-05-16 12:08:03 +000013#include <map>
14#include <vector>
15
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000016#include "webrtc/base/checks.h"
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +000017#include "webrtc/base/scoped_ptr.h"
pbos@webrtc.org38344ed2014-09-24 06:05:00 +000018#include "webrtc/base/thread_annotations.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000019#include "webrtc/call.h"
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000020#include "webrtc/common.h"
pbos@webrtc.orgc49d5b72013-12-05 12:11:47 +000021#include "webrtc/config.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000022#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
sprang@webrtc.org2a6558c2015-01-28 12:37:36 +000023#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000024#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
marpan@webrtc.org5b883172014-11-01 06:10:48 +000025#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
pbos@webrtc.org9e4e5242015-02-12 10:48:23 +000026#include "webrtc/modules/video_render/include/video_render.h"
pbos@webrtc.orgde74b642013-10-02 13:36:09 +000027#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
pbos@webrtc.org32e85282015-01-15 10:09:39 +000028#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000029#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
pbos@webrtc.orgde74b642013-10-02 13:36:09 +000030#include "webrtc/system_wrappers/interface/trace.h"
pbos@webrtc.org50fe3592015-01-29 12:33:07 +000031#include "webrtc/system_wrappers/interface/trace_event.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000032#include "webrtc/video/video_receive_stream.h"
33#include "webrtc/video/video_send_stream.h"
pbos@webrtc.org29d58392013-05-16 12:08:03 +000034#include "webrtc/video_engine/include/vie_base.h"
35#include "webrtc/video_engine/include/vie_codec.h"
36#include "webrtc/video_engine/include/vie_rtp_rtcp.h"
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000037#include "webrtc/video_engine/include/vie_network.h"
38#include "webrtc/video_engine/include/vie_rtp_rtcp.h"
pbos@webrtc.org29d58392013-05-16 12:08:03 +000039
40namespace webrtc {
pbos@webrtc.orgc49d5b72013-12-05 12:11:47 +000041const char* RtpExtension::kTOffset = "urn:ietf:params:rtp-hdrext:toffset";
42const char* RtpExtension::kAbsSendTime =
43 "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time";
guoweis@webrtc.orgfdd10572015-03-12 20:50:57 +000044const char* RtpExtension::kVideoRotation = "urn:3gpp:video-orientation";
pbos@webrtc.org3c107582014-07-20 15:27:35 +000045
46bool RtpExtension::IsSupported(const std::string& name) {
47 return name == webrtc::RtpExtension::kTOffset ||
guoweis@webrtc.orgfdd10572015-03-12 20:50:57 +000048 name == webrtc::RtpExtension::kAbsSendTime ||
49 name == webrtc::RtpExtension::kVideoRotation;
pbos@webrtc.org3c107582014-07-20 15:27:35 +000050}
51
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000052VideoEncoder* VideoEncoder::Create(VideoEncoder::EncoderType codec_type) {
53 switch (codec_type) {
54 case kVp8:
55 return VP8Encoder::Create();
marpan@webrtc.org5b883172014-11-01 06:10:48 +000056 case kVp9:
57 return VP9Encoder::Create();
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000058 }
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000059 RTC_NOTREACHED();
60 return nullptr;
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000061}
62
pbos@webrtc.org776e6f22014-10-29 15:28:39 +000063VideoDecoder* VideoDecoder::Create(VideoDecoder::DecoderType codec_type) {
64 switch (codec_type) {
65 case kVp8:
66 return VP8Decoder::Create();
stefan@webrtc.org7c29e8c2014-11-04 19:41:15 +000067 case kVp9:
68 return VP9Decoder::Create();
pbos@webrtc.org776e6f22014-10-29 15:28:39 +000069 }
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000070 RTC_NOTREACHED();
71 return nullptr;
pbos@webrtc.org776e6f22014-10-29 15:28:39 +000072}
73
pbos@webrtc.orga73a6782014-10-14 11:52:10 +000074const int Call::Config::kDefaultStartBitrateBps = 300000;
75
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000076namespace internal {
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +000077
78class CpuOveruseObserverProxy : public webrtc::CpuOveruseObserver {
79 public:
pbos@webrtc.org42684be2014-10-03 11:25:45 +000080 explicit CpuOveruseObserverProxy(LoadObserver* overuse_callback)
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +000081 : crit_(CriticalSectionWrapper::CreateCriticalSection()),
82 overuse_callback_(overuse_callback) {
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000083 DCHECK(overuse_callback != nullptr);
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +000084 }
85
86 virtual ~CpuOveruseObserverProxy() {}
87
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000088 void OveruseDetected() override {
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +000089 CriticalSectionScoped lock(crit_.get());
pbos@webrtc.org42684be2014-10-03 11:25:45 +000090 overuse_callback_->OnLoadUpdate(LoadObserver::kOveruse);
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +000091 }
92
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000093 void NormalUsage() override {
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +000094 CriticalSectionScoped lock(crit_.get());
pbos@webrtc.org42684be2014-10-03 11:25:45 +000095 overuse_callback_->OnLoadUpdate(LoadObserver::kUnderuse);
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +000096 }
97
98 private:
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +000099 const rtc::scoped_ptr<CriticalSectionWrapper> crit_;
pbos@webrtc.org42684be2014-10-03 11:25:45 +0000100 LoadObserver* overuse_callback_ GUARDED_BY(crit_);
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +0000101};
102
pbos@webrtc.org16e03b72013-10-28 16:32:01 +0000103class Call : public webrtc::Call, public PacketReceiver {
104 public:
105 Call(webrtc::VideoEngine* video_engine, const Call::Config& config);
106 virtual ~Call();
107
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000108 PacketReceiver* Receiver() override;
pbos@webrtc.org16e03b72013-10-28 16:32:01 +0000109
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000110 VideoSendStream* CreateVideoSendStream(
pbos@webrtc.org6ae48c62014-06-06 10:49:19 +0000111 const VideoSendStream::Config& config,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000112 const VideoEncoderConfig& encoder_config) override;
pbos@webrtc.org16e03b72013-10-28 16:32:01 +0000113
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000114 void DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) override;
pbos@webrtc.org16e03b72013-10-28 16:32:01 +0000115
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000116 VideoReceiveStream* CreateVideoReceiveStream(
117 const VideoReceiveStream::Config& config) override;
pbos@webrtc.org16e03b72013-10-28 16:32:01 +0000118
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000119 void DestroyVideoReceiveStream(
120 webrtc::VideoReceiveStream* receive_stream) override;
pbos@webrtc.org16e03b72013-10-28 16:32:01 +0000121
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000122 Stats GetStats() const override;
pbos@webrtc.org16e03b72013-10-28 16:32:01 +0000123
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000124 DeliveryStatus DeliverPacket(const uint8_t* packet, size_t length) override;
pbos@webrtc.org16e03b72013-10-28 16:32:01 +0000125
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000126 void SetBitrateConfig(
127 const webrtc::Call::Config::BitrateConfig& bitrate_config) override;
128 void SignalNetworkState(NetworkState state) override;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000129
pbos@webrtc.org16e03b72013-10-28 16:32:01 +0000130 private:
pbos@webrtc.orgcaba2d22014-05-14 13:57:12 +0000131 DeliveryStatus DeliverRtcp(const uint8_t* packet, size_t length);
pbos@webrtc.orgaf38f4e2014-07-08 07:38:12 +0000132 DeliveryStatus DeliverRtp(const uint8_t* packet, size_t length);
pbos@webrtc.org16e03b72013-10-28 16:32:01 +0000133
134 Call::Config config_;
135
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000136 // Needs to be held while write-locking |receive_crit_| or |send_crit_|. This
137 // ensures that we have a consistent network state signalled to all senders
138 // and receivers.
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000139 rtc::scoped_ptr<CriticalSectionWrapper> network_enabled_crit_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000140 bool network_enabled_ GUARDED_BY(network_enabled_crit_);
pbos@webrtc.org16e03b72013-10-28 16:32:01 +0000141
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000142 rtc::scoped_ptr<RWLockWrapper> receive_crit_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000143 std::map<uint32_t, VideoReceiveStream*> receive_ssrcs_
144 GUARDED_BY(receive_crit_);
Peter Boström3f4eed02015-04-16 15:59:43 +0200145 std::set<VideoReceiveStream*> receive_streams_ GUARDED_BY(receive_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000146
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000147 rtc::scoped_ptr<RWLockWrapper> send_crit_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000148 std::map<uint32_t, VideoSendStream*> send_ssrcs_ GUARDED_BY(send_crit_);
Peter Boström74b97692015-04-14 13:31:46 +0200149 std::set<VideoSendStream*> send_streams_ GUARDED_BY(send_crit_);
pbos@webrtc.org16e03b72013-10-28 16:32:01 +0000150
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000151 rtc::scoped_ptr<CpuOveruseObserverProxy> overuse_observer_proxy_;
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +0000152
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000153 VideoSendStream::RtpStateMap suspended_send_ssrcs_;
154
mflodman@webrtc.orgf3973e82013-12-13 09:40:45 +0000155 VideoEngine* video_engine_;
pbos@webrtc.org16e03b72013-10-28 16:32:01 +0000156 ViERTP_RTCP* rtp_rtcp_;
157 ViECodec* codec_;
pbos@webrtc.org9e4e5242015-02-12 10:48:23 +0000158 ViERender* render_;
mflodman@webrtc.orgf3973e82013-12-13 09:40:45 +0000159 ViEBase* base_;
Stefan Holmere5904162015-03-26 11:11:06 +0100160 ViENetwork* network_;
mflodman@webrtc.orgf3973e82013-12-13 09:40:45 +0000161 int base_channel_id_;
Peter Boström76c53d32015-04-09 14:35:37 +0200162 ChannelGroup* channel_group_;
pbos@webrtc.org16e03b72013-10-28 16:32:01 +0000163
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000164 rtc::scoped_ptr<VideoRender> external_render_;
pbos@webrtc.org9e4e5242015-02-12 10:48:23 +0000165
pbos@webrtc.org16e03b72013-10-28 16:32:01 +0000166 DISALLOW_COPY_AND_ASSIGN(Call);
167};
pbos@webrtc.orgc49d5b72013-12-05 12:11:47 +0000168} // namespace internal
pbos@webrtc.orgfd39e132013-08-14 13:52:52 +0000169
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000170Call* Call::Create(const Call::Config& config) {
Peter Boström76c53d32015-04-09 14:35:37 +0200171 VideoEngine* video_engine = VideoEngine::Create();
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000172 DCHECK(video_engine != nullptr);
pbos@webrtc.orgfd39e132013-08-14 13:52:52 +0000173
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000174 return new internal::Call(video_engine, config);
pbos@webrtc.orgfd39e132013-08-14 13:52:52 +0000175}
pbos@webrtc.orgfd39e132013-08-14 13:52:52 +0000176
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000177namespace internal {
178
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000179Call::Call(webrtc::VideoEngine* video_engine, const Call::Config& config)
mflodman@webrtc.org6879c8a2013-07-23 11:35:00 +0000180 : config_(config),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000181 network_enabled_crit_(CriticalSectionWrapper::CreateCriticalSection()),
182 network_enabled_(true),
183 receive_crit_(RWLockWrapper::CreateRWLock()),
184 send_crit_(RWLockWrapper::CreateRWLock()),
mflodman@webrtc.orgf3973e82013-12-13 09:40:45 +0000185 video_engine_(video_engine),
pbos@webrtc.org9e4e5242015-02-12 10:48:23 +0000186 base_channel_id_(-1),
187 external_render_(
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000188 VideoRender::CreateVideoRender(42, nullptr, false, kRenderExternal)) {
189 DCHECK(video_engine != nullptr);
190 DCHECK(config.send_transport != nullptr);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000191
Stefan Holmere5904162015-03-26 11:11:06 +0100192 DCHECK_GE(config.bitrate_config.min_bitrate_bps, 0);
193 DCHECK_GE(config.bitrate_config.start_bitrate_bps,
194 config.bitrate_config.min_bitrate_bps);
195 if (config.bitrate_config.max_bitrate_bps != -1) {
196 DCHECK_GE(config.bitrate_config.max_bitrate_bps,
197 config.bitrate_config.start_bitrate_bps);
pbos@webrtc.org00873182014-11-25 14:03:34 +0000198 }
199
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +0000200 if (config.overuse_callback) {
201 overuse_observer_proxy_.reset(
202 new CpuOveruseObserverProxy(config.overuse_callback));
203 }
204
pbos@webrtc.org9e4e5242015-02-12 10:48:23 +0000205 render_ = ViERender::GetInterface(video_engine_);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000206 DCHECK(render_ != nullptr);
pbos@webrtc.org9e4e5242015-02-12 10:48:23 +0000207
208 render_->RegisterVideoRenderModule(*external_render_.get());
209
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000210 rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine_);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000211 DCHECK(rtp_rtcp_ != nullptr);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000212
213 codec_ = ViECodec::GetInterface(video_engine_);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000214 DCHECK(codec_ != nullptr);
mflodman@webrtc.orgf3973e82013-12-13 09:40:45 +0000215
Stefan Holmere5904162015-03-26 11:11:06 +0100216 network_ = ViENetwork::GetInterface(video_engine_);
217
mflodman@webrtc.orgf3973e82013-12-13 09:40:45 +0000218 // As a workaround for non-existing calls in the old API, create a base
219 // channel used as default channel when creating send and receive streams.
220 base_ = ViEBase::GetInterface(video_engine_);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000221 DCHECK(base_ != nullptr);
mflodman@webrtc.orgf3973e82013-12-13 09:40:45 +0000222
223 base_->CreateChannel(base_channel_id_);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000224 DCHECK(base_channel_id_ != -1);
Peter Boström76c53d32015-04-09 14:35:37 +0200225 channel_group_ = base_->GetChannelGroup(base_channel_id_);
Stefan Holmere5904162015-03-26 11:11:06 +0100226
227 network_->SetBitrateConfig(base_channel_id_,
228 config_.bitrate_config.min_bitrate_bps,
229 config_.bitrate_config.start_bitrate_bps,
230 config_.bitrate_config.max_bitrate_bps);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000231}
232
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000233Call::~Call() {
Peter Boström9b5f96e2015-03-26 11:25:49 +0100234 CHECK_EQ(0u, send_ssrcs_.size());
Peter Boström74b97692015-04-14 13:31:46 +0200235 CHECK_EQ(0u, send_streams_.size());
Peter Boström9b5f96e2015-03-26 11:25:49 +0100236 CHECK_EQ(0u, receive_ssrcs_.size());
Peter Boström3f4eed02015-04-16 15:59:43 +0200237 CHECK_EQ(0u, receive_streams_.size());
mflodman@webrtc.orgf3973e82013-12-13 09:40:45 +0000238 base_->DeleteChannel(base_channel_id_);
pbos@webrtc.org9e4e5242015-02-12 10:48:23 +0000239
240 render_->DeRegisterVideoRenderModule(*external_render_.get());
241
mflodman@webrtc.orgf3973e82013-12-13 09:40:45 +0000242 base_->Release();
Stefan Holmere5904162015-03-26 11:11:06 +0100243 network_->Release();
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000244 codec_->Release();
pbos@webrtc.org9e4e5242015-02-12 10:48:23 +0000245 render_->Release();
pbos@webrtc.orgfd39e132013-08-14 13:52:52 +0000246 rtp_rtcp_->Release();
Peter Boström9b5f96e2015-03-26 11:25:49 +0100247 CHECK(webrtc::VideoEngine::Delete(video_engine_));
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000248}
249
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000250PacketReceiver* Call::Receiver() { return this; }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000251
pbos@webrtc.org5a636552013-11-20 10:40:25 +0000252VideoSendStream* Call::CreateVideoSendStream(
pbos@webrtc.org6ae48c62014-06-06 10:49:19 +0000253 const VideoSendStream::Config& config,
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000254 const VideoEncoderConfig& encoder_config) {
pbos@webrtc.org50fe3592015-01-29 12:33:07 +0000255 TRACE_EVENT0("webrtc", "Call::CreateVideoSendStream");
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000256 LOG(LS_INFO) << "CreateVideoSendStream: " << config.ToString();
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000257 DCHECK(!config.rtp.ssrcs.empty());
pbos@webrtc.org1819fd72013-06-10 13:48:26 +0000258
mflodman@webrtc.orgeb16b812014-06-16 08:57:39 +0000259 // TODO(mflodman): Base the start bitrate on a current bandwidth estimate, if
260 // the call has already started.
Peter Boström59d91dc2015-04-27 17:24:33 +0200261 VideoSendStream* send_stream =
262 new VideoSendStream(config_.send_transport, overuse_observer_proxy_.get(),
263 video_engine_, channel_group_, config, encoder_config,
264 suspended_send_ssrcs_, base_channel_id_);
pbos@webrtc.org1819fd72013-06-10 13:48:26 +0000265
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000266 // This needs to be taken before send_crit_ as both locks need to be held
267 // while changing network state.
268 CriticalSectionScoped lock(network_enabled_crit_.get());
269 WriteLockScoped write_lock(*send_crit_);
Peter Boström74b97692015-04-14 13:31:46 +0200270 send_streams_.insert(send_stream);
pbos@webrtc.org1819fd72013-06-10 13:48:26 +0000271 for (size_t i = 0; i < config.rtp.ssrcs.size(); ++i) {
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000272 DCHECK(send_ssrcs_.find(config.rtp.ssrcs[i]) == send_ssrcs_.end());
pbos@webrtc.org1819fd72013-06-10 13:48:26 +0000273 send_ssrcs_[config.rtp.ssrcs[i]] = send_stream;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000274 }
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000275 if (!network_enabled_)
276 send_stream->SignalNetworkState(kNetworkDown);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000277 return send_stream;
278}
279
pbos@webrtc.org2c46f8d2013-11-21 13:49:43 +0000280void Call::DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) {
pbos@webrtc.org50fe3592015-01-29 12:33:07 +0000281 TRACE_EVENT0("webrtc", "Call::DestroyVideoSendStream");
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000282 DCHECK(send_stream != nullptr);
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000283
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000284 send_stream->Stop();
285
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000286 VideoSendStream* send_stream_impl = nullptr;
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000287 {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000288 WriteLockScoped write_lock(*send_crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000289 std::map<uint32_t, VideoSendStream*>::iterator it = send_ssrcs_.begin();
290 while (it != send_ssrcs_.end()) {
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000291 if (it->second == static_cast<VideoSendStream*>(send_stream)) {
292 send_stream_impl = it->second;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000293 send_ssrcs_.erase(it++);
294 } else {
295 ++it;
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000296 }
297 }
Peter Boström74b97692015-04-14 13:31:46 +0200298 send_streams_.erase(send_stream_impl);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000299 }
Peter Boström9b5f96e2015-03-26 11:25:49 +0100300 CHECK(send_stream_impl != nullptr);
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000301
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000302 VideoSendStream::RtpStateMap rtp_state = send_stream_impl->GetRtpStates();
303
304 for (VideoSendStream::RtpStateMap::iterator it = rtp_state.begin();
305 it != rtp_state.end();
306 ++it) {
307 suspended_send_ssrcs_[it->first] = it->second;
308 }
309
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000310 delete send_stream_impl;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000311}
312
pbos@webrtc.org5a636552013-11-20 10:40:25 +0000313VideoReceiveStream* Call::CreateVideoReceiveStream(
pbos@webrtc.org74fa4892013-08-23 09:19:30 +0000314 const VideoReceiveStream::Config& config) {
pbos@webrtc.org50fe3592015-01-29 12:33:07 +0000315 TRACE_EVENT0("webrtc", "Call::CreateVideoReceiveStream");
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000316 LOG(LS_INFO) << "CreateVideoReceiveStream: " << config.ToString();
Peter Boströmc4188fd2015-04-24 15:16:03 +0200317 VideoReceiveStream* receive_stream = new VideoReceiveStream(
318 video_engine_, channel_group_, config, config_.send_transport,
319 config_.voice_engine, base_channel_id_);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000320
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000321 // This needs to be taken before receive_crit_ as both locks need to be held
322 // while changing network state.
323 CriticalSectionScoped lock(network_enabled_crit_.get());
324 WriteLockScoped write_lock(*receive_crit_);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000325 DCHECK(receive_ssrcs_.find(config.rtp.remote_ssrc) == receive_ssrcs_.end());
pbos@webrtc.orgb613b5a2013-12-03 10:13:04 +0000326 receive_ssrcs_[config.rtp.remote_ssrc] = receive_stream;
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000327 // TODO(pbos): Configure different RTX payloads per receive payload.
328 VideoReceiveStream::Config::Rtp::RtxMap::const_iterator it =
329 config.rtp.rtx.begin();
330 if (it != config.rtp.rtx.end())
331 receive_ssrcs_[it->second.ssrc] = receive_stream;
Peter Boström3f4eed02015-04-16 15:59:43 +0200332 receive_streams_.insert(receive_stream);
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000333
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000334 if (!network_enabled_)
335 receive_stream->SignalNetworkState(kNetworkDown);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000336 return receive_stream;
337}
338
pbos@webrtc.org2c46f8d2013-11-21 13:49:43 +0000339void Call::DestroyVideoReceiveStream(
340 webrtc::VideoReceiveStream* receive_stream) {
pbos@webrtc.org50fe3592015-01-29 12:33:07 +0000341 TRACE_EVENT0("webrtc", "Call::DestroyVideoReceiveStream");
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000342 DCHECK(receive_stream != nullptr);
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000343
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000344 VideoReceiveStream* receive_stream_impl = nullptr;
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000345 {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000346 WriteLockScoped write_lock(*receive_crit_);
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000347 // Remove all ssrcs pointing to a receive stream. As RTX retransmits on a
348 // separate SSRC there can be either one or two.
349 std::map<uint32_t, VideoReceiveStream*>::iterator it =
350 receive_ssrcs_.begin();
351 while (it != receive_ssrcs_.end()) {
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000352 if (it->second == static_cast<VideoReceiveStream*>(receive_stream)) {
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000353 if (receive_stream_impl != nullptr)
354 DCHECK(receive_stream_impl == it->second);
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000355 receive_stream_impl = it->second;
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000356 receive_ssrcs_.erase(it++);
357 } else {
358 ++it;
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000359 }
360 }
Peter Boström3f4eed02015-04-16 15:59:43 +0200361 receive_streams_.erase(receive_stream_impl);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000362 }
Peter Boström9b5f96e2015-03-26 11:25:49 +0100363 CHECK(receive_stream_impl != nullptr);
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000364 delete receive_stream_impl;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000365}
366
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000367Call::Stats Call::GetStats() const {
368 Stats stats;
369 // Ignoring return values.
370 uint32_t send_bandwidth = 0;
371 rtp_rtcp_->GetEstimatedSendBandwidth(base_channel_id_, &send_bandwidth);
372 stats.send_bandwidth_bps = send_bandwidth;
373 uint32_t recv_bandwidth = 0;
374 rtp_rtcp_->GetEstimatedReceiveBandwidth(base_channel_id_, &recv_bandwidth);
375 stats.recv_bandwidth_bps = recv_bandwidth;
Peter Boström59d91dc2015-04-27 17:24:33 +0200376 stats.pacer_delay_ms = channel_group_->GetPacerQueuingDelayMs();
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000377 {
378 ReadLockScoped read_lock(*send_crit_);
379 for (std::map<uint32_t, VideoSendStream*>::const_iterator it =
380 send_ssrcs_.begin();
381 it != send_ssrcs_.end();
382 ++it) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +0000383 int rtt_ms = it->second->GetRtt();
384 if (rtt_ms > 0)
385 stats.rtt_ms = rtt_ms;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000386 }
387 }
388 return stats;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000389}
390
pbos@webrtc.org00873182014-11-25 14:03:34 +0000391void Call::SetBitrateConfig(
392 const webrtc::Call::Config::BitrateConfig& bitrate_config) {
pbos@webrtc.org50fe3592015-01-29 12:33:07 +0000393 TRACE_EVENT0("webrtc", "Call::SetBitrateConfig");
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000394 DCHECK_GE(bitrate_config.min_bitrate_bps, 0);
395 if (bitrate_config.max_bitrate_bps != -1)
396 DCHECK_GT(bitrate_config.max_bitrate_bps, 0);
Stefan Holmere5904162015-03-26 11:11:06 +0100397 if (config_.bitrate_config.min_bitrate_bps ==
pbos@webrtc.org00873182014-11-25 14:03:34 +0000398 bitrate_config.min_bitrate_bps &&
399 (bitrate_config.start_bitrate_bps <= 0 ||
Stefan Holmere5904162015-03-26 11:11:06 +0100400 config_.bitrate_config.start_bitrate_bps ==
pbos@webrtc.org00873182014-11-25 14:03:34 +0000401 bitrate_config.start_bitrate_bps) &&
Stefan Holmere5904162015-03-26 11:11:06 +0100402 config_.bitrate_config.max_bitrate_bps ==
pbos@webrtc.org00873182014-11-25 14:03:34 +0000403 bitrate_config.max_bitrate_bps) {
404 // Nothing new to set, early abort to avoid encoder reconfigurations.
405 return;
406 }
Stefan Holmere5904162015-03-26 11:11:06 +0100407 config_.bitrate_config = bitrate_config;
408 network_->SetBitrateConfig(base_channel_id_, bitrate_config.min_bitrate_bps,
409 bitrate_config.start_bitrate_bps,
410 bitrate_config.max_bitrate_bps);
pbos@webrtc.org00873182014-11-25 14:03:34 +0000411}
412
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000413void Call::SignalNetworkState(NetworkState state) {
414 // Take crit for entire function, it needs to be held while updating streams
415 // to guarantee a consistent state across streams.
416 CriticalSectionScoped lock(network_enabled_crit_.get());
417 network_enabled_ = state == kNetworkUp;
418 {
419 ReadLockScoped write_lock(*send_crit_);
420 for (std::map<uint32_t, VideoSendStream*>::iterator it =
421 send_ssrcs_.begin();
422 it != send_ssrcs_.end();
423 ++it) {
424 it->second->SignalNetworkState(state);
425 }
426 }
427 {
428 ReadLockScoped write_lock(*receive_crit_);
429 for (std::map<uint32_t, VideoReceiveStream*>::iterator it =
430 receive_ssrcs_.begin();
431 it != receive_ssrcs_.end();
432 ++it) {
433 it->second->SignalNetworkState(state);
434 }
435 }
436}
437
pbos@webrtc.orgaf38f4e2014-07-08 07:38:12 +0000438PacketReceiver::DeliveryStatus Call::DeliverRtcp(const uint8_t* packet,
pbos@webrtc.orgcaba2d22014-05-14 13:57:12 +0000439 size_t length) {
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000440 // TODO(pbos): Figure out what channel needs it actually.
441 // Do NOT broadcast! Also make sure it's a valid packet.
pbos@webrtc.orgcaba2d22014-05-14 13:57:12 +0000442 // Return DELIVERY_UNKNOWN_SSRC if it can be determined that
443 // there's no receiver of the packet.
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000444 bool rtcp_delivered = false;
pbos@webrtc.org40523702013-08-05 12:49:22 +0000445 {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000446 ReadLockScoped read_lock(*receive_crit_);
Peter Boström3f4eed02015-04-16 15:59:43 +0200447 for (VideoReceiveStream* stream : receive_streams_) {
448 if (stream->DeliverRtcp(packet, length))
pbos@webrtc.org40523702013-08-05 12:49:22 +0000449 rtcp_delivered = true;
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000450 }
451 }
pbos@webrtc.org40523702013-08-05 12:49:22 +0000452 {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000453 ReadLockScoped read_lock(*send_crit_);
Peter Boström3f4eed02015-04-16 15:59:43 +0200454 for (VideoSendStream* stream : send_streams_) {
Peter Boström74b97692015-04-14 13:31:46 +0200455 if (stream->DeliverRtcp(packet, length))
pbos@webrtc.org40523702013-08-05 12:49:22 +0000456 rtcp_delivered = true;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000457 }
458 }
pbos@webrtc.orgcaba2d22014-05-14 13:57:12 +0000459 return rtcp_delivered ? DELIVERY_OK : DELIVERY_PACKET_ERROR;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000460}
461
pbos@webrtc.orgaf38f4e2014-07-08 07:38:12 +0000462PacketReceiver::DeliveryStatus Call::DeliverRtp(const uint8_t* packet,
463 size_t length) {
464 // Minimum RTP header size.
465 if (length < 12)
466 return DELIVERY_PACKET_ERROR;
467
sprang@webrtc.org2a6558c2015-01-28 12:37:36 +0000468 uint32_t ssrc = ByteReader<uint32_t>::ReadBigEndian(&packet[8]);
pbos@webrtc.orgaf38f4e2014-07-08 07:38:12 +0000469
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000470 ReadLockScoped read_lock(*receive_crit_);
solenberg@webrtc.org094ac392014-01-29 11:21:58 +0000471 std::map<uint32_t, VideoReceiveStream*>::iterator it =
pbos@webrtc.orgaf38f4e2014-07-08 07:38:12 +0000472 receive_ssrcs_.find(ssrc);
pbos@webrtc.orgcaba2d22014-05-14 13:57:12 +0000473
474 if (it == receive_ssrcs_.end())
475 return DELIVERY_UNKNOWN_SSRC;
476
pbos@webrtc.orgaf38f4e2014-07-08 07:38:12 +0000477 return it->second->DeliverRtp(packet, length) ? DELIVERY_OK
478 : DELIVERY_PACKET_ERROR;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000479}
480
pbos@webrtc.orgaf38f4e2014-07-08 07:38:12 +0000481PacketReceiver::DeliveryStatus Call::DeliverPacket(const uint8_t* packet,
482 size_t length) {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000483 if (RtpHeaderParser::IsRtcp(packet, length))
pbos@webrtc.org40523702013-08-05 12:49:22 +0000484 return DeliverRtcp(packet, length);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000485
pbos@webrtc.orgaf38f4e2014-07-08 07:38:12 +0000486 return DeliverRtp(packet, length);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000487}
488
489} // namespace internal
490} // namespace webrtc