| 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 |