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.
|
// Received RTCP receiver block.
|
||||||
virtual void OnReceivedRtcpReceiverReport(
|
virtual void OnReceivedRtcpReceiverReport(
|
||||||
const uint32_t ssrc,
|
const ReportBlockList& report_blocks,
|
||||||
const uint8_t fraction_loss,
|
uint16_t rtt,
|
||||||
const uint32_t rtt,
|
int64_t now_ms) OVERRIDE {
|
||||||
const uint32_t last_received_extended_high_seq_num,
|
if (report_blocks.empty())
|
||||||
const uint32_t now_ms) OVERRIDE {
|
return;
|
||||||
uint32_t number_of_packets = 0;
|
|
||||||
std::map<uint32_t, uint32_t>::iterator it =
|
|
||||||
ssrc_to_last_received_extended_high_seq_num_.find(ssrc);
|
|
||||||
|
|
||||||
if (it != ssrc_to_last_received_extended_high_seq_num_.end()) {
|
int fraction_lost_aggregate = 0;
|
||||||
number_of_packets = last_received_extended_high_seq_num - it->second;
|
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;
|
||||||
|
|
||||||
|
// Update last received for this SSRC.
|
||||||
|
ssrc_to_last_received_extended_high_seq_num_[it->sourceSSRC] =
|
||||||
|
it->extendedHighSeqNum;
|
||||||
}
|
}
|
||||||
// Update last received for this SSRC.
|
if (total_number_of_packets == 0)
|
||||||
ssrc_to_last_received_extended_high_seq_num_[ssrc] =
|
fraction_lost_aggregate = 0;
|
||||||
last_received_extended_high_seq_num;
|
else
|
||||||
owner_->OnReceivedRtcpReceiverReport(fraction_loss, rtt, number_of_packets,
|
fraction_lost_aggregate = (fraction_lost_aggregate +
|
||||||
now_ms);
|
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:
|
private:
|
||||||
std::map<uint32_t, uint32_t> ssrc_to_last_received_extended_high_seq_num_;
|
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::BitrateObserver;
|
||||||
using webrtc::BitrateController;
|
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 {
|
class TestBitrateObserver: public BitrateObserver {
|
||||||
public:
|
public:
|
||||||
TestBitrateObserver()
|
TestBitrateObserver()
|
||||||
@@ -73,33 +88,49 @@ TEST_F(BitrateControllerTest, OneBitrateObserverOneRtcpObserver) {
|
|||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
|
||||||
|
|
||||||
// Test start bitrate.
|
// 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(0u, bitrate_observer.last_bitrate_);
|
||||||
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
||||||
EXPECT_EQ(0u, bitrate_observer.last_rtt_);
|
EXPECT_EQ(0u, bitrate_observer.last_rtt_);
|
||||||
|
|
||||||
// Test bitrate increase 8% per second.
|
// 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(217000u, bitrate_observer.last_bitrate_);
|
||||||
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
||||||
EXPECT_EQ(50u, bitrate_observer.last_rtt_);
|
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_);
|
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_);
|
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_);
|
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_);
|
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.
|
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.
|
EXPECT_EQ(300000u, bitrate_observer.last_bitrate_); // Max cap.
|
||||||
|
|
||||||
// Test that a low REMB trigger immediately.
|
// Test that a low REMB trigger immediately.
|
||||||
@@ -124,44 +155,73 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
|
|||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
|
||||||
|
|
||||||
// Test start bitrate.
|
// Test start bitrate.
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 1, 1);
|
webrtc::ReportBlockList report_blocks;
|
||||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 100, 1, 1);
|
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(0u, bitrate_observer.last_bitrate_);
|
||||||
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
||||||
EXPECT_EQ(0u, bitrate_observer.last_rtt_);
|
EXPECT_EQ(0u, bitrate_observer.last_rtt_);
|
||||||
|
|
||||||
// Test bitrate increase 8% per second.
|
// Test bitrate increase 8% per second.
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 21, 501);
|
report_blocks.clear();
|
||||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 100, 21, 1001);
|
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(217000u, bitrate_observer.last_bitrate_);
|
||||||
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
||||||
EXPECT_EQ(100u, bitrate_observer.last_rtt_);
|
EXPECT_EQ(100u, bitrate_observer.last_rtt_);
|
||||||
|
|
||||||
// Extra report should not change estimate.
|
// 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_);
|
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_);
|
EXPECT_EQ(235360u, bitrate_observer.last_bitrate_);
|
||||||
|
|
||||||
// Second report should not change estimate.
|
// 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_);
|
EXPECT_EQ(235360u, bitrate_observer.last_bitrate_);
|
||||||
|
|
||||||
// Reports from only one bandwidth observer is ok.
|
// 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_);
|
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_);
|
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_);
|
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.
|
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.
|
EXPECT_EQ(300000u, bitrate_observer.last_bitrate_); // Max cap.
|
||||||
|
|
||||||
// Test that a low REMB trigger immediately.
|
// Test that a low REMB trigger immediately.
|
||||||
@@ -177,6 +237,78 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
|
|||||||
delete second_bandwidth_observer;
|
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) {
|
TEST_F(BitrateControllerTest, TwoBitrateObserversOneRtcpObserver) {
|
||||||
TestBitrateObserver bitrate_observer_1;
|
TestBitrateObserver bitrate_observer_1;
|
||||||
TestBitrateObserver bitrate_observer_2;
|
TestBitrateObserver bitrate_observer_2;
|
||||||
@@ -187,10 +319,14 @@ TEST_F(BitrateControllerTest, TwoBitrateObserversOneRtcpObserver) {
|
|||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
|
||||||
|
|
||||||
// Test too low start bitrate, hence lower than sum of min.
|
// 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.
|
// 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(100000u, bitrate_observer_1.last_bitrate_);
|
||||||
EXPECT_EQ(0, bitrate_observer_1.last_fraction_loss_);
|
EXPECT_EQ(0, bitrate_observer_1.last_fraction_loss_);
|
||||||
EXPECT_EQ(50u, bitrate_observer_1.last_rtt_);
|
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(0, bitrate_observer_2.last_fraction_loss_);
|
||||||
EXPECT_EQ(50u, bitrate_observer_2.last_rtt_);
|
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(112500u, bitrate_observer_1.last_bitrate_);
|
||||||
EXPECT_EQ(212500u, bitrate_observer_2.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(126000u, bitrate_observer_1.last_bitrate_);
|
||||||
EXPECT_EQ(226000u, bitrate_observer_2.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(140580u, bitrate_observer_1.last_bitrate_);
|
||||||
EXPECT_EQ(240580u, bitrate_observer_2.last_bitrate_);
|
EXPECT_EQ(240580u, bitrate_observer_2.last_bitrate_);
|
||||||
|
|
||||||
// Check that the bitrate sum honor our REMB.
|
// 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(150000u, bitrate_observer_1.last_bitrate_);
|
||||||
EXPECT_EQ(250000u, bitrate_observer_2.last_bitrate_);
|
EXPECT_EQ(250000u, bitrate_observer_2.last_bitrate_);
|
||||||
|
|
||||||
// Remove REMB cap, higher than sum of max.
|
// Remove REMB cap, higher than sum of max.
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(700000);
|
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(166500u, bitrate_observer_1.last_bitrate_);
|
||||||
EXPECT_EQ(266500u, bitrate_observer_2.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(184320u, bitrate_observer_1.last_bitrate_);
|
||||||
EXPECT_EQ(284320u, bitrate_observer_2.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(207130u, bitrate_observer_1.last_bitrate_);
|
||||||
EXPECT_EQ(300000u, bitrate_observer_2.last_bitrate_); // Max cap.
|
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(248700u, bitrate_observer_1.last_bitrate_);
|
||||||
EXPECT_EQ(300000u, bitrate_observer_2.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(293596u, bitrate_observer_1.last_bitrate_);
|
||||||
EXPECT_EQ(300000u, bitrate_observer_2.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_1.last_bitrate_); // Max cap.
|
||||||
EXPECT_EQ(300000u, bitrate_observer_2.last_bitrate_);
|
EXPECT_EQ(300000u, bitrate_observer_2.last_bitrate_);
|
||||||
|
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
#define WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_RTCP_DEFINES_H_
|
#define WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_RTCP_DEFINES_H_
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
#include "webrtc/modules/interface/module_common_types.h"
|
#include "webrtc/modules/interface/module_common_types.h"
|
||||||
#include "webrtc/system_wrappers/interface/clock.h"
|
#include "webrtc/system_wrappers/interface/clock.h"
|
||||||
@@ -142,19 +143,42 @@ struct RTCPSenderInfo
|
|||||||
uint32_t sendOctetCount;
|
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.
|
// Fields as described by RFC 3550 6.4.2.
|
||||||
uint32_t remoteSSRC; // SSRC of sender of this report.
|
uint32_t remoteSSRC; // SSRC of sender of this report.
|
||||||
uint32_t sourceSSRC; // SSRC of the RTP packet sender.
|
uint32_t sourceSSRC; // SSRC of the RTP packet sender.
|
||||||
uint8_t fractionLost;
|
uint8_t fractionLost;
|
||||||
uint32_t cumulativeLost; // 24 bits valid
|
uint32_t cumulativeLost; // 24 bits valid.
|
||||||
uint32_t extendedHighSeqNum;
|
uint32_t extendedHighSeqNum;
|
||||||
uint32_t jitter;
|
uint32_t jitter;
|
||||||
uint32_t lastSR;
|
uint32_t lastSR;
|
||||||
uint32_t delaySinceLastSR;
|
uint32_t delaySinceLastSR;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::list<RTCPReportBlock> ReportBlockList;
|
||||||
|
|
||||||
class RtpData
|
class RtpData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -249,11 +273,9 @@ class RtcpBandwidthObserver {
|
|||||||
virtual void OnReceivedEstimatedBitrate(const uint32_t bitrate) = 0;
|
virtual void OnReceivedEstimatedBitrate(const uint32_t bitrate) = 0;
|
||||||
|
|
||||||
virtual void OnReceivedRtcpReceiverReport(
|
virtual void OnReceivedRtcpReceiverReport(
|
||||||
const uint32_t ssrc,
|
const ReportBlockList& report_blocks,
|
||||||
const uint8_t fraction_loss,
|
uint16_t rtt,
|
||||||
const uint32_t rtt,
|
int64_t now_ms) = 0;
|
||||||
const uint32_t last_received_extended_high_seqNum,
|
|
||||||
const uint32_t now_ms) = 0;
|
|
||||||
|
|
||||||
virtual ~RtcpBandwidthObserver() {}
|
virtual ~RtcpBandwidthObserver() {}
|
||||||
};
|
};
|
||||||
|
@@ -46,7 +46,7 @@ RTCPReceiver::RTCPReceiver(const int32_t id, Clock* clock,
|
|||||||
_cbRtcpIntraFrameObserver(NULL),
|
_cbRtcpIntraFrameObserver(NULL),
|
||||||
_criticalSectionRTCPReceiver(
|
_criticalSectionRTCPReceiver(
|
||||||
CriticalSectionWrapper::CreateCriticalSection()),
|
CriticalSectionWrapper::CreateCriticalSection()),
|
||||||
_SSRC(0),
|
main_ssrc_(0),
|
||||||
_remoteSSRC(0),
|
_remoteSSRC(0),
|
||||||
_remoteSenderInfo(),
|
_remoteSenderInfo(),
|
||||||
_lastReceivedSRNTPsecs(0),
|
_lastReceivedSRNTPsecs(0),
|
||||||
@@ -156,18 +156,19 @@ void RTCPReceiver::RegisterRtcpObservers(
|
|||||||
_cbRtcpFeedback = feedback_callback;
|
_cbRtcpFeedback = feedback_callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RTCPReceiver::SetSsrcs(uint32_t main_ssrc,
|
||||||
void RTCPReceiver::SetSSRC(const uint32_t ssrc) {
|
const std::set<uint32_t>& registered_ssrcs) {
|
||||||
uint32_t old_ssrc = 0;
|
uint32_t old_ssrc = 0;
|
||||||
{
|
{
|
||||||
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
|
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
|
||||||
old_ssrc = _SSRC;
|
old_ssrc = main_ssrc_;
|
||||||
_SSRC = ssrc;
|
main_ssrc_ = main_ssrc;
|
||||||
|
registered_ssrcs_ = registered_ssrcs;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
CriticalSectionScoped lock(_criticalSectionFeedbacks);
|
CriticalSectionScoped lock(_criticalSectionFeedbacks);
|
||||||
if (_cbRtcpIntraFrameObserver && old_ssrc != ssrc) {
|
if (_cbRtcpIntraFrameObserver && old_ssrc != main_ssrc) {
|
||||||
_cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, ssrc);
|
_cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, main_ssrc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -405,7 +406,7 @@ RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
|
|||||||
{
|
{
|
||||||
TRACE_EVENT_INSTANT2("webrtc_rtp", "SR",
|
TRACE_EVENT_INSTANT2("webrtc_rtp", "SR",
|
||||||
"remote_ssrc", remoteSSRC,
|
"remote_ssrc", remoteSSRC,
|
||||||
"ssrc", _SSRC);
|
"ssrc", main_ssrc_);
|
||||||
|
|
||||||
if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
|
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",
|
TRACE_EVENT_INSTANT2("webrtc_rtp", "RR",
|
||||||
"remote_ssrc", remoteSSRC,
|
"remote_ssrc", remoteSSRC,
|
||||||
"ssrc", _SSRC);
|
"ssrc", main_ssrc_);
|
||||||
|
|
||||||
rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
|
rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
|
||||||
}
|
}
|
||||||
@@ -467,7 +468,8 @@ RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
|
|||||||
// which the information in this reception report block pertains.
|
// which the information in this reception report block pertains.
|
||||||
|
|
||||||
// Filter out all report blocks that are not for us.
|
// 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.
|
// This block is not for us ignore it.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -564,11 +566,7 @@ RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
|
|||||||
|
|
||||||
TRACE_COUNTER_ID1("webrtc_rtp", "RR_RTT", rb.SSRC, RTT);
|
TRACE_COUNTER_ID1("webrtc_rtp", "RR_RTT", rb.SSRC, RTT);
|
||||||
|
|
||||||
// rtcpPacketInformation
|
rtcpPacketInformation.AddReportInfo(*reportBlock);
|
||||||
rtcpPacketInformation.AddReportInfo(
|
|
||||||
reportBlock->remoteReceiveBlock.fractionLost, (uint16_t) RTT,
|
|
||||||
reportBlock->remoteReceiveBlock.extendedHighSeqNum,
|
|
||||||
reportBlock->remoteReceiveBlock.jitter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RTCPReportBlockInformation*
|
RTCPReportBlockInformation*
|
||||||
@@ -757,7 +755,7 @@ int32_t RTCPReceiver::BoundingSet(bool &tmmbrOwner, TMMBRSet* boundingSetRec) {
|
|||||||
receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
|
receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
|
||||||
for(uint32_t i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
|
for(uint32_t i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
|
||||||
i++) {
|
i++) {
|
||||||
if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == _SSRC) {
|
if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == main_ssrc_) {
|
||||||
// owner of bounding set
|
// owner of bounding set
|
||||||
tmmbrOwner = true;
|
tmmbrOwner = true;
|
||||||
}
|
}
|
||||||
@@ -799,7 +797,7 @@ RTCPReceiver::HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser,
|
|||||||
RTCPPacketInformation& rtcpPacketInformation)
|
RTCPPacketInformation& rtcpPacketInformation)
|
||||||
{
|
{
|
||||||
const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
|
const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
|
||||||
if (_SSRC != rtcpPacket.NACK.MediaSSRC)
|
if (main_ssrc_ != rtcpPacket.NACK.MediaSSRC)
|
||||||
{
|
{
|
||||||
// Not to us.
|
// Not to us.
|
||||||
rtcpParser.Iterate();
|
rtcpParser.Iterate();
|
||||||
@@ -879,7 +877,7 @@ RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser,
|
|||||||
|
|
||||||
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
|
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
|
||||||
|
|
||||||
if(rtcpPacket.XRVOIPMetricItem.SSRC == _SSRC)
|
if(rtcpPacket.XRVOIPMetricItem.SSRC == main_ssrc_)
|
||||||
{
|
{
|
||||||
// Store VoIP metrics block if it's about me
|
// Store VoIP metrics block if it's about me
|
||||||
// from OriginatorSSRC do we filter it?
|
// from OriginatorSSRC do we filter it?
|
||||||
@@ -918,7 +916,7 @@ RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser,
|
|||||||
void RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser,
|
void RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser,
|
||||||
RTCPPacketInformation& rtcpPacketInformation) {
|
RTCPPacketInformation& rtcpPacketInformation) {
|
||||||
const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
|
const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
|
||||||
if (_SSRC == rtcpPacket.PLI.MediaSSRC) {
|
if (main_ssrc_ == rtcpPacket.PLI.MediaSSRC) {
|
||||||
TRACE_EVENT_INSTANT0("webrtc_rtp", "PLI");
|
TRACE_EVENT_INSTANT0("webrtc_rtp", "PLI");
|
||||||
|
|
||||||
// Received a signal that we need to send a new key frame.
|
// Received a signal that we need to send a new key frame.
|
||||||
@@ -977,7 +975,7 @@ RTCPReceiver::HandleTMMBRItem(RTCPReceiveInformation& receiveInfo,
|
|||||||
RTCPPacketInformation& rtcpPacketInformation,
|
RTCPPacketInformation& rtcpPacketInformation,
|
||||||
const uint32_t senderSSRC)
|
const uint32_t senderSSRC)
|
||||||
{
|
{
|
||||||
if (_SSRC == rtcpPacket.TMMBRItem.SSRC &&
|
if (main_ssrc_ == rtcpPacket.TMMBRItem.SSRC &&
|
||||||
rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0)
|
rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0)
|
||||||
{
|
{
|
||||||
receiveInfo.InsertTMMBRItem(senderSSRC, rtcpPacket.TMMBRItem,
|
receiveInfo.InsertTMMBRItem(senderSSRC, rtcpPacket.TMMBRItem,
|
||||||
@@ -1160,7 +1158,7 @@ void RTCPReceiver::HandleFIRItem(RTCPReceiveInformation* receiveInfo,
|
|||||||
const RTCPUtility::RTCPPacket& rtcpPacket,
|
const RTCPUtility::RTCPPacket& rtcpPacket,
|
||||||
RTCPPacketInformation& rtcpPacketInformation) {
|
RTCPPacketInformation& rtcpPacketInformation) {
|
||||||
// Is it our sender that is requested to generate a new keyframe
|
// Is it our sender that is requested to generate a new keyframe
|
||||||
if (_SSRC != rtcpPacket.FIRItem.SSRC) {
|
if (main_ssrc_ != rtcpPacket.FIRItem.SSRC) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it
|
// 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.
|
// We don't want to hold this critsect when triggering the callbacks below.
|
||||||
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
|
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
|
||||||
local_ssrc = _SSRC;
|
local_ssrc = main_ssrc_;
|
||||||
}
|
}
|
||||||
if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq) {
|
if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq) {
|
||||||
_rtpRtcp.OnRequestSendReport();
|
_rtpRtcp.OnRequestSendReport();
|
||||||
@@ -1322,15 +1320,12 @@ void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
|
|||||||
_cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
|
_cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
|
||||||
rtcpPacketInformation.receiverEstimatedMaxBitrate);
|
rtcpPacketInformation.receiverEstimatedMaxBitrate);
|
||||||
}
|
}
|
||||||
if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
|
if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
|
||||||
rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) &&
|
rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) {
|
||||||
rtcpPacketInformation.reportBlock) {
|
|
||||||
int64_t now = _clock->TimeInMilliseconds();
|
int64_t now = _clock->TimeInMilliseconds();
|
||||||
_cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
|
_cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
|
||||||
rtcpPacketInformation.remoteSSRC,
|
rtcpPacketInformation.report_blocks,
|
||||||
rtcpPacketInformation.fractionLost,
|
rtcpPacketInformation.rtt,
|
||||||
rtcpPacketInformation.roundTripTime,
|
|
||||||
rtcpPacketInformation.lastReceivedExtendedHighSeqNum,
|
|
||||||
now);
|
now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
|
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
|
||||||
#include "webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h"
|
#include "webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h"
|
||||||
@@ -39,7 +40,8 @@ public:
|
|||||||
int64_t LastReceived();
|
int64_t LastReceived();
|
||||||
int64_t LastReceivedReceiverReport() const;
|
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);
|
void SetRelaySSRC( const uint32_t ssrc);
|
||||||
int32_t SetRemoteSSRC( const uint32_t ssrc);
|
int32_t SetRemoteSSRC( const uint32_t ssrc);
|
||||||
uint32_t RemoteSSRC() const;
|
uint32_t RemoteSSRC() const;
|
||||||
@@ -211,8 +213,9 @@ protected:
|
|||||||
RtcpIntraFrameObserver* _cbRtcpIntraFrameObserver;
|
RtcpIntraFrameObserver* _cbRtcpIntraFrameObserver;
|
||||||
|
|
||||||
CriticalSectionWrapper* _criticalSectionRTCPReceiver;
|
CriticalSectionWrapper* _criticalSectionRTCPReceiver;
|
||||||
uint32_t _SSRC;
|
uint32_t main_ssrc_;
|
||||||
uint32_t _remoteSSRC;
|
uint32_t _remoteSSRC;
|
||||||
|
std::set<uint32_t> registered_ssrcs_;
|
||||||
|
|
||||||
// Received send report
|
// Received send report
|
||||||
RTCPSenderInfo _remoteSenderInfo;
|
RTCPSenderInfo _remoteSenderInfo;
|
||||||
|
@@ -26,11 +26,7 @@ RTCPPacketInformation::RTCPPacketInformation()
|
|||||||
applicationName(0),
|
applicationName(0),
|
||||||
applicationData(),
|
applicationData(),
|
||||||
applicationLength(0),
|
applicationLength(0),
|
||||||
reportBlock(false),
|
rtt(0),
|
||||||
fractionLost(0),
|
|
||||||
roundTripTime(0),
|
|
||||||
lastReceivedExtendedHighSeqNum(0),
|
|
||||||
jitter(0),
|
|
||||||
interArrivalJitter(0),
|
interArrivalJitter(0),
|
||||||
sliPictureId(0),
|
sliPictureId(0),
|
||||||
rpsiPictureId(0),
|
rpsiPictureId(0),
|
||||||
@@ -95,16 +91,11 @@ RTCPPacketInformation::AddNACKPacket(const uint16_t packetID)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RTCPPacketInformation::AddReportInfo(const uint8_t fraction,
|
RTCPPacketInformation::AddReportInfo(
|
||||||
const uint16_t rtt,
|
const RTCPReportBlockInformation& report_block_info)
|
||||||
const uint32_t extendedHighSeqNum,
|
|
||||||
const uint32_t j)
|
|
||||||
{
|
{
|
||||||
reportBlock = true;
|
this->rtt = report_block_info.RTT;
|
||||||
fractionLost = fraction;
|
report_blocks.push_back(report_block_info.remoteReceiveBlock);
|
||||||
roundTripTime = rtt;
|
|
||||||
jitter = j;
|
|
||||||
lastReceivedExtendedHighSeqNum = extendedHighSeqNum;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RTCPReportBlockInformation::RTCPReportBlockInformation():
|
RTCPReportBlockInformation::RTCPReportBlockInformation():
|
||||||
|
@@ -11,7 +11,6 @@
|
|||||||
#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_HELP_H_
|
#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_HELP_H_
|
||||||
#define 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/interface/rtp_rtcp_defines.h" // RTCPReportBlock
|
||||||
#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
|
#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
|
||||||
@@ -24,58 +23,6 @@ namespace webrtc {
|
|||||||
namespace RTCPHelp
|
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
|
class RTCPReportBlockInformation
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -94,6 +41,51 @@ public:
|
|||||||
uint32_t numAverageCalcs;
|
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
|
class RTCPReceiveInformation
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@@ -33,6 +33,20 @@ class PacketBuilder {
|
|||||||
public:
|
public:
|
||||||
static const int kMaxPacketSize = 1024;
|
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()
|
PacketBuilder()
|
||||||
: pos_(0),
|
: pos_(0),
|
||||||
pos_of_len_(0) {
|
pos_of_len_(0) {
|
||||||
@@ -42,7 +56,7 @@ class PacketBuilder {
|
|||||||
void Add8(uint8_t byte) {
|
void Add8(uint8_t byte) {
|
||||||
EXPECT_LT(pos_, kMaxPacketSize - 1);
|
EXPECT_LT(pos_, kMaxPacketSize - 1);
|
||||||
buffer_[pos_] = byte;
|
buffer_[pos_] = byte;
|
||||||
++ pos_;
|
++pos_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Add16(uint16_t word) {
|
void Add16(uint16_t word) {
|
||||||
@@ -93,11 +107,30 @@ class PacketBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AddRrPacket(uint32_t sender_ssrc, uint32_t rtp_ssrc,
|
void AddRrPacket(uint32_t sender_ssrc, uint32_t rtp_ssrc,
|
||||||
uint32_t extended_max) {
|
uint32_t extended_max, uint8_t fraction_loss,
|
||||||
AddRtcpHeader(201, 1);
|
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);
|
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(rtp_ssrc);
|
||||||
Add32(0); // No loss.
|
Add32((fraction_loss << 24) + cumulative_loss);
|
||||||
Add32(extended_max);
|
Add32(extended_max);
|
||||||
Add32(0); // Jitter.
|
Add32(0); // Jitter.
|
||||||
Add32(0); // Last SR.
|
Add32(0); // Last SR.
|
||||||
@@ -211,12 +244,8 @@ class RtcpReceiverTest : public ::testing::Test {
|
|||||||
rtcp_packet_info_.applicationSubType =
|
rtcp_packet_info_.applicationSubType =
|
||||||
rtcpPacketInformation.applicationSubType;
|
rtcpPacketInformation.applicationSubType;
|
||||||
rtcp_packet_info_.applicationName = rtcpPacketInformation.applicationName;
|
rtcp_packet_info_.applicationName = rtcpPacketInformation.applicationName;
|
||||||
rtcp_packet_info_.reportBlock = rtcpPacketInformation.reportBlock;
|
rtcp_packet_info_.report_blocks = rtcpPacketInformation.report_blocks;
|
||||||
rtcp_packet_info_.fractionLost = rtcpPacketInformation.fractionLost;
|
rtcp_packet_info_.rtt = rtcpPacketInformation.rtt;
|
||||||
rtcp_packet_info_.roundTripTime = rtcpPacketInformation.roundTripTime;
|
|
||||||
rtcp_packet_info_.lastReceivedExtendedHighSeqNum =
|
|
||||||
rtcpPacketInformation.lastReceivedExtendedHighSeqNum;
|
|
||||||
rtcp_packet_info_.jitter = rtcpPacketInformation.jitter;
|
|
||||||
rtcp_packet_info_.interArrivalJitter =
|
rtcp_packet_info_.interArrivalJitter =
|
||||||
rtcpPacketInformation.interArrivalJitter;
|
rtcpPacketInformation.interArrivalJitter;
|
||||||
rtcp_packet_info_.sliPictureId = rtcpPacketInformation.sliPictureId;
|
rtcp_packet_info_.sliPictureId = rtcpPacketInformation.sliPictureId;
|
||||||
@@ -263,7 +292,9 @@ TEST_F(RtcpReceiverTest, ReceiveReportTimeout) {
|
|||||||
const uint32_t kSourceSsrc = 0x40506;
|
const uint32_t kSourceSsrc = 0x40506;
|
||||||
const int64_t kRtcpIntervalMs = 1000;
|
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;
|
uint32_t sequence_number = 1234;
|
||||||
system_clock_.AdvanceTimeMilliseconds(3 * kRtcpIntervalMs);
|
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.
|
// Add a RR and advance the clock just enough to not trigger a timeout.
|
||||||
PacketBuilder p1;
|
PacketBuilder p1;
|
||||||
p1.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number);
|
p1.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number, 0, 0);
|
||||||
EXPECT_EQ(0, InjectRtcpPacket(p1.packet(), p1.length()));
|
EXPECT_EQ(0, InjectRtcpPacket(p1.packet(), p1.length()));
|
||||||
system_clock_.AdvanceTimeMilliseconds(3 * kRtcpIntervalMs - 1);
|
system_clock_.AdvanceTimeMilliseconds(3 * kRtcpIntervalMs - 1);
|
||||||
EXPECT_FALSE(rtcp_receiver_->RtcpRrTimeout(kRtcpIntervalMs));
|
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
|
// Add a RR with the same extended max as the previous RR to trigger a
|
||||||
// sequence number timeout, but not a RR timeout.
|
// sequence number timeout, but not a RR timeout.
|
||||||
PacketBuilder p2;
|
PacketBuilder p2;
|
||||||
p2.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number);
|
p2.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number, 0, 0);
|
||||||
EXPECT_EQ(0, InjectRtcpPacket(p2.packet(), p2.length()));
|
EXPECT_EQ(0, InjectRtcpPacket(p2.packet(), p2.length()));
|
||||||
system_clock_.AdvanceTimeMilliseconds(2);
|
system_clock_.AdvanceTimeMilliseconds(2);
|
||||||
EXPECT_FALSE(rtcp_receiver_->RtcpRrTimeout(kRtcpIntervalMs));
|
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.
|
// Add a new RR with increase sequence number to reset timers.
|
||||||
PacketBuilder p3;
|
PacketBuilder p3;
|
||||||
sequence_number++;
|
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_EQ(0, InjectRtcpPacket(p2.packet(), p2.length()));
|
||||||
EXPECT_FALSE(rtcp_receiver_->RtcpRrTimeout(kRtcpIntervalMs));
|
EXPECT_FALSE(rtcp_receiver_->RtcpRrTimeout(kRtcpIntervalMs));
|
||||||
EXPECT_FALSE(rtcp_receiver_->RtcpRrSequenceNumberTimeout(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.
|
// Verify we can get a timeout again once we've received new RR.
|
||||||
system_clock_.AdvanceTimeMilliseconds(2 * kRtcpIntervalMs);
|
system_clock_.AdvanceTimeMilliseconds(2 * kRtcpIntervalMs);
|
||||||
PacketBuilder p4;
|
PacketBuilder p4;
|
||||||
p4.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number);
|
p4.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number, 0, 0);
|
||||||
EXPECT_EQ(0, InjectRtcpPacket(p4.packet(), p4.length()));
|
EXPECT_EQ(0, InjectRtcpPacket(p4.packet(), p4.length()));
|
||||||
system_clock_.AdvanceTimeMilliseconds(kRtcpIntervalMs + 1);
|
system_clock_.AdvanceTimeMilliseconds(kRtcpIntervalMs + 1);
|
||||||
EXPECT_FALSE(rtcp_receiver_->RtcpRrTimeout(kRtcpIntervalMs));
|
EXPECT_FALSE(rtcp_receiver_->RtcpRrTimeout(kRtcpIntervalMs));
|
||||||
@@ -323,11 +354,47 @@ TEST_F(RtcpReceiverTest, TmmbrReceivedWithNoIncomingPacket) {
|
|||||||
EXPECT_EQ(-1, rtcp_receiver_->TMMBRReceived(0, 0, NULL));
|
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) {
|
TEST_F(RtcpReceiverTest, TmmbrPacketAccepted) {
|
||||||
const uint32_t kMediaFlowSsrc = 0x2040608;
|
const uint32_t kMediaFlowSsrc = 0x2040608;
|
||||||
const uint32_t kSenderSsrc = 0x10203;
|
const uint32_t kSenderSsrc = 0x10203;
|
||||||
const uint32_t kMediaRecipientSsrc = 0x101;
|
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;
|
PacketBuilder p;
|
||||||
p.AddSrPacket(kSenderSsrc);
|
p.AddSrPacket(kSenderSsrc);
|
||||||
@@ -362,7 +429,9 @@ TEST_F(RtcpReceiverTest, TmmbrPacketNotForUsIgnored) {
|
|||||||
p.Add32(kOtherMediaFlowSsrc); // This SSRC is not what we're sending.
|
p.Add32(kOtherMediaFlowSsrc); // This SSRC is not what we're sending.
|
||||||
p.AddTmmbrBandwidth(30000, 0, 0);
|
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, InjectRtcpPacket(p.packet(), p.length()));
|
||||||
EXPECT_EQ(0, rtcp_receiver_->TMMBRReceived(0, 0, NULL));
|
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 kMediaFlowSsrc = 0x2040608;
|
||||||
const uint32_t kSenderSsrc = 0x10203;
|
const uint32_t kSenderSsrc = 0x10203;
|
||||||
const uint32_t kMediaRecipientSsrc = 0x101;
|
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;
|
PacketBuilder p;
|
||||||
p.AddSrPacket(kSenderSsrc);
|
p.AddSrPacket(kSenderSsrc);
|
||||||
@@ -390,7 +461,9 @@ TEST_F(RtcpReceiverTest, TmmbrThreeConstraintsTimeOut) {
|
|||||||
const uint32_t kMediaFlowSsrc = 0x2040608;
|
const uint32_t kMediaFlowSsrc = 0x2040608;
|
||||||
const uint32_t kSenderSsrc = 0x10203;
|
const uint32_t kSenderSsrc = 0x10203;
|
||||||
const uint32_t kMediaRecipientSsrc = 0x101;
|
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.
|
// Inject 3 packets "from" kMediaRecipientSsrc, Ssrc+1, Ssrc+2.
|
||||||
// The times of arrival are starttime + 0, starttime + 5 and starttime + 10.
|
// The times of arrival are starttime + 0, starttime + 5 and starttime + 10.
|
||||||
|
@@ -246,12 +246,8 @@ class TestTransport : public Transport,
|
|||||||
rtcp_packet_info_.applicationSubType =
|
rtcp_packet_info_.applicationSubType =
|
||||||
rtcpPacketInformation.applicationSubType;
|
rtcpPacketInformation.applicationSubType;
|
||||||
rtcp_packet_info_.applicationName = rtcpPacketInformation.applicationName;
|
rtcp_packet_info_.applicationName = rtcpPacketInformation.applicationName;
|
||||||
rtcp_packet_info_.reportBlock = rtcpPacketInformation.reportBlock;
|
rtcp_packet_info_.report_blocks = rtcpPacketInformation.report_blocks;
|
||||||
rtcp_packet_info_.fractionLost = rtcpPacketInformation.fractionLost;
|
rtcp_packet_info_.rtt = rtcpPacketInformation.rtt;
|
||||||
rtcp_packet_info_.roundTripTime = rtcpPacketInformation.roundTripTime;
|
|
||||||
rtcp_packet_info_.lastReceivedExtendedHighSeqNum =
|
|
||||||
rtcpPacketInformation.lastReceivedExtendedHighSeqNum;
|
|
||||||
rtcp_packet_info_.jitter = rtcpPacketInformation.jitter;
|
|
||||||
rtcp_packet_info_.interArrivalJitter =
|
rtcp_packet_info_.interArrivalJitter =
|
||||||
rtcpPacketInformation.interArrivalJitter;
|
rtcpPacketInformation.interArrivalJitter;
|
||||||
rtcp_packet_info_.sliPictureId = rtcpPacketInformation.sliPictureId;
|
rtcp_packet_info_.sliPictureId = rtcpPacketInformation.sliPictureId;
|
||||||
|
@@ -111,10 +111,10 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const Configuration& configuration)
|
|||||||
configuration.rtcp_feedback);
|
configuration.rtcp_feedback);
|
||||||
rtcp_sender_.RegisterSendTransport(configuration.outgoing_transport);
|
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();
|
uint32_t SSRC = rtp_sender_.SSRC();
|
||||||
rtcp_sender_.SetSSRC(SSRC);
|
rtcp_sender_.SetSSRC(SSRC);
|
||||||
rtcp_receiver_.SetSSRC(SSRC);
|
SetRtcpReceiverSsrcs(SSRC);
|
||||||
|
|
||||||
WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id_, "%s created", __FUNCTION__);
|
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,
|
int32_t ModuleRtpRtcpImpl::SetRTXSendStatus(RtxMode mode, bool set_ssrc,
|
||||||
uint32_t ssrc) {
|
uint32_t ssrc) {
|
||||||
rtp_sender_.SetRTXStatus(mode, set_ssrc, ssrc);
|
rtp_sender_.SetRTXStatus(mode, set_ssrc, ssrc);
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,8 +412,9 @@ int32_t ModuleRtpRtcpImpl::SetSSRC(const uint32_t ssrc) {
|
|||||||
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id_, "SetSSRC(%d)", ssrc);
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id_, "SetSSRC(%d)", ssrc);
|
||||||
|
|
||||||
rtp_sender_.SetSSRC(ssrc);
|
rtp_sender_.SetSSRC(ssrc);
|
||||||
rtcp_receiver_.SetSSRC(ssrc);
|
|
||||||
rtcp_sender_.SetSSRC(ssrc);
|
rtcp_sender_.SetSSRC(ssrc);
|
||||||
|
SetRtcpReceiverSsrcs(ssrc);
|
||||||
|
|
||||||
return 0; // TODO(pwestin): change to void.
|
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
|
// Make sure that RTCP objects are aware of our SSRC (it could have changed
|
||||||
// Due to collision)
|
// Due to collision)
|
||||||
uint32_t SSRC = rtp_sender_.SSRC();
|
uint32_t SSRC = rtp_sender_.SSRC();
|
||||||
rtcp_receiver_.SetSSRC(SSRC);
|
|
||||||
rtcp_sender_.SetSSRC(SSRC);
|
rtcp_sender_.SetSSRC(SSRC);
|
||||||
|
SetRtcpReceiverSsrcs(SSRC);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
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.
|
// Change local SSRC and inform all objects about the new SSRC.
|
||||||
rtcp_sender_.SetSSRC(new_ssrc);
|
rtcp_sender_.SetSSRC(new_ssrc);
|
||||||
rtcp_receiver_.SetSSRC(new_ssrc);
|
SetRtcpReceiverSsrcs(new_ssrc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1587,4 +1591,17 @@ int64_t ModuleRtpRtcpImpl::RtcpReportInterval() {
|
|||||||
else
|
else
|
||||||
return RTCP_INTERVAL_VIDEO_MS;
|
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
|
} // Namespace webrtc
|
||||||
|
@@ -377,6 +377,7 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
int64_t RtcpReportInterval();
|
int64_t RtcpReportInterval();
|
||||||
|
void SetRtcpReceiverSsrcs(uint32_t main_ssrc);
|
||||||
|
|
||||||
int32_t id_;
|
int32_t id_;
|
||||||
const bool audio_;
|
const bool audio_;
|
||||||
|
Reference in New Issue
Block a user