Modify bitrate controller to update bitrate based on process call and not
only whenever a RTCP receiver block is received. Additionally: Add condition to only start rampup after a receiver block is received. This was same as old behaviour but now an explicit check is needed to verify process does not ramps up before the first block. Fix logic around capping max bitrate increase at 8% per second. Before it was only increasing once every 1 second and each increase would be as high as 8%. If receiver blocks had a different interval before it would lose an update or waste an update slot and not ramp up as much as a 8% (e.g. if RTCP received < 1 second). Did not touch decrease logic, however since it can be triggered more often it may decrease much faster and closer to the original written cap of once every 300ms + rtt. Note: rampup_tests.cc don't seem to be affected by this since there is no packet loss or REMB that go higher than expected cap. bitrate_controller_unittests.cc are don't really simulate a clock and the process thread, but trigger update by inserting an rtcp block. BUG=3065 R=stefan@webrtc.org, mflodman@webrtc.org Review URL: https://webrtc-codereview.appspot.com/10529004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5775 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
0f0c992336
commit
da07737e68
@ -78,13 +78,22 @@ class BitrateControllerImpl::RtcpBandwidthObserverImpl
|
||||
};
|
||||
|
||||
BitrateController* BitrateController::CreateBitrateController(
|
||||
Clock* clock,
|
||||
bool enforce_min_bitrate) {
|
||||
return new BitrateControllerImpl(enforce_min_bitrate);
|
||||
return new BitrateControllerImpl(clock, enforce_min_bitrate);
|
||||
}
|
||||
|
||||
BitrateControllerImpl::BitrateControllerImpl(bool enforce_min_bitrate)
|
||||
: critsect_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||
enforce_min_bitrate_(enforce_min_bitrate) {}
|
||||
BitrateControllerImpl::BitrateControllerImpl(Clock* clock,
|
||||
bool enforce_min_bitrate)
|
||||
: clock_(clock),
|
||||
last_bitrate_update_ms_(clock_->TimeInMilliseconds()),
|
||||
critsect_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||
enforce_min_bitrate_(enforce_min_bitrate),
|
||||
last_bitrate_bps_(0),
|
||||
last_fraction_loss_(0),
|
||||
last_rtt_ms_(0),
|
||||
last_enforce_min_bitrate_(enforce_min_bitrate_),
|
||||
bitrate_observers_modified_(false) {}
|
||||
|
||||
BitrateControllerImpl::~BitrateControllerImpl() {
|
||||
BitrateObserverConfList::iterator it =
|
||||
@ -193,6 +202,26 @@ void BitrateControllerImpl::OnReceivedEstimatedBitrate(const uint32_t bitrate) {
|
||||
MaybeTriggerOnNetworkChanged();
|
||||
}
|
||||
|
||||
int32_t BitrateControllerImpl::TimeUntilNextProcess() {
|
||||
enum { kBitrateControllerUpdateIntervalMs = 25 };
|
||||
CriticalSectionScoped cs(critsect_);
|
||||
int time_since_update_ms =
|
||||
clock_->TimeInMilliseconds() - last_bitrate_update_ms_;
|
||||
return std::max(0, kBitrateControllerUpdateIntervalMs - time_since_update_ms);
|
||||
}
|
||||
|
||||
int32_t BitrateControllerImpl::Process() {
|
||||
if (TimeUntilNextProcess() > 0)
|
||||
return 0;
|
||||
{
|
||||
CriticalSectionScoped cs(critsect_);
|
||||
bandwidth_estimation_.UpdateEstimate(clock_->TimeInMilliseconds());
|
||||
MaybeTriggerOnNetworkChanged();
|
||||
}
|
||||
last_bitrate_update_ms_ = clock_->TimeInMilliseconds();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BitrateControllerImpl::OnReceivedRtcpReceiverReport(
|
||||
const uint8_t fraction_loss,
|
||||
const uint32_t rtt,
|
||||
@ -210,12 +239,12 @@ void BitrateControllerImpl::MaybeTriggerOnNetworkChanged() {
|
||||
uint32_t rtt;
|
||||
bandwidth_estimation_.CurrentEstimate(&bitrate, &fraction_loss, &rtt);
|
||||
|
||||
if (bitrate_observers_modified_ || bitrate != last_bitrate_ ||
|
||||
fraction_loss != last_fraction_loss_ || rtt != last_rtt_ ||
|
||||
if (bitrate_observers_modified_ || bitrate != last_bitrate_bps_ ||
|
||||
fraction_loss != last_fraction_loss_ || rtt != last_rtt_ms_ ||
|
||||
last_enforce_min_bitrate_ != enforce_min_bitrate_) {
|
||||
last_bitrate_ = bitrate;
|
||||
last_bitrate_bps_ = bitrate;
|
||||
last_fraction_loss_ = fraction_loss;
|
||||
last_rtt_ = rtt;
|
||||
last_rtt_ms_ = rtt;
|
||||
last_enforce_min_bitrate_ = enforce_min_bitrate_;
|
||||
bitrate_observers_modified_ = false;
|
||||
OnNetworkChanged(bitrate, fraction_loss, rtt);
|
||||
|
@ -29,7 +29,7 @@ namespace webrtc {
|
||||
|
||||
class BitrateControllerImpl : public BitrateController {
|
||||
public:
|
||||
explicit BitrateControllerImpl(bool enforce_min_bitrate);
|
||||
BitrateControllerImpl(Clock* clock, bool enforce_min_bitrate);
|
||||
virtual ~BitrateControllerImpl();
|
||||
|
||||
virtual bool AvailableBandwidth(uint32_t* bandwidth) const OVERRIDE;
|
||||
@ -45,6 +45,9 @@ class BitrateControllerImpl : public BitrateController {
|
||||
|
||||
virtual void EnforceMinBitrate(bool enforce_min_bitrate) OVERRIDE;
|
||||
|
||||
virtual int32_t TimeUntilNextProcess() OVERRIDE;
|
||||
virtual int32_t Process() OVERRIDE;
|
||||
|
||||
private:
|
||||
class RtcpBandwidthObserverImpl;
|
||||
|
||||
@ -107,13 +110,17 @@ class BitrateControllerImpl : public BitrateController {
|
||||
BitrateObserverConfList::iterator FindObserverConfigurationPair(
|
||||
const BitrateObserver* observer) EXCLUSIVE_LOCKS_REQUIRED(*critsect_);
|
||||
|
||||
// Used by process thread.
|
||||
Clock* clock_;
|
||||
uint32_t last_bitrate_update_ms_;
|
||||
|
||||
CriticalSectionWrapper* critsect_;
|
||||
SendSideBandwidthEstimation bandwidth_estimation_ GUARDED_BY(*critsect_);
|
||||
BitrateObserverConfList bitrate_observers_ GUARDED_BY(*critsect_);
|
||||
bool enforce_min_bitrate_ GUARDED_BY(*critsect_);
|
||||
uint32_t last_bitrate_ GUARDED_BY(*critsect_);
|
||||
uint32_t last_bitrate_bps_ GUARDED_BY(*critsect_);
|
||||
uint8_t last_fraction_loss_ GUARDED_BY(*critsect_);
|
||||
uint32_t last_rtt_ GUARDED_BY(*critsect_);
|
||||
uint32_t last_rtt_ms_ GUARDED_BY(*critsect_);
|
||||
bool last_enforce_min_bitrate_ GUARDED_BY(*critsect_);
|
||||
bool bitrate_observers_modified_ GUARDED_BY(*critsect_);
|
||||
};
|
||||
|
@ -57,12 +57,12 @@ class TestBitrateObserver: public BitrateObserver {
|
||||
|
||||
class BitrateControllerTest : public ::testing::Test {
|
||||
protected:
|
||||
BitrateControllerTest() : enforce_min_bitrate_(true) {}
|
||||
BitrateControllerTest() : clock_(0), enforce_min_bitrate_(true) {}
|
||||
~BitrateControllerTest() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
controller_ =
|
||||
BitrateController::CreateBitrateController(enforce_min_bitrate_);
|
||||
controller_ = BitrateController::CreateBitrateController(
|
||||
&clock_, enforce_min_bitrate_);
|
||||
bandwidth_observer_ = controller_->CreateRtcpBandwidthObserver();
|
||||
}
|
||||
|
||||
@ -70,6 +70,8 @@ class BitrateControllerTest : public ::testing::Test {
|
||||
delete bandwidth_observer_;
|
||||
delete controller_;
|
||||
}
|
||||
|
||||
webrtc::SimulatedClock clock_;
|
||||
bool enforce_min_bitrate_;
|
||||
BitrateController* controller_;
|
||||
RtcpBandwidthObserver* bandwidth_observer_;
|
||||
@ -87,52 +89,50 @@ TEST_F(BitrateControllerTest, OneBitrateObserverOneRtcpObserver) {
|
||||
|
||||
// Receive a high remb, test bitrate inc.
|
||||
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
|
||||
EXPECT_EQ(200000u, bitrate_observer.last_bitrate_);
|
||||
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
||||
EXPECT_EQ(0u, bitrate_observer.last_rtt_);
|
||||
|
||||
// Test start bitrate.
|
||||
// Test bitrate increase 8% per second.
|
||||
webrtc::ReportBlockList report_blocks;
|
||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 1));
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1);
|
||||
EXPECT_EQ(200000u, bitrate_observer.last_bitrate_);
|
||||
EXPECT_EQ(217000u, bitrate_observer.last_bitrate_);
|
||||
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
||||
EXPECT_EQ(50u, bitrate_observer.last_rtt_);
|
||||
|
||||
// Test bitrate increase 8% per second.
|
||||
report_blocks.clear();
|
||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 21));
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1001);
|
||||
EXPECT_EQ(217000u, bitrate_observer.last_bitrate_);
|
||||
EXPECT_EQ(235360u, bitrate_observer.last_bitrate_);
|
||||
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
||||
EXPECT_EQ(50u, bitrate_observer.last_rtt_);
|
||||
|
||||
report_blocks.clear();
|
||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 41));
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 2001);
|
||||
EXPECT_EQ(235360u, bitrate_observer.last_bitrate_);
|
||||
EXPECT_EQ(255189u, bitrate_observer.last_bitrate_);
|
||||
|
||||
report_blocks.clear();
|
||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 61));
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 3001);
|
||||
EXPECT_EQ(255189u, bitrate_observer.last_bitrate_);
|
||||
EXPECT_EQ(276604u, bitrate_observer.last_bitrate_);
|
||||
|
||||
report_blocks.clear();
|
||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 801));
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 4001);
|
||||
EXPECT_EQ(276604u, bitrate_observer.last_bitrate_);
|
||||
EXPECT_EQ(299732u, bitrate_observer.last_bitrate_);
|
||||
|
||||
// Reach max cap.
|
||||
report_blocks.clear();
|
||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 101));
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 5001);
|
||||
EXPECT_EQ(299732u, bitrate_observer.last_bitrate_);
|
||||
|
||||
report_blocks.clear();
|
||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 121));
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 6001);
|
||||
EXPECT_EQ(300000u, bitrate_observer.last_bitrate_); // Max cap.
|
||||
EXPECT_EQ(300000u, bitrate_observer.last_bitrate_);
|
||||
|
||||
report_blocks.clear();
|
||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 141));
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 7001);
|
||||
EXPECT_EQ(300000u, bitrate_observer.last_bitrate_); // Max cap.
|
||||
EXPECT_EQ(300000u, bitrate_observer.last_bitrate_);
|
||||
|
||||
// Test that a low REMB trigger immediately.
|
||||
bandwidth_observer_->OnReceivedEstimatedBitrate(250000);
|
||||
@ -154,6 +154,9 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
|
||||
|
||||
// Receive a high remb, test bitrate inc.
|
||||
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
|
||||
EXPECT_EQ(200000u, bitrate_observer.last_bitrate_);
|
||||
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
||||
EXPECT_EQ(0u, bitrate_observer.last_rtt_);
|
||||
|
||||
// Test start bitrate.
|
||||
webrtc::ReportBlockList report_blocks;
|
||||
@ -161,7 +164,7 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1);
|
||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
|
||||
report_blocks, 100, 1);
|
||||
EXPECT_EQ(200000u, bitrate_observer.last_bitrate_);
|
||||
EXPECT_EQ(217000u, bitrate_observer.last_bitrate_);
|
||||
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
||||
EXPECT_EQ(100u, bitrate_observer.last_rtt_);
|
||||
|
||||
@ -171,7 +174,7 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 501);
|
||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 100,
|
||||
1001);
|
||||
EXPECT_EQ(217000u, bitrate_observer.last_bitrate_);
|
||||
EXPECT_EQ(235360u, bitrate_observer.last_bitrate_);
|
||||
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
||||
EXPECT_EQ(100u, bitrate_observer.last_rtt_);
|
||||
|
||||
@ -180,50 +183,45 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
|
||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 31));
|
||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 100,
|
||||
1501);
|
||||
EXPECT_EQ(217000u, bitrate_observer.last_bitrate_);
|
||||
EXPECT_EQ(235360u, bitrate_observer.last_bitrate_);
|
||||
|
||||
report_blocks.clear();
|
||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 41));
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 2001);
|
||||
EXPECT_EQ(235360u, bitrate_observer.last_bitrate_);
|
||||
EXPECT_EQ(255189u, bitrate_observer.last_bitrate_);
|
||||
|
||||
// Second report should not change estimate.
|
||||
report_blocks.clear();
|
||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 41));
|
||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 100,
|
||||
2001);
|
||||
EXPECT_EQ(235360u, bitrate_observer.last_bitrate_);
|
||||
EXPECT_EQ(255189u, bitrate_observer.last_bitrate_);
|
||||
|
||||
// Reports from only one bandwidth observer is ok.
|
||||
report_blocks.clear();
|
||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 61));
|
||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 50,
|
||||
3001);
|
||||
EXPECT_EQ(255189u, bitrate_observer.last_bitrate_);
|
||||
EXPECT_EQ(276604u, bitrate_observer.last_bitrate_);
|
||||
|
||||
report_blocks.clear();
|
||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 81));
|
||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 50,
|
||||
4001);
|
||||
EXPECT_EQ(276604u, bitrate_observer.last_bitrate_);
|
||||
|
||||
report_blocks.clear();
|
||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 101));
|
||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 50,
|
||||
5001);
|
||||
EXPECT_EQ(299732u, bitrate_observer.last_bitrate_);
|
||||
|
||||
// Reach max cap.
|
||||
report_blocks.clear();
|
||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 121));
|
||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 50,
|
||||
6001);
|
||||
EXPECT_EQ(300000u, bitrate_observer.last_bitrate_); // Max cap.
|
||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
|
||||
report_blocks, 50, 5001);
|
||||
EXPECT_EQ(300000u, bitrate_observer.last_bitrate_);
|
||||
|
||||
report_blocks.clear();
|
||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 141));
|
||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 50,
|
||||
7001);
|
||||
EXPECT_EQ(300000u, bitrate_observer.last_bitrate_); // Max cap.
|
||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
|
||||
report_blocks, 50, 6001);
|
||||
EXPECT_EQ(300000u, bitrate_observer.last_bitrate_);
|
||||
|
||||
// Test that a low REMB trigger immediately.
|
||||
// We don't care which bandwidth observer that delivers the REMB.
|
||||
@ -232,8 +230,9 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
|
||||
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
||||
EXPECT_EQ(50u, bitrate_observer.last_rtt_);
|
||||
|
||||
// Min cap.
|
||||
bandwidth_observer_->OnReceivedEstimatedBitrate(1000);
|
||||
EXPECT_EQ(100000u, bitrate_observer.last_bitrate_); // Min cap.
|
||||
EXPECT_EQ(100000u, bitrate_observer.last_bitrate_);
|
||||
controller_->RemoveBitrateObserver(&bitrate_observer);
|
||||
delete second_bandwidth_observer;
|
||||
}
|
||||
@ -317,27 +316,24 @@ TEST_F(BitrateControllerTest, TwoBitrateObserversOneRtcpObserver) {
|
||||
controller_->SetBitrateObserver(&bitrate_observer_1, 200000, 100000, 300000);
|
||||
|
||||
// Receive a high remb, test bitrate inc.
|
||||
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
|
||||
|
||||
// Test too low start bitrate, hence lower than sum of min.
|
||||
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
|
||||
EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_);
|
||||
EXPECT_EQ(0, bitrate_observer_1.last_fraction_loss_);
|
||||
EXPECT_EQ(0u, bitrate_observer_1.last_rtt_);
|
||||
|
||||
// Test bitrate increase 8% per second, distributed equally.
|
||||
webrtc::ReportBlockList report_blocks;
|
||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 1));
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1);
|
||||
EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_);
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1001);
|
||||
EXPECT_EQ(112500u, bitrate_observer_1.last_bitrate_);
|
||||
EXPECT_EQ(0, bitrate_observer_1.last_fraction_loss_);
|
||||
EXPECT_EQ(50u, bitrate_observer_1.last_rtt_);
|
||||
|
||||
EXPECT_EQ(200000u, bitrate_observer_2.last_bitrate_);
|
||||
EXPECT_EQ(212500u, bitrate_observer_2.last_bitrate_);
|
||||
EXPECT_EQ(0, bitrate_observer_2.last_fraction_loss_);
|
||||
EXPECT_EQ(50u, bitrate_observer_2.last_rtt_);
|
||||
|
||||
// Test bitrate increase 8% per second, distributed equally.
|
||||
report_blocks.clear();
|
||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 21));
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1001);
|
||||
EXPECT_EQ(112500u, bitrate_observer_1.last_bitrate_);
|
||||
EXPECT_EQ(212500u, bitrate_observer_2.last_bitrate_);
|
||||
|
||||
report_blocks.clear();
|
||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 41));
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 2001);
|
||||
|
@ -15,6 +15,7 @@
|
||||
#ifndef WEBRTC_MODULES_BITRATE_CONTROLLER_INCLUDE_BITRATE_CONTROLLER_H_
|
||||
#define WEBRTC_MODULES_BITRATE_CONTROLLER_INCLUDE_BITRATE_CONTROLLER_H_
|
||||
|
||||
#include "webrtc/modules/interface/module.h"
|
||||
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -35,7 +36,7 @@ class BitrateObserver {
|
||||
virtual ~BitrateObserver() {}
|
||||
};
|
||||
|
||||
class BitrateController {
|
||||
class BitrateController : public Module {
|
||||
/*
|
||||
* This class collects feedback from all streams sent to a peer (via
|
||||
* RTCPBandwidthObservers). It does one aggregated send side bandwidth
|
||||
@ -48,7 +49,8 @@ class BitrateController {
|
||||
// When true, the bitrate will never be set lower than the minimum bitrate(s).
|
||||
// When false, the bitrate observers will be allocated rates up to their
|
||||
// respective minimum bitrate, satisfying one observer after the other.
|
||||
static BitrateController* CreateBitrateController(bool enforce_min_bitrate);
|
||||
static BitrateController* CreateBitrateController(Clock* clock,
|
||||
bool enforce_min_bitrate);
|
||||
virtual ~BitrateController() {}
|
||||
|
||||
virtual RtcpBandwidthObserver* CreateRtcpBandwidthObserver() = 0;
|
||||
|
@ -52,16 +52,20 @@ SendSideBandwidthEstimation::SendSideBandwidthEstimation()
|
||||
bitrate_(0),
|
||||
min_bitrate_configured_(0),
|
||||
max_bitrate_configured_(0),
|
||||
time_last_receiver_block_ms_(0),
|
||||
last_fraction_loss_(0),
|
||||
last_round_trip_time_(0),
|
||||
last_round_trip_time_ms_(0),
|
||||
bwe_incoming_(0),
|
||||
time_last_increase_(0),
|
||||
time_last_decrease_(0) {}
|
||||
time_last_decrease_ms_(0) {}
|
||||
|
||||
SendSideBandwidthEstimation::~SendSideBandwidthEstimation() {}
|
||||
|
||||
void SendSideBandwidthEstimation::SetSendBitrate(uint32_t bitrate) {
|
||||
bitrate_ = bitrate;
|
||||
|
||||
// Clear last sent bitrate history so the new value can be used directly
|
||||
// and not capped.
|
||||
min_bitrate_history_.clear();
|
||||
}
|
||||
|
||||
void SendSideBandwidthEstimation::SetMinMaxBitrate(uint32_t min_bitrate,
|
||||
@ -79,7 +83,7 @@ void SendSideBandwidthEstimation::CurrentEstimate(uint32_t* bitrate,
|
||||
uint32_t* rtt) const {
|
||||
*bitrate = bitrate_;
|
||||
*loss = last_fraction_loss_;
|
||||
*rtt = last_round_trip_time_;
|
||||
*rtt = last_round_trip_time_ms_;
|
||||
}
|
||||
|
||||
void SendSideBandwidthEstimation::UpdateReceiverEstimate(uint32_t bandwidth) {
|
||||
@ -92,7 +96,7 @@ void SendSideBandwidthEstimation::UpdateReceiverBlock(uint8_t fraction_loss,
|
||||
int number_of_packets,
|
||||
uint32_t now_ms) {
|
||||
// Update RTT.
|
||||
last_round_trip_time_ = rtt;
|
||||
last_round_trip_time_ms_ = rtt;
|
||||
|
||||
// Check sequence number diff and weight loss report
|
||||
if (number_of_packets > 0) {
|
||||
@ -115,50 +119,82 @@ void SendSideBandwidthEstimation::UpdateReceiverBlock(uint8_t fraction_loss,
|
||||
return;
|
||||
}
|
||||
}
|
||||
time_last_receiver_block_ms_ = now_ms;
|
||||
UpdateEstimate(now_ms);
|
||||
}
|
||||
|
||||
void SendSideBandwidthEstimation::UpdateEstimate(uint32_t now_ms) {
|
||||
if (last_fraction_loss_ <= 5) {
|
||||
// Loss < 2%: Limit the rate increases to once a kBweIncreaseIntervalMs.
|
||||
if ((now_ms - time_last_increase_) >= kBweIncreaseIntervalMs) {
|
||||
time_last_increase_ = now_ms;
|
||||
UpdateMinHistory(now_ms);
|
||||
|
||||
// Increase rate by 8%.
|
||||
bitrate_ = static_cast<uint32_t>(bitrate_ * 1.08 + 0.5);
|
||||
// Only start updating bitrate when receiving receiver blocks.
|
||||
if (time_last_receiver_block_ms_ != 0) {
|
||||
if (last_fraction_loss_ <= 5) {
|
||||
// Loss < 2%: Increase rate by 8% of the min bitrate in the last
|
||||
// kBweIncreaseIntervalMs.
|
||||
// Note that by remembering the bitrate over the last second one can
|
||||
// rampup up one second faster than if only allowed to start ramping
|
||||
// at 8% per second rate now. E.g.:
|
||||
// If sending a constant 100kbps it can rampup immediatly to 108kbps
|
||||
// whenever a receiver report is received with lower packet loss.
|
||||
// If instead one would do: bitrate_ *= 1.08^(delta time), it would
|
||||
// take over one second since the lower packet loss to achieve 108kbps.
|
||||
bitrate_ = static_cast<uint32_t>(
|
||||
min_bitrate_history_.front().second * 1.08 + 0.5);
|
||||
|
||||
// Add 1 kbps extra, just to make sure that we do not get stuck
|
||||
// (gives a little extra increase at low rates, negligible at higher
|
||||
// rates).
|
||||
bitrate_ += 1000;
|
||||
}
|
||||
|
||||
} else if (last_fraction_loss_ <= 26) {
|
||||
// Loss between 2% - 10%: Do nothing.
|
||||
} else if (last_fraction_loss_ <= 26) {
|
||||
// Loss between 2% - 10%: Do nothing.
|
||||
|
||||
} else {
|
||||
// Loss > 10%: Limit the rate decreases to once a kBweDecreaseIntervalMs +
|
||||
// rtt.
|
||||
if ((now_ms - time_last_decrease_) >=
|
||||
static_cast<uint32_t>(kBweDecreaseIntervalMs + last_round_trip_time_)) {
|
||||
time_last_decrease_ = now_ms;
|
||||
} else {
|
||||
// Loss > 10%: Limit the rate decreases to once a kBweDecreaseIntervalMs +
|
||||
// rtt.
|
||||
if ((now_ms - time_last_decrease_ms_) >=
|
||||
static_cast<uint32_t>(kBweDecreaseIntervalMs +
|
||||
last_round_trip_time_ms_)) {
|
||||
time_last_decrease_ms_ = now_ms;
|
||||
|
||||
// Reduce rate:
|
||||
// newRate = rate * (1 - 0.5*lossRate);
|
||||
// where packetLoss = 256*lossRate;
|
||||
bitrate_ = static_cast<uint32_t>(
|
||||
(bitrate_ * static_cast<double>(512 - last_fraction_loss_)) / 512.0);
|
||||
// Reduce rate:
|
||||
// newRate = rate * (1 - 0.5*lossRate);
|
||||
// where packetLoss = 256*lossRate;
|
||||
bitrate_ = static_cast<uint32_t>(
|
||||
(bitrate_ * static_cast<double>(512 - last_fraction_loss_)) /
|
||||
512.0);
|
||||
|
||||
// Calculate what rate TFRC would apply in this situation and to not
|
||||
// reduce further than it.
|
||||
bitrate_ = std::max(
|
||||
bitrate_, CalcTfrcBps(last_round_trip_time_, last_fraction_loss_));
|
||||
// Calculate what rate TFRC would apply in this situation and to not
|
||||
// reduce further than it.
|
||||
bitrate_ = std::max(
|
||||
bitrate_,
|
||||
CalcTfrcBps(last_round_trip_time_ms_, last_fraction_loss_));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CapBitrateToThresholds();
|
||||
}
|
||||
|
||||
void SendSideBandwidthEstimation::UpdateMinHistory(uint32_t now_ms) {
|
||||
// Remove old data points from history.
|
||||
// Since history precision is in ms, add one so it is able to increase
|
||||
// bitrate if it is off by as little as 0.5ms.
|
||||
while (!min_bitrate_history_.empty() &&
|
||||
now_ms - min_bitrate_history_.front().first + 1 >
|
||||
kBweIncreaseIntervalMs) {
|
||||
min_bitrate_history_.pop_front();
|
||||
}
|
||||
|
||||
// Typical minimum sliding-window algorithm: Pop values higher than current
|
||||
// bitrate before pushing it.
|
||||
while (!min_bitrate_history_.empty() &&
|
||||
bitrate_ <= min_bitrate_history_.back().second) {
|
||||
min_bitrate_history_.pop_back();
|
||||
}
|
||||
|
||||
min_bitrate_history_.push_back(std::make_pair(now_ms, bitrate_));
|
||||
}
|
||||
|
||||
void SendSideBandwidthEstimation::CapBitrateToThresholds() {
|
||||
if (bwe_incoming_ > 0 && bitrate_ > bwe_incoming_) {
|
||||
bitrate_ = bwe_incoming_;
|
||||
|
@ -13,6 +13,8 @@
|
||||
#ifndef WEBRTC_MODULES_BITRATE_CONTROLLER_SEND_SIDE_BANDWIDTH_ESTIMATION_H_
|
||||
#define WEBRTC_MODULES_BITRATE_CONTROLLER_SEND_SIDE_BANDWIDTH_ESTIMATION_H_
|
||||
|
||||
#include <deque>
|
||||
|
||||
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
|
||||
@ -24,6 +26,9 @@ class SendSideBandwidthEstimation {
|
||||
|
||||
void CurrentEstimate(uint32_t* bitrate, uint8_t* loss, uint32_t* rtt) const;
|
||||
|
||||
// Call periodically to update estimate.
|
||||
void UpdateEstimate(uint32_t now_ms);
|
||||
|
||||
// Call when we receive a RTCP message with TMMBR or REMB.
|
||||
void UpdateReceiverEstimate(uint32_t bandwidth);
|
||||
|
||||
@ -38,9 +43,15 @@ class SendSideBandwidthEstimation {
|
||||
void SetMinBitrate(uint32_t min_bitrate);
|
||||
|
||||
private:
|
||||
void UpdateEstimate(uint32_t now_ms);
|
||||
void CapBitrateToThresholds();
|
||||
|
||||
// Updates history of min bitrates.
|
||||
// After this method returns min_bitrate_history_.front().second contains the
|
||||
// min bitrate used during last kBweIncreaseIntervalMs.
|
||||
void UpdateMinHistory(uint32_t now_ms);
|
||||
|
||||
std::deque<std::pair<uint32_t, uint32_t> > min_bitrate_history_;
|
||||
|
||||
// incoming filters
|
||||
int accumulate_lost_packets_Q8_;
|
||||
int accumulate_expected_packets_;
|
||||
@ -49,12 +60,12 @@ class SendSideBandwidthEstimation {
|
||||
uint32_t min_bitrate_configured_;
|
||||
uint32_t max_bitrate_configured_;
|
||||
|
||||
uint32_t time_last_receiver_block_ms_;
|
||||
uint8_t last_fraction_loss_;
|
||||
uint16_t last_round_trip_time_;
|
||||
uint16_t last_round_trip_time_ms_;
|
||||
|
||||
uint32_t bwe_incoming_;
|
||||
uint32_t time_last_increase_;
|
||||
uint32_t time_last_decrease_;
|
||||
uint32_t time_last_decrease_ms_;
|
||||
};
|
||||
} // namespace webrtc
|
||||
#endif // WEBRTC_MODULES_BITRATE_CONTROLLER_SEND_SIDE_BANDWIDTH_ESTIMATION_H_
|
||||
|
@ -1123,9 +1123,12 @@ TEST_F(VideoSendStreamTest, ProducesStats) {
|
||||
// indicate that it should be lowered significantly. The test then observes that
|
||||
// the bitrate observed is sinking well below the min-transmit-bitrate threshold
|
||||
// to verify that the min-transmit bitrate respects incoming REMB.
|
||||
//
|
||||
// Note that the test starts at "high" bitrate and does not ramp up to "higher"
|
||||
// bitrate since no receiver block or remb is sent in the initial phase.
|
||||
TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) {
|
||||
static const int kMinTransmitBitrateBps = 400000;
|
||||
static const int kHighBitrateBps = 200000;
|
||||
static const int kHighBitrateBps = 150000;
|
||||
static const int kRembBitrateBps = 80000;
|
||||
static const int kRembRespectedBitrateBps = 100000;
|
||||
class BitrateObserver: public test::RtpRtcpObserver, public PacketReceiver {
|
||||
|
@ -160,10 +160,13 @@ class WrappingBitrateEstimator : public RemoteBitrateEstimator {
|
||||
};
|
||||
} // namespace
|
||||
|
||||
ChannelGroup::ChannelGroup(int engine_id, ProcessThread* process_thread,
|
||||
ChannelGroup::ChannelGroup(int engine_id,
|
||||
ProcessThread* process_thread,
|
||||
const Config* config)
|
||||
: remb_(new VieRemb()),
|
||||
bitrate_controller_(BitrateController::CreateBitrateController(true)),
|
||||
bitrate_controller_(
|
||||
BitrateController::CreateBitrateController(Clock::GetRealTimeClock(),
|
||||
true)),
|
||||
call_stats_(new CallStats()),
|
||||
encoder_state_feedback_(new EncoderStateFeedback()),
|
||||
config_(config),
|
||||
@ -175,16 +178,21 @@ ChannelGroup::ChannelGroup(int engine_id, ProcessThread* process_thread,
|
||||
}
|
||||
assert(config_); // Must have a valid config pointer here.
|
||||
remote_bitrate_estimator_.reset(
|
||||
new WrappingBitrateEstimator(engine_id, remb_.get(),
|
||||
Clock::GetRealTimeClock(), process_thread,
|
||||
new WrappingBitrateEstimator(engine_id,
|
||||
remb_.get(),
|
||||
Clock::GetRealTimeClock(),
|
||||
process_thread,
|
||||
*config_)),
|
||||
call_stats_->RegisterStatsObserver(remote_bitrate_estimator_.get());
|
||||
call_stats_->RegisterStatsObserver(remote_bitrate_estimator_.get());
|
||||
|
||||
process_thread->RegisterModule(call_stats_.get());
|
||||
process_thread->RegisterModule(bitrate_controller_.get());
|
||||
}
|
||||
|
||||
ChannelGroup::~ChannelGroup() {
|
||||
call_stats_->DeregisterStatsObserver(remote_bitrate_estimator_.get());
|
||||
process_thread_->DeRegisterModule(bitrate_controller_.get());
|
||||
process_thread_->DeRegisterModule(call_stats_.get());
|
||||
call_stats_->DeregisterStatsObserver(remote_bitrate_estimator_.get());
|
||||
assert(channels_.empty());
|
||||
assert(!remb_->InUse());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user