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
This commit is contained in:
@ -30,23 +30,44 @@ class RtcpBandwidthObserverImpl : public RtcpBandwidthObserver {
|
||||
}
|
||||
// Received RTCP receiver block.
|
||||
virtual void OnReceivedRtcpReceiverReport(
|
||||
const uint32_t ssrc,
|
||||
const uint8_t fraction_loss,
|
||||
const uint32_t rtt,
|
||||
const uint32_t last_received_extended_high_seq_num,
|
||||
const uint32_t now_ms) OVERRIDE {
|
||||
uint32_t number_of_packets = 0;
|
||||
std::map<uint32_t, uint32_t>::iterator it =
|
||||
ssrc_to_last_received_extended_high_seq_num_.find(ssrc);
|
||||
const ReportBlockList& report_blocks,
|
||||
uint16_t rtt,
|
||||
int64_t now_ms) OVERRIDE {
|
||||
if (report_blocks.empty())
|
||||
return;
|
||||
|
||||
int fraction_lost_aggregate = 0;
|
||||
int total_number_of_packets = 0;
|
||||
|
||||
// Compute the a weighted average of the fraction loss from all report
|
||||
// blocks.
|
||||
for (ReportBlockList::const_iterator it = report_blocks.begin();
|
||||
it != report_blocks.end(); ++it) {
|
||||
std::map<uint32_t, uint32_t>::iterator seq_num_it =
|
||||
ssrc_to_last_received_extended_high_seq_num_.find(it->sourceSSRC);
|
||||
|
||||
int number_of_packets = 0;
|
||||
if (seq_num_it != ssrc_to_last_received_extended_high_seq_num_.end())
|
||||
number_of_packets = it->extendedHighSeqNum -
|
||||
seq_num_it->second;
|
||||
|
||||
fraction_lost_aggregate += number_of_packets * it->fractionLost;
|
||||
total_number_of_packets += number_of_packets;
|
||||
|
||||
if (it != ssrc_to_last_received_extended_high_seq_num_.end()) {
|
||||
number_of_packets = last_received_extended_high_seq_num - it->second;
|
||||
}
|
||||
// Update last received for this SSRC.
|
||||
ssrc_to_last_received_extended_high_seq_num_[ssrc] =
|
||||
last_received_extended_high_seq_num;
|
||||
owner_->OnReceivedRtcpReceiverReport(fraction_loss, rtt, number_of_packets,
|
||||
now_ms);
|
||||
ssrc_to_last_received_extended_high_seq_num_[it->sourceSSRC] =
|
||||
it->extendedHighSeqNum;
|
||||
}
|
||||
if (total_number_of_packets == 0)
|
||||
fraction_lost_aggregate = 0;
|
||||
else
|
||||
fraction_lost_aggregate = (fraction_lost_aggregate +
|
||||
total_number_of_packets / 2) / total_number_of_packets;
|
||||
if (fraction_lost_aggregate > 255)
|
||||
return;
|
||||
|
||||
owner_->OnReceivedRtcpReceiverReport(fraction_lost_aggregate, rtt,
|
||||
total_number_of_packets, now_ms);
|
||||
}
|
||||
private:
|
||||
std::map<uint32_t, uint32_t> ssrc_to_last_received_extended_high_seq_num_;
|
||||
|
@ -20,6 +20,21 @@ using webrtc::RtcpBandwidthObserver;
|
||||
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 @@ TEST_F(BitrateControllerTest, OneBitrateObserverOneRtcpObserver) {
|
||||
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 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
|
||||
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 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
|
||||
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 @@ TEST_F(BitrateControllerTest, TwoBitrateObserversOneRtcpObserver) {
|
||||
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 @@ TEST_F(BitrateControllerTest, TwoBitrateObserversOneRtcpObserver) {
|
||||
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_);
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#define WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_RTCP_DEFINES_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <list>
|
||||
|
||||
#include "webrtc/modules/interface/module_common_types.h"
|
||||
#include "webrtc/system_wrappers/interface/clock.h"
|
||||
@ -142,19 +143,42 @@ struct RTCPSenderInfo
|
||||
uint32_t sendOctetCount;
|
||||
};
|
||||
|
||||
struct RTCPReportBlock
|
||||
{
|
||||
struct RTCPReportBlock {
|
||||
RTCPReportBlock()
|
||||
: remoteSSRC(0), sourceSSRC(0), fractionLost(0), cumulativeLost(0),
|
||||
extendedHighSeqNum(0), jitter(0), lastSR(0),
|
||||
delaySinceLastSR(0) {}
|
||||
|
||||
RTCPReportBlock(uint32_t remote_ssrc,
|
||||
uint32_t source_ssrc,
|
||||
uint8_t fraction_lost,
|
||||
uint32_t cumulative_lost,
|
||||
uint32_t extended_high_sequence_number,
|
||||
uint32_t jitter,
|
||||
uint32_t last_sender_report,
|
||||
uint32_t delay_since_last_sender_report)
|
||||
: remoteSSRC(remote_ssrc),
|
||||
sourceSSRC(source_ssrc),
|
||||
fractionLost(fraction_lost),
|
||||
cumulativeLost(cumulative_lost),
|
||||
extendedHighSeqNum(extended_high_sequence_number),
|
||||
jitter(jitter),
|
||||
lastSR(last_sender_report),
|
||||
delaySinceLastSR(delay_since_last_sender_report) {}
|
||||
|
||||
// Fields as described by RFC 3550 6.4.2.
|
||||
uint32_t remoteSSRC; // SSRC of sender of this report.
|
||||
uint32_t sourceSSRC; // SSRC of the RTP packet sender.
|
||||
uint8_t fractionLost;
|
||||
uint32_t cumulativeLost; // 24 bits valid
|
||||
uint32_t cumulativeLost; // 24 bits valid.
|
||||
uint32_t extendedHighSeqNum;
|
||||
uint32_t jitter;
|
||||
uint32_t lastSR;
|
||||
uint32_t delaySinceLastSR;
|
||||
};
|
||||
|
||||
typedef std::list<RTCPReportBlock> ReportBlockList;
|
||||
|
||||
class RtpData
|
||||
{
|
||||
public:
|
||||
@ -249,11 +273,9 @@ class RtcpBandwidthObserver {
|
||||
virtual void OnReceivedEstimatedBitrate(const uint32_t bitrate) = 0;
|
||||
|
||||
virtual void OnReceivedRtcpReceiverReport(
|
||||
const uint32_t ssrc,
|
||||
const uint8_t fraction_loss,
|
||||
const uint32_t rtt,
|
||||
const uint32_t last_received_extended_high_seqNum,
|
||||
const uint32_t now_ms) = 0;
|
||||
const ReportBlockList& report_blocks,
|
||||
uint16_t rtt,
|
||||
int64_t now_ms) = 0;
|
||||
|
||||
virtual ~RtcpBandwidthObserver() {}
|
||||
};
|
||||
|
@ -46,7 +46,7 @@ RTCPReceiver::RTCPReceiver(const int32_t id, Clock* clock,
|
||||
_cbRtcpIntraFrameObserver(NULL),
|
||||
_criticalSectionRTCPReceiver(
|
||||
CriticalSectionWrapper::CreateCriticalSection()),
|
||||
_SSRC(0),
|
||||
main_ssrc_(0),
|
||||
_remoteSSRC(0),
|
||||
_remoteSenderInfo(),
|
||||
_lastReceivedSRNTPsecs(0),
|
||||
@ -156,18 +156,19 @@ void RTCPReceiver::RegisterRtcpObservers(
|
||||
_cbRtcpFeedback = feedback_callback;
|
||||
}
|
||||
|
||||
|
||||
void RTCPReceiver::SetSSRC(const uint32_t ssrc) {
|
||||
void RTCPReceiver::SetSsrcs(uint32_t main_ssrc,
|
||||
const std::set<uint32_t>& registered_ssrcs) {
|
||||
uint32_t old_ssrc = 0;
|
||||
{
|
||||
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
|
||||
old_ssrc = _SSRC;
|
||||
_SSRC = ssrc;
|
||||
old_ssrc = main_ssrc_;
|
||||
main_ssrc_ = main_ssrc;
|
||||
registered_ssrcs_ = registered_ssrcs;
|
||||
}
|
||||
{
|
||||
CriticalSectionScoped lock(_criticalSectionFeedbacks);
|
||||
if (_cbRtcpIntraFrameObserver && old_ssrc != ssrc) {
|
||||
_cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, ssrc);
|
||||
if (_cbRtcpIntraFrameObserver && old_ssrc != main_ssrc) {
|
||||
_cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, main_ssrc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -405,7 +406,7 @@ RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
|
||||
{
|
||||
TRACE_EVENT_INSTANT2("webrtc_rtp", "SR",
|
||||
"remote_ssrc", remoteSSRC,
|
||||
"ssrc", _SSRC);
|
||||
"ssrc", main_ssrc_);
|
||||
|
||||
if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
|
||||
{
|
||||
@ -436,7 +437,7 @@ RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
|
||||
{
|
||||
TRACE_EVENT_INSTANT2("webrtc_rtp", "RR",
|
||||
"remote_ssrc", remoteSSRC,
|
||||
"ssrc", _SSRC);
|
||||
"ssrc", main_ssrc_);
|
||||
|
||||
rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
|
||||
}
|
||||
@ -467,7 +468,8 @@ RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
|
||||
// which the information in this reception report block pertains.
|
||||
|
||||
// Filter out all report blocks that are not for us.
|
||||
if (rtcpPacket.ReportBlockItem.SSRC != _SSRC) {
|
||||
if (registered_ssrcs_.find(rtcpPacket.ReportBlockItem.SSRC) ==
|
||||
registered_ssrcs_.end()) {
|
||||
// This block is not for us ignore it.
|
||||
return;
|
||||
}
|
||||
@ -564,11 +566,7 @@ RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
|
||||
|
||||
TRACE_COUNTER_ID1("webrtc_rtp", "RR_RTT", rb.SSRC, RTT);
|
||||
|
||||
// rtcpPacketInformation
|
||||
rtcpPacketInformation.AddReportInfo(
|
||||
reportBlock->remoteReceiveBlock.fractionLost, (uint16_t) RTT,
|
||||
reportBlock->remoteReceiveBlock.extendedHighSeqNum,
|
||||
reportBlock->remoteReceiveBlock.jitter);
|
||||
rtcpPacketInformation.AddReportInfo(*reportBlock);
|
||||
}
|
||||
|
||||
RTCPReportBlockInformation*
|
||||
@ -757,7 +755,7 @@ int32_t RTCPReceiver::BoundingSet(bool &tmmbrOwner, TMMBRSet* boundingSetRec) {
|
||||
receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
|
||||
for(uint32_t i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
|
||||
i++) {
|
||||
if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == _SSRC) {
|
||||
if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == main_ssrc_) {
|
||||
// owner of bounding set
|
||||
tmmbrOwner = true;
|
||||
}
|
||||
@ -799,7 +797,7 @@ RTCPReceiver::HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser,
|
||||
RTCPPacketInformation& rtcpPacketInformation)
|
||||
{
|
||||
const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
|
||||
if (_SSRC != rtcpPacket.NACK.MediaSSRC)
|
||||
if (main_ssrc_ != rtcpPacket.NACK.MediaSSRC)
|
||||
{
|
||||
// Not to us.
|
||||
rtcpParser.Iterate();
|
||||
@ -879,7 +877,7 @@ RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser,
|
||||
|
||||
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
|
||||
|
||||
if(rtcpPacket.XRVOIPMetricItem.SSRC == _SSRC)
|
||||
if(rtcpPacket.XRVOIPMetricItem.SSRC == main_ssrc_)
|
||||
{
|
||||
// Store VoIP metrics block if it's about me
|
||||
// from OriginatorSSRC do we filter it?
|
||||
@ -918,7 +916,7 @@ RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser,
|
||||
void RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser,
|
||||
RTCPPacketInformation& rtcpPacketInformation) {
|
||||
const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
|
||||
if (_SSRC == rtcpPacket.PLI.MediaSSRC) {
|
||||
if (main_ssrc_ == rtcpPacket.PLI.MediaSSRC) {
|
||||
TRACE_EVENT_INSTANT0("webrtc_rtp", "PLI");
|
||||
|
||||
// Received a signal that we need to send a new key frame.
|
||||
@ -977,7 +975,7 @@ RTCPReceiver::HandleTMMBRItem(RTCPReceiveInformation& receiveInfo,
|
||||
RTCPPacketInformation& rtcpPacketInformation,
|
||||
const uint32_t senderSSRC)
|
||||
{
|
||||
if (_SSRC == rtcpPacket.TMMBRItem.SSRC &&
|
||||
if (main_ssrc_ == rtcpPacket.TMMBRItem.SSRC &&
|
||||
rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0)
|
||||
{
|
||||
receiveInfo.InsertTMMBRItem(senderSSRC, rtcpPacket.TMMBRItem,
|
||||
@ -1160,7 +1158,7 @@ void RTCPReceiver::HandleFIRItem(RTCPReceiveInformation* receiveInfo,
|
||||
const RTCPUtility::RTCPPacket& rtcpPacket,
|
||||
RTCPPacketInformation& rtcpPacketInformation) {
|
||||
// Is it our sender that is requested to generate a new keyframe
|
||||
if (_SSRC != rtcpPacket.FIRItem.SSRC) {
|
||||
if (main_ssrc_ != rtcpPacket.FIRItem.SSRC) {
|
||||
return;
|
||||
}
|
||||
// rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it
|
||||
@ -1271,7 +1269,7 @@ void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
|
||||
{
|
||||
// We don't want to hold this critsect when triggering the callbacks below.
|
||||
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
|
||||
local_ssrc = _SSRC;
|
||||
local_ssrc = main_ssrc_;
|
||||
}
|
||||
if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq) {
|
||||
_rtpRtcp.OnRequestSendReport();
|
||||
@ -1322,15 +1320,12 @@ void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
|
||||
_cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
|
||||
rtcpPacketInformation.receiverEstimatedMaxBitrate);
|
||||
}
|
||||
if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
|
||||
rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) &&
|
||||
rtcpPacketInformation.reportBlock) {
|
||||
if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
|
||||
rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) {
|
||||
int64_t now = _clock->TimeInMilliseconds();
|
||||
_cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
|
||||
rtcpPacketInformation.remoteSSRC,
|
||||
rtcpPacketInformation.fractionLost,
|
||||
rtcpPacketInformation.roundTripTime,
|
||||
rtcpPacketInformation.lastReceivedExtendedHighSeqNum,
|
||||
rtcpPacketInformation.report_blocks,
|
||||
rtcpPacketInformation.rtt,
|
||||
now);
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h"
|
||||
@ -39,7 +40,8 @@ public:
|
||||
int64_t LastReceived();
|
||||
int64_t LastReceivedReceiverReport() const;
|
||||
|
||||
void SetSSRC( const uint32_t ssrc);
|
||||
void SetSsrcs(uint32_t main_ssrc,
|
||||
const std::set<uint32_t>& registered_ssrcs);
|
||||
void SetRelaySSRC( const uint32_t ssrc);
|
||||
int32_t SetRemoteSSRC( const uint32_t ssrc);
|
||||
uint32_t RemoteSSRC() const;
|
||||
@ -211,8 +213,9 @@ protected:
|
||||
RtcpIntraFrameObserver* _cbRtcpIntraFrameObserver;
|
||||
|
||||
CriticalSectionWrapper* _criticalSectionRTCPReceiver;
|
||||
uint32_t _SSRC;
|
||||
uint32_t main_ssrc_;
|
||||
uint32_t _remoteSSRC;
|
||||
std::set<uint32_t> registered_ssrcs_;
|
||||
|
||||
// Received send report
|
||||
RTCPSenderInfo _remoteSenderInfo;
|
||||
|
@ -26,11 +26,7 @@ RTCPPacketInformation::RTCPPacketInformation()
|
||||
applicationName(0),
|
||||
applicationData(),
|
||||
applicationLength(0),
|
||||
reportBlock(false),
|
||||
fractionLost(0),
|
||||
roundTripTime(0),
|
||||
lastReceivedExtendedHighSeqNum(0),
|
||||
jitter(0),
|
||||
rtt(0),
|
||||
interArrivalJitter(0),
|
||||
sliPictureId(0),
|
||||
rpsiPictureId(0),
|
||||
@ -95,16 +91,11 @@ RTCPPacketInformation::AddNACKPacket(const uint16_t packetID)
|
||||
}
|
||||
|
||||
void
|
||||
RTCPPacketInformation::AddReportInfo(const uint8_t fraction,
|
||||
const uint16_t rtt,
|
||||
const uint32_t extendedHighSeqNum,
|
||||
const uint32_t j)
|
||||
RTCPPacketInformation::AddReportInfo(
|
||||
const RTCPReportBlockInformation& report_block_info)
|
||||
{
|
||||
reportBlock = true;
|
||||
fractionLost = fraction;
|
||||
roundTripTime = rtt;
|
||||
jitter = j;
|
||||
lastReceivedExtendedHighSeqNum = extendedHighSeqNum;
|
||||
this->rtt = report_block_info.RTT;
|
||||
report_blocks.push_back(report_block_info.remoteReceiveBlock);
|
||||
}
|
||||
|
||||
RTCPReportBlockInformation::RTCPReportBlockInformation():
|
||||
|
@ -11,7 +11,6 @@
|
||||
#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_HELP_H_
|
||||
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_HELP_H_
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" // RTCPReportBlock
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
|
||||
@ -24,58 +23,6 @@ namespace webrtc {
|
||||
namespace RTCPHelp
|
||||
{
|
||||
|
||||
class RTCPPacketInformation
|
||||
{
|
||||
public:
|
||||
RTCPPacketInformation();
|
||||
~RTCPPacketInformation();
|
||||
|
||||
void AddVoIPMetric(const RTCPVoIPMetric* metric);
|
||||
|
||||
void AddApplicationData(const uint8_t* data,
|
||||
const uint16_t size);
|
||||
|
||||
void AddNACKPacket(const uint16_t packetID);
|
||||
void ResetNACKPacketIdArray();
|
||||
|
||||
void AddReportInfo(const uint8_t fractionLost,
|
||||
const uint16_t rtt,
|
||||
const uint32_t extendedHighSeqNum,
|
||||
const uint32_t jitter);
|
||||
|
||||
uint32_t rtcpPacketTypeFlags; // RTCPPacketTypeFlags bit field
|
||||
uint32_t remoteSSRC;
|
||||
|
||||
std::list<uint16_t> nackSequenceNumbers;
|
||||
|
||||
uint8_t applicationSubType;
|
||||
uint32_t applicationName;
|
||||
uint8_t* applicationData;
|
||||
uint16_t applicationLength;
|
||||
|
||||
bool reportBlock;
|
||||
uint8_t fractionLost;
|
||||
uint16_t roundTripTime;
|
||||
uint32_t lastReceivedExtendedHighSeqNum;
|
||||
uint32_t jitter;
|
||||
|
||||
uint32_t interArrivalJitter;
|
||||
|
||||
uint8_t sliPictureId;
|
||||
uint64_t rpsiPictureId;
|
||||
uint32_t receiverEstimatedMaxBitrate;
|
||||
|
||||
uint32_t ntp_secs;
|
||||
uint32_t ntp_frac;
|
||||
uint32_t rtp_timestamp;
|
||||
|
||||
RTCPVoIPMetric* VoIPMetric;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(RTCPPacketInformation);
|
||||
};
|
||||
|
||||
|
||||
class RTCPReportBlockInformation
|
||||
{
|
||||
public:
|
||||
@ -94,6 +41,51 @@ public:
|
||||
uint32_t numAverageCalcs;
|
||||
};
|
||||
|
||||
class RTCPPacketInformation
|
||||
{
|
||||
public:
|
||||
RTCPPacketInformation();
|
||||
~RTCPPacketInformation();
|
||||
|
||||
void AddVoIPMetric(const RTCPVoIPMetric* metric);
|
||||
|
||||
void AddApplicationData(const uint8_t* data,
|
||||
const uint16_t size);
|
||||
|
||||
void AddNACKPacket(const uint16_t packetID);
|
||||
void ResetNACKPacketIdArray();
|
||||
|
||||
void AddReportInfo(const RTCPReportBlockInformation& report_block_info);
|
||||
|
||||
uint32_t rtcpPacketTypeFlags; // RTCPPacketTypeFlags bit field
|
||||
uint32_t remoteSSRC;
|
||||
|
||||
std::list<uint16_t> nackSequenceNumbers;
|
||||
|
||||
uint8_t applicationSubType;
|
||||
uint32_t applicationName;
|
||||
uint8_t* applicationData;
|
||||
uint16_t applicationLength;
|
||||
|
||||
ReportBlockList report_blocks;
|
||||
uint16_t rtt;
|
||||
|
||||
uint32_t interArrivalJitter;
|
||||
|
||||
uint8_t sliPictureId;
|
||||
uint64_t rpsiPictureId;
|
||||
uint32_t receiverEstimatedMaxBitrate;
|
||||
|
||||
uint32_t ntp_secs;
|
||||
uint32_t ntp_frac;
|
||||
uint32_t rtp_timestamp;
|
||||
|
||||
RTCPVoIPMetric* VoIPMetric;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(RTCPPacketInformation);
|
||||
};
|
||||
|
||||
class RTCPReceiveInformation
|
||||
{
|
||||
public:
|
||||
|
@ -33,6 +33,20 @@ class PacketBuilder {
|
||||
public:
|
||||
static const int kMaxPacketSize = 1024;
|
||||
|
||||
struct ReportBlock {
|
||||
ReportBlock(uint32_t ssrc, uint32_t extended_max, uint8_t fraction_loss,
|
||||
uint32_t cumulative_loss)
|
||||
: ssrc(ssrc),
|
||||
extended_max(extended_max),
|
||||
fraction_loss(fraction_loss),
|
||||
cumulative_loss(cumulative_loss) {}
|
||||
|
||||
uint32_t ssrc;
|
||||
uint32_t extended_max;
|
||||
uint8_t fraction_loss;
|
||||
uint32_t cumulative_loss;
|
||||
};
|
||||
|
||||
PacketBuilder()
|
||||
: pos_(0),
|
||||
pos_of_len_(0) {
|
||||
@ -42,7 +56,7 @@ class PacketBuilder {
|
||||
void Add8(uint8_t byte) {
|
||||
EXPECT_LT(pos_, kMaxPacketSize - 1);
|
||||
buffer_[pos_] = byte;
|
||||
++ pos_;
|
||||
++pos_;
|
||||
}
|
||||
|
||||
void Add16(uint16_t word) {
|
||||
@ -93,11 +107,30 @@ class PacketBuilder {
|
||||
}
|
||||
|
||||
void AddRrPacket(uint32_t sender_ssrc, uint32_t rtp_ssrc,
|
||||
uint32_t extended_max) {
|
||||
AddRtcpHeader(201, 1);
|
||||
uint32_t extended_max, uint8_t fraction_loss,
|
||||
uint32_t cumulative_loss) {
|
||||
ReportBlock report_block(rtp_ssrc, extended_max, fraction_loss,
|
||||
cumulative_loss);
|
||||
std::list<ReportBlock> report_block_vector(&report_block,
|
||||
&report_block + 1);
|
||||
AddRrPacketMultipleReportBlocks(sender_ssrc, report_block_vector);
|
||||
}
|
||||
|
||||
void AddRrPacketMultipleReportBlocks(
|
||||
uint32_t sender_ssrc, const std::list<ReportBlock>& report_blocks) {
|
||||
AddRtcpHeader(201, report_blocks.size());
|
||||
Add32(sender_ssrc);
|
||||
for (std::list<ReportBlock>::const_iterator it = report_blocks.begin();
|
||||
it != report_blocks.end(); ++it) {
|
||||
AddReportBlock(it->ssrc, it->extended_max, it->fraction_loss,
|
||||
it->cumulative_loss);
|
||||
}
|
||||
}
|
||||
|
||||
void AddReportBlock(uint32_t rtp_ssrc, uint32_t extended_max,
|
||||
uint8_t fraction_loss, uint32_t cumulative_loss) {
|
||||
Add32(rtp_ssrc);
|
||||
Add32(0); // No loss.
|
||||
Add32((fraction_loss << 24) + cumulative_loss);
|
||||
Add32(extended_max);
|
||||
Add32(0); // Jitter.
|
||||
Add32(0); // Last SR.
|
||||
@ -211,12 +244,8 @@ class RtcpReceiverTest : public ::testing::Test {
|
||||
rtcp_packet_info_.applicationSubType =
|
||||
rtcpPacketInformation.applicationSubType;
|
||||
rtcp_packet_info_.applicationName = rtcpPacketInformation.applicationName;
|
||||
rtcp_packet_info_.reportBlock = rtcpPacketInformation.reportBlock;
|
||||
rtcp_packet_info_.fractionLost = rtcpPacketInformation.fractionLost;
|
||||
rtcp_packet_info_.roundTripTime = rtcpPacketInformation.roundTripTime;
|
||||
rtcp_packet_info_.lastReceivedExtendedHighSeqNum =
|
||||
rtcpPacketInformation.lastReceivedExtendedHighSeqNum;
|
||||
rtcp_packet_info_.jitter = rtcpPacketInformation.jitter;
|
||||
rtcp_packet_info_.report_blocks = rtcpPacketInformation.report_blocks;
|
||||
rtcp_packet_info_.rtt = rtcpPacketInformation.rtt;
|
||||
rtcp_packet_info_.interArrivalJitter =
|
||||
rtcpPacketInformation.interArrivalJitter;
|
||||
rtcp_packet_info_.sliPictureId = rtcpPacketInformation.sliPictureId;
|
||||
@ -263,7 +292,9 @@ TEST_F(RtcpReceiverTest, ReceiveReportTimeout) {
|
||||
const uint32_t kSourceSsrc = 0x40506;
|
||||
const int64_t kRtcpIntervalMs = 1000;
|
||||
|
||||
rtcp_receiver_->SetSSRC(kSourceSsrc);
|
||||
std::set<uint32_t> ssrcs;
|
||||
ssrcs.insert(kSourceSsrc);
|
||||
rtcp_receiver_->SetSsrcs(kSourceSsrc, ssrcs);
|
||||
|
||||
uint32_t sequence_number = 1234;
|
||||
system_clock_.AdvanceTimeMilliseconds(3 * kRtcpIntervalMs);
|
||||
@ -274,7 +305,7 @@ TEST_F(RtcpReceiverTest, ReceiveReportTimeout) {
|
||||
|
||||
// Add a RR and advance the clock just enough to not trigger a timeout.
|
||||
PacketBuilder p1;
|
||||
p1.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number);
|
||||
p1.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number, 0, 0);
|
||||
EXPECT_EQ(0, InjectRtcpPacket(p1.packet(), p1.length()));
|
||||
system_clock_.AdvanceTimeMilliseconds(3 * kRtcpIntervalMs - 1);
|
||||
EXPECT_FALSE(rtcp_receiver_->RtcpRrTimeout(kRtcpIntervalMs));
|
||||
@ -283,7 +314,7 @@ TEST_F(RtcpReceiverTest, ReceiveReportTimeout) {
|
||||
// Add a RR with the same extended max as the previous RR to trigger a
|
||||
// sequence number timeout, but not a RR timeout.
|
||||
PacketBuilder p2;
|
||||
p2.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number);
|
||||
p2.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number, 0, 0);
|
||||
EXPECT_EQ(0, InjectRtcpPacket(p2.packet(), p2.length()));
|
||||
system_clock_.AdvanceTimeMilliseconds(2);
|
||||
EXPECT_FALSE(rtcp_receiver_->RtcpRrTimeout(kRtcpIntervalMs));
|
||||
@ -301,7 +332,7 @@ TEST_F(RtcpReceiverTest, ReceiveReportTimeout) {
|
||||
// Add a new RR with increase sequence number to reset timers.
|
||||
PacketBuilder p3;
|
||||
sequence_number++;
|
||||
p2.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number);
|
||||
p2.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number, 0, 0);
|
||||
EXPECT_EQ(0, InjectRtcpPacket(p2.packet(), p2.length()));
|
||||
EXPECT_FALSE(rtcp_receiver_->RtcpRrTimeout(kRtcpIntervalMs));
|
||||
EXPECT_FALSE(rtcp_receiver_->RtcpRrSequenceNumberTimeout(kRtcpIntervalMs));
|
||||
@ -309,7 +340,7 @@ TEST_F(RtcpReceiverTest, ReceiveReportTimeout) {
|
||||
// Verify we can get a timeout again once we've received new RR.
|
||||
system_clock_.AdvanceTimeMilliseconds(2 * kRtcpIntervalMs);
|
||||
PacketBuilder p4;
|
||||
p4.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number);
|
||||
p4.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number, 0, 0);
|
||||
EXPECT_EQ(0, InjectRtcpPacket(p4.packet(), p4.length()));
|
||||
system_clock_.AdvanceTimeMilliseconds(kRtcpIntervalMs + 1);
|
||||
EXPECT_FALSE(rtcp_receiver_->RtcpRrTimeout(kRtcpIntervalMs));
|
||||
@ -323,11 +354,47 @@ TEST_F(RtcpReceiverTest, TmmbrReceivedWithNoIncomingPacket) {
|
||||
EXPECT_EQ(-1, rtcp_receiver_->TMMBRReceived(0, 0, NULL));
|
||||
}
|
||||
|
||||
TEST_F(RtcpReceiverTest, TwoReportBlocks) {
|
||||
const uint32_t kSenderSsrc = 0x10203;
|
||||
const int kNumSsrcs = 2;
|
||||
const uint32_t kSourceSsrcs[kNumSsrcs] = {0x40506, 0x50607};
|
||||
uint32_t sequence_numbers[kNumSsrcs] = {10, 12423};
|
||||
|
||||
std::set<uint32_t> ssrcs(kSourceSsrcs, kSourceSsrcs + kNumSsrcs);
|
||||
rtcp_receiver_->SetSsrcs(kSourceSsrcs[0], ssrcs);
|
||||
|
||||
PacketBuilder packet;
|
||||
std::list<PacketBuilder::ReportBlock> report_blocks;
|
||||
report_blocks.push_back(PacketBuilder::ReportBlock(
|
||||
kSourceSsrcs[0], sequence_numbers[0], 10, 5));
|
||||
report_blocks.push_back(PacketBuilder::ReportBlock(
|
||||
kSourceSsrcs[1], sequence_numbers[1], 0, 0));
|
||||
packet.AddRrPacketMultipleReportBlocks(kSenderSsrc, report_blocks);
|
||||
EXPECT_EQ(0, InjectRtcpPacket(packet.packet(), packet.length()));
|
||||
ASSERT_EQ(2u, rtcp_packet_info_.report_blocks.size());
|
||||
EXPECT_EQ(10, rtcp_packet_info_.report_blocks.front().fractionLost);
|
||||
EXPECT_EQ(0, rtcp_packet_info_.report_blocks.back().fractionLost);
|
||||
|
||||
PacketBuilder packet2;
|
||||
report_blocks.clear();
|
||||
report_blocks.push_back(PacketBuilder::ReportBlock(
|
||||
kSourceSsrcs[0], sequence_numbers[0], 0, 0));
|
||||
report_blocks.push_back(PacketBuilder::ReportBlock(
|
||||
kSourceSsrcs[1], sequence_numbers[1], 20, 10));
|
||||
packet2.AddRrPacketMultipleReportBlocks(kSenderSsrc, report_blocks);
|
||||
EXPECT_EQ(0, InjectRtcpPacket(packet2.packet(), packet2.length()));
|
||||
ASSERT_EQ(2u, rtcp_packet_info_.report_blocks.size());
|
||||
EXPECT_EQ(0, rtcp_packet_info_.report_blocks.front().fractionLost);
|
||||
EXPECT_EQ(20, rtcp_packet_info_.report_blocks.back().fractionLost);
|
||||
}
|
||||
|
||||
TEST_F(RtcpReceiverTest, TmmbrPacketAccepted) {
|
||||
const uint32_t kMediaFlowSsrc = 0x2040608;
|
||||
const uint32_t kSenderSsrc = 0x10203;
|
||||
const uint32_t kMediaRecipientSsrc = 0x101;
|
||||
rtcp_receiver_->SetSSRC(kMediaFlowSsrc); // Matches "media source" above.
|
||||
std::set<uint32_t> ssrcs;
|
||||
ssrcs.insert(kMediaFlowSsrc); // Matches "media source" above.
|
||||
rtcp_receiver_->SetSsrcs(kMediaFlowSsrc, ssrcs);
|
||||
|
||||
PacketBuilder p;
|
||||
p.AddSrPacket(kSenderSsrc);
|
||||
@ -362,7 +429,9 @@ TEST_F(RtcpReceiverTest, TmmbrPacketNotForUsIgnored) {
|
||||
p.Add32(kOtherMediaFlowSsrc); // This SSRC is not what we're sending.
|
||||
p.AddTmmbrBandwidth(30000, 0, 0);
|
||||
|
||||
rtcp_receiver_->SetSSRC(kMediaFlowSsrc);
|
||||
std::set<uint32_t> ssrcs;
|
||||
ssrcs.insert(kMediaFlowSsrc);
|
||||
rtcp_receiver_->SetSsrcs(kMediaFlowSsrc, ssrcs);
|
||||
EXPECT_EQ(0, InjectRtcpPacket(p.packet(), p.length()));
|
||||
EXPECT_EQ(0, rtcp_receiver_->TMMBRReceived(0, 0, NULL));
|
||||
}
|
||||
@ -371,7 +440,9 @@ TEST_F(RtcpReceiverTest, TmmbrPacketZeroRateIgnored) {
|
||||
const uint32_t kMediaFlowSsrc = 0x2040608;
|
||||
const uint32_t kSenderSsrc = 0x10203;
|
||||
const uint32_t kMediaRecipientSsrc = 0x101;
|
||||
rtcp_receiver_->SetSSRC(kMediaFlowSsrc); // Matches "media source" above.
|
||||
std::set<uint32_t> ssrcs;
|
||||
ssrcs.insert(kMediaFlowSsrc); // Matches "media source" above.
|
||||
rtcp_receiver_->SetSsrcs(kMediaFlowSsrc, ssrcs);
|
||||
|
||||
PacketBuilder p;
|
||||
p.AddSrPacket(kSenderSsrc);
|
||||
@ -390,7 +461,9 @@ TEST_F(RtcpReceiverTest, TmmbrThreeConstraintsTimeOut) {
|
||||
const uint32_t kMediaFlowSsrc = 0x2040608;
|
||||
const uint32_t kSenderSsrc = 0x10203;
|
||||
const uint32_t kMediaRecipientSsrc = 0x101;
|
||||
rtcp_receiver_->SetSSRC(kMediaFlowSsrc); // Matches "media source" above.
|
||||
std::set<uint32_t> ssrcs;
|
||||
ssrcs.insert(kMediaFlowSsrc); // Matches "media source" above.
|
||||
rtcp_receiver_->SetSsrcs(kMediaFlowSsrc, ssrcs);
|
||||
|
||||
// Inject 3 packets "from" kMediaRecipientSsrc, Ssrc+1, Ssrc+2.
|
||||
// The times of arrival are starttime + 0, starttime + 5 and starttime + 10.
|
||||
|
@ -246,12 +246,8 @@ class TestTransport : public Transport,
|
||||
rtcp_packet_info_.applicationSubType =
|
||||
rtcpPacketInformation.applicationSubType;
|
||||
rtcp_packet_info_.applicationName = rtcpPacketInformation.applicationName;
|
||||
rtcp_packet_info_.reportBlock = rtcpPacketInformation.reportBlock;
|
||||
rtcp_packet_info_.fractionLost = rtcpPacketInformation.fractionLost;
|
||||
rtcp_packet_info_.roundTripTime = rtcpPacketInformation.roundTripTime;
|
||||
rtcp_packet_info_.lastReceivedExtendedHighSeqNum =
|
||||
rtcpPacketInformation.lastReceivedExtendedHighSeqNum;
|
||||
rtcp_packet_info_.jitter = rtcpPacketInformation.jitter;
|
||||
rtcp_packet_info_.report_blocks = rtcpPacketInformation.report_blocks;
|
||||
rtcp_packet_info_.rtt = rtcpPacketInformation.rtt;
|
||||
rtcp_packet_info_.interArrivalJitter =
|
||||
rtcpPacketInformation.interArrivalJitter;
|
||||
rtcp_packet_info_.sliPictureId = rtcpPacketInformation.sliPictureId;
|
||||
|
@ -111,10 +111,10 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const Configuration& configuration)
|
||||
configuration.rtcp_feedback);
|
||||
rtcp_sender_.RegisterSendTransport(configuration.outgoing_transport);
|
||||
|
||||
// Make sure that RTCP objects are aware of our SSRC
|
||||
// Make sure that RTCP objects are aware of our SSRC.
|
||||
uint32_t SSRC = rtp_sender_.SSRC();
|
||||
rtcp_sender_.SetSSRC(SSRC);
|
||||
rtcp_receiver_.SetSSRC(SSRC);
|
||||
SetRtcpReceiverSsrcs(SSRC);
|
||||
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id_, "%s created", __FUNCTION__);
|
||||
}
|
||||
@ -261,6 +261,8 @@ int32_t ModuleRtpRtcpImpl::Process() {
|
||||
int32_t ModuleRtpRtcpImpl::SetRTXSendStatus(RtxMode mode, bool set_ssrc,
|
||||
uint32_t ssrc) {
|
||||
rtp_sender_.SetRTXStatus(mode, set_ssrc, ssrc);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -410,8 +412,9 @@ int32_t ModuleRtpRtcpImpl::SetSSRC(const uint32_t ssrc) {
|
||||
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id_, "SetSSRC(%d)", ssrc);
|
||||
|
||||
rtp_sender_.SetSSRC(ssrc);
|
||||
rtcp_receiver_.SetSSRC(ssrc);
|
||||
rtcp_sender_.SetSSRC(ssrc);
|
||||
SetRtcpReceiverSsrcs(ssrc);
|
||||
|
||||
return 0; // TODO(pwestin): change to void.
|
||||
}
|
||||
|
||||
@ -510,8 +513,9 @@ int32_t ModuleRtpRtcpImpl::SetSendingStatus(const bool sending) {
|
||||
// Make sure that RTCP objects are aware of our SSRC (it could have changed
|
||||
// Due to collision)
|
||||
uint32_t SSRC = rtp_sender_.SSRC();
|
||||
rtcp_receiver_.SetSSRC(SSRC);
|
||||
rtcp_sender_.SetSSRC(SSRC);
|
||||
SetRtcpReceiverSsrcs(SSRC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
@ -1459,7 +1463,7 @@ void ModuleRtpRtcpImpl::SetRemoteSSRC(const uint32_t ssrc) {
|
||||
}
|
||||
// Change local SSRC and inform all objects about the new SSRC.
|
||||
rtcp_sender_.SetSSRC(new_ssrc);
|
||||
rtcp_receiver_.SetSSRC(new_ssrc);
|
||||
SetRtcpReceiverSsrcs(new_ssrc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1587,4 +1591,17 @@ int64_t ModuleRtpRtcpImpl::RtcpReportInterval() {
|
||||
else
|
||||
return RTCP_INTERVAL_VIDEO_MS;
|
||||
}
|
||||
|
||||
void ModuleRtpRtcpImpl::SetRtcpReceiverSsrcs(uint32_t main_ssrc) {
|
||||
std::set<uint32_t> ssrcs;
|
||||
ssrcs.insert(main_ssrc);
|
||||
RtxMode rtx_mode = kRtxOff;
|
||||
uint32_t rtx_ssrc = 0;
|
||||
int rtx_payload_type = 0;
|
||||
rtp_sender_.RTXStatus(&rtx_mode, &rtx_ssrc, &rtx_payload_type);
|
||||
if (rtx_mode != kRtxOff)
|
||||
ssrcs.insert(rtx_ssrc);
|
||||
rtcp_receiver_.SetSsrcs(main_ssrc, ssrcs);
|
||||
}
|
||||
|
||||
} // Namespace webrtc
|
||||
|
@ -377,6 +377,7 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
|
||||
|
||||
private:
|
||||
int64_t RtcpReportInterval();
|
||||
void SetRtcpReceiverSsrcs(uint32_t main_ssrc);
|
||||
|
||||
int32_t id_;
|
||||
const bool audio_;
|
||||
|
Reference in New Issue
Block a user