blob: 9a036c9ede2bd8ae32c2de92151a9603401aaeec [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
Peter Boström5c389d32015-09-25 13:58:30 +020016#include "webrtc/audio/audio_receive_stream.h"
solenbergc7a8b082015-10-16 14:35:07 -070017#include "webrtc/audio/audio_send_stream.h"
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000018#include "webrtc/base/checks.h"
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +000019#include "webrtc/base/scoped_ptr.h"
pbos@webrtc.org38344ed2014-09-24 06:05:00 +000020#include "webrtc/base/thread_annotations.h"
solenberg5a289392015-10-19 03:39:20 -070021#include "webrtc/base/thread_checker.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000022#include "webrtc/call.h"
Peter Boström5c389d32015-09-25 13:58:30 +020023#include "webrtc/call/rtc_event_log.h"
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000024#include "webrtc/common.h"
pbos@webrtc.orgc49d5b72013-12-05 12:11:47 +000025#include "webrtc/config.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000026#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
sprang@webrtc.org2a6558c2015-01-28 12:37:36 +000027#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
Peter Boström45553ae2015-05-08 13:54:38 +020028#include "webrtc/modules/utility/interface/process_thread.h"
Peter Boström45553ae2015-05-08 13:54:38 +020029#include "webrtc/system_wrappers/interface/cpu_info.h"
pbos@webrtc.orgde74b642013-10-02 13:36:09 +000030#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
pbos@webrtc.org32e85282015-01-15 10:09:39 +000031#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000032#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
pbos@webrtc.orgde74b642013-10-02 13:36:09 +000033#include "webrtc/system_wrappers/interface/trace.h"
pbos@webrtc.org50fe3592015-01-29 12:33:07 +000034#include "webrtc/system_wrappers/interface/trace_event.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000035#include "webrtc/video/video_receive_stream.h"
36#include "webrtc/video/video_send_stream.h"
ivocb04965c2015-09-09 00:09:43 -070037#include "webrtc/voice_engine/include/voe_codec.h"
pbos@webrtc.org29d58392013-05-16 12:08:03 +000038
39namespace webrtc {
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000040
pbos@webrtc.orga73a6782014-10-14 11:52:10 +000041const int Call::Config::kDefaultStartBitrateBps = 300000;
42
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000043namespace internal {
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +000044
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000045class Call : public webrtc::Call, public PacketReceiver {
46 public:
Peter Boström45553ae2015-05-08 13:54:38 +020047 explicit Call(const Call::Config& config);
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000048 virtual ~Call();
49
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000050 PacketReceiver* Receiver() override;
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000051
Fredrik Solenberg04f49312015-06-08 13:04:56 +020052 webrtc::AudioSendStream* CreateAudioSendStream(
53 const webrtc::AudioSendStream::Config& config) override;
54 void DestroyAudioSendStream(webrtc::AudioSendStream* send_stream) override;
55
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +020056 webrtc::AudioReceiveStream* CreateAudioReceiveStream(
57 const webrtc::AudioReceiveStream::Config& config) override;
58 void DestroyAudioReceiveStream(
59 webrtc::AudioReceiveStream* receive_stream) override;
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000060
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +020061 webrtc::VideoSendStream* CreateVideoSendStream(
62 const webrtc::VideoSendStream::Config& config,
63 const VideoEncoderConfig& encoder_config) override;
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000064 void DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) override;
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000065
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +020066 webrtc::VideoReceiveStream* CreateVideoReceiveStream(
67 const webrtc::VideoReceiveStream::Config& config) override;
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000068 void DestroyVideoReceiveStream(
69 webrtc::VideoReceiveStream* receive_stream) override;
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000070
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000071 Stats GetStats() const override;
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000072
stefan68786d22015-09-08 05:36:15 -070073 DeliveryStatus DeliverPacket(MediaType media_type,
74 const uint8_t* packet,
75 size_t length,
76 const PacketTime& packet_time) override;
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000077
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000078 void SetBitrateConfig(
79 const webrtc::Call::Config::BitrateConfig& bitrate_config) override;
80 void SignalNetworkState(NetworkState state) override;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000081
stefanc1aeaf02015-10-15 07:26:07 -070082 void OnSentPacket(const rtc::SentPacket& sent_packet) override;
83
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000084 private:
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +020085 DeliveryStatus DeliverRtcp(MediaType media_type, const uint8_t* packet,
86 size_t length);
stefan68786d22015-09-08 05:36:15 -070087 DeliveryStatus DeliverRtp(MediaType media_type,
88 const uint8_t* packet,
89 size_t length,
90 const PacketTime& packet_time);
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000091
pbos8fc7fa72015-07-15 08:02:58 -070092 void ConfigureSync(const std::string& sync_group)
93 EXCLUSIVE_LOCKS_REQUIRED(receive_crit_);
94
Peter Boström45553ae2015-05-08 13:54:38 +020095 const int num_cpu_cores_;
96 const rtc::scoped_ptr<ProcessThread> module_process_thread_;
97 const rtc::scoped_ptr<ChannelGroup> channel_group_;
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000098 Call::Config config_;
solenberg5a289392015-10-19 03:39:20 -070099 rtc::ThreadChecker configuration_thread_checker_;
pbos@webrtc.org16e03b72013-10-28 16:32:01 +0000100
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000101 // Needs to be held while write-locking |receive_crit_| or |send_crit_|. This
102 // ensures that we have a consistent network state signalled to all senders
103 // and receivers.
Peter Boströmf2f82832015-05-01 13:00:41 +0200104 rtc::CriticalSection network_enabled_crit_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000105 bool network_enabled_ GUARDED_BY(network_enabled_crit_);
pbos@webrtc.org16e03b72013-10-28 16:32:01 +0000106
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000107 rtc::scoped_ptr<RWLockWrapper> receive_crit_;
solenbergc7a8b082015-10-16 14:35:07 -0700108 // Audio and Video receive streams are owned by the client that creates them.
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200109 std::map<uint32_t, AudioReceiveStream*> audio_receive_ssrcs_
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000110 GUARDED_BY(receive_crit_);
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200111 std::map<uint32_t, VideoReceiveStream*> video_receive_ssrcs_
112 GUARDED_BY(receive_crit_);
113 std::set<VideoReceiveStream*> video_receive_streams_
114 GUARDED_BY(receive_crit_);
pbos8fc7fa72015-07-15 08:02:58 -0700115 std::map<std::string, AudioReceiveStream*> sync_stream_mapping_
116 GUARDED_BY(receive_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000117
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000118 rtc::scoped_ptr<RWLockWrapper> send_crit_;
solenbergc7a8b082015-10-16 14:35:07 -0700119 // Audio and Video send streams are owned by the client that creates them.
120 std::map<uint32_t, AudioSendStream*> audio_send_ssrcs_ GUARDED_BY(send_crit_);
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200121 std::map<uint32_t, VideoSendStream*> video_send_ssrcs_ GUARDED_BY(send_crit_);
122 std::set<VideoSendStream*> video_send_streams_ GUARDED_BY(send_crit_);
pbos@webrtc.org16e03b72013-10-28 16:32:01 +0000123
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200124 VideoSendStream::RtpStateMap suspended_video_send_ssrcs_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000125
ivocb04965c2015-09-09 00:09:43 -0700126 RtcEventLog* event_log_;
127
henrikg3c089d72015-09-16 05:37:44 -0700128 RTC_DISALLOW_COPY_AND_ASSIGN(Call);
pbos@webrtc.org16e03b72013-10-28 16:32:01 +0000129};
pbos@webrtc.orgc49d5b72013-12-05 12:11:47 +0000130} // namespace internal
pbos@webrtc.orgfd39e132013-08-14 13:52:52 +0000131
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000132Call* Call::Create(const Call::Config& config) {
Peter Boström45553ae2015-05-08 13:54:38 +0200133 return new internal::Call(config);
pbos@webrtc.orgfd39e132013-08-14 13:52:52 +0000134}
pbos@webrtc.orgfd39e132013-08-14 13:52:52 +0000135
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000136namespace internal {
137
Peter Boström45553ae2015-05-08 13:54:38 +0200138Call::Call(const Call::Config& config)
139 : num_cpu_cores_(CpuInfo::DetectNumberOfCores()),
stefan847855b2015-09-11 09:52:15 -0700140 module_process_thread_(ProcessThread::Create("ModuleProcessThread")),
Peter Boström2251d6e2015-05-28 14:10:39 +0200141 channel_group_(new ChannelGroup(module_process_thread_.get())),
Peter Boström45553ae2015-05-08 13:54:38 +0200142 config_(config),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000143 network_enabled_(true),
144 receive_crit_(RWLockWrapper::CreateRWLock()),
ivocb04965c2015-09-09 00:09:43 -0700145 send_crit_(RWLockWrapper::CreateRWLock()),
146 event_log_(nullptr) {
solenberg5a289392015-10-19 03:39:20 -0700147 RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
henrikg91d6ede2015-09-17 00:24:34 -0700148 RTC_DCHECK_GE(config.bitrate_config.min_bitrate_bps, 0);
149 RTC_DCHECK_GE(config.bitrate_config.start_bitrate_bps,
150 config.bitrate_config.min_bitrate_bps);
Stefan Holmere5904162015-03-26 11:11:06 +0100151 if (config.bitrate_config.max_bitrate_bps != -1) {
henrikg91d6ede2015-09-17 00:24:34 -0700152 RTC_DCHECK_GE(config.bitrate_config.max_bitrate_bps,
153 config.bitrate_config.start_bitrate_bps);
pbos@webrtc.org00873182014-11-25 14:03:34 +0000154 }
ivocb04965c2015-09-09 00:09:43 -0700155 if (config.voice_engine) {
156 VoECodec* voe_codec = VoECodec::GetInterface(config.voice_engine);
157 if (voe_codec) {
158 event_log_ = voe_codec->GetEventLog();
159 voe_codec->Release();
160 }
161 }
pbos@webrtc.org00873182014-11-25 14:03:34 +0000162
Peter Boström45553ae2015-05-08 13:54:38 +0200163 Trace::CreateTrace();
164 module_process_thread_->Start();
165
stefan4fbd1452015-09-28 03:57:14 -0700166 channel_group_->SetBweBitrates(config_.bitrate_config.min_bitrate_bps,
167 config_.bitrate_config.start_bitrate_bps,
168 config_.bitrate_config.max_bitrate_bps);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000169}
170
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000171Call::~Call() {
solenberg5a289392015-10-19 03:39:20 -0700172 RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
solenbergc7a8b082015-10-16 14:35:07 -0700173 RTC_CHECK(audio_send_ssrcs_.empty());
174 RTC_CHECK(video_send_ssrcs_.empty());
175 RTC_CHECK(video_send_streams_.empty());
176 RTC_CHECK(audio_receive_ssrcs_.empty());
177 RTC_CHECK(video_receive_ssrcs_.empty());
178 RTC_CHECK(video_receive_streams_.empty());
pbos@webrtc.org9e4e5242015-02-12 10:48:23 +0000179
Peter Boström45553ae2015-05-08 13:54:38 +0200180 module_process_thread_->Stop();
181 Trace::ReturnTrace();
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000182}
183
solenberg5a289392015-10-19 03:39:20 -0700184PacketReceiver* Call::Receiver() {
185 // TODO(solenberg): Some test cases in EndToEndTest use this from a different
186 // thread. Re-enable once that is fixed.
187 // RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
188 return this;
189}
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000190
Fredrik Solenberg04f49312015-06-08 13:04:56 +0200191webrtc::AudioSendStream* Call::CreateAudioSendStream(
192 const webrtc::AudioSendStream::Config& config) {
solenbergc7a8b082015-10-16 14:35:07 -0700193 TRACE_EVENT0("webrtc", "Call::CreateAudioSendStream");
solenberg5a289392015-10-19 03:39:20 -0700194 RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
solenbergc7a8b082015-10-16 14:35:07 -0700195 AudioSendStream* send_stream = new AudioSendStream(config);
196 {
197 rtc::CritScope lock(&network_enabled_crit_);
198 WriteLockScoped write_lock(*send_crit_);
199 RTC_DCHECK(audio_send_ssrcs_.find(config.rtp.ssrc) ==
200 audio_send_ssrcs_.end());
201 audio_send_ssrcs_[config.rtp.ssrc] = send_stream;
202
203 if (!network_enabled_)
204 send_stream->SignalNetworkState(kNetworkDown);
205 }
206 return send_stream;
Fredrik Solenberg04f49312015-06-08 13:04:56 +0200207}
208
209void Call::DestroyAudioSendStream(webrtc::AudioSendStream* send_stream) {
solenbergc7a8b082015-10-16 14:35:07 -0700210 TRACE_EVENT0("webrtc", "Call::DestroyAudioSendStream");
solenberg5a289392015-10-19 03:39:20 -0700211 RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
solenbergc7a8b082015-10-16 14:35:07 -0700212 RTC_DCHECK(send_stream != nullptr);
213
214 send_stream->Stop();
215
216 webrtc::internal::AudioSendStream* audio_send_stream =
217 static_cast<webrtc::internal::AudioSendStream*>(send_stream);
218 {
219 WriteLockScoped write_lock(*send_crit_);
220 size_t num_deleted = audio_send_ssrcs_.erase(
221 audio_send_stream->config().rtp.ssrc);
222 RTC_DCHECK(num_deleted == 1);
223 }
224 delete audio_send_stream;
Fredrik Solenberg04f49312015-06-08 13:04:56 +0200225}
226
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200227webrtc::AudioReceiveStream* Call::CreateAudioReceiveStream(
228 const webrtc::AudioReceiveStream::Config& config) {
229 TRACE_EVENT0("webrtc", "Call::CreateAudioReceiveStream");
solenberg5a289392015-10-19 03:39:20 -0700230 RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200231 AudioReceiveStream* receive_stream = new AudioReceiveStream(
mflodmana20de202015-10-18 22:08:19 -0700232 channel_group_->GetRemoteBitrateEstimator(false), config);
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200233 {
234 WriteLockScoped write_lock(*receive_crit_);
henrikg91d6ede2015-09-17 00:24:34 -0700235 RTC_DCHECK(audio_receive_ssrcs_.find(config.rtp.remote_ssrc) ==
236 audio_receive_ssrcs_.end());
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200237 audio_receive_ssrcs_[config.rtp.remote_ssrc] = receive_stream;
pbos8fc7fa72015-07-15 08:02:58 -0700238 ConfigureSync(config.sync_group);
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200239 }
240 return receive_stream;
241}
242
243void Call::DestroyAudioReceiveStream(
244 webrtc::AudioReceiveStream* receive_stream) {
245 TRACE_EVENT0("webrtc", "Call::DestroyAudioReceiveStream");
solenberg5a289392015-10-19 03:39:20 -0700246 RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
henrikg91d6ede2015-09-17 00:24:34 -0700247 RTC_DCHECK(receive_stream != nullptr);
solenbergc7a8b082015-10-16 14:35:07 -0700248 webrtc::internal::AudioReceiveStream* audio_receive_stream =
249 static_cast<webrtc::internal::AudioReceiveStream*>(receive_stream);
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200250 {
251 WriteLockScoped write_lock(*receive_crit_);
252 size_t num_deleted = audio_receive_ssrcs_.erase(
253 audio_receive_stream->config().rtp.remote_ssrc);
henrikg91d6ede2015-09-17 00:24:34 -0700254 RTC_DCHECK(num_deleted == 1);
pbos8fc7fa72015-07-15 08:02:58 -0700255 const std::string& sync_group = audio_receive_stream->config().sync_group;
256 const auto it = sync_stream_mapping_.find(sync_group);
257 if (it != sync_stream_mapping_.end() &&
258 it->second == audio_receive_stream) {
259 sync_stream_mapping_.erase(it);
260 ConfigureSync(sync_group);
261 }
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200262 }
263 delete audio_receive_stream;
264}
265
266webrtc::VideoSendStream* Call::CreateVideoSendStream(
267 const webrtc::VideoSendStream::Config& config,
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000268 const VideoEncoderConfig& encoder_config) {
pbos@webrtc.org50fe3592015-01-29 12:33:07 +0000269 TRACE_EVENT0("webrtc", "Call::CreateVideoSendStream");
solenberg5a289392015-10-19 03:39:20 -0700270 RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
pbos@webrtc.org1819fd72013-06-10 13:48:26 +0000271
mflodman@webrtc.orgeb16b812014-06-16 08:57:39 +0000272 // TODO(mflodman): Base the start bitrate on a current bandwidth estimate, if
273 // the call has already started.
solenberge5269742015-09-08 05:13:22 -0700274 VideoSendStream* send_stream = new VideoSendStream(num_cpu_cores_,
mflodman0dbf0092015-10-19 08:12:12 -0700275 module_process_thread_.get(), channel_group_.get(), config,
276 encoder_config, suspended_video_send_ssrcs_);
pbos@webrtc.org1819fd72013-06-10 13:48:26 +0000277
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000278 // This needs to be taken before send_crit_ as both locks need to be held
279 // while changing network state.
Peter Boströmf2f82832015-05-01 13:00:41 +0200280 rtc::CritScope lock(&network_enabled_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000281 WriteLockScoped write_lock(*send_crit_);
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200282 for (uint32_t ssrc : config.rtp.ssrcs) {
henrikg91d6ede2015-09-17 00:24:34 -0700283 RTC_DCHECK(video_send_ssrcs_.find(ssrc) == video_send_ssrcs_.end());
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200284 video_send_ssrcs_[ssrc] = send_stream;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000285 }
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200286 video_send_streams_.insert(send_stream);
287
ivocb04965c2015-09-09 00:09:43 -0700288 if (event_log_)
289 event_log_->LogVideoSendStreamConfig(config);
290
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000291 if (!network_enabled_)
292 send_stream->SignalNetworkState(kNetworkDown);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000293 return send_stream;
294}
295
pbos@webrtc.org2c46f8d2013-11-21 13:49:43 +0000296void Call::DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) {
pbos@webrtc.org50fe3592015-01-29 12:33:07 +0000297 TRACE_EVENT0("webrtc", "Call::DestroyVideoSendStream");
henrikg91d6ede2015-09-17 00:24:34 -0700298 RTC_DCHECK(send_stream != nullptr);
solenberg5a289392015-10-19 03:39:20 -0700299 RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000300
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000301 send_stream->Stop();
302
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000303 VideoSendStream* send_stream_impl = nullptr;
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000304 {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000305 WriteLockScoped write_lock(*send_crit_);
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200306 auto it = video_send_ssrcs_.begin();
307 while (it != video_send_ssrcs_.end()) {
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000308 if (it->second == static_cast<VideoSendStream*>(send_stream)) {
309 send_stream_impl = it->second;
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200310 video_send_ssrcs_.erase(it++);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000311 } else {
312 ++it;
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000313 }
314 }
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200315 video_send_streams_.erase(send_stream_impl);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000316 }
henrikg91d6ede2015-09-17 00:24:34 -0700317 RTC_CHECK(send_stream_impl != nullptr);
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000318
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000319 VideoSendStream::RtpStateMap rtp_state = send_stream_impl->GetRtpStates();
320
321 for (VideoSendStream::RtpStateMap::iterator it = rtp_state.begin();
322 it != rtp_state.end();
323 ++it) {
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200324 suspended_video_send_ssrcs_[it->first] = it->second;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000325 }
326
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000327 delete send_stream_impl;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000328}
329
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200330webrtc::VideoReceiveStream* Call::CreateVideoReceiveStream(
331 const webrtc::VideoReceiveStream::Config& config) {
pbos@webrtc.org50fe3592015-01-29 12:33:07 +0000332 TRACE_EVENT0("webrtc", "Call::CreateVideoReceiveStream");
solenberg5a289392015-10-19 03:39:20 -0700333 RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
Peter Boströmc4188fd2015-04-24 15:16:03 +0200334 VideoReceiveStream* receive_stream = new VideoReceiveStream(
mflodman0dbf0092015-10-19 08:12:12 -0700335 num_cpu_cores_, channel_group_.get(), config, config_.voice_engine,
336 module_process_thread_.get());
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000337
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000338 // This needs to be taken before receive_crit_ as both locks need to be held
339 // while changing network state.
Peter Boströmf2f82832015-05-01 13:00:41 +0200340 rtc::CritScope lock(&network_enabled_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000341 WriteLockScoped write_lock(*receive_crit_);
henrikg91d6ede2015-09-17 00:24:34 -0700342 RTC_DCHECK(video_receive_ssrcs_.find(config.rtp.remote_ssrc) ==
343 video_receive_ssrcs_.end());
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200344 video_receive_ssrcs_[config.rtp.remote_ssrc] = receive_stream;
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000345 // TODO(pbos): Configure different RTX payloads per receive payload.
346 VideoReceiveStream::Config::Rtp::RtxMap::const_iterator it =
347 config.rtp.rtx.begin();
348 if (it != config.rtp.rtx.end())
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200349 video_receive_ssrcs_[it->second.ssrc] = receive_stream;
350 video_receive_streams_.insert(receive_stream);
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000351
pbos8fc7fa72015-07-15 08:02:58 -0700352 ConfigureSync(config.sync_group);
353
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000354 if (!network_enabled_)
355 receive_stream->SignalNetworkState(kNetworkDown);
pbos8fc7fa72015-07-15 08:02:58 -0700356
ivocb04965c2015-09-09 00:09:43 -0700357 if (event_log_)
358 event_log_->LogVideoReceiveStreamConfig(config);
359
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000360 return receive_stream;
361}
362
pbos@webrtc.org2c46f8d2013-11-21 13:49:43 +0000363void Call::DestroyVideoReceiveStream(
364 webrtc::VideoReceiveStream* receive_stream) {
pbos@webrtc.org50fe3592015-01-29 12:33:07 +0000365 TRACE_EVENT0("webrtc", "Call::DestroyVideoReceiveStream");
solenberg5a289392015-10-19 03:39:20 -0700366 RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
henrikg91d6ede2015-09-17 00:24:34 -0700367 RTC_DCHECK(receive_stream != nullptr);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000368 VideoReceiveStream* receive_stream_impl = nullptr;
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000369 {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000370 WriteLockScoped write_lock(*receive_crit_);
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000371 // Remove all ssrcs pointing to a receive stream. As RTX retransmits on a
372 // separate SSRC there can be either one or two.
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200373 auto it = video_receive_ssrcs_.begin();
374 while (it != video_receive_ssrcs_.end()) {
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000375 if (it->second == static_cast<VideoReceiveStream*>(receive_stream)) {
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000376 if (receive_stream_impl != nullptr)
henrikg91d6ede2015-09-17 00:24:34 -0700377 RTC_DCHECK(receive_stream_impl == it->second);
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000378 receive_stream_impl = it->second;
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200379 video_receive_ssrcs_.erase(it++);
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000380 } else {
381 ++it;
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000382 }
383 }
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200384 video_receive_streams_.erase(receive_stream_impl);
henrikg91d6ede2015-09-17 00:24:34 -0700385 RTC_CHECK(receive_stream_impl != nullptr);
pbos8fc7fa72015-07-15 08:02:58 -0700386 ConfigureSync(receive_stream_impl->config().sync_group);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000387 }
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000388 delete receive_stream_impl;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000389}
390
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000391Call::Stats Call::GetStats() const {
solenberg5a289392015-10-19 03:39:20 -0700392 // TODO(solenberg): Some test cases in EndToEndTest use this from a different
393 // thread. Re-enable once that is fixed.
394 // RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000395 Stats stats;
Peter Boström45553ae2015-05-08 13:54:38 +0200396 // Fetch available send/receive bitrates.
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000397 uint32_t send_bandwidth = 0;
Peter Boström45553ae2015-05-08 13:54:38 +0200398 channel_group_->GetBitrateController()->AvailableBandwidth(&send_bandwidth);
399 std::vector<unsigned int> ssrcs;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000400 uint32_t recv_bandwidth = 0;
mflodmana20de202015-10-18 22:08:19 -0700401 channel_group_->GetRemoteBitrateEstimator(false)->LatestEstimate(
402 &ssrcs, &recv_bandwidth);
Peter Boström45553ae2015-05-08 13:54:38 +0200403 stats.send_bandwidth_bps = send_bandwidth;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000404 stats.recv_bandwidth_bps = recv_bandwidth;
Peter Boström59d91dc2015-04-27 17:24:33 +0200405 stats.pacer_delay_ms = channel_group_->GetPacerQueuingDelayMs();
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000406 {
407 ReadLockScoped read_lock(*send_crit_);
solenbergc7a8b082015-10-16 14:35:07 -0700408 // TODO(solenberg): Add audio send streams.
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200409 for (const auto& kv : video_send_ssrcs_) {
410 int rtt_ms = kv.second->GetRtt();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +0000411 if (rtt_ms > 0)
412 stats.rtt_ms = rtt_ms;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000413 }
414 }
415 return stats;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000416}
417
pbos@webrtc.org00873182014-11-25 14:03:34 +0000418void Call::SetBitrateConfig(
419 const webrtc::Call::Config::BitrateConfig& bitrate_config) {
pbos@webrtc.org50fe3592015-01-29 12:33:07 +0000420 TRACE_EVENT0("webrtc", "Call::SetBitrateConfig");
solenberg5a289392015-10-19 03:39:20 -0700421 RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
henrikg91d6ede2015-09-17 00:24:34 -0700422 RTC_DCHECK_GE(bitrate_config.min_bitrate_bps, 0);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000423 if (bitrate_config.max_bitrate_bps != -1)
henrikg91d6ede2015-09-17 00:24:34 -0700424 RTC_DCHECK_GT(bitrate_config.max_bitrate_bps, 0);
Stefan Holmere5904162015-03-26 11:11:06 +0100425 if (config_.bitrate_config.min_bitrate_bps ==
pbos@webrtc.org00873182014-11-25 14:03:34 +0000426 bitrate_config.min_bitrate_bps &&
427 (bitrate_config.start_bitrate_bps <= 0 ||
Stefan Holmere5904162015-03-26 11:11:06 +0100428 config_.bitrate_config.start_bitrate_bps ==
pbos@webrtc.org00873182014-11-25 14:03:34 +0000429 bitrate_config.start_bitrate_bps) &&
Stefan Holmere5904162015-03-26 11:11:06 +0100430 config_.bitrate_config.max_bitrate_bps ==
pbos@webrtc.org00873182014-11-25 14:03:34 +0000431 bitrate_config.max_bitrate_bps) {
432 // Nothing new to set, early abort to avoid encoder reconfigurations.
433 return;
434 }
Stefan Holmere5904162015-03-26 11:11:06 +0100435 config_.bitrate_config = bitrate_config;
stefan4fbd1452015-09-28 03:57:14 -0700436 channel_group_->SetBweBitrates(bitrate_config.min_bitrate_bps,
437 bitrate_config.start_bitrate_bps,
438 bitrate_config.max_bitrate_bps);
pbos@webrtc.org00873182014-11-25 14:03:34 +0000439}
440
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000441void Call::SignalNetworkState(NetworkState state) {
solenberg5a289392015-10-19 03:39:20 -0700442 RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000443 // Take crit for entire function, it needs to be held while updating streams
444 // to guarantee a consistent state across streams.
Peter Boströmf2f82832015-05-01 13:00:41 +0200445 rtc::CritScope lock(&network_enabled_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000446 network_enabled_ = state == kNetworkUp;
stefan457a61d2015-10-14 03:12:59 -0700447 channel_group_->SignalNetworkState(state);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000448 {
449 ReadLockScoped write_lock(*send_crit_);
solenbergc7a8b082015-10-16 14:35:07 -0700450 for (auto& kv : audio_send_ssrcs_) {
451 kv.second->SignalNetworkState(state);
452 }
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200453 for (auto& kv : video_send_ssrcs_) {
454 kv.second->SignalNetworkState(state);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000455 }
456 }
457 {
458 ReadLockScoped write_lock(*receive_crit_);
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200459 for (auto& kv : video_receive_ssrcs_) {
460 kv.second->SignalNetworkState(state);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000461 }
462 }
463}
464
stefanc1aeaf02015-10-15 07:26:07 -0700465void Call::OnSentPacket(const rtc::SentPacket& sent_packet) {
solenberg5a289392015-10-19 03:39:20 -0700466 RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
stefanc1aeaf02015-10-15 07:26:07 -0700467 channel_group_->OnSentPacket(sent_packet);
468}
469
pbos8fc7fa72015-07-15 08:02:58 -0700470void Call::ConfigureSync(const std::string& sync_group) {
471 // Set sync only if there was no previous one.
472 if (config_.voice_engine == nullptr || sync_group.empty())
473 return;
474
475 AudioReceiveStream* sync_audio_stream = nullptr;
476 // Find existing audio stream.
477 const auto it = sync_stream_mapping_.find(sync_group);
478 if (it != sync_stream_mapping_.end()) {
479 sync_audio_stream = it->second;
480 } else {
481 // No configured audio stream, see if we can find one.
482 for (const auto& kv : audio_receive_ssrcs_) {
483 if (kv.second->config().sync_group == sync_group) {
484 if (sync_audio_stream != nullptr) {
485 LOG(LS_WARNING) << "Attempting to sync more than one audio stream "
486 "within the same sync group. This is not "
487 "supported in the current implementation.";
488 break;
489 }
490 sync_audio_stream = kv.second;
491 }
492 }
493 }
494 if (sync_audio_stream)
495 sync_stream_mapping_[sync_group] = sync_audio_stream;
496 size_t num_synced_streams = 0;
497 for (VideoReceiveStream* video_stream : video_receive_streams_) {
498 if (video_stream->config().sync_group != sync_group)
499 continue;
500 ++num_synced_streams;
501 if (num_synced_streams > 1) {
502 // TODO(pbos): Support synchronizing more than one A/V pair.
503 // https://code.google.com/p/webrtc/issues/detail?id=4762
504 LOG(LS_WARNING) << "Attempting to sync more than one audio/video pair "
505 "within the same sync group. This is not supported in "
506 "the current implementation.";
507 }
508 // Only sync the first A/V pair within this sync group.
509 if (sync_audio_stream != nullptr && num_synced_streams == 1) {
510 video_stream->SetSyncChannel(config_.voice_engine,
511 sync_audio_stream->config().voe_channel_id);
512 } else {
513 video_stream->SetSyncChannel(config_.voice_engine, -1);
514 }
515 }
516}
517
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200518PacketReceiver::DeliveryStatus Call::DeliverRtcp(MediaType media_type,
519 const uint8_t* packet,
520 size_t length) {
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000521 // TODO(pbos): Figure out what channel needs it actually.
522 // Do NOT broadcast! Also make sure it's a valid packet.
pbos@webrtc.orgcaba2d22014-05-14 13:57:12 +0000523 // Return DELIVERY_UNKNOWN_SSRC if it can be determined that
524 // there's no receiver of the packet.
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000525 bool rtcp_delivered = false;
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200526 if (media_type == MediaType::ANY || media_type == MediaType::VIDEO) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000527 ReadLockScoped read_lock(*receive_crit_);
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200528 for (VideoReceiveStream* stream : video_receive_streams_) {
ivocb04965c2015-09-09 00:09:43 -0700529 if (stream->DeliverRtcp(packet, length)) {
pbos@webrtc.org40523702013-08-05 12:49:22 +0000530 rtcp_delivered = true;
ivocb04965c2015-09-09 00:09:43 -0700531 if (event_log_)
532 event_log_->LogRtcpPacket(true, media_type, packet, length);
533 }
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000534 }
535 }
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200536 if (media_type == MediaType::ANY || media_type == MediaType::VIDEO) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000537 ReadLockScoped read_lock(*send_crit_);
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200538 for (VideoSendStream* stream : video_send_streams_) {
ivocb04965c2015-09-09 00:09:43 -0700539 if (stream->DeliverRtcp(packet, length)) {
pbos@webrtc.org40523702013-08-05 12:49:22 +0000540 rtcp_delivered = true;
ivocb04965c2015-09-09 00:09:43 -0700541 if (event_log_)
542 event_log_->LogRtcpPacket(false, media_type, packet, length);
543 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000544 }
545 }
pbos@webrtc.orgcaba2d22014-05-14 13:57:12 +0000546 return rtcp_delivered ? DELIVERY_OK : DELIVERY_PACKET_ERROR;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000547}
548
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200549PacketReceiver::DeliveryStatus Call::DeliverRtp(MediaType media_type,
550 const uint8_t* packet,
stefan68786d22015-09-08 05:36:15 -0700551 size_t length,
552 const PacketTime& packet_time) {
pbos@webrtc.orgaf38f4e2014-07-08 07:38:12 +0000553 // Minimum RTP header size.
554 if (length < 12)
555 return DELIVERY_PACKET_ERROR;
556
sprang@webrtc.org2a6558c2015-01-28 12:37:36 +0000557 uint32_t ssrc = ByteReader<uint32_t>::ReadBigEndian(&packet[8]);
pbos@webrtc.orgaf38f4e2014-07-08 07:38:12 +0000558
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000559 ReadLockScoped read_lock(*receive_crit_);
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200560 if (media_type == MediaType::ANY || media_type == MediaType::AUDIO) {
561 auto it = audio_receive_ssrcs_.find(ssrc);
562 if (it != audio_receive_ssrcs_.end()) {
ivocb04965c2015-09-09 00:09:43 -0700563 auto status = it->second->DeliverRtp(packet, length, packet_time)
564 ? DELIVERY_OK
565 : DELIVERY_PACKET_ERROR;
566 if (status == DELIVERY_OK && event_log_)
567 event_log_->LogRtpHeader(true, media_type, packet, length);
568 return status;
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200569 }
570 }
571 if (media_type == MediaType::ANY || media_type == MediaType::VIDEO) {
572 auto it = video_receive_ssrcs_.find(ssrc);
573 if (it != video_receive_ssrcs_.end()) {
ivocb04965c2015-09-09 00:09:43 -0700574 auto status = it->second->DeliverRtp(packet, length, packet_time)
575 ? DELIVERY_OK
576 : DELIVERY_PACKET_ERROR;
577 if (status == DELIVERY_OK && event_log_)
578 event_log_->LogRtpHeader(true, media_type, packet, length);
579 return status;
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200580 }
581 }
582 return DELIVERY_UNKNOWN_SSRC;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000583}
584
stefan68786d22015-09-08 05:36:15 -0700585PacketReceiver::DeliveryStatus Call::DeliverPacket(
586 MediaType media_type,
587 const uint8_t* packet,
588 size_t length,
589 const PacketTime& packet_time) {
solenberg5a289392015-10-19 03:39:20 -0700590 // TODO(solenberg): Tests call this function on a network thread, libjingle
591 // calls on the worker thread. We should move towards always using a network
592 // thread. Then this check can be enabled.
593 // RTC_DCHECK(!configuration_thread_checker_.CalledOnValidThread());
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000594 if (RtpHeaderParser::IsRtcp(packet, length))
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200595 return DeliverRtcp(media_type, packet, length);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000596
stefan68786d22015-09-08 05:36:15 -0700597 return DeliverRtp(media_type, packet, length, packet_time);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000598}
599
600} // namespace internal
601} // namespace webrtc