blob: a14c65e7196c8232e10f202f92b0518f54bcc6bc [file] [log] [blame]
Stefan Holmere5904162015-03-26 11:11:06 +01001/*
2 * Copyright (c) 2015 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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/pacing/packet_router.h"
Stefan Holmere5904162015-03-26 11:11:06 +010012
danilchap47085372017-08-10 06:03:57 -070013#include <algorithm>
Yves Gerey988cc082018-10-23 12:03:01 +020014#include <cstdint>
danilchap47085372017-08-10 06:03:57 -070015#include <limits>
Erik Språng58ee1872019-06-18 16:20:11 +020016#include <utility>
danilchap47085372017-08-10 06:03:57 -070017
Yves Gerey988cc082018-10-23 12:03:01 +020018#include "absl/types/optional.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "modules/rtp_rtcp/include/rtp_rtcp.h"
20#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
21#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
Steve Anton10542f22019-01-11 09:11:00 -080022#include "rtc_base/atomic_ops.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "rtc_base/checks.h"
Erik Språng58ee1872019-06-18 16:20:11 +020024#include "rtc_base/logging.h"
Steve Anton10542f22019-01-11 09:11:00 -080025#include "rtc_base/time_utils.h"
Stefan Holmere5904162015-03-26 11:11:06 +010026
27namespace webrtc {
danilchap47085372017-08-10 06:03:57 -070028namespace {
29
30constexpr int kRembSendIntervalMs = 200;
31
32} // namespace
Stefan Holmere5904162015-03-26 11:11:06 +010033
nisse05843312017-04-18 23:38:35 -070034PacketRouter::PacketRouter()
Erik Språng8b7ca4a2018-05-17 13:43:35 +020035 : last_send_module_(nullptr),
36 last_remb_time_ms_(rtc::TimeMillis()),
nisse05843312017-04-18 23:38:35 -070037 last_send_bitrate_bps_(0),
danilchap47085372017-08-10 06:03:57 -070038 bitrate_bps_(0),
39 max_bitrate_bps_(std::numeric_limits<decltype(max_bitrate_bps_)>::max()),
eladalon822ff2b2017-08-01 06:30:28 -070040 active_remb_module_(nullptr),
erikvargabf5a2fc2017-06-16 05:02:05 -070041 transport_seq_(0) {}
Stefan Holmere5904162015-03-26 11:11:06 +010042
43PacketRouter::~PacketRouter() {
nissefdbfdc92017-03-31 05:44:52 -070044 RTC_DCHECK(rtp_send_modules_.empty());
Danil Chapovaloveb0edd82017-12-14 16:02:31 +010045 RTC_DCHECK(rtcp_feedback_senders_.empty());
eladalon822ff2b2017-08-01 06:30:28 -070046 RTC_DCHECK(sender_remb_candidates_.empty());
47 RTC_DCHECK(receiver_remb_candidates_.empty());
48 RTC_DCHECK(active_remb_module_ == nullptr);
Stefan Holmere5904162015-03-26 11:11:06 +010049}
50
eladalon822ff2b2017-08-01 06:30:28 -070051void PacketRouter::AddSendRtpModule(RtpRtcp* rtp_module, bool remb_candidate) {
stefanbba9dec2016-02-01 04:39:55 -080052 rtc::CritScope cs(&modules_crit_);
nissefdbfdc92017-03-31 05:44:52 -070053 RTC_DCHECK(std::find(rtp_send_modules_.begin(), rtp_send_modules_.end(),
54 rtp_module) == rtp_send_modules_.end());
stefan16b02212017-01-27 07:12:16 -080055 // Put modules which can use regular payload packets (over rtx) instead of
56 // padding first as it's less of a waste
57 if ((rtp_module->RtxSendStatus() & kRtxRedundantPayloads) > 0) {
nissefdbfdc92017-03-31 05:44:52 -070058 rtp_send_modules_.push_front(rtp_module);
stefan16b02212017-01-27 07:12:16 -080059 } else {
nissefdbfdc92017-03-31 05:44:52 -070060 rtp_send_modules_.push_back(rtp_module);
stefan16b02212017-01-27 07:12:16 -080061 }
eladalon822ff2b2017-08-01 06:30:28 -070062
63 if (remb_candidate) {
Danil Chapovaloveb0edd82017-12-14 16:02:31 +010064 AddRembModuleCandidate(rtp_module, /* media_sender = */ true);
eladalon822ff2b2017-08-01 06:30:28 -070065 }
Stefan Holmere5904162015-03-26 11:11:06 +010066}
67
nissefdbfdc92017-03-31 05:44:52 -070068void PacketRouter::RemoveSendRtpModule(RtpRtcp* rtp_module) {
stefanbba9dec2016-02-01 04:39:55 -080069 rtc::CritScope cs(&modules_crit_);
Danil Chapovalovdb59de32019-06-26 11:06:41 +020070 rtp_module_cache_map_.clear();
Danil Chapovaloveb0edd82017-12-14 16:02:31 +010071 MaybeRemoveRembModuleCandidate(rtp_module, /* media_sender = */ true);
eladalon822ff2b2017-08-01 06:30:28 -070072 auto it =
73 std::find(rtp_send_modules_.begin(), rtp_send_modules_.end(), rtp_module);
74 RTC_DCHECK(it != rtp_send_modules_.end());
75 rtp_send_modules_.erase(it);
Erik Språng8b7ca4a2018-05-17 13:43:35 +020076 if (last_send_module_ == rtp_module) {
77 last_send_module_ = nullptr;
78 }
nissefdbfdc92017-03-31 05:44:52 -070079}
80
Danil Chapovaloveb0edd82017-12-14 16:02:31 +010081void PacketRouter::AddReceiveRtpModule(RtcpFeedbackSenderInterface* rtcp_sender,
eladalon822ff2b2017-08-01 06:30:28 -070082 bool remb_candidate) {
nissefdbfdc92017-03-31 05:44:52 -070083 rtc::CritScope cs(&modules_crit_);
Danil Chapovaloveb0edd82017-12-14 16:02:31 +010084 RTC_DCHECK(std::find(rtcp_feedback_senders_.begin(),
85 rtcp_feedback_senders_.end(),
86 rtcp_sender) == rtcp_feedback_senders_.end());
eladalon822ff2b2017-08-01 06:30:28 -070087
Danil Chapovaloveb0edd82017-12-14 16:02:31 +010088 rtcp_feedback_senders_.push_back(rtcp_sender);
eladalon822ff2b2017-08-01 06:30:28 -070089
90 if (remb_candidate) {
Danil Chapovaloveb0edd82017-12-14 16:02:31 +010091 AddRembModuleCandidate(rtcp_sender, /* media_sender = */ false);
eladalon822ff2b2017-08-01 06:30:28 -070092 }
nissefdbfdc92017-03-31 05:44:52 -070093}
94
Danil Chapovaloveb0edd82017-12-14 16:02:31 +010095void PacketRouter::RemoveReceiveRtpModule(
96 RtcpFeedbackSenderInterface* rtcp_sender) {
nissefdbfdc92017-03-31 05:44:52 -070097 rtc::CritScope cs(&modules_crit_);
Danil Chapovaloveb0edd82017-12-14 16:02:31 +010098 MaybeRemoveRembModuleCandidate(rtcp_sender, /* media_sender = */ false);
99 auto it = std::find(rtcp_feedback_senders_.begin(),
100 rtcp_feedback_senders_.end(), rtcp_sender);
101 RTC_DCHECK(it != rtcp_feedback_senders_.end());
102 rtcp_feedback_senders_.erase(it);
Stefan Holmere5904162015-03-26 11:11:06 +0100103}
104
Erik Språngd2879622019-05-10 08:29:01 -0700105RtpPacketSendResult PacketRouter::TimeToSendPacket(
106 uint32_t ssrc,
107 uint16_t sequence_number,
108 int64_t capture_timestamp,
109 bool retransmission,
110 const PacedPacketInfo& pacing_info) {
stefanbba9dec2016-02-01 04:39:55 -0800111 rtc::CritScope cs(&modules_crit_);
Danil Chapovalovdb59de32019-06-26 11:06:41 +0200112 RtpRtcp* rtp_module = FindRtpModule(ssrc);
113 if (rtp_module == nullptr || !rtp_module->SendingMedia()) {
114 return RtpPacketSendResult::kPacketNotFound;
115 }
116
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000117 RtpPacketSendResult result = rtp_module->TimeToSendPacket(
118 ssrc, sequence_number, capture_timestamp, retransmission, pacing_info);
119 if (result == RtpPacketSendResult::kSuccess &&
120 rtp_module->SupportsRtxPayloadPadding()) {
Danil Chapovalovdb59de32019-06-26 11:06:41 +0200121 // This is now the last module to send media, and has the desired
122 // properties needed for payload based padding. Cache it for later use.
123 last_send_module_ = rtp_module;
124 }
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000125 return result;
Danil Chapovalovdb59de32019-06-26 11:06:41 +0200126}
127
128RtpRtcp* PacketRouter::FindRtpModule(uint32_t ssrc) {
129 auto it = rtp_module_cache_map_.find(ssrc);
130 if (it != rtp_module_cache_map_.end()) {
131 if (ssrc == it->second->SSRC() || ssrc == it->second->FlexfecSsrc()) {
132 return it->second;
Erik Språng8b7ca4a2018-05-17 13:43:35 +0200133 }
Danil Chapovalovdb59de32019-06-26 11:06:41 +0200134 // This entry is stale due to a changed ssrc - remove it.
135 rtp_module_cache_map_.erase(it);
136 }
137 // Slow path - find and cache matching module
138 for (RtpRtcp* rtp_module : rtp_send_modules_) {
brandtr9dfff292016-11-14 05:14:50 -0800139 if (ssrc == rtp_module->SSRC() || ssrc == rtp_module->FlexfecSsrc()) {
Danil Chapovalovdb59de32019-06-26 11:06:41 +0200140 rtp_module_cache_map_[ssrc] = rtp_module;
141 return rtp_module;
Stefan Holmere5904162015-03-26 11:11:06 +0100142 }
143 }
Danil Chapovalovdb59de32019-06-26 11:06:41 +0200144 return nullptr;
Stefan Holmere5904162015-03-26 11:11:06 +0100145}
146
Erik Språng58ee1872019-06-18 16:20:11 +0200147void PacketRouter::SendPacket(std::unique_ptr<RtpPacketToSend> packet,
148 const PacedPacketInfo& cluster_info) {
149 rtc::CritScope cs(&modules_crit_);
Erik Språngf6468d22019-07-05 16:53:43 +0200150 // With the new pacer code path, transport sequence numbers are only set here,
151 // on the pacer thread. Therefore we don't need atomics/synchronization.
Erik Språng6cdab462019-07-15 19:40:13 +0200152 if (packet->IsExtensionReserved<TransportSequenceNumber>()) {
153 packet->SetExtension<TransportSequenceNumber>(++transport_seq_);
Erik Språngf6468d22019-07-05 16:53:43 +0200154 }
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000155
156 auto it = rtp_module_cache_map_.find(packet->Ssrc());
157 if (it != rtp_module_cache_map_.end()) {
158 if (TrySendPacket(packet.get(), cluster_info, it->second)) {
159 return;
160 }
161 // Entry is stale, remove it.
162 rtp_module_cache_map_.erase(it);
163 }
164
165 // Slow path, find the correct send module.
Erik Språng58ee1872019-06-18 16:20:11 +0200166 for (auto* rtp_module : rtp_send_modules_) {
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000167 if (TrySendPacket(packet.get(), cluster_info, rtp_module)) {
Erik Språng58ee1872019-06-18 16:20:11 +0200168 return;
169 }
170 }
171
172 RTC_LOG(LS_WARNING) << "Failed to send packet, matching RTP module not found "
173 "or transport error. SSRC = "
174 << packet->Ssrc() << ", sequence number "
175 << packet->SequenceNumber();
176}
177
philipela1ed0b32016-06-01 06:31:17 -0700178size_t PacketRouter::TimeToSendPadding(size_t bytes_to_send,
philipelc7bf32a2017-02-17 03:59:43 -0800179 const PacedPacketInfo& pacing_info) {
sprang867fb522015-08-03 04:38:41 -0700180 size_t total_bytes_sent = 0;
stefanbba9dec2016-02-01 04:39:55 -0800181 rtc::CritScope cs(&modules_crit_);
Erik Språng8b7ca4a2018-05-17 13:43:35 +0200182 // First try on the last rtp module to have sent media. This increases the
183 // the chance that any payload based padding will be useful as it will be
184 // somewhat distributed over modules according the packet rate, even if it
185 // will be more skewed towards the highest bitrate stream. At the very least
186 // this prevents sending payload padding on a disabled stream where it's
187 // guaranteed not to be useful.
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000188 if (last_send_module_ != nullptr &&
189 last_send_module_->SupportsRtxPayloadPadding()) {
Erik Språng8b7ca4a2018-05-17 13:43:35 +0200190 RTC_DCHECK(std::find(rtp_send_modules_.begin(), rtp_send_modules_.end(),
191 last_send_module_) != rtp_send_modules_.end());
Erik Språng8b7ca4a2018-05-17 13:43:35 +0200192 total_bytes_sent += last_send_module_->TimeToSendPadding(
193 bytes_to_send - total_bytes_sent, pacing_info);
194 if (total_bytes_sent >= bytes_to_send) {
195 return total_bytes_sent;
196 }
197 }
198
stefan16b02212017-01-27 07:12:16 -0800199 // Rtp modules are ordered by which stream can most benefit from padding.
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000200 // Don't require RTX payload padding in the general case.
nissefdbfdc92017-03-31 05:44:52 -0700201 for (RtpRtcp* module : rtp_send_modules_) {
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000202 if (module->SupportsPadding()) {
philipela1ed0b32016-06-01 06:31:17 -0700203 size_t bytes_sent = module->TimeToSendPadding(
philipelc7bf32a2017-02-17 03:59:43 -0800204 bytes_to_send - total_bytes_sent, pacing_info);
sprang867fb522015-08-03 04:38:41 -0700205 total_bytes_sent += bytes_sent;
206 if (total_bytes_sent >= bytes_to_send)
207 break;
208 }
Stefan Holmere5904162015-03-26 11:11:06 +0100209 }
sprang867fb522015-08-03 04:38:41 -0700210 return total_bytes_sent;
Stefan Holmere5904162015-03-26 11:11:06 +0100211}
sprang867fb522015-08-03 04:38:41 -0700212
Erik Språngf6468d22019-07-05 16:53:43 +0200213std::vector<std::unique_ptr<RtpPacketToSend>> PacketRouter::GeneratePadding(
214 size_t target_size_bytes) {
Erik Språng478cb462019-06-26 15:49:27 +0200215 rtc::CritScope cs(&modules_crit_);
216 // First try on the last rtp module to have sent media. This increases the
217 // the chance that any payload based padding will be useful as it will be
218 // somewhat distributed over modules according the packet rate, even if it
219 // will be more skewed towards the highest bitrate stream. At the very least
220 // this prevents sending payload padding on a disabled stream where it's
221 // guaranteed not to be useful.
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000222 if (last_send_module_ != nullptr &&
223 last_send_module_->SupportsRtxPayloadPadding()) {
Erik Språng478cb462019-06-26 15:49:27 +0200224 RTC_DCHECK(std::find(rtp_send_modules_.begin(), rtp_send_modules_.end(),
225 last_send_module_) != rtp_send_modules_.end());
Erik Språngf6468d22019-07-05 16:53:43 +0200226 return last_send_module_->GeneratePadding(target_size_bytes);
Erik Språng478cb462019-06-26 15:49:27 +0200227 }
228
229 // Rtp modules are ordered by which stream can most benefit from padding.
230 for (RtpRtcp* rtp_module : rtp_send_modules_) {
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000231 if (rtp_module->SupportsPadding()) {
232 auto padding_packets = rtp_module->GeneratePadding(target_size_bytes);
233 if (!padding_packets.empty()) {
234 last_send_module_ = rtp_module;
235 }
236 return padding_packets;
Erik Språng478cb462019-06-26 15:49:27 +0200237 }
238 }
Erik Språngf6468d22019-07-05 16:53:43 +0200239
240 return {};
Erik Språng478cb462019-06-26 15:49:27 +0200241}
242
sprang867fb522015-08-03 04:38:41 -0700243void PacketRouter::SetTransportWideSequenceNumber(uint16_t sequence_number) {
pbos46ad5422015-12-07 14:29:14 -0800244 rtc::AtomicOps::ReleaseStore(&transport_seq_, sequence_number);
sprang867fb522015-08-03 04:38:41 -0700245}
246
247uint16_t PacketRouter::AllocateSequenceNumber() {
pbos46ad5422015-12-07 14:29:14 -0800248 int prev_seq = rtc::AtomicOps::AcquireLoad(&transport_seq_);
sprang867fb522015-08-03 04:38:41 -0700249 int desired_prev_seq;
250 int new_seq;
251 do {
252 desired_prev_seq = prev_seq;
253 new_seq = (desired_prev_seq + 1) & 0xFFFF;
254 // Note: CompareAndSwap returns the actual value of transport_seq at the
255 // time the CAS operation was executed. Thus, if prev_seq is returned, the
256 // operation was successful - otherwise we need to retry. Saving the
257 // return value saves us a load on retry.
pbos46ad5422015-12-07 14:29:14 -0800258 prev_seq = rtc::AtomicOps::CompareAndSwap(&transport_seq_, desired_prev_seq,
sprang867fb522015-08-03 04:38:41 -0700259 new_seq);
260 } while (prev_seq != desired_prev_seq);
261
262 return new_seq;
263}
264
nisse05843312017-04-18 23:38:35 -0700265void PacketRouter::OnReceiveBitrateChanged(const std::vector<uint32_t>& ssrcs,
266 uint32_t bitrate_bps) {
nisse05843312017-04-18 23:38:35 -0700267 // % threshold for if we should send a new REMB asap.
Danil Chapovalov1de4b622017-12-13 13:35:10 +0100268 const int64_t kSendThresholdPercent = 97;
269 // TODO(danilchap): Remove receive_bitrate_bps variable and the cast
270 // when OnReceiveBitrateChanged takes bitrate as int64_t.
271 int64_t receive_bitrate_bps = static_cast<int64_t>(bitrate_bps);
nisse05843312017-04-18 23:38:35 -0700272
273 int64_t now_ms = rtc::TimeMillis();
274 {
275 rtc::CritScope lock(&remb_crit_);
276
277 // If we already have an estimate, check if the new total estimate is below
278 // kSendThresholdPercent of the previous estimate.
279 if (last_send_bitrate_bps_ > 0) {
Danil Chapovalov1de4b622017-12-13 13:35:10 +0100280 int64_t new_remb_bitrate_bps =
281 last_send_bitrate_bps_ - bitrate_bps_ + receive_bitrate_bps;
nisse05843312017-04-18 23:38:35 -0700282
283 if (new_remb_bitrate_bps <
284 kSendThresholdPercent * last_send_bitrate_bps_ / 100) {
285 // The new bitrate estimate is less than kSendThresholdPercent % of the
286 // last report. Send a REMB asap.
287 last_remb_time_ms_ = now_ms - kRembSendIntervalMs;
288 }
289 }
Danil Chapovalov1de4b622017-12-13 13:35:10 +0100290 bitrate_bps_ = receive_bitrate_bps;
nisse05843312017-04-18 23:38:35 -0700291
292 if (now_ms - last_remb_time_ms_ < kRembSendIntervalMs) {
293 return;
294 }
295 // NOTE: Updated if we intend to send the data; we might not have
296 // a module to actually send it.
297 last_remb_time_ms_ = now_ms;
Danil Chapovalov1de4b622017-12-13 13:35:10 +0100298 last_send_bitrate_bps_ = receive_bitrate_bps;
danilchap47085372017-08-10 06:03:57 -0700299 // Cap the value to send in remb with configured value.
Danil Chapovalov1de4b622017-12-13 13:35:10 +0100300 receive_bitrate_bps = std::min(receive_bitrate_bps, max_bitrate_bps_);
nisse05843312017-04-18 23:38:35 -0700301 }
Danil Chapovalov1de4b622017-12-13 13:35:10 +0100302 SendRemb(receive_bitrate_bps, ssrcs);
nisse05843312017-04-18 23:38:35 -0700303}
304
Danil Chapovalov1de4b622017-12-13 13:35:10 +0100305void PacketRouter::SetMaxDesiredReceiveBitrate(int64_t bitrate_bps) {
306 RTC_DCHECK_GE(bitrate_bps, 0);
danilchap47085372017-08-10 06:03:57 -0700307 {
308 rtc::CritScope lock(&remb_crit_);
309 max_bitrate_bps_ = bitrate_bps;
310 if (rtc::TimeMillis() - last_remb_time_ms_ < kRembSendIntervalMs &&
311 last_send_bitrate_bps_ > 0 &&
312 last_send_bitrate_bps_ <= max_bitrate_bps_) {
313 // Recent measured bitrate is already below the cap.
314 return;
315 }
316 }
317 SendRemb(bitrate_bps, /*ssrcs=*/{});
318}
319
Danil Chapovalov1de4b622017-12-13 13:35:10 +0100320bool PacketRouter::SendRemb(int64_t bitrate_bps,
nisse05843312017-04-18 23:38:35 -0700321 const std::vector<uint32_t>& ssrcs) {
322 rtc::CritScope lock(&modules_crit_);
eladalon822ff2b2017-08-01 06:30:28 -0700323
324 if (!active_remb_module_) {
nisse05843312017-04-18 23:38:35 -0700325 return false;
eladalon822ff2b2017-08-01 06:30:28 -0700326 }
327
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200328 // The Add* and Remove* methods above ensure that REMB is disabled on all
329 // other modules, because otherwise, they will send REMB with stale info.
330 active_remb_module_->SetRemb(bitrate_bps, ssrcs);
eladalon822ff2b2017-08-01 06:30:28 -0700331
nisse05843312017-04-18 23:38:35 -0700332 return true;
333}
334
335bool PacketRouter::SendTransportFeedback(rtcp::TransportFeedback* packet) {
stefanbba9dec2016-02-01 04:39:55 -0800336 rtc::CritScope cs(&modules_crit_);
nissefdbfdc92017-03-31 05:44:52 -0700337 // Prefer send modules.
338 for (auto* rtp_module : rtp_send_modules_) {
339 packet->SetSenderSsrc(rtp_module->SSRC());
Erik Språng8b7ca4a2018-05-17 13:43:35 +0200340 if (rtp_module->SendFeedbackPacket(*packet)) {
nissefdbfdc92017-03-31 05:44:52 -0700341 return true;
Erik Språng8b7ca4a2018-05-17 13:43:35 +0200342 }
nissefdbfdc92017-03-31 05:44:52 -0700343 }
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100344 for (auto* rtcp_sender : rtcp_feedback_senders_) {
345 packet->SetSenderSsrc(rtcp_sender->SSRC());
Erik Språng8b7ca4a2018-05-17 13:43:35 +0200346 if (rtcp_sender->SendFeedbackPacket(*packet)) {
Peter Boström3dd5d1d2016-02-25 16:56:48 +0100347 return true;
Erik Språng8b7ca4a2018-05-17 13:43:35 +0200348 }
Peter Boström3dd5d1d2016-02-25 16:56:48 +0100349 }
sprang233bd872015-09-08 13:25:16 -0700350 return false;
351}
352
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100353void PacketRouter::AddRembModuleCandidate(
354 RtcpFeedbackSenderInterface* candidate_module,
355 bool media_sender) {
eladalon822ff2b2017-08-01 06:30:28 -0700356 RTC_DCHECK(candidate_module);
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100357 std::vector<RtcpFeedbackSenderInterface*>& candidates =
358 media_sender ? sender_remb_candidates_ : receiver_remb_candidates_;
eladalon822ff2b2017-08-01 06:30:28 -0700359 RTC_DCHECK(std::find(candidates.cbegin(), candidates.cend(),
360 candidate_module) == candidates.cend());
361 candidates.push_back(candidate_module);
362 DetermineActiveRembModule();
363}
364
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100365void PacketRouter::MaybeRemoveRembModuleCandidate(
366 RtcpFeedbackSenderInterface* candidate_module,
367 bool media_sender) {
eladalon822ff2b2017-08-01 06:30:28 -0700368 RTC_DCHECK(candidate_module);
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100369 std::vector<RtcpFeedbackSenderInterface*>& candidates =
370 media_sender ? sender_remb_candidates_ : receiver_remb_candidates_;
eladalon822ff2b2017-08-01 06:30:28 -0700371 auto it = std::find(candidates.begin(), candidates.end(), candidate_module);
372
373 if (it == candidates.end()) {
374 return; // Function called due to removal of non-REMB-candidate module.
375 }
376
377 if (*it == active_remb_module_) {
378 UnsetActiveRembModule();
379 }
380 candidates.erase(it);
381 DetermineActiveRembModule();
382}
383
384void PacketRouter::UnsetActiveRembModule() {
385 RTC_CHECK(active_remb_module_);
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200386 active_remb_module_->UnsetRemb();
eladalon822ff2b2017-08-01 06:30:28 -0700387 active_remb_module_ = nullptr;
388}
389
390void PacketRouter::DetermineActiveRembModule() {
391 // Sender modules take precedence over receiver modules, because SRs (sender
392 // reports) are sent more frequently than RR (receiver reports).
393 // When adding the first sender module, we should change the active REMB
394 // module to be that. Otherwise, we remain with the current active module.
395
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100396 RtcpFeedbackSenderInterface* new_active_remb_module;
eladalon822ff2b2017-08-01 06:30:28 -0700397
398 if (!sender_remb_candidates_.empty()) {
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200399 new_active_remb_module = sender_remb_candidates_.front();
eladalon822ff2b2017-08-01 06:30:28 -0700400 } else if (!receiver_remb_candidates_.empty()) {
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200401 new_active_remb_module = receiver_remb_candidates_.front();
eladalon822ff2b2017-08-01 06:30:28 -0700402 } else {
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200403 new_active_remb_module = nullptr;
eladalon822ff2b2017-08-01 06:30:28 -0700404 }
405
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200406 if (new_active_remb_module != active_remb_module_ && active_remb_module_) {
407 UnsetActiveRembModule();
eladalon822ff2b2017-08-01 06:30:28 -0700408 }
409
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200410 active_remb_module_ = new_active_remb_module;
eladalon822ff2b2017-08-01 06:30:28 -0700411}
412
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000413bool PacketRouter::TrySendPacket(RtpPacketToSend* packet,
414 const PacedPacketInfo& cluster_info,
415 RtpRtcp* rtp_module) {
416 uint32_t ssrc = packet->Ssrc();
417 if (rtp_module->TrySendPacket(packet, cluster_info)) {
418 // Sending succeeded, make sure this SSRC mapping for future use.
419 rtp_module_cache_map_[ssrc] = rtp_module;
420
421 if (rtp_module->SupportsRtxPayloadPadding()) {
422 // This is now the last module to send media, and has the desired
423 // properties needed for payload based padding. Cache it for later use.
424 last_send_module_ = rtp_module;
425 }
426
427 return true;
428 }
429 return false;
430}
431
Stefan Holmere5904162015-03-26 11:11:06 +0100432} // namespace webrtc