Add support for multiple report blocks.
Use a weighted average of fraction loss for bandwidth estimation.
TEST=trybots and vie_auto_test --automated
BUG=1811
R=mflodman@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/2198004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@4762 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc b/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc
index fcf419e..7abe71b 100644
--- a/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc
+++ b/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc
@@ -20,6 +20,21 @@
using webrtc::BitrateObserver;
using webrtc::BitrateController;
+uint8_t WeightedLoss(int num_packets1, uint8_t fraction_loss1,
+ int num_packets2, uint8_t fraction_loss2) {
+ int weighted_sum = num_packets1 * fraction_loss1 +
+ num_packets2 * fraction_loss2;
+ int total_num_packets = num_packets1 + num_packets2;
+ return (weighted_sum + total_num_packets / 2) / total_num_packets;
+}
+
+webrtc::RTCPReportBlock CreateReportBlock(
+ uint32_t remote_ssrc, uint32_t source_ssrc,
+ uint8_t fraction_lost, uint32_t extended_high_sequence_number) {
+ return webrtc::RTCPReportBlock(remote_ssrc, source_ssrc, fraction_lost, 0,
+ extended_high_sequence_number, 0, 0, 0);
+}
+
class TestBitrateObserver: public BitrateObserver {
public:
TestBitrateObserver()
@@ -73,33 +88,49 @@
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
// Test start bitrate.
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 1, 1);
+ webrtc::ReportBlockList report_blocks;
+ report_blocks.push_back(CreateReportBlock(1, 2, 0, 1));
+ bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1);
EXPECT_EQ(0u, bitrate_observer.last_bitrate_);
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
EXPECT_EQ(0u, bitrate_observer.last_rtt_);
// Test bitrate increase 8% per second.
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 21, 1001);
+ 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(0, bitrate_observer.last_fraction_loss_);
EXPECT_EQ(50u, bitrate_observer.last_rtt_);
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 41, 2001);
+ 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_);
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 61, 3001);
+ 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_);
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 801, 4001);
+ 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_);
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 101, 5001);
+ 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_);
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 121, 6001);
+ 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.
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 141, 7001);
+ 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.
// Test that a low REMB trigger immediately.
@@ -124,44 +155,73 @@
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
// Test start bitrate.
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 1, 1);
- second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 100, 1, 1);
+ webrtc::ReportBlockList report_blocks;
+ report_blocks.push_back(CreateReportBlock(1, 2, 0, 1));
+ bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1);
+ second_bandwidth_observer->OnReceivedRtcpReceiverReport(
+ report_blocks, 100, 1);
EXPECT_EQ(0u, bitrate_observer.last_bitrate_);
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
EXPECT_EQ(0u, bitrate_observer.last_rtt_);
// Test bitrate increase 8% per second.
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 21, 501);
- second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 100, 21, 1001);
+ report_blocks.clear();
+ report_blocks.push_back(CreateReportBlock(1, 2, 0, 21));
+ bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 501);
+ second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 100,
+ 1001);
EXPECT_EQ(217000u, bitrate_observer.last_bitrate_);
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
EXPECT_EQ(100u, bitrate_observer.last_rtt_);
// Extra report should not change estimate.
- second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 100, 31, 1501);
+ report_blocks.clear();
+ report_blocks.push_back(CreateReportBlock(1, 2, 0, 31));
+ second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 100,
+ 1501);
EXPECT_EQ(217000u, bitrate_observer.last_bitrate_);
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 41, 2001);
+ 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_);
// Second report should not change estimate.
- second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 100, 41, 2001);
+ 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_);
// Reports from only one bandwidth observer is ok.
- second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 50, 61, 3001);
+ 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_);
- second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 50, 81, 4001);
+ 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_);
- second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 50, 101, 5001);
+ 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_);
- second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 50, 121, 6001);
+ 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(1, 0, 50, 141, 7001);
+ 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.
// Test that a low REMB trigger immediately.
@@ -177,6 +237,78 @@
delete second_bandwidth_observer;
}
+TEST_F(BitrateControllerTest, OneBitrateObserverMultipleReportBlocks) {
+ TestBitrateObserver bitrate_observer;
+ uint32_t sequence_number[2] = {0, 0xFF00};
+ const uint32_t kStartBitrate = 200000;
+ const uint32_t kMinBitrate = 100000;
+ const uint32_t kMaxBitrate = 300000;
+ controller_->SetBitrateObserver(&bitrate_observer, kStartBitrate, kMinBitrate,
+ kMaxBitrate);
+
+ // Receive a high REMB, test bitrate increase.
+ bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
+
+ webrtc::ReportBlockList report_blocks;
+ int64_t time_ms = 1001;
+ uint32_t last_bitrate = 0;
+ // Ramp up to max bitrate.
+ for (int i = 0; i < 6; ++i) {
+ report_blocks.push_back(CreateReportBlock(1, 2, 0, sequence_number[0]));
+ report_blocks.push_back(CreateReportBlock(1, 3, 0, sequence_number[1]));
+ bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50,
+ time_ms);
+ EXPECT_GT(bitrate_observer.last_bitrate_, last_bitrate);
+ EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
+ EXPECT_EQ(50u, bitrate_observer.last_rtt_);
+ last_bitrate = bitrate_observer.last_bitrate_;
+ time_ms += 1000;
+ sequence_number[0] += 20;
+ sequence_number[1] += 1;
+ report_blocks.clear();
+ }
+
+ EXPECT_EQ(kMaxBitrate, bitrate_observer.last_bitrate_);
+
+ // Packet loss on the first stream. Verify that bitrate decreases.
+ report_blocks.push_back(CreateReportBlock(1, 2, 50, sequence_number[0]));
+ report_blocks.push_back(CreateReportBlock(1, 3, 0, sequence_number[1]));
+ bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
+ EXPECT_LT(bitrate_observer.last_bitrate_, last_bitrate);
+ EXPECT_EQ(WeightedLoss(20, 50, 1, 0), bitrate_observer.last_fraction_loss_);
+ EXPECT_EQ(50u, bitrate_observer.last_rtt_);
+ last_bitrate = bitrate_observer.last_bitrate_;
+ sequence_number[0] += 20;
+ sequence_number[1] += 20;
+ time_ms += 1000;
+ report_blocks.clear();
+
+ // Packet loss on the second stream. Verify that bitrate decreases.
+ report_blocks.push_back(CreateReportBlock(1, 2, 0, sequence_number[0]));
+ report_blocks.push_back(CreateReportBlock(1, 3, 75, sequence_number[1]));
+ bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
+ EXPECT_LT(bitrate_observer.last_bitrate_, last_bitrate);
+ EXPECT_EQ(WeightedLoss(20, 0, 20, 75), bitrate_observer.last_fraction_loss_);
+ EXPECT_EQ(50u, bitrate_observer.last_rtt_);
+ last_bitrate = bitrate_observer.last_bitrate_;
+ sequence_number[0] += 20;
+ sequence_number[1] += 1;
+ time_ms += 1000;
+ report_blocks.clear();
+
+ // All packets lost on stream with few packets, no back-off.
+ report_blocks.push_back(CreateReportBlock(1, 2, 1, sequence_number[0]));
+ report_blocks.push_back(CreateReportBlock(1, 3, 255, sequence_number[1]));
+ bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
+ EXPECT_EQ(bitrate_observer.last_bitrate_, last_bitrate);
+ EXPECT_EQ(WeightedLoss(20, 1, 1, 255), bitrate_observer.last_fraction_loss_);
+ EXPECT_EQ(50u, bitrate_observer.last_rtt_);
+ last_bitrate = bitrate_observer.last_bitrate_;
+ sequence_number[0] += 20;
+ sequence_number[1] += 1;
+ report_blocks.clear();
+}
+
TEST_F(BitrateControllerTest, TwoBitrateObserversOneRtcpObserver) {
TestBitrateObserver bitrate_observer_1;
TestBitrateObserver bitrate_observer_2;
@@ -187,10 +319,14 @@
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
// Test too low start bitrate, hence lower than sum of min.
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 1, 1);
+ webrtc::ReportBlockList report_blocks;
+ report_blocks.push_back(CreateReportBlock(1, 2, 0, 1));
+ bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1);
// Test bitrate increase 8% per second, distributed equally.
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 21, 1001);
+ report_blocks.clear();
+ report_blocks.push_back(CreateReportBlock(1, 2, 0, 21));
+ bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1001);
EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_);
EXPECT_EQ(0, bitrate_observer_1.last_fraction_loss_);
EXPECT_EQ(50u, bitrate_observer_1.last_rtt_);
@@ -199,47 +335,67 @@
EXPECT_EQ(0, bitrate_observer_2.last_fraction_loss_);
EXPECT_EQ(50u, bitrate_observer_2.last_rtt_);
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 41, 2001);
+ report_blocks.clear();
+ report_blocks.push_back(CreateReportBlock(1, 2, 0, 41));
+ bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 2001);
EXPECT_EQ(112500u, bitrate_observer_1.last_bitrate_);
EXPECT_EQ(212500u, bitrate_observer_2.last_bitrate_);
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 61, 3001);
+ report_blocks.clear();
+ report_blocks.push_back(CreateReportBlock(1, 2, 0, 61));
+ bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 3001);
EXPECT_EQ(126000u, bitrate_observer_1.last_bitrate_);
EXPECT_EQ(226000u, bitrate_observer_2.last_bitrate_);
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 81, 4001);
+ report_blocks.clear();
+ report_blocks.push_back(CreateReportBlock(1, 2, 0, 81));
+ bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 4001);
EXPECT_EQ(140580u, bitrate_observer_1.last_bitrate_);
EXPECT_EQ(240580u, bitrate_observer_2.last_bitrate_);
// Check that the bitrate sum honor our REMB.
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 101, 5001);
+ report_blocks.clear();
+ report_blocks.push_back(CreateReportBlock(1, 2, 0, 101));
+ bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 5001);
EXPECT_EQ(150000u, bitrate_observer_1.last_bitrate_);
EXPECT_EQ(250000u, bitrate_observer_2.last_bitrate_);
// Remove REMB cap, higher than sum of max.
bandwidth_observer_->OnReceivedEstimatedBitrate(700000);
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 121, 6001);
+ report_blocks.clear();
+ report_blocks.push_back(CreateReportBlock(1, 2, 0, 121));
+ bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 6001);
EXPECT_EQ(166500u, bitrate_observer_1.last_bitrate_);
EXPECT_EQ(266500u, bitrate_observer_2.last_bitrate_);
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 141, 7001);
+ report_blocks.clear();
+ report_blocks.push_back(CreateReportBlock(1, 2, 0, 141));
+ bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 7001);
EXPECT_EQ(184320u, bitrate_observer_1.last_bitrate_);
EXPECT_EQ(284320u, bitrate_observer_2.last_bitrate_);
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 161, 8001);
+ report_blocks.clear();
+ report_blocks.push_back(CreateReportBlock(1, 2, 0, 161));
+ bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 8001);
EXPECT_EQ(207130u, bitrate_observer_1.last_bitrate_);
EXPECT_EQ(300000u, bitrate_observer_2.last_bitrate_); // Max cap.
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 181, 9001);
+ report_blocks.clear();
+ report_blocks.push_back(CreateReportBlock(1, 2, 0, 181));
+ bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 9001);
EXPECT_EQ(248700u, bitrate_observer_1.last_bitrate_);
EXPECT_EQ(300000u, bitrate_observer_2.last_bitrate_);
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 201, 10001);
+ report_blocks.clear();
+ report_blocks.push_back(CreateReportBlock(1, 2, 0, 201));
+ bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 10001);
EXPECT_EQ(293596u, bitrate_observer_1.last_bitrate_);
EXPECT_EQ(300000u, bitrate_observer_2.last_bitrate_);
- bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 221, 11001);
+ report_blocks.clear();
+ report_blocks.push_back(CreateReportBlock(1, 2, 0, 221));
+ bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 11001);
EXPECT_EQ(300000u, bitrate_observer_1.last_bitrate_); // Max cap.
EXPECT_EQ(300000u, bitrate_observer_2.last_bitrate_);