diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc b/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc index 43c6e172b..20cc3acee 100644 --- a/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc +++ b/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc @@ -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::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; - if (it != ssrc_to_last_received_extended_high_seq_num_.end()) { - number_of_packets = last_received_extended_high_seq_num - it->second; + 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::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. - 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); + 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 ssrc_to_last_received_extended_high_seq_num_; diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc b/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc index fcf419e8c..7abe71b51 100644 --- a/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc +++ b/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc @@ -20,6 +20,21 @@ using webrtc::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_); diff --git a/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h b/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h index 8ec9f0c8a..de5fcb2f5 100644 --- a/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h +++ b/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h @@ -12,6 +12,7 @@ #define WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_RTCP_DEFINES_H_ #include +#include #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 extendedHighSeqNum; - uint32_t jitter; - uint32_t lastSR; - uint32_t delaySinceLastSR; + 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 extendedHighSeqNum; + uint32_t jitter; + uint32_t lastSR; + uint32_t delaySinceLastSR; }; +typedef std::list 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() {} }; diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc b/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc index 6bc004491..9ab1fb69b 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc @@ -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& 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); } } diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h b/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h index 45e3b680c..014323188 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h +++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h @@ -13,6 +13,7 @@ #include #include +#include #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& 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 registered_ssrcs_; // Received send report RTCPSenderInfo _remoteSenderInfo; diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.cc b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.cc index be07c4e07..964512c4b 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.cc @@ -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(): diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h index a7ffab98a..85d3f5362 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h +++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h @@ -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 #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 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 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: diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc index d5c1120aa..b63f5ebb5 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc @@ -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 report_block_vector(&report_block, + &report_block + 1); + AddRrPacketMultipleReportBlocks(sender_ssrc, report_block_vector); + } + + void AddRrPacketMultipleReportBlocks( + uint32_t sender_ssrc, const std::list& report_blocks) { + AddRtcpHeader(201, report_blocks.size()); Add32(sender_ssrc); + for (std::list::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 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 ssrcs(kSourceSsrcs, kSourceSsrcs + kNumSsrcs); + rtcp_receiver_->SetSsrcs(kSourceSsrcs[0], ssrcs); + + PacketBuilder packet; + std::list 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 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 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 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 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. diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_sender_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_sender_unittest.cc index 3442758cb..d8d439037 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_sender_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_sender_unittest.cc @@ -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; diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc index 7d3aebe92..7c4cee7e8 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc @@ -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 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 diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h index 8f339b6d0..ada2442fe 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h @@ -377,6 +377,7 @@ class ModuleRtpRtcpImpl : public RtpRtcp { private: int64_t RtcpReportInterval(); + void SetRtcpReceiverSsrcs(uint32_t main_ssrc); int32_t id_; const bool audio_;