Index: webrtc/modules/pacing/packet_router.cc |
diff --git a/webrtc/modules/pacing/packet_router.cc b/webrtc/modules/pacing/packet_router.cc |
index ab86bfa4bd82551f8014cd5652540e743577ce8d..871ba0fcec984b99d7696a498e21b967bd2d5b8a 100644 |
--- a/webrtc/modules/pacing/packet_router.cc |
+++ b/webrtc/modules/pacing/packet_router.cc |
@@ -12,13 +12,17 @@ |
#include "webrtc/base/atomicops.h" |
#include "webrtc/base/checks.h" |
+#include "webrtc/base/timeutils.h" |
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" |
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" |
#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" |
namespace webrtc { |
-PacketRouter::PacketRouter() : transport_seq_(0) { |
+PacketRouter::PacketRouter() |
+ : last_remb_time_ms_(rtc::TimeMillis()), |
+ last_send_bitrate_bps_(0), |
+ transport_seq_(0) { |
pacer_thread_checker_.DetachFromThread(); |
} |
@@ -31,11 +35,23 @@ void PacketRouter::AddSendRtpModule(RtpRtcp* rtp_module) { |
rtc::CritScope cs(&modules_crit_); |
RTC_DCHECK(std::find(rtp_send_modules_.begin(), rtp_send_modules_.end(), |
rtp_module) == rtp_send_modules_.end()); |
+ if (rtp_send_modules_.empty() && !rtp_receive_modules_.empty()) { |
+ rtp_receive_modules_.front()->SetREMBStatus(false); |
+ } |
+ |
// Put modules which can use regular payload packets (over rtx) instead of |
// padding first as it's less of a waste |
if ((rtp_module->RtxSendStatus() & kRtxRedundantPayloads) > 0) { |
+ if (!rtp_send_modules_.empty()) { |
+ rtp_send_modules_.front()->SetREMBStatus(false); |
+ } |
rtp_send_modules_.push_front(rtp_module); |
+ rtp_module->SetREMBStatus(true); |
} else { |
+ if (rtp_send_modules_.empty()) { |
+ rtp_module->SetREMBStatus(true); |
+ } |
+ |
rtp_send_modules_.push_back(rtp_module); |
} |
} |
@@ -45,12 +61,21 @@ void PacketRouter::RemoveSendRtpModule(RtpRtcp* rtp_module) { |
RTC_DCHECK(std::find(rtp_send_modules_.begin(), rtp_send_modules_.end(), |
rtp_module) != rtp_send_modules_.end()); |
rtp_send_modules_.remove(rtp_module); |
+ rtp_module->SetREMBStatus(false); |
+ if (!rtp_send_modules_.empty()) { |
+ rtp_send_modules_.front()->SetREMBStatus(true); |
+ } else if (!rtp_receive_modules_.empty()) { |
+ rtp_receive_modules_.front()->SetREMBStatus(true); |
+ } |
} |
void PacketRouter::AddReceiveRtpModule(RtpRtcp* rtp_module) { |
rtc::CritScope cs(&modules_crit_); |
RTC_DCHECK(std::find(rtp_receive_modules_.begin(), rtp_receive_modules_.end(), |
rtp_module) == rtp_receive_modules_.end()); |
+ if (rtp_send_modules_.empty() && rtp_receive_modules_.empty()) { |
+ rtp_module->SetREMBStatus(true); |
+ } |
rtp_receive_modules_.push_back(rtp_module); |
} |
@@ -60,6 +85,12 @@ void PacketRouter::RemoveReceiveRtpModule(RtpRtcp* rtp_module) { |
rtp_receive_modules_.end(), rtp_module); |
RTC_DCHECK(it != rtp_receive_modules_.end()); |
rtp_receive_modules_.erase(it); |
+ if (rtp_send_modules_.empty()) { |
+ rtp_module->SetREMBStatus(false); |
+ if (!rtp_receive_modules_.empty()) { |
+ rtp_receive_modules_.front()->SetREMBStatus(true); |
+ } |
+ } |
} |
bool PacketRouter::TimeToSendPacket(uint32_t ssrc, |
@@ -121,7 +152,62 @@ uint16_t PacketRouter::AllocateSequenceNumber() { |
return new_seq; |
} |
-bool PacketRouter::SendFeedback(rtcp::TransportFeedback* packet) { |
+void PacketRouter::OnReceiveBitrateChanged(const std::vector<uint32_t>& ssrcs, |
+ uint32_t bitrate_bps) { |
+ const int kRembSendIntervalMs = 200; |
+ |
+ // % threshold for if we should send a new REMB asap. |
+ const uint32_t kSendThresholdPercent = 97; |
+ |
+ int64_t now_ms = rtc::TimeMillis(); |
+ { |
+ rtc::CritScope lock(&remb_crit_); |
+ |
+ // If we already have an estimate, check if the new total estimate is below |
+ // kSendThresholdPercent of the previous estimate. |
+ if (last_send_bitrate_bps_ > 0) { |
+ uint32_t new_remb_bitrate_bps = |
+ last_send_bitrate_bps_ - bitrate_bps_ + bitrate_bps; |
+ |
+ if (new_remb_bitrate_bps < |
+ kSendThresholdPercent * last_send_bitrate_bps_ / 100) { |
+ // The new bitrate estimate is less than kSendThresholdPercent % of the |
+ // last report. Send a REMB asap. |
+ last_remb_time_ms_ = now_ms - kRembSendIntervalMs; |
+ } |
+ } |
+ bitrate_bps_ = bitrate_bps; |
+ |
+ if (now_ms - last_remb_time_ms_ < kRembSendIntervalMs) { |
+ return; |
+ } |
+ // NOTE: Updated if we intend to send the data; we might not have |
+ // a module to actually send it. |
+ last_remb_time_ms_ = now_ms; |
+ last_send_bitrate_bps_ = bitrate_bps; |
+ } |
+ SendRemb(bitrate_bps, ssrcs); |
+} |
+ |
+bool PacketRouter::SendRemb(uint32_t bitrate_bps, |
+ const std::vector<uint32_t>& ssrcs) { |
+ rtc::CritScope lock(&modules_crit_); |
+ RtpRtcp* remb_module; |
+ if (!rtp_send_modules_.empty()) |
+ remb_module = rtp_send_modules_.front(); |
+ else if (!rtp_receive_modules_.empty()) |
+ remb_module = rtp_receive_modules_.front(); |
+ else |
+ return false; |
+ // The Add* and Remove* methods above ensure that this (and only this) module |
+ // has REMB enabled. REMB should be disabled on all other modules, because |
+ // otherwise, they will send REMB with stale info. |
+ RTC_DCHECK(remb_module->REMB()); |
+ remb_module->SetREMBData(bitrate_bps, ssrcs); |
+ return true; |
+} |
+ |
+bool PacketRouter::SendTransportFeedback(rtcp::TransportFeedback* packet) { |
RTC_DCHECK(pacer_thread_checker_.CalledOnValidThread()); |
rtc::CritScope cs(&modules_crit_); |
// Prefer send modules. |