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