1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "modules/pacing/packet_router.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
14*d9f75844SAndroid Build Coastguard Worker #include <cstdint>
15*d9f75844SAndroid Build Coastguard Worker #include <limits>
16*d9f75844SAndroid Build Coastguard Worker #include <memory>
17*d9f75844SAndroid Build Coastguard Worker #include <utility>
18*d9f75844SAndroid Build Coastguard Worker
19*d9f75844SAndroid Build Coastguard Worker #include "absl/types/optional.h"
20*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
21*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/rtcp_packet.h"
22*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
23*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/rtp_rtcp_interface.h"
24*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
25*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
26*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/system/unused.h"
27*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/time_utils.h"
28*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/trace_event.h"
29*d9f75844SAndroid Build Coastguard Worker
30*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
31*d9f75844SAndroid Build Coastguard Worker
PacketRouter()32*d9f75844SAndroid Build Coastguard Worker PacketRouter::PacketRouter() : PacketRouter(0) {}
33*d9f75844SAndroid Build Coastguard Worker
PacketRouter(uint16_t start_transport_seq)34*d9f75844SAndroid Build Coastguard Worker PacketRouter::PacketRouter(uint16_t start_transport_seq)
35*d9f75844SAndroid Build Coastguard Worker : last_send_module_(nullptr),
36*d9f75844SAndroid Build Coastguard Worker active_remb_module_(nullptr),
37*d9f75844SAndroid Build Coastguard Worker transport_seq_(start_transport_seq) {}
38*d9f75844SAndroid Build Coastguard Worker
~PacketRouter()39*d9f75844SAndroid Build Coastguard Worker PacketRouter::~PacketRouter() {
40*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(send_modules_map_.empty());
41*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(send_modules_list_.empty());
42*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(rtcp_feedback_senders_.empty());
43*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(sender_remb_candidates_.empty());
44*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(receiver_remb_candidates_.empty());
45*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(active_remb_module_ == nullptr);
46*d9f75844SAndroid Build Coastguard Worker }
47*d9f75844SAndroid Build Coastguard Worker
AddSendRtpModule(RtpRtcpInterface * rtp_module,bool remb_candidate)48*d9f75844SAndroid Build Coastguard Worker void PacketRouter::AddSendRtpModule(RtpRtcpInterface* rtp_module,
49*d9f75844SAndroid Build Coastguard Worker bool remb_candidate) {
50*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&modules_mutex_);
51*d9f75844SAndroid Build Coastguard Worker
52*d9f75844SAndroid Build Coastguard Worker AddSendRtpModuleToMap(rtp_module, rtp_module->SSRC());
53*d9f75844SAndroid Build Coastguard Worker if (absl::optional<uint32_t> rtx_ssrc = rtp_module->RtxSsrc()) {
54*d9f75844SAndroid Build Coastguard Worker AddSendRtpModuleToMap(rtp_module, *rtx_ssrc);
55*d9f75844SAndroid Build Coastguard Worker }
56*d9f75844SAndroid Build Coastguard Worker if (absl::optional<uint32_t> flexfec_ssrc = rtp_module->FlexfecSsrc()) {
57*d9f75844SAndroid Build Coastguard Worker AddSendRtpModuleToMap(rtp_module, *flexfec_ssrc);
58*d9f75844SAndroid Build Coastguard Worker }
59*d9f75844SAndroid Build Coastguard Worker
60*d9f75844SAndroid Build Coastguard Worker if (rtp_module->SupportsRtxPayloadPadding()) {
61*d9f75844SAndroid Build Coastguard Worker last_send_module_ = rtp_module;
62*d9f75844SAndroid Build Coastguard Worker }
63*d9f75844SAndroid Build Coastguard Worker
64*d9f75844SAndroid Build Coastguard Worker if (remb_candidate) {
65*d9f75844SAndroid Build Coastguard Worker AddRembModuleCandidate(rtp_module, /* media_sender = */ true);
66*d9f75844SAndroid Build Coastguard Worker }
67*d9f75844SAndroid Build Coastguard Worker }
68*d9f75844SAndroid Build Coastguard Worker
AddSendRtpModuleToMap(RtpRtcpInterface * rtp_module,uint32_t ssrc)69*d9f75844SAndroid Build Coastguard Worker void PacketRouter::AddSendRtpModuleToMap(RtpRtcpInterface* rtp_module,
70*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc) {
71*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(send_modules_map_.find(ssrc) == send_modules_map_.end());
72*d9f75844SAndroid Build Coastguard Worker
73*d9f75844SAndroid Build Coastguard Worker // Signal to module that the pacer thread is attached and can send packets.
74*d9f75844SAndroid Build Coastguard Worker rtp_module->OnPacketSendingThreadSwitched();
75*d9f75844SAndroid Build Coastguard Worker
76*d9f75844SAndroid Build Coastguard Worker // Always keep the audio modules at the back of the list, so that when we
77*d9f75844SAndroid Build Coastguard Worker // iterate over the modules in order to find one that can send padding we
78*d9f75844SAndroid Build Coastguard Worker // will prioritize video. This is important to make sure they are counted
79*d9f75844SAndroid Build Coastguard Worker // into the bandwidth estimate properly.
80*d9f75844SAndroid Build Coastguard Worker if (rtp_module->IsAudioConfigured()) {
81*d9f75844SAndroid Build Coastguard Worker send_modules_list_.push_back(rtp_module);
82*d9f75844SAndroid Build Coastguard Worker } else {
83*d9f75844SAndroid Build Coastguard Worker send_modules_list_.push_front(rtp_module);
84*d9f75844SAndroid Build Coastguard Worker }
85*d9f75844SAndroid Build Coastguard Worker send_modules_map_[ssrc] = rtp_module;
86*d9f75844SAndroid Build Coastguard Worker }
87*d9f75844SAndroid Build Coastguard Worker
RemoveSendRtpModuleFromMap(uint32_t ssrc)88*d9f75844SAndroid Build Coastguard Worker void PacketRouter::RemoveSendRtpModuleFromMap(uint32_t ssrc) {
89*d9f75844SAndroid Build Coastguard Worker auto it = send_modules_map_.find(ssrc);
90*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(it != send_modules_map_.end());
91*d9f75844SAndroid Build Coastguard Worker send_modules_list_.remove(it->second);
92*d9f75844SAndroid Build Coastguard Worker send_modules_map_.erase(it);
93*d9f75844SAndroid Build Coastguard Worker }
94*d9f75844SAndroid Build Coastguard Worker
RemoveSendRtpModule(RtpRtcpInterface * rtp_module)95*d9f75844SAndroid Build Coastguard Worker void PacketRouter::RemoveSendRtpModule(RtpRtcpInterface* rtp_module) {
96*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&modules_mutex_);
97*d9f75844SAndroid Build Coastguard Worker MaybeRemoveRembModuleCandidate(rtp_module, /* media_sender = */ true);
98*d9f75844SAndroid Build Coastguard Worker
99*d9f75844SAndroid Build Coastguard Worker RemoveSendRtpModuleFromMap(rtp_module->SSRC());
100*d9f75844SAndroid Build Coastguard Worker if (absl::optional<uint32_t> rtx_ssrc = rtp_module->RtxSsrc()) {
101*d9f75844SAndroid Build Coastguard Worker RemoveSendRtpModuleFromMap(*rtx_ssrc);
102*d9f75844SAndroid Build Coastguard Worker }
103*d9f75844SAndroid Build Coastguard Worker if (absl::optional<uint32_t> flexfec_ssrc = rtp_module->FlexfecSsrc()) {
104*d9f75844SAndroid Build Coastguard Worker RemoveSendRtpModuleFromMap(*flexfec_ssrc);
105*d9f75844SAndroid Build Coastguard Worker }
106*d9f75844SAndroid Build Coastguard Worker
107*d9f75844SAndroid Build Coastguard Worker if (last_send_module_ == rtp_module) {
108*d9f75844SAndroid Build Coastguard Worker last_send_module_ = nullptr;
109*d9f75844SAndroid Build Coastguard Worker }
110*d9f75844SAndroid Build Coastguard Worker rtp_module->OnPacketSendingThreadSwitched();
111*d9f75844SAndroid Build Coastguard Worker }
112*d9f75844SAndroid Build Coastguard Worker
AddReceiveRtpModule(RtcpFeedbackSenderInterface * rtcp_sender,bool remb_candidate)113*d9f75844SAndroid Build Coastguard Worker void PacketRouter::AddReceiveRtpModule(RtcpFeedbackSenderInterface* rtcp_sender,
114*d9f75844SAndroid Build Coastguard Worker bool remb_candidate) {
115*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&modules_mutex_);
116*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(std::find(rtcp_feedback_senders_.begin(),
117*d9f75844SAndroid Build Coastguard Worker rtcp_feedback_senders_.end(),
118*d9f75844SAndroid Build Coastguard Worker rtcp_sender) == rtcp_feedback_senders_.end());
119*d9f75844SAndroid Build Coastguard Worker
120*d9f75844SAndroid Build Coastguard Worker rtcp_feedback_senders_.push_back(rtcp_sender);
121*d9f75844SAndroid Build Coastguard Worker
122*d9f75844SAndroid Build Coastguard Worker if (remb_candidate) {
123*d9f75844SAndroid Build Coastguard Worker AddRembModuleCandidate(rtcp_sender, /* media_sender = */ false);
124*d9f75844SAndroid Build Coastguard Worker }
125*d9f75844SAndroid Build Coastguard Worker }
126*d9f75844SAndroid Build Coastguard Worker
RemoveReceiveRtpModule(RtcpFeedbackSenderInterface * rtcp_sender)127*d9f75844SAndroid Build Coastguard Worker void PacketRouter::RemoveReceiveRtpModule(
128*d9f75844SAndroid Build Coastguard Worker RtcpFeedbackSenderInterface* rtcp_sender) {
129*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&modules_mutex_);
130*d9f75844SAndroid Build Coastguard Worker MaybeRemoveRembModuleCandidate(rtcp_sender, /* media_sender = */ false);
131*d9f75844SAndroid Build Coastguard Worker auto it = std::find(rtcp_feedback_senders_.begin(),
132*d9f75844SAndroid Build Coastguard Worker rtcp_feedback_senders_.end(), rtcp_sender);
133*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(it != rtcp_feedback_senders_.end());
134*d9f75844SAndroid Build Coastguard Worker rtcp_feedback_senders_.erase(it);
135*d9f75844SAndroid Build Coastguard Worker }
136*d9f75844SAndroid Build Coastguard Worker
SendPacket(std::unique_ptr<RtpPacketToSend> packet,const PacedPacketInfo & cluster_info)137*d9f75844SAndroid Build Coastguard Worker void PacketRouter::SendPacket(std::unique_ptr<RtpPacketToSend> packet,
138*d9f75844SAndroid Build Coastguard Worker const PacedPacketInfo& cluster_info) {
139*d9f75844SAndroid Build Coastguard Worker TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("webrtc"), "PacketRouter::SendPacket",
140*d9f75844SAndroid Build Coastguard Worker "sequence_number", packet->SequenceNumber(), "rtp_timestamp",
141*d9f75844SAndroid Build Coastguard Worker packet->Timestamp());
142*d9f75844SAndroid Build Coastguard Worker
143*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&modules_mutex_);
144*d9f75844SAndroid Build Coastguard Worker // With the new pacer code path, transport sequence numbers are only set here,
145*d9f75844SAndroid Build Coastguard Worker // on the pacer thread. Therefore we don't need atomics/synchronization.
146*d9f75844SAndroid Build Coastguard Worker bool assign_transport_sequence_number =
147*d9f75844SAndroid Build Coastguard Worker packet->HasExtension<TransportSequenceNumber>();
148*d9f75844SAndroid Build Coastguard Worker if (assign_transport_sequence_number) {
149*d9f75844SAndroid Build Coastguard Worker packet->SetExtension<TransportSequenceNumber>((transport_seq_ + 1) &
150*d9f75844SAndroid Build Coastguard Worker 0xFFFF);
151*d9f75844SAndroid Build Coastguard Worker }
152*d9f75844SAndroid Build Coastguard Worker
153*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc = packet->Ssrc();
154*d9f75844SAndroid Build Coastguard Worker auto it = send_modules_map_.find(ssrc);
155*d9f75844SAndroid Build Coastguard Worker if (it == send_modules_map_.end()) {
156*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING)
157*d9f75844SAndroid Build Coastguard Worker << "Failed to send packet, matching RTP module not found "
158*d9f75844SAndroid Build Coastguard Worker "or transport error. SSRC = "
159*d9f75844SAndroid Build Coastguard Worker << packet->Ssrc() << ", sequence number " << packet->SequenceNumber();
160*d9f75844SAndroid Build Coastguard Worker return;
161*d9f75844SAndroid Build Coastguard Worker }
162*d9f75844SAndroid Build Coastguard Worker
163*d9f75844SAndroid Build Coastguard Worker RtpRtcpInterface* rtp_module = it->second;
164*d9f75844SAndroid Build Coastguard Worker if (!rtp_module->TrySendPacket(packet.get(), cluster_info)) {
165*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING) << "Failed to send packet, rejected by RTP module.";
166*d9f75844SAndroid Build Coastguard Worker return;
167*d9f75844SAndroid Build Coastguard Worker }
168*d9f75844SAndroid Build Coastguard Worker
169*d9f75844SAndroid Build Coastguard Worker // Sending succeeded.
170*d9f75844SAndroid Build Coastguard Worker
171*d9f75844SAndroid Build Coastguard Worker if (assign_transport_sequence_number) {
172*d9f75844SAndroid Build Coastguard Worker ++transport_seq_;
173*d9f75844SAndroid Build Coastguard Worker }
174*d9f75844SAndroid Build Coastguard Worker
175*d9f75844SAndroid Build Coastguard Worker if (rtp_module->SupportsRtxPayloadPadding()) {
176*d9f75844SAndroid Build Coastguard Worker // This is now the last module to send media, and has the desired
177*d9f75844SAndroid Build Coastguard Worker // properties needed for payload based padding. Cache it for later use.
178*d9f75844SAndroid Build Coastguard Worker last_send_module_ = rtp_module;
179*d9f75844SAndroid Build Coastguard Worker }
180*d9f75844SAndroid Build Coastguard Worker
181*d9f75844SAndroid Build Coastguard Worker for (auto& packet : rtp_module->FetchFecPackets()) {
182*d9f75844SAndroid Build Coastguard Worker pending_fec_packets_.push_back(std::move(packet));
183*d9f75844SAndroid Build Coastguard Worker }
184*d9f75844SAndroid Build Coastguard Worker }
185*d9f75844SAndroid Build Coastguard Worker
FetchFec()186*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<RtpPacketToSend>> PacketRouter::FetchFec() {
187*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&modules_mutex_);
188*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets =
189*d9f75844SAndroid Build Coastguard Worker std::move(pending_fec_packets_);
190*d9f75844SAndroid Build Coastguard Worker pending_fec_packets_.clear();
191*d9f75844SAndroid Build Coastguard Worker return fec_packets;
192*d9f75844SAndroid Build Coastguard Worker }
193*d9f75844SAndroid Build Coastguard Worker
GeneratePadding(DataSize size)194*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<RtpPacketToSend>> PacketRouter::GeneratePadding(
195*d9f75844SAndroid Build Coastguard Worker DataSize size) {
196*d9f75844SAndroid Build Coastguard Worker TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("webrtc"),
197*d9f75844SAndroid Build Coastguard Worker "PacketRouter::GeneratePadding", "bytes", size.bytes());
198*d9f75844SAndroid Build Coastguard Worker
199*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&modules_mutex_);
200*d9f75844SAndroid Build Coastguard Worker // First try on the last rtp module to have sent media. This increases the
201*d9f75844SAndroid Build Coastguard Worker // the chance that any payload based padding will be useful as it will be
202*d9f75844SAndroid Build Coastguard Worker // somewhat distributed over modules according the packet rate, even if it
203*d9f75844SAndroid Build Coastguard Worker // will be more skewed towards the highest bitrate stream. At the very least
204*d9f75844SAndroid Build Coastguard Worker // this prevents sending payload padding on a disabled stream where it's
205*d9f75844SAndroid Build Coastguard Worker // guaranteed not to be useful.
206*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<RtpPacketToSend>> padding_packets;
207*d9f75844SAndroid Build Coastguard Worker if (last_send_module_ != nullptr &&
208*d9f75844SAndroid Build Coastguard Worker last_send_module_->SupportsRtxPayloadPadding()) {
209*d9f75844SAndroid Build Coastguard Worker padding_packets = last_send_module_->GeneratePadding(size.bytes());
210*d9f75844SAndroid Build Coastguard Worker }
211*d9f75844SAndroid Build Coastguard Worker
212*d9f75844SAndroid Build Coastguard Worker if (padding_packets.empty()) {
213*d9f75844SAndroid Build Coastguard Worker // Iterate over all modules send module. Video modules will be at the front
214*d9f75844SAndroid Build Coastguard Worker // and so will be prioritized. This is important since audio packets may not
215*d9f75844SAndroid Build Coastguard Worker // be taken into account by the bandwidth estimator, e.g. in FF.
216*d9f75844SAndroid Build Coastguard Worker for (RtpRtcpInterface* rtp_module : send_modules_list_) {
217*d9f75844SAndroid Build Coastguard Worker if (rtp_module->SupportsPadding()) {
218*d9f75844SAndroid Build Coastguard Worker padding_packets = rtp_module->GeneratePadding(size.bytes());
219*d9f75844SAndroid Build Coastguard Worker if (!padding_packets.empty()) {
220*d9f75844SAndroid Build Coastguard Worker last_send_module_ = rtp_module;
221*d9f75844SAndroid Build Coastguard Worker break;
222*d9f75844SAndroid Build Coastguard Worker }
223*d9f75844SAndroid Build Coastguard Worker }
224*d9f75844SAndroid Build Coastguard Worker }
225*d9f75844SAndroid Build Coastguard Worker }
226*d9f75844SAndroid Build Coastguard Worker
227*d9f75844SAndroid Build Coastguard Worker for (auto& packet : padding_packets) {
228*d9f75844SAndroid Build Coastguard Worker RTC_UNUSED(packet);
229*d9f75844SAndroid Build Coastguard Worker TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("webrtc"),
230*d9f75844SAndroid Build Coastguard Worker "PacketRouter::GeneratePadding::Loop", "sequence_number",
231*d9f75844SAndroid Build Coastguard Worker packet->SequenceNumber(), "rtp_timestamp",
232*d9f75844SAndroid Build Coastguard Worker packet->Timestamp());
233*d9f75844SAndroid Build Coastguard Worker }
234*d9f75844SAndroid Build Coastguard Worker
235*d9f75844SAndroid Build Coastguard Worker return padding_packets;
236*d9f75844SAndroid Build Coastguard Worker }
237*d9f75844SAndroid Build Coastguard Worker
OnAbortedRetransmissions(uint32_t ssrc,rtc::ArrayView<const uint16_t> sequence_numbers)238*d9f75844SAndroid Build Coastguard Worker void PacketRouter::OnAbortedRetransmissions(
239*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc,
240*d9f75844SAndroid Build Coastguard Worker rtc::ArrayView<const uint16_t> sequence_numbers) {
241*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&modules_mutex_);
242*d9f75844SAndroid Build Coastguard Worker auto it = send_modules_map_.find(ssrc);
243*d9f75844SAndroid Build Coastguard Worker if (it != send_modules_map_.end()) {
244*d9f75844SAndroid Build Coastguard Worker it->second->OnAbortedRetransmissions(sequence_numbers);
245*d9f75844SAndroid Build Coastguard Worker }
246*d9f75844SAndroid Build Coastguard Worker }
247*d9f75844SAndroid Build Coastguard Worker
GetRtxSsrcForMedia(uint32_t ssrc) const248*d9f75844SAndroid Build Coastguard Worker absl::optional<uint32_t> PacketRouter::GetRtxSsrcForMedia(uint32_t ssrc) const {
249*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&modules_mutex_);
250*d9f75844SAndroid Build Coastguard Worker auto it = send_modules_map_.find(ssrc);
251*d9f75844SAndroid Build Coastguard Worker if (it != send_modules_map_.end() && it->second->SSRC() == ssrc) {
252*d9f75844SAndroid Build Coastguard Worker // A module is registered with the given SSRC, and that SSRC is the main
253*d9f75844SAndroid Build Coastguard Worker // media SSRC for that RTP module.
254*d9f75844SAndroid Build Coastguard Worker return it->second->RtxSsrc();
255*d9f75844SAndroid Build Coastguard Worker }
256*d9f75844SAndroid Build Coastguard Worker return absl::nullopt;
257*d9f75844SAndroid Build Coastguard Worker }
258*d9f75844SAndroid Build Coastguard Worker
CurrentTransportSequenceNumber() const259*d9f75844SAndroid Build Coastguard Worker uint16_t PacketRouter::CurrentTransportSequenceNumber() const {
260*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&modules_mutex_);
261*d9f75844SAndroid Build Coastguard Worker return transport_seq_ & 0xFFFF;
262*d9f75844SAndroid Build Coastguard Worker }
263*d9f75844SAndroid Build Coastguard Worker
SendRemb(int64_t bitrate_bps,std::vector<uint32_t> ssrcs)264*d9f75844SAndroid Build Coastguard Worker void PacketRouter::SendRemb(int64_t bitrate_bps, std::vector<uint32_t> ssrcs) {
265*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&modules_mutex_);
266*d9f75844SAndroid Build Coastguard Worker
267*d9f75844SAndroid Build Coastguard Worker if (!active_remb_module_) {
268*d9f75844SAndroid Build Coastguard Worker return;
269*d9f75844SAndroid Build Coastguard Worker }
270*d9f75844SAndroid Build Coastguard Worker
271*d9f75844SAndroid Build Coastguard Worker // The Add* and Remove* methods above ensure that REMB is disabled on all
272*d9f75844SAndroid Build Coastguard Worker // other modules, because otherwise, they will send REMB with stale info.
273*d9f75844SAndroid Build Coastguard Worker active_remb_module_->SetRemb(bitrate_bps, std::move(ssrcs));
274*d9f75844SAndroid Build Coastguard Worker }
275*d9f75844SAndroid Build Coastguard Worker
SendCombinedRtcpPacket(std::vector<std::unique_ptr<rtcp::RtcpPacket>> packets)276*d9f75844SAndroid Build Coastguard Worker void PacketRouter::SendCombinedRtcpPacket(
277*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<rtcp::RtcpPacket>> packets) {
278*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&modules_mutex_);
279*d9f75844SAndroid Build Coastguard Worker
280*d9f75844SAndroid Build Coastguard Worker // Prefer send modules.
281*d9f75844SAndroid Build Coastguard Worker for (RtpRtcpInterface* rtp_module : send_modules_list_) {
282*d9f75844SAndroid Build Coastguard Worker if (rtp_module->RTCP() == RtcpMode::kOff) {
283*d9f75844SAndroid Build Coastguard Worker continue;
284*d9f75844SAndroid Build Coastguard Worker }
285*d9f75844SAndroid Build Coastguard Worker rtp_module->SendCombinedRtcpPacket(std::move(packets));
286*d9f75844SAndroid Build Coastguard Worker return;
287*d9f75844SAndroid Build Coastguard Worker }
288*d9f75844SAndroid Build Coastguard Worker
289*d9f75844SAndroid Build Coastguard Worker if (rtcp_feedback_senders_.empty()) {
290*d9f75844SAndroid Build Coastguard Worker return;
291*d9f75844SAndroid Build Coastguard Worker }
292*d9f75844SAndroid Build Coastguard Worker auto* rtcp_sender = rtcp_feedback_senders_[0];
293*d9f75844SAndroid Build Coastguard Worker rtcp_sender->SendCombinedRtcpPacket(std::move(packets));
294*d9f75844SAndroid Build Coastguard Worker }
295*d9f75844SAndroid Build Coastguard Worker
AddRembModuleCandidate(RtcpFeedbackSenderInterface * candidate_module,bool media_sender)296*d9f75844SAndroid Build Coastguard Worker void PacketRouter::AddRembModuleCandidate(
297*d9f75844SAndroid Build Coastguard Worker RtcpFeedbackSenderInterface* candidate_module,
298*d9f75844SAndroid Build Coastguard Worker bool media_sender) {
299*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(candidate_module);
300*d9f75844SAndroid Build Coastguard Worker std::vector<RtcpFeedbackSenderInterface*>& candidates =
301*d9f75844SAndroid Build Coastguard Worker media_sender ? sender_remb_candidates_ : receiver_remb_candidates_;
302*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(std::find(candidates.cbegin(), candidates.cend(),
303*d9f75844SAndroid Build Coastguard Worker candidate_module) == candidates.cend());
304*d9f75844SAndroid Build Coastguard Worker candidates.push_back(candidate_module);
305*d9f75844SAndroid Build Coastguard Worker DetermineActiveRembModule();
306*d9f75844SAndroid Build Coastguard Worker }
307*d9f75844SAndroid Build Coastguard Worker
MaybeRemoveRembModuleCandidate(RtcpFeedbackSenderInterface * candidate_module,bool media_sender)308*d9f75844SAndroid Build Coastguard Worker void PacketRouter::MaybeRemoveRembModuleCandidate(
309*d9f75844SAndroid Build Coastguard Worker RtcpFeedbackSenderInterface* candidate_module,
310*d9f75844SAndroid Build Coastguard Worker bool media_sender) {
311*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(candidate_module);
312*d9f75844SAndroid Build Coastguard Worker std::vector<RtcpFeedbackSenderInterface*>& candidates =
313*d9f75844SAndroid Build Coastguard Worker media_sender ? sender_remb_candidates_ : receiver_remb_candidates_;
314*d9f75844SAndroid Build Coastguard Worker auto it = std::find(candidates.begin(), candidates.end(), candidate_module);
315*d9f75844SAndroid Build Coastguard Worker
316*d9f75844SAndroid Build Coastguard Worker if (it == candidates.end()) {
317*d9f75844SAndroid Build Coastguard Worker return; // Function called due to removal of non-REMB-candidate module.
318*d9f75844SAndroid Build Coastguard Worker }
319*d9f75844SAndroid Build Coastguard Worker
320*d9f75844SAndroid Build Coastguard Worker if (*it == active_remb_module_) {
321*d9f75844SAndroid Build Coastguard Worker UnsetActiveRembModule();
322*d9f75844SAndroid Build Coastguard Worker }
323*d9f75844SAndroid Build Coastguard Worker candidates.erase(it);
324*d9f75844SAndroid Build Coastguard Worker DetermineActiveRembModule();
325*d9f75844SAndroid Build Coastguard Worker }
326*d9f75844SAndroid Build Coastguard Worker
UnsetActiveRembModule()327*d9f75844SAndroid Build Coastguard Worker void PacketRouter::UnsetActiveRembModule() {
328*d9f75844SAndroid Build Coastguard Worker RTC_CHECK(active_remb_module_);
329*d9f75844SAndroid Build Coastguard Worker active_remb_module_->UnsetRemb();
330*d9f75844SAndroid Build Coastguard Worker active_remb_module_ = nullptr;
331*d9f75844SAndroid Build Coastguard Worker }
332*d9f75844SAndroid Build Coastguard Worker
DetermineActiveRembModule()333*d9f75844SAndroid Build Coastguard Worker void PacketRouter::DetermineActiveRembModule() {
334*d9f75844SAndroid Build Coastguard Worker // Sender modules take precedence over receiver modules, because SRs (sender
335*d9f75844SAndroid Build Coastguard Worker // reports) are sent more frequently than RR (receiver reports).
336*d9f75844SAndroid Build Coastguard Worker // When adding the first sender module, we should change the active REMB
337*d9f75844SAndroid Build Coastguard Worker // module to be that. Otherwise, we remain with the current active module.
338*d9f75844SAndroid Build Coastguard Worker
339*d9f75844SAndroid Build Coastguard Worker RtcpFeedbackSenderInterface* new_active_remb_module;
340*d9f75844SAndroid Build Coastguard Worker
341*d9f75844SAndroid Build Coastguard Worker if (!sender_remb_candidates_.empty()) {
342*d9f75844SAndroid Build Coastguard Worker new_active_remb_module = sender_remb_candidates_.front();
343*d9f75844SAndroid Build Coastguard Worker } else if (!receiver_remb_candidates_.empty()) {
344*d9f75844SAndroid Build Coastguard Worker new_active_remb_module = receiver_remb_candidates_.front();
345*d9f75844SAndroid Build Coastguard Worker } else {
346*d9f75844SAndroid Build Coastguard Worker new_active_remb_module = nullptr;
347*d9f75844SAndroid Build Coastguard Worker }
348*d9f75844SAndroid Build Coastguard Worker
349*d9f75844SAndroid Build Coastguard Worker if (new_active_remb_module != active_remb_module_ && active_remb_module_) {
350*d9f75844SAndroid Build Coastguard Worker UnsetActiveRembModule();
351*d9f75844SAndroid Build Coastguard Worker }
352*d9f75844SAndroid Build Coastguard Worker
353*d9f75844SAndroid Build Coastguard Worker active_remb_module_ = new_active_remb_module;
354*d9f75844SAndroid Build Coastguard Worker }
355*d9f75844SAndroid Build Coastguard Worker
356*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
357