blob: d508a1064e164080bb99101605026884bac1446e [file] [log] [blame]
nissecae45d02017-04-24 05:53:20 -07001/*
2 * Copyright (c) 2017 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 */
Jonas Olssona4d87372019-07-05 19:08:33 +020010#include "call/rtp_transport_controller_send.h"
11
Mirko Bonadei317a1f02019-09-17 17:06:18 +020012#include <memory>
Sebastian Jansson91bb6672018-02-21 13:02:51 +010013#include <utility>
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020014#include <vector>
nissecae45d02017-04-24 05:53:20 -070015
Mirko Bonadei06d35592020-04-01 13:43:08 +020016#include "absl/strings/match.h"
Yves Gerey3e707812018-11-28 16:47:49 +010017#include "absl/types/optional.h"
Sebastian Jansson87609be2018-12-05 17:35:35 +010018#include "api/transport/goog_cc_factory.h"
Yves Gerey3e707812018-11-28 16:47:49 +010019#include "api/transport/network_types.h"
20#include "api/units/data_rate.h"
21#include "api/units/time_delta.h"
22#include "api/units/timestamp.h"
Yves Gerey3e707812018-11-28 16:47:49 +010023#include "call/rtp_video_sender.h"
Sebastian Jansson0a5ed892019-09-18 15:37:31 +020024#include "logging/rtc_event_log/events/rtc_event_remote_estimate.h"
Sebastian Jansson166b45d2019-05-13 11:57:42 +020025#include "logging/rtc_event_log/events/rtc_event_route_change.h"
Sebastian Jansson658f1812020-01-16 10:59:28 +010026#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
Yves Gerey3e707812018-11-28 16:47:49 +010027#include "rtc_base/checks.h"
Sebastian Jansson97f61ea2018-02-21 13:01:55 +010028#include "rtc_base/logging.h"
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020029#include "rtc_base/rate_limiter.h"
nissecae45d02017-04-24 05:53:20 -070030
31namespace webrtc {
Sebastian Jansson19bea512018-03-13 19:07:46 +010032namespace {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020033static const int64_t kRetransmitWindowSizeMs = 500;
Stefan Holmer64be7fa2018-10-04 15:21:55 +020034static const size_t kMaxOverheadBytes = 500;
Sebastian Jansson19bea512018-03-13 19:07:46 +010035
Danil Chapovalov0c626af2020-02-10 11:16:00 +010036constexpr TimeDelta kPacerQueueUpdateInterval = TimeDelta::Millis(25);
Sebastian Jansson87609be2018-12-05 17:35:35 +010037
38TargetRateConstraints ConvertConstraints(int min_bitrate_bps,
39 int max_bitrate_bps,
40 int start_bitrate_bps,
Sebastian Janssonaa01f272019-01-30 11:28:59 +010041 Clock* clock) {
Sebastian Jansson87609be2018-12-05 17:35:35 +010042 TargetRateConstraints msg;
Danil Chapovalov0c626af2020-02-10 11:16:00 +010043 msg.at_time = Timestamp::Millis(clock->TimeInMilliseconds());
Danil Chapovalovcad3e0e2020-02-17 18:46:07 +010044 msg.min_data_rate = min_bitrate_bps >= 0
45 ? DataRate::BitsPerSec(min_bitrate_bps)
46 : DataRate::Zero();
47 msg.max_data_rate = max_bitrate_bps > 0
48 ? DataRate::BitsPerSec(max_bitrate_bps)
49 : DataRate::Infinity();
Sebastian Jansson87609be2018-12-05 17:35:35 +010050 if (start_bitrate_bps > 0)
Danil Chapovalovcad3e0e2020-02-17 18:46:07 +010051 msg.starting_rate = DataRate::BitsPerSec(start_bitrate_bps);
Sebastian Jansson87609be2018-12-05 17:35:35 +010052 return msg;
53}
54
55TargetRateConstraints ConvertConstraints(const BitrateConstraints& contraints,
Sebastian Janssonaa01f272019-01-30 11:28:59 +010056 Clock* clock) {
Sebastian Jansson87609be2018-12-05 17:35:35 +010057 return ConvertConstraints(contraints.min_bitrate_bps,
58 contraints.max_bitrate_bps,
59 contraints.start_bitrate_bps, clock);
60}
Erik Språng662678d2019-11-15 17:18:52 +010061
62bool IsEnabled(const WebRtcKeyValueConfig* trials, absl::string_view key) {
Erik Språng014dd3c2019-11-28 13:44:25 +010063 RTC_DCHECK(trials != nullptr);
Mirko Bonadei06d35592020-04-01 13:43:08 +020064 return absl::StartsWith(trials->Lookup(key), "Enabled");
Erik Språng662678d2019-11-15 17:18:52 +010065}
66
Christoffer Rodbro6404cdd2020-03-26 20:37:21 +010067bool IsRelayed(const rtc::NetworkRoute& route) {
68 return route.local.uses_turn() || route.remote.uses_turn();
Christoffer Rodbrob0ca5192020-03-26 09:22:24 +010069}
70
Sebastian Jansson19bea512018-03-13 19:07:46 +010071} // namespace
nissecae45d02017-04-24 05:53:20 -070072
73RtpTransportControllerSend::RtpTransportControllerSend(
74 Clock* clock,
Sebastian Jansson97f61ea2018-02-21 13:01:55 +010075 webrtc::RtcEventLog* event_log,
Ying Wang0810a7c2019-04-10 13:48:24 +020076 NetworkStatePredictorFactoryInterface* predictor_factory,
Sebastian Janssondfce03a2018-05-18 18:05:10 +020077 NetworkControllerFactoryInterface* controller_factory,
Sebastian Janssoned50e6c2019-03-01 14:45:21 +010078 const BitrateConstraints& bitrate_config,
79 std::unique_ptr<ProcessThread> process_thread,
Erik Språng662678d2019-11-15 17:18:52 +010080 TaskQueueFactory* task_queue_factory,
81 const WebRtcKeyValueConfig* trials)
Sebastian Jansson19704ec2018-03-12 15:59:12 +010082 : clock_(clock),
Sebastian Jansson166b45d2019-05-13 11:57:42 +020083 event_log_(event_log),
Sebastian Jansson317a5222018-03-16 15:36:37 +010084 bitrate_configurator_(bitrate_config),
Erik Språng7703f232020-09-14 11:03:13 +020085 process_thread_started_(false),
Sebastian Janssoned50e6c2019-03-01 14:45:21 +010086 process_thread_(std::move(process_thread)),
Erik Språng014dd3c2019-11-28 13:44:25 +010087 use_task_queue_pacer_(IsEnabled(trials, "WebRTC-TaskQueuePacer")),
Erik Språng4314a492019-11-26 17:48:49 +010088 process_thread_pacer_(use_task_queue_pacer_
89 ? nullptr
90 : new PacedSender(clock,
91 &packet_router_,
92 event_log,
Erik Språng014dd3c2019-11-28 13:44:25 +010093 trials,
Erik Språng4314a492019-11-26 17:48:49 +010094 process_thread_.get())),
Erik Språng4ab61cb2020-05-19 17:40:58 +020095 task_queue_pacer_(
96 use_task_queue_pacer_
97 ? new TaskQueuePacedSender(
98 clock,
99 &packet_router_,
100 event_log,
101 trials,
102 task_queue_factory,
103 /*hold_back_window = */ PacingController::kMinSleepTime)
104 : nullptr),
Sebastian Jansson317a5222018-03-16 15:36:37 +0100105 observer_(nullptr),
Sebastian Jansson87609be2018-12-05 17:35:35 +0100106 controller_factory_override_(controller_factory),
107 controller_factory_fallback_(
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200108 std::make_unique<GoogCcNetworkControllerFactory>(predictor_factory)),
Sebastian Jansson87609be2018-12-05 17:35:35 +0100109 process_interval_(controller_factory_fallback_->GetProcessInterval()),
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100110 last_report_block_time_(Timestamp::Millis(clock_->TimeInMilliseconds())),
Sebastian Jansson87609be2018-12-05 17:35:35 +0100111 reset_feedback_on_route_change_(
Erik Språng014dd3c2019-11-28 13:44:25 +0100112 !IsEnabled(trials, "WebRTC-Bwe-NoFeedbackReset")),
Sebastian Jansson87609be2018-12-05 17:35:35 +0100113 send_side_bwe_with_overhead_(
Erik Språng014dd3c2019-11-28 13:44:25 +0100114 IsEnabled(trials, "WebRTC-SendSideBwe-WithOverhead")),
Christoffer Rodbroc610e262019-01-08 10:49:19 +0100115 add_pacing_to_cwin_(
Erik Språng014dd3c2019-11-28 13:44:25 +0100116 IsEnabled(trials, "WebRTC-AddPacingToCongestionWindowPushback")),
Christoffer Rodbro6404cdd2020-03-26 20:37:21 +0100117 relay_bandwidth_cap_("relay_cap", DataRate::PlusInfinity()),
Sebastian Jansson87609be2018-12-05 17:35:35 +0100118 transport_overhead_bytes_per_packet_(0),
119 network_available_(false),
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200120 retransmission_rate_limiter_(clock, kRetransmitWindowSizeMs),
Sebastian Janssoned50e6c2019-03-01 14:45:21 +0100121 task_queue_(task_queue_factory->CreateTaskQueue(
122 "rtp_send_controller",
123 TaskQueueFactory::Priority::NORMAL)) {
Christoffer Rodbro6404cdd2020-03-26 20:37:21 +0100124 ParseFieldTrial({&relay_bandwidth_cap_},
125 trials->Lookup("WebRTC-Bwe-NetworkRouteConstraints"));
Sebastian Jansson87609be2018-12-05 17:35:35 +0100126 initial_config_.constraints = ConvertConstraints(bitrate_config, clock_);
Sebastian Janssondf88cc02019-04-15 15:42:25 +0200127 initial_config_.event_log = event_log;
Erik Språng014dd3c2019-11-28 13:44:25 +0100128 initial_config_.key_value_config = trials;
Sebastian Jansson87609be2018-12-05 17:35:35 +0100129 RTC_DCHECK(bitrate_config.start_bitrate_bps > 0);
130
Danil Chapovalovcad3e0e2020-02-17 18:46:07 +0100131 pacer()->SetPacingRates(
132 DataRate::BitsPerSec(bitrate_config.start_bitrate_bps), DataRate::Zero());
Sebastian Janssonbd9fe092018-05-07 16:33:50 +0200133
Erik Språng7703f232020-09-14 11:03:13 +0200134 if (!absl::StartsWith(trials->Lookup("WebRTC-LazyPacerStart"), "Disabled")) {
135 EnsureStarted();
Erik Språng4314a492019-11-26 17:48:49 +0100136 }
Sebastian Jansson97f61ea2018-02-21 13:01:55 +0100137}
Sebastian Janssonc33c0fc2018-02-22 11:10:18 +0100138
139RtpTransportControllerSend::~RtpTransportControllerSend() {
Erik Språng7703f232020-09-14 11:03:13 +0200140 process_thread_->Stop();
Sebastian Janssonc33c0fc2018-02-22 11:10:18 +0100141}
nissecae45d02017-04-24 05:53:20 -0700142
Stefan Holmer9416ef82018-07-19 10:34:38 +0200143RtpVideoSenderInterface* RtpTransportControllerSend::CreateRtpVideoSender(
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200144 std::map<uint32_t, RtpState> suspended_ssrcs,
145 const std::map<uint32_t, RtpPayloadState>& states,
146 const RtpConfig& rtp_config,
Jiawei Ou55718122018-11-09 13:17:39 -0800147 int rtcp_report_interval_ms,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200148 Transport* send_transport,
149 const RtpSenderObservers& observers,
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200150 RtcEventLog* event_log,
Benjamin Wright192eeec2018-10-17 17:27:25 -0700151 std::unique_ptr<FecController> fec_controller,
Marina Cioceae77912b2020-02-27 16:16:55 +0100152 const RtpSenderFrameEncryptionConfig& frame_encryption_config,
153 rtc::scoped_refptr<FrameTransformerInterface> frame_transformer) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200154 video_rtp_senders_.push_back(std::make_unique<RtpVideoSender>(
Sebastian Jansson572c60f2019-03-04 18:30:41 +0100155 clock_, suspended_ssrcs, states, rtp_config, rtcp_report_interval_ms,
Oleh Prypine8964902019-03-29 15:33:01 +0000156 send_transport, observers,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200157 // TODO(holmer): Remove this circular dependency by injecting
158 // the parts of RtpTransportControllerSendInterface that are really used.
Benjamin Wright192eeec2018-10-17 17:27:25 -0700159 this, event_log, &retransmission_rate_limiter_, std::move(fec_controller),
160 frame_encryption_config.frame_encryptor,
Marina Cioceae77912b2020-02-27 16:16:55 +0100161 frame_encryption_config.crypto_options, std::move(frame_transformer)));
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200162 return video_rtp_senders_.back().get();
163}
164
Stefan Holmer9416ef82018-07-19 10:34:38 +0200165void RtpTransportControllerSend::DestroyRtpVideoSender(
166 RtpVideoSenderInterface* rtp_video_sender) {
167 std::vector<std::unique_ptr<RtpVideoSenderInterface>>::iterator it =
Stefan Holmer5ed25af2018-07-18 15:17:14 +0200168 video_rtp_senders_.end();
169 for (it = video_rtp_senders_.begin(); it != video_rtp_senders_.end(); ++it) {
170 if (it->get() == rtp_video_sender) {
171 break;
172 }
173 }
174 RTC_DCHECK(it != video_rtp_senders_.end());
175 video_rtp_senders_.erase(it);
176}
177
Sebastian Jansson16180952018-12-12 16:49:10 +0100178void RtpTransportControllerSend::UpdateControlState() {
179 absl::optional<TargetTransferRate> update = control_handler_->GetUpdate();
180 if (!update)
181 return;
Sebastian Janssonf34116e2019-09-24 17:55:50 +0200182 retransmission_rate_limiter_.SetMaxRate(update->target_rate.bps());
Sebastian Jansson16180952018-12-12 16:49:10 +0100183 // We won't create control_handler_ until we have an observers.
Sebastian Jansson87609be2018-12-05 17:35:35 +0100184 RTC_DCHECK(observer_ != nullptr);
Sebastian Jansson16180952018-12-12 16:49:10 +0100185 observer_->OnTargetTransferRate(*update);
Sebastian Janssone6256052018-05-04 14:08:15 +0200186}
187
Erik Språng425d6aa2019-07-29 16:38:27 +0200188RtpPacketPacer* RtpTransportControllerSend::pacer() {
Erik Språng4314a492019-11-26 17:48:49 +0100189 if (use_task_queue_pacer_) {
190 return task_queue_pacer_.get();
191 }
192 return process_thread_pacer_.get();
Erik Språng425d6aa2019-07-29 16:38:27 +0200193}
194
195const RtpPacketPacer* RtpTransportControllerSend::pacer() const {
Erik Språng4314a492019-11-26 17:48:49 +0100196 if (use_task_queue_pacer_) {
197 return task_queue_pacer_.get();
198 }
199 return process_thread_pacer_.get();
Erik Språng425d6aa2019-07-29 16:38:27 +0200200}
201
Sebastian Janssone6256052018-05-04 14:08:15 +0200202rtc::TaskQueue* RtpTransportControllerSend::GetWorkerQueue() {
203 return &task_queue_;
Sebastian Jansson19704ec2018-03-12 15:59:12 +0100204}
205
nisse76e62b02017-05-31 02:24:52 -0700206PacketRouter* RtpTransportControllerSend::packet_router() {
207 return &packet_router_;
208}
209
Sebastian Janssone1795f42019-07-24 11:38:03 +0200210NetworkStateEstimateObserver*
211RtpTransportControllerSend::network_state_estimate_observer() {
212 return this;
213}
214
nisse76e62b02017-05-31 02:24:52 -0700215TransportFeedbackObserver*
216RtpTransportControllerSend::transport_feedback_observer() {
Sebastian Jansson87609be2018-12-05 17:35:35 +0100217 return this;
nisse76e62b02017-05-31 02:24:52 -0700218}
219
Erik Språngaa59eca2019-07-24 14:52:55 +0200220RtpPacketSender* RtpTransportControllerSend::packet_sender() {
Erik Språng4314a492019-11-26 17:48:49 +0100221 if (use_task_queue_pacer_) {
222 return task_queue_pacer_.get();
223 }
224 return process_thread_pacer_.get();
nisse76e62b02017-05-31 02:24:52 -0700225}
226
Stefan Holmer5c8942a2017-08-22 16:16:44 +0200227void RtpTransportControllerSend::SetAllocatedSendBitrateLimits(
Sebastian Jansson93b1ea22019-09-18 18:31:52 +0200228 BitrateAllocationLimits limits) {
Sebastian Jansson87609be2018-12-05 17:35:35 +0100229 RTC_DCHECK_RUN_ON(&task_queue_);
Sebastian Jansson93b1ea22019-09-18 18:31:52 +0200230 streams_config_.min_total_allocated_bitrate = limits.min_allocatable_rate;
231 streams_config_.max_padding_rate = limits.max_padding_rate;
232 streams_config_.max_total_allocated_bitrate = limits.max_allocatable_rate;
Sebastian Jansson87609be2018-12-05 17:35:35 +0100233 UpdateStreamsConfig();
Stefan Holmer5c8942a2017-08-22 16:16:44 +0200234}
Sebastian Jansson4c1ffb82018-02-15 16:51:58 +0100235void RtpTransportControllerSend::SetPacingFactor(float pacing_factor) {
Sebastian Jansson87609be2018-12-05 17:35:35 +0100236 RTC_DCHECK_RUN_ON(&task_queue_);
237 streams_config_.pacing_factor = pacing_factor;
238 UpdateStreamsConfig();
Sebastian Jansson4c1ffb82018-02-15 16:51:58 +0100239}
240void RtpTransportControllerSend::SetQueueTimeLimit(int limit_ms) {
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100241 pacer()->SetQueueTimeLimit(TimeDelta::Millis(limit_ms));
Sebastian Jansson4c1ffb82018-02-15 16:51:58 +0100242}
Sebastian Janssonf2988552019-10-29 17:18:51 +0100243StreamFeedbackProvider*
244RtpTransportControllerSend::GetStreamFeedbackProvider() {
JT Tehea992f82020-01-15 18:24:20 +0000245 return &feedback_demuxer_;
Sebastian Janssone4be6da2018-02-15 16:51:41 +0100246}
Sebastian Jansson19704ec2018-03-12 15:59:12 +0100247
248void RtpTransportControllerSend::RegisterTargetTransferRateObserver(
249 TargetTransferRateObserver* observer) {
Sebastian Jansson87609be2018-12-05 17:35:35 +0100250 task_queue_.PostTask([this, observer] {
251 RTC_DCHECK_RUN_ON(&task_queue_);
Sebastian Jansson19704ec2018-03-12 15:59:12 +0100252 RTC_DCHECK(observer_ == nullptr);
253 observer_ = observer;
Sebastian Jansson2701bc92018-12-11 15:02:47 +0100254 observer_->OnStartRateUpdate(*initial_config_.constraints.starting_rate);
Sebastian Jansson87609be2018-12-05 17:35:35 +0100255 MaybeCreateControllers();
256 });
Sebastian Janssone4be6da2018-02-15 16:51:41 +0100257}
Christoffer Rodbro6404cdd2020-03-26 20:37:21 +0100258
259bool RtpTransportControllerSend::IsRelevantRouteChange(
260 const rtc::NetworkRoute& old_route,
261 const rtc::NetworkRoute& new_route) const {
262 // TODO(bugs.webrtc.org/11438): Experiment with using more information/
263 // other conditions.
264 bool connected_changed = old_route.connected != new_route.connected;
265 bool route_ids_changed =
266 old_route.local.network_id() != new_route.local.network_id() ||
267 old_route.remote.network_id() != new_route.remote.network_id();
268 if (relay_bandwidth_cap_->IsFinite()) {
269 bool relaying_changed = IsRelayed(old_route) != IsRelayed(new_route);
270 return connected_changed || route_ids_changed || relaying_changed;
271 } else {
272 return connected_changed || route_ids_changed;
273 }
274}
275
Sebastian Janssone4be6da2018-02-15 16:51:41 +0100276void RtpTransportControllerSend::OnNetworkRouteChanged(
Sebastian Jansson97f61ea2018-02-21 13:01:55 +0100277 const std::string& transport_name,
278 const rtc::NetworkRoute& network_route) {
Sebastian Jansson91bb6672018-02-21 13:02:51 +0100279 // Check if the network route is connected.
Jonas Oreland71fda362020-03-20 16:11:56 +0100280
Sebastian Jansson91bb6672018-02-21 13:02:51 +0100281 if (!network_route.connected) {
Sebastian Jansson91bb6672018-02-21 13:02:51 +0100282 // TODO(honghaiz): Perhaps handle this in SignalChannelNetworkState and
283 // consider merging these two methods.
284 return;
285 }
286
Christoffer Rodbro6404cdd2020-03-26 20:37:21 +0100287 absl::optional<BitrateConstraints> relay_constraint_update =
288 ApplyOrLiftRelayCap(IsRelayed(network_route));
289
Sebastian Jansson91bb6672018-02-21 13:02:51 +0100290 // Check whether the network route has changed on each transport.
291 auto result =
292 network_routes_.insert(std::make_pair(transport_name, network_route));
293 auto kv = result.first;
294 bool inserted = result.second;
Jonas Oreland5b6a4d82020-03-24 07:36:52 +0100295 if (inserted || !(kv->second == network_route)) {
296 RTC_LOG(LS_INFO) << "Network route changed on transport " << transport_name
297 << ": new_route = " << network_route.DebugString();
298 if (!inserted) {
299 RTC_LOG(LS_INFO) << "old_route = " << kv->second.DebugString();
300 }
301 }
302
Sebastian Jansson91bb6672018-02-21 13:02:51 +0100303 if (inserted) {
Christoffer Rodbro6404cdd2020-03-26 20:37:21 +0100304 if (relay_constraint_update.has_value()) {
305 UpdateBitrateConstraints(*relay_constraint_update);
306 }
Jakob Ivarssonb4cdd622020-02-13 14:01:26 +0100307 task_queue_.PostTask([this, network_route] {
308 RTC_DCHECK_RUN_ON(&task_queue_);
309 transport_overhead_bytes_per_packet_ = network_route.packet_overhead;
310 });
Sebastian Jansson91bb6672018-02-21 13:02:51 +0100311 // No need to reset BWE if this is the first time the network connects.
312 return;
313 }
Jonas Oreland5b6a4d82020-03-24 07:36:52 +0100314
315 const rtc::NetworkRoute old_route = kv->second;
Jonas Oreland71fda362020-03-20 16:11:56 +0100316 kv->second = network_route;
Jonas Oreland71fda362020-03-20 16:11:56 +0100317
318 // Check if enough conditions of the new/old route has changed
319 // to trigger resetting of bitrates (and a probe).
Christoffer Rodbrob0ca5192020-03-26 09:22:24 +0100320 if (IsRelevantRouteChange(old_route, network_route)) {
Sebastian Jansson91bb6672018-02-21 13:02:51 +0100321 BitrateConstraints bitrate_config = bitrate_configurator_.GetConfig();
Jonas Oreland71fda362020-03-20 16:11:56 +0100322 RTC_LOG(LS_INFO) << "Reset bitrates to min: "
Sebastian Jansson91bb6672018-02-21 13:02:51 +0100323 << bitrate_config.min_bitrate_bps
324 << " bps, start: " << bitrate_config.start_bitrate_bps
325 << " bps, max: " << bitrate_config.max_bitrate_bps
326 << " bps.";
327 RTC_DCHECK_GT(bitrate_config.start_bitrate_bps, 0);
Sebastian Jansson87609be2018-12-05 17:35:35 +0100328
Sebastian Jansson166b45d2019-05-13 11:57:42 +0200329 if (event_log_) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200330 event_log_->Log(std::make_unique<RtcEventRouteChange>(
Sebastian Jansson166b45d2019-05-13 11:57:42 +0200331 network_route.connected, network_route.packet_overhead));
332 }
Sebastian Jansson87609be2018-12-05 17:35:35 +0100333 NetworkRouteChange msg;
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100334 msg.at_time = Timestamp::Millis(clock_->TimeInMilliseconds());
Sebastian Jansson87609be2018-12-05 17:35:35 +0100335 msg.constraints = ConvertConstraints(bitrate_config, clock_);
Sebastian Jansson658f1812020-01-16 10:59:28 +0100336 task_queue_.PostTask([this, msg, network_route] {
Sebastian Jansson87609be2018-12-05 17:35:35 +0100337 RTC_DCHECK_RUN_ON(&task_queue_);
Sebastian Jansson658f1812020-01-16 10:59:28 +0100338 transport_overhead_bytes_per_packet_ = network_route.packet_overhead;
339 if (reset_feedback_on_route_change_) {
Christoffer Rodbrob0ca5192020-03-26 09:22:24 +0100340 transport_feedback_adapter_.SetNetworkRoute(network_route);
Sebastian Jansson658f1812020-01-16 10:59:28 +0100341 }
Sebastian Jansson87609be2018-12-05 17:35:35 +0100342 if (controller_) {
Sebastian Jansson16180952018-12-12 16:49:10 +0100343 PostUpdates(controller_->OnNetworkRouteChange(msg));
Sebastian Jansson87609be2018-12-05 17:35:35 +0100344 } else {
345 UpdateInitialConstraints(msg.constraints);
346 }
Erik Språng425d6aa2019-07-29 16:38:27 +0200347 pacer()->UpdateOutstandingData(DataSize::Zero());
Sebastian Jansson87609be2018-12-05 17:35:35 +0100348 });
Sebastian Jansson91bb6672018-02-21 13:02:51 +0100349 }
Sebastian Janssone4be6da2018-02-15 16:51:41 +0100350}
351void RtpTransportControllerSend::OnNetworkAvailability(bool network_available) {
Harald Alvestrand977b2652019-12-12 13:40:50 +0100352 RTC_LOG(LS_VERBOSE) << "SignalNetworkState "
353 << (network_available ? "Up" : "Down");
Sebastian Jansson87609be2018-12-05 17:35:35 +0100354 NetworkAvailability msg;
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100355 msg.at_time = Timestamp::Millis(clock_->TimeInMilliseconds());
Sebastian Jansson87609be2018-12-05 17:35:35 +0100356 msg.network_available = network_available;
357 task_queue_.PostTask([this, msg]() {
358 RTC_DCHECK_RUN_ON(&task_queue_);
Sebastian Jansson16180952018-12-12 16:49:10 +0100359 if (network_available_ == msg.network_available)
360 return;
Sebastian Jansson87609be2018-12-05 17:35:35 +0100361 network_available_ = msg.network_available;
Sebastian Jansson16180952018-12-12 16:49:10 +0100362 if (network_available_) {
Erik Språng425d6aa2019-07-29 16:38:27 +0200363 pacer()->Resume();
Sebastian Jansson16180952018-12-12 16:49:10 +0100364 } else {
Erik Språng425d6aa2019-07-29 16:38:27 +0200365 pacer()->Pause();
Sebastian Jansson16180952018-12-12 16:49:10 +0100366 }
Erik Språng425d6aa2019-07-29 16:38:27 +0200367 pacer()->UpdateOutstandingData(DataSize::Zero());
Sebastian Jansson16180952018-12-12 16:49:10 +0100368
Sebastian Jansson87609be2018-12-05 17:35:35 +0100369 if (controller_) {
Sebastian Jansson16180952018-12-12 16:49:10 +0100370 control_handler_->SetNetworkAvailability(network_available_);
371 PostUpdates(controller_->OnNetworkAvailability(msg));
372 UpdateControlState();
Sebastian Jansson87609be2018-12-05 17:35:35 +0100373 } else {
374 MaybeCreateControllers();
375 }
376 });
377
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200378 for (auto& rtp_sender : video_rtp_senders_) {
379 rtp_sender->OnNetworkAvailability(network_available);
380 }
Sebastian Janssone4be6da2018-02-15 16:51:41 +0100381}
Sebastian Janssone4be6da2018-02-15 16:51:41 +0100382RtcpBandwidthObserver* RtpTransportControllerSend::GetBandwidthObserver() {
Sebastian Jansson87609be2018-12-05 17:35:35 +0100383 return this;
Sebastian Janssone4be6da2018-02-15 16:51:41 +0100384}
Sebastian Janssone4be6da2018-02-15 16:51:41 +0100385int64_t RtpTransportControllerSend::GetPacerQueuingDelayMs() const {
Erik Språng425d6aa2019-07-29 16:38:27 +0200386 return pacer()->OldestPacketWaitTime().ms();
Sebastian Janssone4be6da2018-02-15 16:51:41 +0100387}
Erik Språng425d6aa2019-07-29 16:38:27 +0200388absl::optional<Timestamp> RtpTransportControllerSend::GetFirstPacketTime()
389 const {
390 return pacer()->FirstSentPacketTime();
Sebastian Janssone4be6da2018-02-15 16:51:41 +0100391}
Sebastian Janssone4be6da2018-02-15 16:51:41 +0100392void RtpTransportControllerSend::EnablePeriodicAlrProbing(bool enable) {
Sebastian Jansson87609be2018-12-05 17:35:35 +0100393 task_queue_.PostTask([this, enable]() {
394 RTC_DCHECK_RUN_ON(&task_queue_);
395 streams_config_.requests_alr_probing = enable;
396 UpdateStreamsConfig();
397 });
Sebastian Janssone4be6da2018-02-15 16:51:41 +0100398}
399void RtpTransportControllerSend::OnSentPacket(
400 const rtc::SentPacket& sent_packet) {
Sebastian Jansson658f1812020-01-16 10:59:28 +0100401 task_queue_.PostTask([this, sent_packet]() {
402 RTC_DCHECK_RUN_ON(&task_queue_);
403 absl::optional<SentPacket> packet_msg =
404 transport_feedback_adapter_.ProcessSentPacket(sent_packet);
405 pacer()->UpdateOutstandingData(
406 transport_feedback_adapter_.GetOutstandingData());
407 if (packet_msg && controller_)
408 PostUpdates(controller_->OnSentPacket(*packet_msg));
409 });
Sebastian Janssone4be6da2018-02-15 16:51:41 +0100410}
sprangdb2a9fc2017-08-09 06:42:32 -0700411
Ying Wang8b279102019-05-27 17:19:08 +0200412void RtpTransportControllerSend::OnReceivedPacket(
Sebastian Jansson607a6f12019-06-13 17:48:53 +0200413 const ReceivedPacket& packet_msg) {
Ying Wang8b279102019-05-27 17:19:08 +0200414 task_queue_.PostTask([this, packet_msg]() {
415 RTC_DCHECK_RUN_ON(&task_queue_);
416 if (controller_)
417 PostUpdates(controller_->OnReceivedPacket(packet_msg));
418 });
419}
420
Christoffer Rodbrob0ca5192020-03-26 09:22:24 +0100421void RtpTransportControllerSend::UpdateBitrateConstraints(
422 const BitrateConstraints& updated) {
423 TargetRateConstraints msg = ConvertConstraints(updated, clock_);
424 task_queue_.PostTask([this, msg]() {
425 RTC_DCHECK_RUN_ON(&task_queue_);
426 if (controller_) {
427 PostUpdates(controller_->OnTargetRateConstraints(msg));
428 } else {
429 UpdateInitialConstraints(msg);
430 }
431 });
432}
433
Sebastian Jansson97f61ea2018-02-21 13:01:55 +0100434void RtpTransportControllerSend::SetSdpBitrateParameters(
435 const BitrateConstraints& constraints) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200436 absl::optional<BitrateConstraints> updated =
Sebastian Jansson97f61ea2018-02-21 13:01:55 +0100437 bitrate_configurator_.UpdateWithSdpParameters(constraints);
438 if (updated.has_value()) {
Christoffer Rodbrob0ca5192020-03-26 09:22:24 +0100439 UpdateBitrateConstraints(*updated);
Sebastian Jansson97f61ea2018-02-21 13:01:55 +0100440 } else {
441 RTC_LOG(LS_VERBOSE)
Sebastian Jansson8f83b422018-02-21 13:07:13 +0100442 << "WebRTC.RtpTransportControllerSend.SetSdpBitrateParameters: "
Jonas Olssonb2b20312020-01-14 12:11:31 +0100443 "nothing to update";
Sebastian Jansson97f61ea2018-02-21 13:01:55 +0100444 }
445}
446
447void RtpTransportControllerSend::SetClientBitratePreferences(
Niels Möller0c4f7be2018-05-07 14:01:37 +0200448 const BitrateSettings& preferences) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200449 absl::optional<BitrateConstraints> updated =
Sebastian Jansson97f61ea2018-02-21 13:01:55 +0100450 bitrate_configurator_.UpdateWithClientPreferences(preferences);
451 if (updated.has_value()) {
Christoffer Rodbrob0ca5192020-03-26 09:22:24 +0100452 UpdateBitrateConstraints(*updated);
Sebastian Jansson97f61ea2018-02-21 13:01:55 +0100453 } else {
454 RTC_LOG(LS_VERBOSE)
Sebastian Jansson8f83b422018-02-21 13:07:13 +0100455 << "WebRTC.RtpTransportControllerSend.SetClientBitratePreferences: "
Jonas Olssonb2b20312020-01-14 12:11:31 +0100456 "nothing to update";
Sebastian Jansson97f61ea2018-02-21 13:01:55 +0100457 }
458}
Alex Narestbcf91802018-06-25 16:08:36 +0200459
Christoffer Rodbro6404cdd2020-03-26 20:37:21 +0100460absl::optional<BitrateConstraints>
461RtpTransportControllerSend::ApplyOrLiftRelayCap(bool is_relayed) {
462 DataRate cap = is_relayed ? relay_bandwidth_cap_ : DataRate::PlusInfinity();
463 return bitrate_configurator_.UpdateWithRelayCap(cap);
464}
465
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200466void RtpTransportControllerSend::OnTransportOverheadChanged(
467 size_t transport_overhead_bytes_per_packet) {
468 if (transport_overhead_bytes_per_packet >= kMaxOverheadBytes) {
469 RTC_LOG(LS_ERROR) << "Transport overhead exceeds " << kMaxOverheadBytes;
470 return;
471 }
472
Mirko Bonadeie7bc3a32020-01-29 18:45:00 +0000473 pacer()->SetTransportOverhead(
Danil Chapovalovcad3e0e2020-02-17 18:46:07 +0100474 DataSize::Bytes(transport_overhead_bytes_per_packet));
Mirko Bonadeie7bc3a32020-01-29 18:45:00 +0000475
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200476 // TODO(holmer): Call AudioRtpSenders when they have been moved to
477 // RtpTransportControllerSend.
478 for (auto& rtp_video_sender : video_rtp_senders_) {
479 rtp_video_sender->OnTransportOverheadChanged(
480 transport_overhead_bytes_per_packet);
481 }
482}
Sebastian Jansson87609be2018-12-05 17:35:35 +0100483
Erik Språngaa59eca2019-07-24 14:52:55 +0200484void RtpTransportControllerSend::AccountForAudioPacketsInPacedSender(
485 bool account_for_audio) {
Erik Språng425d6aa2019-07-29 16:38:27 +0200486 pacer()->SetAccountForAudioPackets(account_for_audio);
Erik Språngaa59eca2019-07-24 14:52:55 +0200487}
488
Sebastian Janssonc3eb9fd2020-01-29 17:42:52 +0100489void RtpTransportControllerSend::IncludeOverheadInPacedSender() {
490 pacer()->SetIncludeOverhead();
491}
492
Erik Språng7703f232020-09-14 11:03:13 +0200493void RtpTransportControllerSend::EnsureStarted() {
494 if (!use_task_queue_pacer_ && !process_thread_started_) {
495 process_thread_started_ = true;
496 process_thread_->Start();
497 }
498}
499
Sebastian Jansson87609be2018-12-05 17:35:35 +0100500void RtpTransportControllerSend::OnReceivedEstimatedBitrate(uint32_t bitrate) {
501 RemoteBitrateReport msg;
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100502 msg.receive_time = Timestamp::Millis(clock_->TimeInMilliseconds());
Danil Chapovalovcad3e0e2020-02-17 18:46:07 +0100503 msg.bandwidth = DataRate::BitsPerSec(bitrate);
Sebastian Jansson87609be2018-12-05 17:35:35 +0100504 task_queue_.PostTask([this, msg]() {
505 RTC_DCHECK_RUN_ON(&task_queue_);
506 if (controller_)
Sebastian Jansson16180952018-12-12 16:49:10 +0100507 PostUpdates(controller_->OnRemoteBitrateReport(msg));
Sebastian Jansson87609be2018-12-05 17:35:35 +0100508 });
509}
510
511void RtpTransportControllerSend::OnReceivedRtcpReceiverReport(
512 const ReportBlockList& report_blocks,
513 int64_t rtt_ms,
514 int64_t now_ms) {
515 task_queue_.PostTask([this, report_blocks, now_ms]() {
516 RTC_DCHECK_RUN_ON(&task_queue_);
517 OnReceivedRtcpReceiverReportBlocks(report_blocks, now_ms);
518 });
519
520 task_queue_.PostTask([this, now_ms, rtt_ms]() {
521 RTC_DCHECK_RUN_ON(&task_queue_);
522 RoundTripTimeUpdate report;
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100523 report.receive_time = Timestamp::Millis(now_ms);
524 report.round_trip_time = TimeDelta::Millis(rtt_ms);
Sebastian Jansson87609be2018-12-05 17:35:35 +0100525 report.smoothed = false;
Christoffer Rodbro4bd31772019-03-27 12:34:21 +0100526 if (controller_ && !report.round_trip_time.IsZero())
Sebastian Jansson16180952018-12-12 16:49:10 +0100527 PostUpdates(controller_->OnRoundTripTimeUpdate(report));
Sebastian Jansson87609be2018-12-05 17:35:35 +0100528 });
529}
530
Erik Språng30a276b2019-04-23 12:00:11 +0200531void RtpTransportControllerSend::OnAddPacket(
532 const RtpPacketSendInfo& packet_info) {
JT Tehea992f82020-01-15 18:24:20 +0000533 feedback_demuxer_.AddPacket(packet_info);
534
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100535 Timestamp creation_time = Timestamp::Millis(clock_->TimeInMilliseconds());
Sebastian Jansson658f1812020-01-16 10:59:28 +0100536 task_queue_.PostTask([this, packet_info, creation_time]() {
537 RTC_DCHECK_RUN_ON(&task_queue_);
538 transport_feedback_adapter_.AddPacket(
539 packet_info,
540 send_side_bwe_with_overhead_ ? transport_overhead_bytes_per_packet_ : 0,
541 creation_time);
542 });
Sebastian Jansson87609be2018-12-05 17:35:35 +0100543}
544
545void RtpTransportControllerSend::OnTransportFeedback(
546 const rtcp::TransportFeedback& feedback) {
JT Tehea992f82020-01-15 18:24:20 +0000547 feedback_demuxer_.OnTransportFeedback(feedback);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100548 auto feedback_time = Timestamp::Millis(clock_->TimeInMilliseconds());
Sebastian Jansson658f1812020-01-16 10:59:28 +0100549 task_queue_.PostTask([this, feedback, feedback_time]() {
550 RTC_DCHECK_RUN_ON(&task_queue_);
551 absl::optional<TransportPacketsFeedback> feedback_msg =
552 transport_feedback_adapter_.ProcessTransportFeedback(feedback,
553 feedback_time);
554 if (feedback_msg && controller_) {
555 PostUpdates(controller_->OnTransportPacketsFeedback(*feedback_msg));
556 }
557 pacer()->UpdateOutstandingData(
558 transport_feedback_adapter_.GetOutstandingData());
559 });
Sebastian Jansson87609be2018-12-05 17:35:35 +0100560}
561
Sebastian Janssone1795f42019-07-24 11:38:03 +0200562void RtpTransportControllerSend::OnRemoteNetworkEstimate(
563 NetworkStateEstimate estimate) {
Sebastian Jansson0a5ed892019-09-18 15:37:31 +0200564 if (event_log_) {
565 event_log_->Log(std::make_unique<RtcEventRemoteEstimate>(
566 estimate.link_capacity_lower, estimate.link_capacity_upper));
567 }
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100568 estimate.update_time = Timestamp::Millis(clock_->TimeInMilliseconds());
Sebastian Janssone1795f42019-07-24 11:38:03 +0200569 task_queue_.PostTask([this, estimate] {
570 RTC_DCHECK_RUN_ON(&task_queue_);
571 if (controller_)
Danil Chapovalove34fb872019-10-21 10:51:08 +0200572 PostUpdates(controller_->OnNetworkStateEstimate(estimate));
Sebastian Janssone1795f42019-07-24 11:38:03 +0200573 });
574}
575
Sebastian Jansson87609be2018-12-05 17:35:35 +0100576void RtpTransportControllerSend::MaybeCreateControllers() {
577 RTC_DCHECK(!controller_);
578 RTC_DCHECK(!control_handler_);
579
580 if (!network_available_ || !observer_)
581 return;
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200582 control_handler_ = std::make_unique<CongestionControlHandler>();
Sebastian Jansson87609be2018-12-05 17:35:35 +0100583
584 initial_config_.constraints.at_time =
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100585 Timestamp::Millis(clock_->TimeInMilliseconds());
Sebastian Jansson87609be2018-12-05 17:35:35 +0100586 initial_config_.stream_based_config = streams_config_;
587
588 // TODO(srte): Use fallback controller if no feedback is available.
589 if (controller_factory_override_) {
590 RTC_LOG(LS_INFO) << "Creating overridden congestion controller";
591 controller_ = controller_factory_override_->Create(initial_config_);
592 process_interval_ = controller_factory_override_->GetProcessInterval();
593 } else {
594 RTC_LOG(LS_INFO) << "Creating fallback congestion controller";
595 controller_ = controller_factory_fallback_->Create(initial_config_);
596 process_interval_ = controller_factory_fallback_->GetProcessInterval();
597 }
598 UpdateControllerWithTimeInterval();
599 StartProcessPeriodicTasks();
600}
601
602void RtpTransportControllerSend::UpdateInitialConstraints(
603 TargetRateConstraints new_contraints) {
604 if (!new_contraints.starting_rate)
605 new_contraints.starting_rate = initial_config_.constraints.starting_rate;
606 RTC_DCHECK(new_contraints.starting_rate);
607 initial_config_.constraints = new_contraints;
608}
609
610void RtpTransportControllerSend::StartProcessPeriodicTasks() {
Sebastian Janssonecb68972019-01-18 10:30:54 +0100611 if (!pacer_queue_update_task_.Running()) {
612 pacer_queue_update_task_ = RepeatingTaskHandle::DelayedStart(
Danil Chapovalov4423c362019-03-06 18:41:39 +0100613 task_queue_.Get(), kPacerQueueUpdateInterval, [this]() {
Sebastian Jansson87609be2018-12-05 17:35:35 +0100614 RTC_DCHECK_RUN_ON(&task_queue_);
Erik Språng425d6aa2019-07-29 16:38:27 +0200615 TimeDelta expected_queue_time = pacer()->ExpectedQueueTime();
Sebastian Jansson16180952018-12-12 16:49:10 +0100616 control_handler_->SetPacerQueue(expected_queue_time);
617 UpdateControlState();
Sebastian Janssonecb68972019-01-18 10:30:54 +0100618 return kPacerQueueUpdateInterval;
Sebastian Jansson87609be2018-12-05 17:35:35 +0100619 });
620 }
Sebastian Janssonecb68972019-01-18 10:30:54 +0100621 controller_task_.Stop();
Sebastian Jansson87609be2018-12-05 17:35:35 +0100622 if (process_interval_.IsFinite()) {
Sebastian Janssonecb68972019-01-18 10:30:54 +0100623 controller_task_ = RepeatingTaskHandle::DelayedStart(
Danil Chapovalov4423c362019-03-06 18:41:39 +0100624 task_queue_.Get(), process_interval_, [this]() {
Sebastian Jansson87609be2018-12-05 17:35:35 +0100625 RTC_DCHECK_RUN_ON(&task_queue_);
626 UpdateControllerWithTimeInterval();
Sebastian Janssonecb68972019-01-18 10:30:54 +0100627 return process_interval_;
Sebastian Jansson87609be2018-12-05 17:35:35 +0100628 });
629 }
630}
631
632void RtpTransportControllerSend::UpdateControllerWithTimeInterval() {
Sebastian Jansson16180952018-12-12 16:49:10 +0100633 RTC_DCHECK(controller_);
634 ProcessInterval msg;
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100635 msg.at_time = Timestamp::Millis(clock_->TimeInMilliseconds());
Christoffer Rodbroc610e262019-01-08 10:49:19 +0100636 if (add_pacing_to_cwin_)
Erik Språng425d6aa2019-07-29 16:38:27 +0200637 msg.pacer_queue = pacer()->QueueSizeData();
Sebastian Jansson16180952018-12-12 16:49:10 +0100638 PostUpdates(controller_->OnProcessInterval(msg));
Sebastian Jansson87609be2018-12-05 17:35:35 +0100639}
640
641void RtpTransportControllerSend::UpdateStreamsConfig() {
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100642 streams_config_.at_time = Timestamp::Millis(clock_->TimeInMilliseconds());
Sebastian Jansson87609be2018-12-05 17:35:35 +0100643 if (controller_)
Sebastian Jansson16180952018-12-12 16:49:10 +0100644 PostUpdates(controller_->OnStreamsConfig(streams_config_));
645}
646
647void RtpTransportControllerSend::PostUpdates(NetworkControlUpdate update) {
648 if (update.congestion_window) {
Erik Språng425d6aa2019-07-29 16:38:27 +0200649 pacer()->SetCongestionWindow(*update.congestion_window);
Sebastian Jansson16180952018-12-12 16:49:10 +0100650 }
651 if (update.pacer_config) {
Erik Språng425d6aa2019-07-29 16:38:27 +0200652 pacer()->SetPacingRates(update.pacer_config->data_rate(),
653 update.pacer_config->pad_rate());
Sebastian Jansson16180952018-12-12 16:49:10 +0100654 }
655 for (const auto& probe : update.probe_cluster_configs) {
Erik Språng425d6aa2019-07-29 16:38:27 +0200656 pacer()->CreateProbeCluster(probe.target_data_rate, probe.id);
Sebastian Jansson16180952018-12-12 16:49:10 +0100657 }
658 if (update.target_rate) {
659 control_handler_->SetTargetRate(*update.target_rate);
660 UpdateControlState();
661 }
Sebastian Jansson87609be2018-12-05 17:35:35 +0100662}
663
664void RtpTransportControllerSend::OnReceivedRtcpReceiverReportBlocks(
665 const ReportBlockList& report_blocks,
666 int64_t now_ms) {
667 if (report_blocks.empty())
668 return;
669
670 int total_packets_lost_delta = 0;
671 int total_packets_delta = 0;
672
673 // Compute the packet loss from all report blocks.
674 for (const RTCPReportBlock& report_block : report_blocks) {
675 auto it = last_report_blocks_.find(report_block.source_ssrc);
676 if (it != last_report_blocks_.end()) {
677 auto number_of_packets = report_block.extended_highest_sequence_number -
678 it->second.extended_highest_sequence_number;
679 total_packets_delta += number_of_packets;
680 auto lost_delta = report_block.packets_lost - it->second.packets_lost;
681 total_packets_lost_delta += lost_delta;
682 }
683 last_report_blocks_[report_block.source_ssrc] = report_block;
684 }
685 // Can only compute delta if there has been previous blocks to compare to. If
686 // not, total_packets_delta will be unchanged and there's nothing more to do.
687 if (!total_packets_delta)
688 return;
689 int packets_received_delta = total_packets_delta - total_packets_lost_delta;
690 // To detect lost packets, at least one packet has to be received. This check
691 // is needed to avoid bandwith detection update in
692 // VideoSendStreamTest.SuspendBelowMinBitrate
693
694 if (packets_received_delta < 1)
695 return;
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100696 Timestamp now = Timestamp::Millis(now_ms);
Sebastian Jansson87609be2018-12-05 17:35:35 +0100697 TransportLossReport msg;
698 msg.packets_lost_delta = total_packets_lost_delta;
699 msg.packets_received_delta = packets_received_delta;
700 msg.receive_time = now;
701 msg.start_time = last_report_block_time_;
702 msg.end_time = now;
703 if (controller_)
Sebastian Jansson16180952018-12-12 16:49:10 +0100704 PostUpdates(controller_->OnTransportLossReport(msg));
Sebastian Jansson87609be2018-12-05 17:35:35 +0100705 last_report_block_time_ = now;
706}
707
nissecae45d02017-04-24 05:53:20 -0700708} // namespace webrtc