OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/pacing/packet_router.h" | 11 #include "webrtc/modules/pacing/packet_router.h" |
12 | 12 |
13 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" | 13 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" |
14 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" | 14 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" |
15 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" | 15 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" |
16 #include "webrtc/rtc_base/atomicops.h" | 16 #include "webrtc/rtc_base/atomicops.h" |
17 #include "webrtc/rtc_base/checks.h" | 17 #include "webrtc/rtc_base/checks.h" |
18 #include "webrtc/rtc_base/timeutils.h" | 18 #include "webrtc/rtc_base/timeutils.h" |
19 | 19 |
20 namespace webrtc { | 20 namespace webrtc { |
21 | 21 |
22 PacketRouter::PacketRouter() | 22 PacketRouter::PacketRouter() |
23 : last_remb_time_ms_(rtc::TimeMillis()), | 23 : last_remb_time_ms_(rtc::TimeMillis()), |
24 last_send_bitrate_bps_(0), | 24 last_send_bitrate_bps_(0), |
| 25 active_remb_module_(nullptr), |
25 transport_seq_(0) {} | 26 transport_seq_(0) {} |
26 | 27 |
27 PacketRouter::~PacketRouter() { | 28 PacketRouter::~PacketRouter() { |
28 RTC_DCHECK(rtp_send_modules_.empty()); | 29 RTC_DCHECK(rtp_send_modules_.empty()); |
29 RTC_DCHECK(rtp_receive_modules_.empty()); | 30 RTC_DCHECK(rtp_receive_modules_.empty()); |
| 31 RTC_DCHECK(sender_remb_candidates_.empty()); |
| 32 RTC_DCHECK(receiver_remb_candidates_.empty()); |
| 33 RTC_DCHECK(active_remb_module_ == nullptr); |
30 } | 34 } |
31 | 35 |
32 void PacketRouter::AddSendRtpModule(RtpRtcp* rtp_module) { | 36 void PacketRouter::AddSendRtpModule(RtpRtcp* rtp_module, bool remb_candidate) { |
33 rtc::CritScope cs(&modules_crit_); | 37 rtc::CritScope cs(&modules_crit_); |
34 RTC_DCHECK(std::find(rtp_send_modules_.begin(), rtp_send_modules_.end(), | 38 RTC_DCHECK(std::find(rtp_send_modules_.begin(), rtp_send_modules_.end(), |
35 rtp_module) == rtp_send_modules_.end()); | 39 rtp_module) == rtp_send_modules_.end()); |
36 if (rtp_send_modules_.empty() && !rtp_receive_modules_.empty()) { | |
37 rtp_receive_modules_.front()->SetREMBStatus(false); | |
38 } | |
39 | |
40 // Put modules which can use regular payload packets (over rtx) instead of | 40 // Put modules which can use regular payload packets (over rtx) instead of |
41 // padding first as it's less of a waste | 41 // padding first as it's less of a waste |
42 if ((rtp_module->RtxSendStatus() & kRtxRedundantPayloads) > 0) { | 42 if ((rtp_module->RtxSendStatus() & kRtxRedundantPayloads) > 0) { |
43 if (!rtp_send_modules_.empty()) { | |
44 rtp_send_modules_.front()->SetREMBStatus(false); | |
45 } | |
46 rtp_send_modules_.push_front(rtp_module); | 43 rtp_send_modules_.push_front(rtp_module); |
47 rtp_module->SetREMBStatus(true); | |
48 } else { | 44 } else { |
49 if (rtp_send_modules_.empty()) { | 45 rtp_send_modules_.push_back(rtp_module); |
50 rtp_module->SetREMBStatus(true); | 46 } |
51 } | |
52 | 47 |
53 rtp_send_modules_.push_back(rtp_module); | 48 if (remb_candidate) { |
| 49 AddRembModuleCandidate(rtp_module, true); |
54 } | 50 } |
55 } | 51 } |
56 | 52 |
57 void PacketRouter::RemoveSendRtpModule(RtpRtcp* rtp_module) { | 53 void PacketRouter::RemoveSendRtpModule(RtpRtcp* rtp_module) { |
58 rtc::CritScope cs(&modules_crit_); | 54 rtc::CritScope cs(&modules_crit_); |
59 RTC_DCHECK(std::find(rtp_send_modules_.begin(), rtp_send_modules_.end(), | 55 MaybeRemoveRembModuleCandidate(rtp_module, /* sender = */ true); |
60 rtp_module) != rtp_send_modules_.end()); | 56 auto it = |
61 rtp_send_modules_.remove(rtp_module); | 57 std::find(rtp_send_modules_.begin(), rtp_send_modules_.end(), rtp_module); |
62 rtp_module->SetREMBStatus(false); | 58 RTC_DCHECK(it != rtp_send_modules_.end()); |
63 if (!rtp_send_modules_.empty()) { | 59 rtp_send_modules_.erase(it); |
64 rtp_send_modules_.front()->SetREMBStatus(true); | |
65 } else if (!rtp_receive_modules_.empty()) { | |
66 rtp_receive_modules_.front()->SetREMBStatus(true); | |
67 } | |
68 } | 60 } |
69 | 61 |
70 void PacketRouter::AddReceiveRtpModule(RtpRtcp* rtp_module) { | 62 void PacketRouter::AddReceiveRtpModule(RtpRtcp* rtp_module, |
| 63 bool remb_candidate) { |
71 rtc::CritScope cs(&modules_crit_); | 64 rtc::CritScope cs(&modules_crit_); |
72 RTC_DCHECK(std::find(rtp_receive_modules_.begin(), rtp_receive_modules_.end(), | 65 RTC_DCHECK(std::find(rtp_receive_modules_.begin(), rtp_receive_modules_.end(), |
73 rtp_module) == rtp_receive_modules_.end()); | 66 rtp_module) == rtp_receive_modules_.end()); |
74 if (rtp_send_modules_.empty() && rtp_receive_modules_.empty()) { | 67 |
75 rtp_module->SetREMBStatus(true); | 68 rtp_receive_modules_.push_back(rtp_module); |
| 69 |
| 70 if (remb_candidate) { |
| 71 AddRembModuleCandidate(rtp_module, false); |
76 } | 72 } |
77 rtp_receive_modules_.push_back(rtp_module); | |
78 } | 73 } |
79 | 74 |
80 void PacketRouter::RemoveReceiveRtpModule(RtpRtcp* rtp_module) { | 75 void PacketRouter::RemoveReceiveRtpModule(RtpRtcp* rtp_module) { |
81 rtc::CritScope cs(&modules_crit_); | 76 rtc::CritScope cs(&modules_crit_); |
| 77 MaybeRemoveRembModuleCandidate(rtp_module, /* sender = */ false); |
82 const auto& it = std::find(rtp_receive_modules_.begin(), | 78 const auto& it = std::find(rtp_receive_modules_.begin(), |
83 rtp_receive_modules_.end(), rtp_module); | 79 rtp_receive_modules_.end(), rtp_module); |
84 RTC_DCHECK(it != rtp_receive_modules_.end()); | 80 RTC_DCHECK(it != rtp_receive_modules_.end()); |
85 rtp_receive_modules_.erase(it); | 81 rtp_receive_modules_.erase(it); |
86 if (rtp_send_modules_.empty()) { | |
87 rtp_module->SetREMBStatus(false); | |
88 if (!rtp_receive_modules_.empty()) { | |
89 rtp_receive_modules_.front()->SetREMBStatus(true); | |
90 } | |
91 } | |
92 } | 82 } |
93 | 83 |
94 bool PacketRouter::TimeToSendPacket(uint32_t ssrc, | 84 bool PacketRouter::TimeToSendPacket(uint32_t ssrc, |
95 uint16_t sequence_number, | 85 uint16_t sequence_number, |
96 int64_t capture_timestamp, | 86 int64_t capture_timestamp, |
97 bool retransmission, | 87 bool retransmission, |
98 const PacedPacketInfo& pacing_info) { | 88 const PacedPacketInfo& pacing_info) { |
99 RTC_DCHECK_RUNS_SERIALIZED(&pacer_race_); | 89 RTC_DCHECK_RUNS_SERIALIZED(&pacer_race_); |
100 rtc::CritScope cs(&modules_crit_); | 90 rtc::CritScope cs(&modules_crit_); |
101 for (auto* rtp_module : rtp_send_modules_) { | 91 for (auto* rtp_module : rtp_send_modules_) { |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 // a module to actually send it. | 173 // a module to actually send it. |
184 last_remb_time_ms_ = now_ms; | 174 last_remb_time_ms_ = now_ms; |
185 last_send_bitrate_bps_ = bitrate_bps; | 175 last_send_bitrate_bps_ = bitrate_bps; |
186 } | 176 } |
187 SendRemb(bitrate_bps, ssrcs); | 177 SendRemb(bitrate_bps, ssrcs); |
188 } | 178 } |
189 | 179 |
190 bool PacketRouter::SendRemb(uint32_t bitrate_bps, | 180 bool PacketRouter::SendRemb(uint32_t bitrate_bps, |
191 const std::vector<uint32_t>& ssrcs) { | 181 const std::vector<uint32_t>& ssrcs) { |
192 rtc::CritScope lock(&modules_crit_); | 182 rtc::CritScope lock(&modules_crit_); |
193 RtpRtcp* remb_module; | 183 |
194 if (!rtp_send_modules_.empty()) | 184 if (!active_remb_module_) { |
195 remb_module = rtp_send_modules_.front(); | |
196 else if (!rtp_receive_modules_.empty()) | |
197 remb_module = rtp_receive_modules_.front(); | |
198 else | |
199 return false; | 185 return false; |
| 186 } |
| 187 |
200 // The Add* and Remove* methods above ensure that this (and only this) module | 188 // The Add* and Remove* methods above ensure that this (and only this) module |
201 // has REMB enabled. REMB should be disabled on all other modules, because | 189 // has REMB enabled. REMB should be disabled on all other modules, because |
202 // otherwise, they will send REMB with stale info. | 190 // otherwise, they will send REMB with stale info. |
203 RTC_DCHECK(remb_module->REMB()); | 191 RTC_DCHECK(active_remb_module_->REMB()); |
204 remb_module->SetREMBData(bitrate_bps, ssrcs); | 192 active_remb_module_->SetREMBData(bitrate_bps, ssrcs); |
| 193 |
205 return true; | 194 return true; |
206 } | 195 } |
207 | 196 |
208 bool PacketRouter::SendTransportFeedback(rtcp::TransportFeedback* packet) { | 197 bool PacketRouter::SendTransportFeedback(rtcp::TransportFeedback* packet) { |
209 RTC_DCHECK_RUNS_SERIALIZED(&pacer_race_); | 198 RTC_DCHECK_RUNS_SERIALIZED(&pacer_race_); |
210 rtc::CritScope cs(&modules_crit_); | 199 rtc::CritScope cs(&modules_crit_); |
211 // Prefer send modules. | 200 // Prefer send modules. |
212 for (auto* rtp_module : rtp_send_modules_) { | 201 for (auto* rtp_module : rtp_send_modules_) { |
213 packet->SetSenderSsrc(rtp_module->SSRC()); | 202 packet->SetSenderSsrc(rtp_module->SSRC()); |
214 if (rtp_module->SendFeedbackPacket(*packet)) | 203 if (rtp_module->SendFeedbackPacket(*packet)) |
215 return true; | 204 return true; |
216 } | 205 } |
217 for (auto* rtp_module : rtp_receive_modules_) { | 206 for (auto* rtp_module : rtp_receive_modules_) { |
218 packet->SetSenderSsrc(rtp_module->SSRC()); | 207 packet->SetSenderSsrc(rtp_module->SSRC()); |
219 if (rtp_module->SendFeedbackPacket(*packet)) | 208 if (rtp_module->SendFeedbackPacket(*packet)) |
220 return true; | 209 return true; |
221 } | 210 } |
222 return false; | 211 return false; |
223 } | 212 } |
224 | 213 |
| 214 void PacketRouter::AddRembModuleCandidate(RtpRtcp* candidate_module, |
| 215 bool sender) { |
| 216 RTC_DCHECK(candidate_module); |
| 217 std::vector<RtpRtcp*>& candidates = |
| 218 sender ? sender_remb_candidates_ : receiver_remb_candidates_; |
| 219 RTC_DCHECK(std::find(candidates.cbegin(), candidates.cend(), |
| 220 candidate_module) == candidates.cend()); |
| 221 candidates.push_back(candidate_module); |
| 222 DetermineActiveRembModule(); |
| 223 } |
| 224 |
| 225 void PacketRouter::MaybeRemoveRembModuleCandidate(RtpRtcp* candidate_module, |
| 226 bool sender) { |
| 227 RTC_DCHECK(candidate_module); |
| 228 std::vector<RtpRtcp*>& candidates = |
| 229 sender ? sender_remb_candidates_ : receiver_remb_candidates_; |
| 230 auto it = std::find(candidates.begin(), candidates.end(), candidate_module); |
| 231 |
| 232 if (it == candidates.end()) { |
| 233 return; // Function called due to removal of non-REMB-candidate module. |
| 234 } |
| 235 |
| 236 if (*it == active_remb_module_) { |
| 237 UnsetActiveRembModule(); |
| 238 } |
| 239 candidates.erase(it); |
| 240 DetermineActiveRembModule(); |
| 241 } |
| 242 |
| 243 void PacketRouter::UnsetActiveRembModule() { |
| 244 RTC_CHECK(active_remb_module_); |
| 245 RTC_DCHECK(active_remb_module_->REMB()); |
| 246 active_remb_module_->SetREMBStatus(false); |
| 247 active_remb_module_ = nullptr; |
| 248 } |
| 249 |
| 250 void PacketRouter::DetermineActiveRembModule() { |
| 251 // Sender modules take precedence over receiver modules, because SRs (sender |
| 252 // reports) are sent more frequently than RR (receiver reports). |
| 253 // When adding the first sender module, we should change the active REMB |
| 254 // module to be that. Otherwise, we remain with the current active module. |
| 255 |
| 256 RtpRtcp* new_active_remb_module_; |
| 257 |
| 258 if (!sender_remb_candidates_.empty()) { |
| 259 new_active_remb_module_ = sender_remb_candidates_.front(); |
| 260 } else if (!receiver_remb_candidates_.empty()) { |
| 261 new_active_remb_module_ = receiver_remb_candidates_.front(); |
| 262 } else { |
| 263 new_active_remb_module_ = nullptr; |
| 264 } |
| 265 |
| 266 if (new_active_remb_module_ != active_remb_module_) { |
| 267 if (active_remb_module_) { |
| 268 UnsetActiveRembModule(); |
| 269 } |
| 270 if (new_active_remb_module_) { |
| 271 RTC_DCHECK(!new_active_remb_module_->REMB()); |
| 272 new_active_remb_module_->SetREMBStatus(true); |
| 273 } |
| 274 } |
| 275 |
| 276 active_remb_module_ = new_active_remb_module_; |
| 277 } |
| 278 |
225 } // namespace webrtc | 279 } // namespace webrtc |
OLD | NEW |