blob: ce5bceb359d520607fbb4c7813a52b16c943fd4a [file] [log] [blame]
pbos@webrtc.org2a9108f2013-05-16 12:08:031/*
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.org3f45c2e2013-08-05 16:22:5311#include <string.h>
12
pbos@webrtc.org2a9108f2013-05-16 12:08:0313#include <map>
14#include <vector>
15
Peter Boströmbf9f73c2015-09-25 11:58:3016#include "webrtc/audio/audio_receive_stream.h"
solenbergf707c682015-10-16 21:35:0717#include "webrtc/audio/audio_send_stream.h"
pbos@webrtc.org6eaf09a2015-03-23 13:12:2418#include "webrtc/base/checks.h"
kwiberg@webrtc.orgdeb9dae2015-02-26 14:34:5519#include "webrtc/base/scoped_ptr.h"
pbos@webrtc.orgd54aa962014-09-24 06:05:0020#include "webrtc/base/thread_annotations.h"
pbos@webrtc.org24e20892013-10-28 16:32:0121#include "webrtc/call.h"
Peter Boströmbf9f73c2015-09-25 11:58:3022#include "webrtc/call/rtc_event_log.h"
stefan@webrtc.org47f0c412013-12-04 10:24:2623#include "webrtc/common.h"
pbos@webrtc.orgd05597a2013-12-05 12:11:4724#include "webrtc/config.h"
pbos@webrtc.org24e20892013-10-28 16:32:0125#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
sprang@webrtc.orgcce642c2015-01-28 12:37:3626#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
Peter Boström8e07f3a2015-05-08 11:54:3827#include "webrtc/modules/utility/interface/process_thread.h"
Peter Boström8e07f3a2015-05-08 11:54:3828#include "webrtc/system_wrappers/interface/cpu_info.h"
pbos@webrtc.orgb5d2d162013-10-02 13:36:0929#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
pbos@webrtc.orgf076e172015-01-15 10:09:3930#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.org24e20892013-10-28 16:32:0131#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
pbos@webrtc.orgb5d2d162013-10-02 13:36:0932#include "webrtc/system_wrappers/interface/trace.h"
pbos@webrtc.orge2863932015-01-29 12:33:0733#include "webrtc/system_wrappers/interface/trace_event.h"
pbos@webrtc.org24e20892013-10-28 16:32:0134#include "webrtc/video/video_receive_stream.h"
35#include "webrtc/video/video_send_stream.h"
ivoc35fd7532015-09-09 07:09:4336#include "webrtc/voice_engine/include/voe_codec.h"
pbos@webrtc.org2a9108f2013-05-16 12:08:0337
38namespace webrtc {
pbos@webrtc.org1c655452014-09-17 09:02:2539
pbos@webrtc.org7da30672014-10-14 11:52:1040const int Call::Config::kDefaultStartBitrateBps = 300000;
41
pbos@webrtc.org24e20892013-10-28 16:32:0142namespace internal {
asapersson@webrtc.org8ef65482014-01-31 10:05:0743
pbos@webrtc.org24e20892013-10-28 16:32:0144class Call : public webrtc::Call, public PacketReceiver {
45 public:
Peter Boström8e07f3a2015-05-08 11:54:3846 explicit Call(const Call::Config& config);
pbos@webrtc.org24e20892013-10-28 16:32:0147 virtual ~Call();
48
kjellander@webrtc.org860ac532015-03-04 12:58:3549 PacketReceiver* Receiver() override;
pbos@webrtc.org24e20892013-10-28 16:32:0150
Fredrik Solenbergee9b72e2015-06-08 11:04:5651 webrtc::AudioSendStream* CreateAudioSendStream(
52 const webrtc::AudioSendStream::Config& config) override;
53 void DestroyAudioSendStream(webrtc::AudioSendStream* send_stream) override;
54
Fredrik Solenbergad867862015-04-29 13:24:0155 webrtc::AudioReceiveStream* CreateAudioReceiveStream(
56 const webrtc::AudioReceiveStream::Config& config) override;
57 void DestroyAudioReceiveStream(
58 webrtc::AudioReceiveStream* receive_stream) override;
pbos@webrtc.org24e20892013-10-28 16:32:0159
Fredrik Solenbergad867862015-04-29 13:24:0160 webrtc::VideoSendStream* CreateVideoSendStream(
61 const webrtc::VideoSendStream::Config& config,
62 const VideoEncoderConfig& encoder_config) override;
kjellander@webrtc.org860ac532015-03-04 12:58:3563 void DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) override;
pbos@webrtc.org24e20892013-10-28 16:32:0164
Fredrik Solenbergad867862015-04-29 13:24:0165 webrtc::VideoReceiveStream* CreateVideoReceiveStream(
66 const webrtc::VideoReceiveStream::Config& config) override;
kjellander@webrtc.org860ac532015-03-04 12:58:3567 void DestroyVideoReceiveStream(
68 webrtc::VideoReceiveStream* receive_stream) override;
pbos@webrtc.org24e20892013-10-28 16:32:0169
kjellander@webrtc.org860ac532015-03-04 12:58:3570 Stats GetStats() const override;
pbos@webrtc.org24e20892013-10-28 16:32:0171
stefan30bf7782015-09-08 12:36:1572 DeliveryStatus DeliverPacket(MediaType media_type,
73 const uint8_t* packet,
74 size_t length,
75 const PacketTime& packet_time) override;
pbos@webrtc.org24e20892013-10-28 16:32:0176
kjellander@webrtc.org860ac532015-03-04 12:58:3577 void SetBitrateConfig(
78 const webrtc::Call::Config::BitrateConfig& bitrate_config) override;
79 void SignalNetworkState(NetworkState state) override;
pbos@webrtc.org9b707ca2014-09-03 16:17:1280
stefan15b20992015-10-15 14:26:0781 void OnSentPacket(const rtc::SentPacket& sent_packet) override;
82
pbos@webrtc.org24e20892013-10-28 16:32:0183 private:
Fredrik Solenbergad867862015-04-29 13:24:0184 DeliveryStatus DeliverRtcp(MediaType media_type, const uint8_t* packet,
85 size_t length);
stefan30bf7782015-09-08 12:36:1586 DeliveryStatus DeliverRtp(MediaType media_type,
87 const uint8_t* packet,
88 size_t length,
89 const PacketTime& packet_time);
pbos@webrtc.org24e20892013-10-28 16:32:0190
pbos495b3502015-07-15 15:02:5891 void ConfigureSync(const std::string& sync_group)
92 EXCLUSIVE_LOCKS_REQUIRED(receive_crit_);
93
Peter Boström8e07f3a2015-05-08 11:54:3894 const int num_cpu_cores_;
95 const rtc::scoped_ptr<ProcessThread> module_process_thread_;
96 const rtc::scoped_ptr<ChannelGroup> channel_group_;
Peter Boström8e07f3a2015-05-08 11:54:3897 volatile int next_channel_id_;
pbos@webrtc.org24e20892013-10-28 16:32:0198 Call::Config config_;
99
pbos@webrtc.org9b707ca2014-09-03 16:17:12100 // Needs to be held while write-locking |receive_crit_| or |send_crit_|. This
101 // ensures that we have a consistent network state signalled to all senders
102 // and receivers.
Peter Boström7d6ce5f2015-05-01 11:00:41103 rtc::CriticalSection network_enabled_crit_;
pbos@webrtc.org9b707ca2014-09-03 16:17:12104 bool network_enabled_ GUARDED_BY(network_enabled_crit_);
pbos@webrtc.org24e20892013-10-28 16:32:01105
kwiberg@webrtc.orgdeb9dae2015-02-26 14:34:55106 rtc::scoped_ptr<RWLockWrapper> receive_crit_;
solenbergf707c682015-10-16 21:35:07107 // Audio and Video receive streams are owned by the client that creates them.
Fredrik Solenbergad867862015-04-29 13:24:01108 std::map<uint32_t, AudioReceiveStream*> audio_receive_ssrcs_
pbos@webrtc.org9b707ca2014-09-03 16:17:12109 GUARDED_BY(receive_crit_);
Fredrik Solenbergad867862015-04-29 13:24:01110 std::map<uint32_t, VideoReceiveStream*> video_receive_ssrcs_
111 GUARDED_BY(receive_crit_);
112 std::set<VideoReceiveStream*> video_receive_streams_
113 GUARDED_BY(receive_crit_);
pbos495b3502015-07-15 15:02:58114 std::map<std::string, AudioReceiveStream*> sync_stream_mapping_
115 GUARDED_BY(receive_crit_);
pbos@webrtc.org9b707ca2014-09-03 16:17:12116
kwiberg@webrtc.orgdeb9dae2015-02-26 14:34:55117 rtc::scoped_ptr<RWLockWrapper> send_crit_;
solenbergf707c682015-10-16 21:35:07118 // Audio and Video send streams are owned by the client that creates them.
119 std::map<uint32_t, AudioSendStream*> audio_send_ssrcs_ GUARDED_BY(send_crit_);
Fredrik Solenbergad867862015-04-29 13:24:01120 std::map<uint32_t, VideoSendStream*> video_send_ssrcs_ GUARDED_BY(send_crit_);
121 std::set<VideoSendStream*> video_send_streams_ GUARDED_BY(send_crit_);
pbos@webrtc.org24e20892013-10-28 16:32:01122
Fredrik Solenbergad867862015-04-29 13:24:01123 VideoSendStream::RtpStateMap suspended_video_send_ssrcs_;
pbos@webrtc.org2fd91bd2014-07-07 13:06:48124
ivoc35fd7532015-09-09 07:09:43125 RtcEventLog* event_log_;
126
henrikg9199c0e2015-09-16 12:37:44127 RTC_DISALLOW_COPY_AND_ASSIGN(Call);
pbos@webrtc.org24e20892013-10-28 16:32:01128};
pbos@webrtc.orgd05597a2013-12-05 12:11:47129} // namespace internal
pbos@webrtc.orgc2014fd2013-08-14 13:52:52130
stefan@webrtc.org47f0c412013-12-04 10:24:26131Call* Call::Create(const Call::Config& config) {
Peter Boström8e07f3a2015-05-08 11:54:38132 return new internal::Call(config);
pbos@webrtc.orgc2014fd2013-08-14 13:52:52133}
pbos@webrtc.orgc2014fd2013-08-14 13:52:52134
pbos@webrtc.org2a9108f2013-05-16 12:08:03135namespace internal {
136
Peter Boström8e07f3a2015-05-08 11:54:38137Call::Call(const Call::Config& config)
138 : num_cpu_cores_(CpuInfo::DetectNumberOfCores()),
stefan63ac87f2015-09-11 16:52:15139 module_process_thread_(ProcessThread::Create("ModuleProcessThread")),
Peter Boströma28bdde2015-05-28 12:10:39140 channel_group_(new ChannelGroup(module_process_thread_.get())),
pboscce61412015-07-23 13:58:33141 next_channel_id_(0),
Peter Boström8e07f3a2015-05-08 11:54:38142 config_(config),
pbos@webrtc.org9b707ca2014-09-03 16:17:12143 network_enabled_(true),
144 receive_crit_(RWLockWrapper::CreateRWLock()),
ivoc35fd7532015-09-09 07:09:43145 send_crit_(RWLockWrapper::CreateRWLock()),
146 event_log_(nullptr) {
henrikg5c075c82015-09-17 07:24:34147 RTC_DCHECK_GE(config.bitrate_config.min_bitrate_bps, 0);
148 RTC_DCHECK_GE(config.bitrate_config.start_bitrate_bps,
149 config.bitrate_config.min_bitrate_bps);
Stefan Holmerca55fa12015-03-26 10:11:06150 if (config.bitrate_config.max_bitrate_bps != -1) {
henrikg5c075c82015-09-17 07:24:34151 RTC_DCHECK_GE(config.bitrate_config.max_bitrate_bps,
152 config.bitrate_config.start_bitrate_bps);
pbos@webrtc.org5e3f6b42014-11-25 14:03:34153 }
ivoc35fd7532015-09-09 07:09:43154 if (config.voice_engine) {
155 VoECodec* voe_codec = VoECodec::GetInterface(config.voice_engine);
156 if (voe_codec) {
157 event_log_ = voe_codec->GetEventLog();
158 voe_codec->Release();
159 }
160 }
pbos@webrtc.org5e3f6b42014-11-25 14:03:34161
Peter Boström8e07f3a2015-05-08 11:54:38162 Trace::CreateTrace();
163 module_process_thread_->Start();
164
stefan9aa9de92015-09-28 10:57:14165 channel_group_->SetBweBitrates(config_.bitrate_config.min_bitrate_bps,
166 config_.bitrate_config.start_bitrate_bps,
167 config_.bitrate_config.max_bitrate_bps);
pbos@webrtc.org2a9108f2013-05-16 12:08:03168}
169
pbos@webrtc.orgbf6d5722013-09-09 15:04:25170Call::~Call() {
solenbergf707c682015-10-16 21:35:07171 RTC_CHECK(audio_send_ssrcs_.empty());
172 RTC_CHECK(video_send_ssrcs_.empty());
173 RTC_CHECK(video_send_streams_.empty());
174 RTC_CHECK(audio_receive_ssrcs_.empty());
175 RTC_CHECK(video_receive_ssrcs_.empty());
176 RTC_CHECK(video_receive_streams_.empty());
pbos@webrtc.orgf71c9742015-02-12 10:48:23177
Peter Boström8e07f3a2015-05-08 11:54:38178 module_process_thread_->Stop();
179 Trace::ReturnTrace();
pbos@webrtc.org2a9108f2013-05-16 12:08:03180}
181
pbos@webrtc.orgbf6d5722013-09-09 15:04:25182PacketReceiver* Call::Receiver() { return this; }
pbos@webrtc.org2a9108f2013-05-16 12:08:03183
Fredrik Solenbergee9b72e2015-06-08 11:04:56184webrtc::AudioSendStream* Call::CreateAudioSendStream(
185 const webrtc::AudioSendStream::Config& config) {
solenbergf707c682015-10-16 21:35:07186 TRACE_EVENT0("webrtc", "Call::CreateAudioSendStream");
187 AudioSendStream* send_stream = new AudioSendStream(config);
188 {
189 rtc::CritScope lock(&network_enabled_crit_);
190 WriteLockScoped write_lock(*send_crit_);
191 RTC_DCHECK(audio_send_ssrcs_.find(config.rtp.ssrc) ==
192 audio_send_ssrcs_.end());
193 audio_send_ssrcs_[config.rtp.ssrc] = send_stream;
194
195 if (!network_enabled_)
196 send_stream->SignalNetworkState(kNetworkDown);
197 }
198 return send_stream;
Fredrik Solenbergee9b72e2015-06-08 11:04:56199}
200
201void Call::DestroyAudioSendStream(webrtc::AudioSendStream* send_stream) {
solenbergf707c682015-10-16 21:35:07202 TRACE_EVENT0("webrtc", "Call::DestroyAudioSendStream");
203 RTC_DCHECK(send_stream != nullptr);
204
205 send_stream->Stop();
206
207 webrtc::internal::AudioSendStream* audio_send_stream =
208 static_cast<webrtc::internal::AudioSendStream*>(send_stream);
209 {
210 WriteLockScoped write_lock(*send_crit_);
211 size_t num_deleted = audio_send_ssrcs_.erase(
212 audio_send_stream->config().rtp.ssrc);
213 RTC_DCHECK(num_deleted == 1);
214 }
215 delete audio_send_stream;
Fredrik Solenbergee9b72e2015-06-08 11:04:56216}
217
Fredrik Solenbergad867862015-04-29 13:24:01218webrtc::AudioReceiveStream* Call::CreateAudioReceiveStream(
219 const webrtc::AudioReceiveStream::Config& config) {
220 TRACE_EVENT0("webrtc", "Call::CreateAudioReceiveStream");
Fredrik Solenbergad867862015-04-29 13:24:01221 AudioReceiveStream* receive_stream = new AudioReceiveStream(
mflodman7d393832015-10-19 05:08:19222 channel_group_->GetRemoteBitrateEstimator(false), config);
Fredrik Solenbergad867862015-04-29 13:24:01223 {
224 WriteLockScoped write_lock(*receive_crit_);
henrikg5c075c82015-09-17 07:24:34225 RTC_DCHECK(audio_receive_ssrcs_.find(config.rtp.remote_ssrc) ==
226 audio_receive_ssrcs_.end());
Fredrik Solenbergad867862015-04-29 13:24:01227 audio_receive_ssrcs_[config.rtp.remote_ssrc] = receive_stream;
pbos495b3502015-07-15 15:02:58228 ConfigureSync(config.sync_group);
Fredrik Solenbergad867862015-04-29 13:24:01229 }
230 return receive_stream;
231}
232
233void Call::DestroyAudioReceiveStream(
234 webrtc::AudioReceiveStream* receive_stream) {
235 TRACE_EVENT0("webrtc", "Call::DestroyAudioReceiveStream");
henrikg5c075c82015-09-17 07:24:34236 RTC_DCHECK(receive_stream != nullptr);
solenbergf707c682015-10-16 21:35:07237 webrtc::internal::AudioReceiveStream* audio_receive_stream =
238 static_cast<webrtc::internal::AudioReceiveStream*>(receive_stream);
Fredrik Solenbergad867862015-04-29 13:24:01239 {
240 WriteLockScoped write_lock(*receive_crit_);
241 size_t num_deleted = audio_receive_ssrcs_.erase(
242 audio_receive_stream->config().rtp.remote_ssrc);
henrikg5c075c82015-09-17 07:24:34243 RTC_DCHECK(num_deleted == 1);
pbos495b3502015-07-15 15:02:58244 const std::string& sync_group = audio_receive_stream->config().sync_group;
245 const auto it = sync_stream_mapping_.find(sync_group);
246 if (it != sync_stream_mapping_.end() &&
247 it->second == audio_receive_stream) {
248 sync_stream_mapping_.erase(it);
249 ConfigureSync(sync_group);
250 }
Fredrik Solenbergad867862015-04-29 13:24:01251 }
252 delete audio_receive_stream;
253}
254
255webrtc::VideoSendStream* Call::CreateVideoSendStream(
256 const webrtc::VideoSendStream::Config& config,
pbos@webrtc.org58b51402014-09-19 12:30:25257 const VideoEncoderConfig& encoder_config) {
pbos@webrtc.orge2863932015-01-29 12:33:07258 TRACE_EVENT0("webrtc", "Call::CreateVideoSendStream");
pbos@webrtc.org63988b22013-06-10 13:48:26259
mflodman@webrtc.orgf89ce462014-06-16 08:57:39260 // TODO(mflodman): Base the start bitrate on a current bandwidth estimate, if
261 // the call has already started.
solenbergbe5952f2015-09-08 12:13:22262 VideoSendStream* send_stream = new VideoSendStream(num_cpu_cores_,
Peter Boström8e07f3a2015-05-08 11:54:38263 module_process_thread_.get(), channel_group_.get(),
264 rtc::AtomicOps::Increment(&next_channel_id_), config, encoder_config,
265 suspended_video_send_ssrcs_);
pbos@webrtc.org63988b22013-06-10 13:48:26266
pbos@webrtc.org9b707ca2014-09-03 16:17:12267 // This needs to be taken before send_crit_ as both locks need to be held
268 // while changing network state.
Peter Boström7d6ce5f2015-05-01 11:00:41269 rtc::CritScope lock(&network_enabled_crit_);
pbos@webrtc.org9b707ca2014-09-03 16:17:12270 WriteLockScoped write_lock(*send_crit_);
Fredrik Solenbergad867862015-04-29 13:24:01271 for (uint32_t ssrc : config.rtp.ssrcs) {
henrikg5c075c82015-09-17 07:24:34272 RTC_DCHECK(video_send_ssrcs_.find(ssrc) == video_send_ssrcs_.end());
Fredrik Solenbergad867862015-04-29 13:24:01273 video_send_ssrcs_[ssrc] = send_stream;
pbos@webrtc.org2a9108f2013-05-16 12:08:03274 }
Fredrik Solenbergad867862015-04-29 13:24:01275 video_send_streams_.insert(send_stream);
276
ivoc35fd7532015-09-09 07:09:43277 if (event_log_)
278 event_log_->LogVideoSendStreamConfig(config);
279
pbos@webrtc.org9b707ca2014-09-03 16:17:12280 if (!network_enabled_)
281 send_stream->SignalNetworkState(kNetworkDown);
pbos@webrtc.org2a9108f2013-05-16 12:08:03282 return send_stream;
283}
284
pbos@webrtc.org12a93e02013-11-21 13:49:43285void Call::DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) {
pbos@webrtc.orge2863932015-01-29 12:33:07286 TRACE_EVENT0("webrtc", "Call::DestroyVideoSendStream");
henrikg5c075c82015-09-17 07:24:34287 RTC_DCHECK(send_stream != nullptr);
pbos@webrtc.org00208582013-09-05 12:38:54288
pbos@webrtc.org2fd91bd2014-07-07 13:06:48289 send_stream->Stop();
290
pbos@webrtc.org6eaf09a2015-03-23 13:12:24291 VideoSendStream* send_stream_impl = nullptr;
pbos@webrtc.org00208582013-09-05 12:38:54292 {
pbos@webrtc.org9b707ca2014-09-03 16:17:12293 WriteLockScoped write_lock(*send_crit_);
Fredrik Solenbergad867862015-04-29 13:24:01294 auto it = video_send_ssrcs_.begin();
295 while (it != video_send_ssrcs_.end()) {
pbos@webrtc.org00208582013-09-05 12:38:54296 if (it->second == static_cast<VideoSendStream*>(send_stream)) {
297 send_stream_impl = it->second;
Fredrik Solenbergad867862015-04-29 13:24:01298 video_send_ssrcs_.erase(it++);
pbos@webrtc.org2fd91bd2014-07-07 13:06:48299 } else {
300 ++it;
pbos@webrtc.org00208582013-09-05 12:38:54301 }
302 }
Fredrik Solenbergad867862015-04-29 13:24:01303 video_send_streams_.erase(send_stream_impl);
pbos@webrtc.org2a9108f2013-05-16 12:08:03304 }
henrikg5c075c82015-09-17 07:24:34305 RTC_CHECK(send_stream_impl != nullptr);
pbos@webrtc.org00208582013-09-05 12:38:54306
pbos@webrtc.org2fd91bd2014-07-07 13:06:48307 VideoSendStream::RtpStateMap rtp_state = send_stream_impl->GetRtpStates();
308
309 for (VideoSendStream::RtpStateMap::iterator it = rtp_state.begin();
310 it != rtp_state.end();
311 ++it) {
Fredrik Solenbergad867862015-04-29 13:24:01312 suspended_video_send_ssrcs_[it->first] = it->second;
pbos@webrtc.org2fd91bd2014-07-07 13:06:48313 }
314
pbos@webrtc.org00208582013-09-05 12:38:54315 delete send_stream_impl;
pbos@webrtc.org2a9108f2013-05-16 12:08:03316}
317
Fredrik Solenbergad867862015-04-29 13:24:01318webrtc::VideoReceiveStream* Call::CreateVideoReceiveStream(
319 const webrtc::VideoReceiveStream::Config& config) {
pbos@webrtc.orge2863932015-01-29 12:33:07320 TRACE_EVENT0("webrtc", "Call::CreateVideoReceiveStream");
Peter Boströme7c0a782015-04-24 13:16:03321 VideoReceiveStream* receive_stream = new VideoReceiveStream(
pboscce61412015-07-23 13:58:33322 num_cpu_cores_, channel_group_.get(),
Peter Boström8e07f3a2015-05-08 11:54:38323 rtc::AtomicOps::Increment(&next_channel_id_), config,
mflodman7d393832015-10-19 05:08:19324 config_.voice_engine, module_process_thread_.get());
pbos@webrtc.org2a9108f2013-05-16 12:08:03325
pbos@webrtc.org9b707ca2014-09-03 16:17:12326 // This needs to be taken before receive_crit_ as both locks need to be held
327 // while changing network state.
Peter Boström7d6ce5f2015-05-01 11:00:41328 rtc::CritScope lock(&network_enabled_crit_);
pbos@webrtc.org9b707ca2014-09-03 16:17:12329 WriteLockScoped write_lock(*receive_crit_);
henrikg5c075c82015-09-17 07:24:34330 RTC_DCHECK(video_receive_ssrcs_.find(config.rtp.remote_ssrc) ==
331 video_receive_ssrcs_.end());
Fredrik Solenbergad867862015-04-29 13:24:01332 video_receive_ssrcs_[config.rtp.remote_ssrc] = receive_stream;
pbos@webrtc.orgc71929d2014-01-24 09:30:53333 // TODO(pbos): Configure different RTX payloads per receive payload.
334 VideoReceiveStream::Config::Rtp::RtxMap::const_iterator it =
335 config.rtp.rtx.begin();
336 if (it != config.rtp.rtx.end())
Fredrik Solenbergad867862015-04-29 13:24:01337 video_receive_ssrcs_[it->second.ssrc] = receive_stream;
338 video_receive_streams_.insert(receive_stream);
pbos@webrtc.orgc71929d2014-01-24 09:30:53339
pbos495b3502015-07-15 15:02:58340 ConfigureSync(config.sync_group);
341
pbos@webrtc.org9b707ca2014-09-03 16:17:12342 if (!network_enabled_)
343 receive_stream->SignalNetworkState(kNetworkDown);
pbos495b3502015-07-15 15:02:58344
ivoc35fd7532015-09-09 07:09:43345 if (event_log_)
346 event_log_->LogVideoReceiveStreamConfig(config);
347
pbos@webrtc.org2a9108f2013-05-16 12:08:03348 return receive_stream;
349}
350
pbos@webrtc.org12a93e02013-11-21 13:49:43351void Call::DestroyVideoReceiveStream(
352 webrtc::VideoReceiveStream* receive_stream) {
pbos@webrtc.orge2863932015-01-29 12:33:07353 TRACE_EVENT0("webrtc", "Call::DestroyVideoReceiveStream");
henrikg5c075c82015-09-17 07:24:34354 RTC_DCHECK(receive_stream != nullptr);
pbos@webrtc.org6eaf09a2015-03-23 13:12:24355 VideoReceiveStream* receive_stream_impl = nullptr;
pbos@webrtc.org00208582013-09-05 12:38:54356 {
pbos@webrtc.org9b707ca2014-09-03 16:17:12357 WriteLockScoped write_lock(*receive_crit_);
pbos@webrtc.orgc71929d2014-01-24 09:30:53358 // Remove all ssrcs pointing to a receive stream. As RTX retransmits on a
359 // separate SSRC there can be either one or two.
Fredrik Solenbergad867862015-04-29 13:24:01360 auto it = video_receive_ssrcs_.begin();
361 while (it != video_receive_ssrcs_.end()) {
pbos@webrtc.org00208582013-09-05 12:38:54362 if (it->second == static_cast<VideoReceiveStream*>(receive_stream)) {
pbos@webrtc.org6eaf09a2015-03-23 13:12:24363 if (receive_stream_impl != nullptr)
henrikg5c075c82015-09-17 07:24:34364 RTC_DCHECK(receive_stream_impl == it->second);
pbos@webrtc.org00208582013-09-05 12:38:54365 receive_stream_impl = it->second;
Fredrik Solenbergad867862015-04-29 13:24:01366 video_receive_ssrcs_.erase(it++);
pbos@webrtc.orgc71929d2014-01-24 09:30:53367 } else {
368 ++it;
pbos@webrtc.org00208582013-09-05 12:38:54369 }
370 }
Fredrik Solenbergad867862015-04-29 13:24:01371 video_receive_streams_.erase(receive_stream_impl);
henrikg5c075c82015-09-17 07:24:34372 RTC_CHECK(receive_stream_impl != nullptr);
pbos495b3502015-07-15 15:02:58373 ConfigureSync(receive_stream_impl->config().sync_group);
pbos@webrtc.org2a9108f2013-05-16 12:08:03374 }
pbos@webrtc.org00208582013-09-05 12:38:54375 delete receive_stream_impl;
pbos@webrtc.org2a9108f2013-05-16 12:08:03376}
377
stefan@webrtc.org52322672014-11-05 14:05:29378Call::Stats Call::GetStats() const {
379 Stats stats;
Peter Boström8e07f3a2015-05-08 11:54:38380 // Fetch available send/receive bitrates.
stefan@webrtc.org52322672014-11-05 14:05:29381 uint32_t send_bandwidth = 0;
Peter Boström8e07f3a2015-05-08 11:54:38382 channel_group_->GetBitrateController()->AvailableBandwidth(&send_bandwidth);
383 std::vector<unsigned int> ssrcs;
stefan@webrtc.org52322672014-11-05 14:05:29384 uint32_t recv_bandwidth = 0;
mflodman7d393832015-10-19 05:08:19385 channel_group_->GetRemoteBitrateEstimator(false)->LatestEstimate(
386 &ssrcs, &recv_bandwidth);
Peter Boström8e07f3a2015-05-08 11:54:38387 stats.send_bandwidth_bps = send_bandwidth;
stefan@webrtc.org52322672014-11-05 14:05:29388 stats.recv_bandwidth_bps = recv_bandwidth;
Peter Boströmad9dcaf2015-04-27 15:24:33389 stats.pacer_delay_ms = channel_group_->GetPacerQueuingDelayMs();
stefan@webrtc.org52322672014-11-05 14:05:29390 {
391 ReadLockScoped read_lock(*send_crit_);
solenbergf707c682015-10-16 21:35:07392 // TODO(solenberg): Add audio send streams.
Fredrik Solenbergad867862015-04-29 13:24:01393 for (const auto& kv : video_send_ssrcs_) {
394 int rtt_ms = kv.second->GetRtt();
pbos@webrtc.org834b4752014-12-11 13:26:09395 if (rtt_ms > 0)
396 stats.rtt_ms = rtt_ms;
stefan@webrtc.org52322672014-11-05 14:05:29397 }
398 }
399 return stats;
pbos@webrtc.org2a9108f2013-05-16 12:08:03400}
401
pbos@webrtc.org5e3f6b42014-11-25 14:03:34402void Call::SetBitrateConfig(
403 const webrtc::Call::Config::BitrateConfig& bitrate_config) {
pbos@webrtc.orge2863932015-01-29 12:33:07404 TRACE_EVENT0("webrtc", "Call::SetBitrateConfig");
henrikg5c075c82015-09-17 07:24:34405 RTC_DCHECK_GE(bitrate_config.min_bitrate_bps, 0);
pbos@webrtc.org6eaf09a2015-03-23 13:12:24406 if (bitrate_config.max_bitrate_bps != -1)
henrikg5c075c82015-09-17 07:24:34407 RTC_DCHECK_GT(bitrate_config.max_bitrate_bps, 0);
Stefan Holmerca55fa12015-03-26 10:11:06408 if (config_.bitrate_config.min_bitrate_bps ==
pbos@webrtc.org5e3f6b42014-11-25 14:03:34409 bitrate_config.min_bitrate_bps &&
410 (bitrate_config.start_bitrate_bps <= 0 ||
Stefan Holmerca55fa12015-03-26 10:11:06411 config_.bitrate_config.start_bitrate_bps ==
pbos@webrtc.org5e3f6b42014-11-25 14:03:34412 bitrate_config.start_bitrate_bps) &&
Stefan Holmerca55fa12015-03-26 10:11:06413 config_.bitrate_config.max_bitrate_bps ==
pbos@webrtc.org5e3f6b42014-11-25 14:03:34414 bitrate_config.max_bitrate_bps) {
415 // Nothing new to set, early abort to avoid encoder reconfigurations.
416 return;
417 }
Stefan Holmerca55fa12015-03-26 10:11:06418 config_.bitrate_config = bitrate_config;
stefan9aa9de92015-09-28 10:57:14419 channel_group_->SetBweBitrates(bitrate_config.min_bitrate_bps,
420 bitrate_config.start_bitrate_bps,
421 bitrate_config.max_bitrate_bps);
pbos@webrtc.org5e3f6b42014-11-25 14:03:34422}
423
pbos@webrtc.org9b707ca2014-09-03 16:17:12424void Call::SignalNetworkState(NetworkState state) {
425 // Take crit for entire function, it needs to be held while updating streams
426 // to guarantee a consistent state across streams.
Peter Boström7d6ce5f2015-05-01 11:00:41427 rtc::CritScope lock(&network_enabled_crit_);
pbos@webrtc.org9b707ca2014-09-03 16:17:12428 network_enabled_ = state == kNetworkUp;
stefandf65b2e2015-10-14 10:12:59429 channel_group_->SignalNetworkState(state);
pbos@webrtc.org9b707ca2014-09-03 16:17:12430 {
431 ReadLockScoped write_lock(*send_crit_);
solenbergf707c682015-10-16 21:35:07432 for (auto& kv : audio_send_ssrcs_) {
433 kv.second->SignalNetworkState(state);
434 }
Fredrik Solenbergad867862015-04-29 13:24:01435 for (auto& kv : video_send_ssrcs_) {
436 kv.second->SignalNetworkState(state);
pbos@webrtc.org9b707ca2014-09-03 16:17:12437 }
438 }
439 {
440 ReadLockScoped write_lock(*receive_crit_);
Fredrik Solenbergad867862015-04-29 13:24:01441 for (auto& kv : video_receive_ssrcs_) {
442 kv.second->SignalNetworkState(state);
pbos@webrtc.org9b707ca2014-09-03 16:17:12443 }
444 }
445}
446
stefan15b20992015-10-15 14:26:07447void Call::OnSentPacket(const rtc::SentPacket& sent_packet) {
448 channel_group_->OnSentPacket(sent_packet);
449}
450
pbos495b3502015-07-15 15:02:58451void Call::ConfigureSync(const std::string& sync_group) {
452 // Set sync only if there was no previous one.
453 if (config_.voice_engine == nullptr || sync_group.empty())
454 return;
455
456 AudioReceiveStream* sync_audio_stream = nullptr;
457 // Find existing audio stream.
458 const auto it = sync_stream_mapping_.find(sync_group);
459 if (it != sync_stream_mapping_.end()) {
460 sync_audio_stream = it->second;
461 } else {
462 // No configured audio stream, see if we can find one.
463 for (const auto& kv : audio_receive_ssrcs_) {
464 if (kv.second->config().sync_group == sync_group) {
465 if (sync_audio_stream != nullptr) {
466 LOG(LS_WARNING) << "Attempting to sync more than one audio stream "
467 "within the same sync group. This is not "
468 "supported in the current implementation.";
469 break;
470 }
471 sync_audio_stream = kv.second;
472 }
473 }
474 }
475 if (sync_audio_stream)
476 sync_stream_mapping_[sync_group] = sync_audio_stream;
477 size_t num_synced_streams = 0;
478 for (VideoReceiveStream* video_stream : video_receive_streams_) {
479 if (video_stream->config().sync_group != sync_group)
480 continue;
481 ++num_synced_streams;
482 if (num_synced_streams > 1) {
483 // TODO(pbos): Support synchronizing more than one A/V pair.
484 // https://code.google.com/p/webrtc/issues/detail?id=4762
485 LOG(LS_WARNING) << "Attempting to sync more than one audio/video pair "
486 "within the same sync group. This is not supported in "
487 "the current implementation.";
488 }
489 // Only sync the first A/V pair within this sync group.
490 if (sync_audio_stream != nullptr && num_synced_streams == 1) {
491 video_stream->SetSyncChannel(config_.voice_engine,
492 sync_audio_stream->config().voe_channel_id);
493 } else {
494 video_stream->SetSyncChannel(config_.voice_engine, -1);
495 }
496 }
497}
498
Fredrik Solenbergad867862015-04-29 13:24:01499PacketReceiver::DeliveryStatus Call::DeliverRtcp(MediaType media_type,
500 const uint8_t* packet,
501 size_t length) {
pbos@webrtc.org2a9108f2013-05-16 12:08:03502 // TODO(pbos): Figure out what channel needs it actually.
503 // Do NOT broadcast! Also make sure it's a valid packet.
pbos@webrtc.orgbc57e0f2014-05-14 13:57:12504 // Return DELIVERY_UNKNOWN_SSRC if it can be determined that
505 // there's no receiver of the packet.
pbos@webrtc.org2a9108f2013-05-16 12:08:03506 bool rtcp_delivered = false;
Fredrik Solenbergad867862015-04-29 13:24:01507 if (media_type == MediaType::ANY || media_type == MediaType::VIDEO) {
pbos@webrtc.org9b707ca2014-09-03 16:17:12508 ReadLockScoped read_lock(*receive_crit_);
Fredrik Solenbergad867862015-04-29 13:24:01509 for (VideoReceiveStream* stream : video_receive_streams_) {
ivoc35fd7532015-09-09 07:09:43510 if (stream->DeliverRtcp(packet, length)) {
pbos@webrtc.org78ab5112013-08-05 12:49:22511 rtcp_delivered = true;
ivoc35fd7532015-09-09 07:09:43512 if (event_log_)
513 event_log_->LogRtcpPacket(true, media_type, packet, length);
514 }
pbos@webrtc.orgce851092013-08-05 12:01:36515 }
516 }
Fredrik Solenbergad867862015-04-29 13:24:01517 if (media_type == MediaType::ANY || media_type == MediaType::VIDEO) {
pbos@webrtc.org9b707ca2014-09-03 16:17:12518 ReadLockScoped read_lock(*send_crit_);
Fredrik Solenbergad867862015-04-29 13:24:01519 for (VideoSendStream* stream : video_send_streams_) {
ivoc35fd7532015-09-09 07:09:43520 if (stream->DeliverRtcp(packet, length)) {
pbos@webrtc.org78ab5112013-08-05 12:49:22521 rtcp_delivered = true;
ivoc35fd7532015-09-09 07:09:43522 if (event_log_)
523 event_log_->LogRtcpPacket(false, media_type, packet, length);
524 }
pbos@webrtc.org2a9108f2013-05-16 12:08:03525 }
526 }
pbos@webrtc.orgbc57e0f2014-05-14 13:57:12527 return rtcp_delivered ? DELIVERY_OK : DELIVERY_PACKET_ERROR;
pbos@webrtc.org2a9108f2013-05-16 12:08:03528}
529
Fredrik Solenbergad867862015-04-29 13:24:01530PacketReceiver::DeliveryStatus Call::DeliverRtp(MediaType media_type,
531 const uint8_t* packet,
stefan30bf7782015-09-08 12:36:15532 size_t length,
533 const PacketTime& packet_time) {
pbos@webrtc.orgf8be3d22014-07-08 07:38:12534 // Minimum RTP header size.
535 if (length < 12)
536 return DELIVERY_PACKET_ERROR;
537
sprang@webrtc.orgcce642c2015-01-28 12:37:36538 uint32_t ssrc = ByteReader<uint32_t>::ReadBigEndian(&packet[8]);
pbos@webrtc.orgf8be3d22014-07-08 07:38:12539
pbos@webrtc.org9b707ca2014-09-03 16:17:12540 ReadLockScoped read_lock(*receive_crit_);
Fredrik Solenbergad867862015-04-29 13:24:01541 if (media_type == MediaType::ANY || media_type == MediaType::AUDIO) {
542 auto it = audio_receive_ssrcs_.find(ssrc);
543 if (it != audio_receive_ssrcs_.end()) {
ivoc35fd7532015-09-09 07:09:43544 auto status = it->second->DeliverRtp(packet, length, packet_time)
545 ? DELIVERY_OK
546 : DELIVERY_PACKET_ERROR;
547 if (status == DELIVERY_OK && event_log_)
548 event_log_->LogRtpHeader(true, media_type, packet, length);
549 return status;
Fredrik Solenbergad867862015-04-29 13:24:01550 }
551 }
552 if (media_type == MediaType::ANY || media_type == MediaType::VIDEO) {
553 auto it = video_receive_ssrcs_.find(ssrc);
554 if (it != video_receive_ssrcs_.end()) {
ivoc35fd7532015-09-09 07:09:43555 auto status = it->second->DeliverRtp(packet, length, packet_time)
556 ? DELIVERY_OK
557 : DELIVERY_PACKET_ERROR;
558 if (status == DELIVERY_OK && event_log_)
559 event_log_->LogRtpHeader(true, media_type, packet, length);
560 return status;
Fredrik Solenbergad867862015-04-29 13:24:01561 }
562 }
563 return DELIVERY_UNKNOWN_SSRC;
pbos@webrtc.org2a9108f2013-05-16 12:08:03564}
565
stefan30bf7782015-09-08 12:36:15566PacketReceiver::DeliveryStatus Call::DeliverPacket(
567 MediaType media_type,
568 const uint8_t* packet,
569 size_t length,
570 const PacketTime& packet_time) {
pbos@webrtc.org6aae61c2014-07-08 12:10:51571 if (RtpHeaderParser::IsRtcp(packet, length))
Fredrik Solenbergad867862015-04-29 13:24:01572 return DeliverRtcp(media_type, packet, length);
pbos@webrtc.org2a9108f2013-05-16 12:08:03573
stefan30bf7782015-09-08 12:36:15574 return DeliverRtp(media_type, packet, length, packet_time);
pbos@webrtc.org2a9108f2013-05-16 12:08:03575}
576
577} // namespace internal
578} // namespace webrtc