Add support for multiple report blocks.
Use a weighted average of fraction loss for bandwidth estimation. TEST=trybots and vie_auto_test --automated BUG=1811 R=mflodman@webrtc.org Review URL: https://webrtc-codereview.appspot.com/2198004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@4762 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
		| @@ -30,23 +30,44 @@ class RtcpBandwidthObserverImpl : public RtcpBandwidthObserver { | ||||
|   } | ||||
|   // Received RTCP receiver block. | ||||
|   virtual void OnReceivedRtcpReceiverReport( | ||||
|       const uint32_t ssrc, | ||||
|       const uint8_t fraction_loss, | ||||
|       const uint32_t rtt, | ||||
|       const uint32_t last_received_extended_high_seq_num, | ||||
|       const uint32_t now_ms) OVERRIDE { | ||||
|     uint32_t number_of_packets = 0; | ||||
|     std::map<uint32_t, uint32_t>::iterator it = | ||||
|         ssrc_to_last_received_extended_high_seq_num_.find(ssrc); | ||||
|       const ReportBlockList& report_blocks, | ||||
|       uint16_t rtt, | ||||
|       int64_t now_ms) OVERRIDE { | ||||
|     if (report_blocks.empty()) | ||||
|       return; | ||||
|  | ||||
|     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<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. | ||||
|     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<uint32_t, uint32_t> ssrc_to_last_received_extended_high_seq_num_; | ||||
|   | ||||
| @@ -20,6 +20,21 @@ using webrtc::RtcpBandwidthObserver; | ||||
| using webrtc::BitrateObserver; | ||||
| using webrtc::BitrateController; | ||||
|  | ||||
| uint8_t WeightedLoss(int num_packets1, uint8_t fraction_loss1, | ||||
|                      int num_packets2, uint8_t fraction_loss2) { | ||||
|   int weighted_sum = num_packets1 * fraction_loss1 + | ||||
|       num_packets2 * fraction_loss2; | ||||
|   int total_num_packets = num_packets1 + num_packets2; | ||||
|   return (weighted_sum + total_num_packets / 2) / total_num_packets; | ||||
| } | ||||
|  | ||||
| webrtc::RTCPReportBlock CreateReportBlock( | ||||
|     uint32_t remote_ssrc, uint32_t source_ssrc, | ||||
|     uint8_t fraction_lost, uint32_t extended_high_sequence_number) { | ||||
|   return webrtc::RTCPReportBlock(remote_ssrc, source_ssrc, fraction_lost, 0, | ||||
|                                  extended_high_sequence_number, 0, 0, 0); | ||||
| } | ||||
|  | ||||
| class TestBitrateObserver: public BitrateObserver { | ||||
|  public: | ||||
|   TestBitrateObserver() | ||||
| @@ -73,33 +88,49 @@ TEST_F(BitrateControllerTest, OneBitrateObserverOneRtcpObserver) { | ||||
|   bandwidth_observer_->OnReceivedEstimatedBitrate(400000); | ||||
|  | ||||
|   // Test start bitrate. | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 1, 1); | ||||
|   webrtc::ReportBlockList report_blocks; | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 1)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1); | ||||
|   EXPECT_EQ(0u, bitrate_observer.last_bitrate_); | ||||
|   EXPECT_EQ(0, bitrate_observer.last_fraction_loss_); | ||||
|   EXPECT_EQ(0u, bitrate_observer.last_rtt_); | ||||
|  | ||||
|   // Test bitrate increase 8% per second. | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 21, 1001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 21)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1001); | ||||
|   EXPECT_EQ(217000u, bitrate_observer.last_bitrate_); | ||||
|   EXPECT_EQ(0, bitrate_observer.last_fraction_loss_); | ||||
|   EXPECT_EQ(50u, bitrate_observer.last_rtt_); | ||||
|  | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 41, 2001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 41)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 2001); | ||||
|   EXPECT_EQ(235360u, bitrate_observer.last_bitrate_); | ||||
|  | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 61, 3001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 61)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 3001); | ||||
|   EXPECT_EQ(255189u, bitrate_observer.last_bitrate_); | ||||
|  | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 801, 4001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 801)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 4001); | ||||
|   EXPECT_EQ(276604u, bitrate_observer.last_bitrate_); | ||||
|  | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 101, 5001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 101)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 5001); | ||||
|   EXPECT_EQ(299732u, bitrate_observer.last_bitrate_); | ||||
|  | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 121, 6001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 121)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 6001); | ||||
|   EXPECT_EQ(300000u, bitrate_observer.last_bitrate_);  // Max cap. | ||||
|  | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 141, 7001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 141)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 7001); | ||||
|   EXPECT_EQ(300000u, bitrate_observer.last_bitrate_);  // Max cap. | ||||
|  | ||||
|   // Test that a low REMB trigger immediately. | ||||
| @@ -124,44 +155,73 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) { | ||||
|   bandwidth_observer_->OnReceivedEstimatedBitrate(400000); | ||||
|  | ||||
|   // Test start bitrate. | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 1, 1); | ||||
|   second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 100, 1, 1); | ||||
|   webrtc::ReportBlockList report_blocks; | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 1)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1); | ||||
|   second_bandwidth_observer->OnReceivedRtcpReceiverReport( | ||||
|       report_blocks, 100, 1); | ||||
|   EXPECT_EQ(0u, bitrate_observer.last_bitrate_); | ||||
|   EXPECT_EQ(0, bitrate_observer.last_fraction_loss_); | ||||
|   EXPECT_EQ(0u, bitrate_observer.last_rtt_); | ||||
|  | ||||
|   // Test bitrate increase 8% per second. | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 21, 501); | ||||
|   second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 100, 21, 1001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 21)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 501); | ||||
|   second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 100, | ||||
|                                                           1001); | ||||
|   EXPECT_EQ(217000u, bitrate_observer.last_bitrate_); | ||||
|   EXPECT_EQ(0, bitrate_observer.last_fraction_loss_); | ||||
|   EXPECT_EQ(100u, bitrate_observer.last_rtt_); | ||||
|  | ||||
|   // Extra report should not change estimate. | ||||
|   second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 100, 31, 1501); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 31)); | ||||
|   second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 100, | ||||
|                                                           1501); | ||||
|   EXPECT_EQ(217000u, bitrate_observer.last_bitrate_); | ||||
|  | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 41, 2001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 41)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 2001); | ||||
|   EXPECT_EQ(235360u, bitrate_observer.last_bitrate_); | ||||
|  | ||||
|   // Second report should not change estimate. | ||||
|   second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 100, 41, 2001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 41)); | ||||
|   second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 100, | ||||
|                                                           2001); | ||||
|   EXPECT_EQ(235360u, bitrate_observer.last_bitrate_); | ||||
|  | ||||
|   // Reports from only one bandwidth observer is ok. | ||||
|   second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 50, 61, 3001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 61)); | ||||
|   second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 50, | ||||
|                                                           3001); | ||||
|   EXPECT_EQ(255189u, bitrate_observer.last_bitrate_); | ||||
|  | ||||
|   second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 50, 81, 4001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 81)); | ||||
|   second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 50, | ||||
|                                                           4001); | ||||
|   EXPECT_EQ(276604u, bitrate_observer.last_bitrate_); | ||||
|  | ||||
|   second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 50, 101, 5001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 101)); | ||||
|   second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 50, | ||||
|                                                           5001); | ||||
|   EXPECT_EQ(299732u, bitrate_observer.last_bitrate_); | ||||
|  | ||||
|   second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 50, 121, 6001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 121)); | ||||
|   second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 50, | ||||
|                                                           6001); | ||||
|   EXPECT_EQ(300000u, bitrate_observer.last_bitrate_);  // Max cap. | ||||
|  | ||||
|   second_bandwidth_observer->OnReceivedRtcpReceiverReport(1, 0, 50, 141, 7001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 141)); | ||||
|   second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 50, | ||||
|                                                           7001); | ||||
|   EXPECT_EQ(300000u, bitrate_observer.last_bitrate_);  // Max cap. | ||||
|  | ||||
|   // Test that a low REMB trigger immediately. | ||||
| @@ -177,6 +237,78 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) { | ||||
|   delete second_bandwidth_observer; | ||||
| } | ||||
|  | ||||
| TEST_F(BitrateControllerTest, OneBitrateObserverMultipleReportBlocks) { | ||||
|   TestBitrateObserver bitrate_observer; | ||||
|   uint32_t sequence_number[2] = {0, 0xFF00}; | ||||
|   const uint32_t kStartBitrate = 200000; | ||||
|   const uint32_t kMinBitrate = 100000; | ||||
|   const uint32_t kMaxBitrate = 300000; | ||||
|   controller_->SetBitrateObserver(&bitrate_observer, kStartBitrate, kMinBitrate, | ||||
|                                   kMaxBitrate); | ||||
|  | ||||
|   // Receive a high REMB, test bitrate increase. | ||||
|   bandwidth_observer_->OnReceivedEstimatedBitrate(400000); | ||||
|  | ||||
|   webrtc::ReportBlockList report_blocks; | ||||
|   int64_t time_ms = 1001; | ||||
|   uint32_t last_bitrate = 0; | ||||
|   // Ramp up to max bitrate. | ||||
|   for (int i = 0; i < 6; ++i) { | ||||
|     report_blocks.push_back(CreateReportBlock(1, 2, 0, sequence_number[0])); | ||||
|     report_blocks.push_back(CreateReportBlock(1, 3, 0, sequence_number[1])); | ||||
|     bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, | ||||
|                                                       time_ms); | ||||
|     EXPECT_GT(bitrate_observer.last_bitrate_, last_bitrate); | ||||
|     EXPECT_EQ(0, bitrate_observer.last_fraction_loss_); | ||||
|     EXPECT_EQ(50u, bitrate_observer.last_rtt_); | ||||
|     last_bitrate = bitrate_observer.last_bitrate_; | ||||
|     time_ms += 1000; | ||||
|     sequence_number[0] += 20; | ||||
|     sequence_number[1] += 1; | ||||
|     report_blocks.clear(); | ||||
|   } | ||||
|  | ||||
|   EXPECT_EQ(kMaxBitrate, bitrate_observer.last_bitrate_); | ||||
|  | ||||
|   // Packet loss on the first stream. Verify that bitrate decreases. | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 50, sequence_number[0])); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 3, 0, sequence_number[1])); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms); | ||||
|   EXPECT_LT(bitrate_observer.last_bitrate_, last_bitrate); | ||||
|   EXPECT_EQ(WeightedLoss(20, 50, 1, 0), bitrate_observer.last_fraction_loss_); | ||||
|   EXPECT_EQ(50u, bitrate_observer.last_rtt_); | ||||
|   last_bitrate = bitrate_observer.last_bitrate_; | ||||
|   sequence_number[0] += 20; | ||||
|   sequence_number[1] += 20; | ||||
|   time_ms += 1000; | ||||
|   report_blocks.clear(); | ||||
|  | ||||
|   // Packet loss on the second stream. Verify that bitrate decreases. | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, sequence_number[0])); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 3, 75, sequence_number[1])); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms); | ||||
|   EXPECT_LT(bitrate_observer.last_bitrate_, last_bitrate); | ||||
|   EXPECT_EQ(WeightedLoss(20, 0, 20, 75), bitrate_observer.last_fraction_loss_); | ||||
|   EXPECT_EQ(50u, bitrate_observer.last_rtt_); | ||||
|   last_bitrate = bitrate_observer.last_bitrate_; | ||||
|   sequence_number[0] += 20; | ||||
|   sequence_number[1] += 1; | ||||
|   time_ms += 1000; | ||||
|   report_blocks.clear(); | ||||
|  | ||||
|   // All packets lost on stream with few packets, no back-off. | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 1, sequence_number[0])); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 3, 255, sequence_number[1])); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms); | ||||
|   EXPECT_EQ(bitrate_observer.last_bitrate_, last_bitrate); | ||||
|   EXPECT_EQ(WeightedLoss(20, 1, 1, 255), bitrate_observer.last_fraction_loss_); | ||||
|   EXPECT_EQ(50u, bitrate_observer.last_rtt_); | ||||
|   last_bitrate = bitrate_observer.last_bitrate_; | ||||
|   sequence_number[0] += 20; | ||||
|   sequence_number[1] += 1; | ||||
|   report_blocks.clear(); | ||||
| } | ||||
|  | ||||
| TEST_F(BitrateControllerTest, TwoBitrateObserversOneRtcpObserver) { | ||||
|   TestBitrateObserver bitrate_observer_1; | ||||
|   TestBitrateObserver bitrate_observer_2; | ||||
| @@ -187,10 +319,14 @@ TEST_F(BitrateControllerTest, TwoBitrateObserversOneRtcpObserver) { | ||||
|   bandwidth_observer_->OnReceivedEstimatedBitrate(400000); | ||||
|  | ||||
|   // Test too low start bitrate, hence lower than sum of min. | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 1, 1); | ||||
|   webrtc::ReportBlockList report_blocks; | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 1)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1); | ||||
|  | ||||
|   // Test bitrate increase 8% per second, distributed equally. | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 21, 1001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 21)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1001); | ||||
|   EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_); | ||||
|   EXPECT_EQ(0, bitrate_observer_1.last_fraction_loss_); | ||||
|   EXPECT_EQ(50u, bitrate_observer_1.last_rtt_); | ||||
| @@ -199,47 +335,67 @@ TEST_F(BitrateControllerTest, TwoBitrateObserversOneRtcpObserver) { | ||||
|   EXPECT_EQ(0, bitrate_observer_2.last_fraction_loss_); | ||||
|   EXPECT_EQ(50u, bitrate_observer_2.last_rtt_); | ||||
|  | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 41, 2001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 41)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 2001); | ||||
|   EXPECT_EQ(112500u, bitrate_observer_1.last_bitrate_); | ||||
|   EXPECT_EQ(212500u, bitrate_observer_2.last_bitrate_); | ||||
|  | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 61, 3001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 61)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 3001); | ||||
|   EXPECT_EQ(126000u, bitrate_observer_1.last_bitrate_); | ||||
|   EXPECT_EQ(226000u, bitrate_observer_2.last_bitrate_); | ||||
|  | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 81, 4001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 81)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 4001); | ||||
|   EXPECT_EQ(140580u, bitrate_observer_1.last_bitrate_); | ||||
|   EXPECT_EQ(240580u, bitrate_observer_2.last_bitrate_); | ||||
|  | ||||
|   // Check that the bitrate sum honor our REMB. | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 101, 5001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 101)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 5001); | ||||
|   EXPECT_EQ(150000u, bitrate_observer_1.last_bitrate_); | ||||
|   EXPECT_EQ(250000u, bitrate_observer_2.last_bitrate_); | ||||
|  | ||||
|   // Remove REMB cap, higher than sum of max. | ||||
|   bandwidth_observer_->OnReceivedEstimatedBitrate(700000); | ||||
|  | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 121, 6001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 121)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 6001); | ||||
|   EXPECT_EQ(166500u, bitrate_observer_1.last_bitrate_); | ||||
|   EXPECT_EQ(266500u, bitrate_observer_2.last_bitrate_); | ||||
|  | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 141, 7001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 141)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 7001); | ||||
|   EXPECT_EQ(184320u, bitrate_observer_1.last_bitrate_); | ||||
|   EXPECT_EQ(284320u, bitrate_observer_2.last_bitrate_); | ||||
|  | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 161, 8001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 161)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 8001); | ||||
|   EXPECT_EQ(207130u, bitrate_observer_1.last_bitrate_); | ||||
|   EXPECT_EQ(300000u, bitrate_observer_2.last_bitrate_);  // Max cap. | ||||
|  | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 181, 9001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 181)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 9001); | ||||
|   EXPECT_EQ(248700u, bitrate_observer_1.last_bitrate_); | ||||
|   EXPECT_EQ(300000u, bitrate_observer_2.last_bitrate_); | ||||
|  | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 201, 10001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 201)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 10001); | ||||
|   EXPECT_EQ(293596u, bitrate_observer_1.last_bitrate_); | ||||
|   EXPECT_EQ(300000u, bitrate_observer_2.last_bitrate_); | ||||
|  | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(1, 0, 50, 221, 11001); | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(CreateReportBlock(1, 2, 0, 221)); | ||||
|   bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 11001); | ||||
|   EXPECT_EQ(300000u, bitrate_observer_1.last_bitrate_);  // Max cap. | ||||
|   EXPECT_EQ(300000u, bitrate_observer_2.last_bitrate_); | ||||
|  | ||||
|   | ||||
| @@ -12,6 +12,7 @@ | ||||
| #define WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_RTCP_DEFINES_H_ | ||||
|  | ||||
| #include <stddef.h> | ||||
| #include <list> | ||||
|  | ||||
| #include "webrtc/modules/interface/module_common_types.h" | ||||
| #include "webrtc/system_wrappers/interface/clock.h" | ||||
| @@ -142,19 +143,42 @@ struct RTCPSenderInfo | ||||
|     uint32_t sendOctetCount; | ||||
| }; | ||||
|  | ||||
| struct RTCPReportBlock | ||||
| { | ||||
| struct RTCPReportBlock { | ||||
|   RTCPReportBlock() | ||||
|       : remoteSSRC(0), sourceSSRC(0), fractionLost(0), cumulativeLost(0), | ||||
|         extendedHighSeqNum(0), jitter(0), lastSR(0), | ||||
|         delaySinceLastSR(0) {} | ||||
|  | ||||
|   RTCPReportBlock(uint32_t remote_ssrc, | ||||
|                   uint32_t source_ssrc, | ||||
|                   uint8_t fraction_lost, | ||||
|                   uint32_t cumulative_lost, | ||||
|                   uint32_t extended_high_sequence_number, | ||||
|                   uint32_t jitter, | ||||
|                   uint32_t last_sender_report, | ||||
|                   uint32_t delay_since_last_sender_report) | ||||
|       : remoteSSRC(remote_ssrc), | ||||
|         sourceSSRC(source_ssrc), | ||||
|         fractionLost(fraction_lost), | ||||
|         cumulativeLost(cumulative_lost), | ||||
|         extendedHighSeqNum(extended_high_sequence_number), | ||||
|         jitter(jitter), | ||||
|         lastSR(last_sender_report), | ||||
|         delaySinceLastSR(delay_since_last_sender_report) {} | ||||
|  | ||||
|   // Fields as described by RFC 3550 6.4.2. | ||||
|     uint32_t remoteSSRC;  // SSRC of sender of this report. | ||||
|     uint32_t sourceSSRC;  // SSRC of the RTP packet sender. | ||||
|     uint8_t fractionLost; | ||||
|     uint32_t cumulativeLost;  // 24 bits valid | ||||
|     uint32_t 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<RTCPReportBlock> ReportBlockList; | ||||
|  | ||||
| class RtpData | ||||
| { | ||||
| public: | ||||
| @@ -249,11 +273,9 @@ class RtcpBandwidthObserver { | ||||
|   virtual void OnReceivedEstimatedBitrate(const uint32_t bitrate) = 0; | ||||
|  | ||||
|   virtual void OnReceivedRtcpReceiverReport( | ||||
|       const uint32_t ssrc, | ||||
|       const uint8_t fraction_loss, | ||||
|       const uint32_t rtt, | ||||
|       const uint32_t last_received_extended_high_seqNum, | ||||
|       const uint32_t now_ms) = 0; | ||||
|       const ReportBlockList& report_blocks, | ||||
|       uint16_t rtt, | ||||
|       int64_t now_ms) = 0; | ||||
|  | ||||
|   virtual ~RtcpBandwidthObserver() {} | ||||
| }; | ||||
|   | ||||
| @@ -46,7 +46,7 @@ RTCPReceiver::RTCPReceiver(const int32_t id, Clock* clock, | ||||
|     _cbRtcpIntraFrameObserver(NULL), | ||||
|     _criticalSectionRTCPReceiver( | ||||
|         CriticalSectionWrapper::CreateCriticalSection()), | ||||
|     _SSRC(0), | ||||
|     main_ssrc_(0), | ||||
|     _remoteSSRC(0), | ||||
|     _remoteSenderInfo(), | ||||
|     _lastReceivedSRNTPsecs(0), | ||||
| @@ -156,18 +156,19 @@ void RTCPReceiver::RegisterRtcpObservers( | ||||
|   _cbRtcpFeedback = feedback_callback; | ||||
| } | ||||
|  | ||||
|  | ||||
| void RTCPReceiver::SetSSRC(const uint32_t ssrc) { | ||||
| void RTCPReceiver::SetSsrcs(uint32_t main_ssrc, | ||||
|                             const std::set<uint32_t>& registered_ssrcs) { | ||||
|   uint32_t old_ssrc = 0; | ||||
|   { | ||||
|     CriticalSectionScoped lock(_criticalSectionRTCPReceiver); | ||||
|     old_ssrc = _SSRC; | ||||
|     _SSRC = ssrc; | ||||
|     old_ssrc = main_ssrc_; | ||||
|     main_ssrc_ = main_ssrc; | ||||
|     registered_ssrcs_ = registered_ssrcs; | ||||
|   } | ||||
|   { | ||||
|     CriticalSectionScoped lock(_criticalSectionFeedbacks); | ||||
|     if (_cbRtcpIntraFrameObserver && old_ssrc != ssrc) { | ||||
|       _cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, ssrc); | ||||
|     if (_cbRtcpIntraFrameObserver && old_ssrc != main_ssrc) { | ||||
|       _cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, main_ssrc); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -405,7 +406,7 @@ RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser, | ||||
|     { | ||||
|         TRACE_EVENT_INSTANT2("webrtc_rtp", "SR", | ||||
|                              "remote_ssrc", remoteSSRC, | ||||
|                              "ssrc", _SSRC); | ||||
|                              "ssrc", main_ssrc_); | ||||
|  | ||||
|         if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party | ||||
|         { | ||||
| @@ -436,7 +437,7 @@ RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser, | ||||
|     { | ||||
|         TRACE_EVENT_INSTANT2("webrtc_rtp", "RR", | ||||
|                              "remote_ssrc", remoteSSRC, | ||||
|                              "ssrc", _SSRC); | ||||
|                              "ssrc", main_ssrc_); | ||||
|  | ||||
|         rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr; | ||||
|     } | ||||
| @@ -467,7 +468,8 @@ RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket, | ||||
|   // which the information in this reception report block pertains. | ||||
|  | ||||
|   // Filter out all report blocks that are not for us. | ||||
|   if (rtcpPacket.ReportBlockItem.SSRC != _SSRC) { | ||||
|   if (registered_ssrcs_.find(rtcpPacket.ReportBlockItem.SSRC) == | ||||
|       registered_ssrcs_.end()) { | ||||
|     // This block is not for us ignore it. | ||||
|     return; | ||||
|   } | ||||
| @@ -564,11 +566,7 @@ RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket, | ||||
|  | ||||
|   TRACE_COUNTER_ID1("webrtc_rtp", "RR_RTT", rb.SSRC, RTT); | ||||
|  | ||||
|   // rtcpPacketInformation | ||||
|   rtcpPacketInformation.AddReportInfo( | ||||
|       reportBlock->remoteReceiveBlock.fractionLost, (uint16_t) RTT, | ||||
|       reportBlock->remoteReceiveBlock.extendedHighSeqNum, | ||||
|       reportBlock->remoteReceiveBlock.jitter); | ||||
|   rtcpPacketInformation.AddReportInfo(*reportBlock); | ||||
| } | ||||
|  | ||||
| RTCPReportBlockInformation* | ||||
| @@ -757,7 +755,7 @@ int32_t RTCPReceiver::BoundingSet(bool &tmmbrOwner, TMMBRSet* boundingSetRec) { | ||||
|         receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1); | ||||
|     for(uint32_t i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet(); | ||||
|         i++) { | ||||
|       if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == _SSRC) { | ||||
|       if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == main_ssrc_) { | ||||
|         // owner of bounding set | ||||
|         tmmbrOwner = true; | ||||
|       } | ||||
| @@ -799,7 +797,7 @@ RTCPReceiver::HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser, | ||||
|                          RTCPPacketInformation& rtcpPacketInformation) | ||||
| { | ||||
|     const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet(); | ||||
|     if (_SSRC != rtcpPacket.NACK.MediaSSRC) | ||||
|     if (main_ssrc_ != rtcpPacket.NACK.MediaSSRC) | ||||
|     { | ||||
|         // Not to us. | ||||
|         rtcpParser.Iterate(); | ||||
| @@ -879,7 +877,7 @@ RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser, | ||||
|  | ||||
|     CriticalSectionScoped lock(_criticalSectionRTCPReceiver); | ||||
|  | ||||
|     if(rtcpPacket.XRVOIPMetricItem.SSRC == _SSRC) | ||||
|     if(rtcpPacket.XRVOIPMetricItem.SSRC == main_ssrc_) | ||||
|     { | ||||
|         // Store VoIP metrics block if it's about me | ||||
|         // from OriginatorSSRC do we filter it? | ||||
| @@ -918,7 +916,7 @@ RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser, | ||||
| void RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser, | ||||
|                              RTCPPacketInformation& rtcpPacketInformation) { | ||||
|   const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet(); | ||||
|   if (_SSRC == rtcpPacket.PLI.MediaSSRC) { | ||||
|   if (main_ssrc_ == rtcpPacket.PLI.MediaSSRC) { | ||||
|     TRACE_EVENT_INSTANT0("webrtc_rtp", "PLI"); | ||||
|  | ||||
|     // Received a signal that we need to send a new key frame. | ||||
| @@ -977,7 +975,7 @@ RTCPReceiver::HandleTMMBRItem(RTCPReceiveInformation& receiveInfo, | ||||
|                               RTCPPacketInformation& rtcpPacketInformation, | ||||
|                               const uint32_t senderSSRC) | ||||
| { | ||||
|     if (_SSRC == rtcpPacket.TMMBRItem.SSRC && | ||||
|     if (main_ssrc_ == rtcpPacket.TMMBRItem.SSRC && | ||||
|         rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0) | ||||
|     { | ||||
|         receiveInfo.InsertTMMBRItem(senderSSRC, rtcpPacket.TMMBRItem, | ||||
| @@ -1160,7 +1158,7 @@ void RTCPReceiver::HandleFIRItem(RTCPReceiveInformation* receiveInfo, | ||||
|                                  const RTCPUtility::RTCPPacket& rtcpPacket, | ||||
|                                  RTCPPacketInformation& rtcpPacketInformation) { | ||||
|   // Is it our sender that is requested to generate a new keyframe | ||||
|   if (_SSRC != rtcpPacket.FIRItem.SSRC) { | ||||
|   if (main_ssrc_ != rtcpPacket.FIRItem.SSRC) { | ||||
|     return; | ||||
|   } | ||||
|   // rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it | ||||
| @@ -1271,7 +1269,7 @@ void RTCPReceiver::TriggerCallbacksFromRTCPPacket( | ||||
|   { | ||||
|     // We don't want to hold this critsect when triggering the callbacks below. | ||||
|     CriticalSectionScoped lock(_criticalSectionRTCPReceiver); | ||||
|     local_ssrc = _SSRC; | ||||
|     local_ssrc = main_ssrc_; | ||||
|   } | ||||
|   if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq) { | ||||
|     _rtpRtcp.OnRequestSendReport(); | ||||
| @@ -1322,15 +1320,12 @@ void RTCPReceiver::TriggerCallbacksFromRTCPPacket( | ||||
|         _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate( | ||||
|             rtcpPacketInformation.receiverEstimatedMaxBitrate); | ||||
|       } | ||||
|       if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr || | ||||
|           rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) && | ||||
|           rtcpPacketInformation.reportBlock) { | ||||
|       if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr || | ||||
|           rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) { | ||||
|         int64_t now = _clock->TimeInMilliseconds(); | ||||
|         _cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport( | ||||
|             rtcpPacketInformation.remoteSSRC, | ||||
|             rtcpPacketInformation.fractionLost, | ||||
|             rtcpPacketInformation.roundTripTime, | ||||
|             rtcpPacketInformation.lastReceivedExtendedHighSeqNum, | ||||
|             rtcpPacketInformation.report_blocks, | ||||
|             rtcpPacketInformation.rtt, | ||||
|             now); | ||||
|       } | ||||
|     } | ||||
|   | ||||
| @@ -13,6 +13,7 @@ | ||||
|  | ||||
| #include <map> | ||||
| #include <vector> | ||||
| #include <set> | ||||
|  | ||||
| #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" | ||||
| #include "webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h" | ||||
| @@ -39,7 +40,8 @@ public: | ||||
|     int64_t LastReceived(); | ||||
|     int64_t LastReceivedReceiverReport() const; | ||||
|  | ||||
|     void SetSSRC( const uint32_t ssrc); | ||||
|     void SetSsrcs(uint32_t main_ssrc, | ||||
|                   const std::set<uint32_t>& registered_ssrcs); | ||||
|     void SetRelaySSRC( const uint32_t ssrc); | ||||
|     int32_t SetRemoteSSRC( const uint32_t ssrc); | ||||
|     uint32_t RemoteSSRC() const; | ||||
| @@ -211,8 +213,9 @@ protected: | ||||
|   RtcpIntraFrameObserver* _cbRtcpIntraFrameObserver; | ||||
|  | ||||
|   CriticalSectionWrapper* _criticalSectionRTCPReceiver; | ||||
|   uint32_t          _SSRC; | ||||
|   uint32_t          main_ssrc_; | ||||
|   uint32_t          _remoteSSRC; | ||||
|   std::set<uint32_t> registered_ssrcs_; | ||||
|  | ||||
|   // Received send report | ||||
|   RTCPSenderInfo _remoteSenderInfo; | ||||
|   | ||||
| @@ -26,11 +26,7 @@ RTCPPacketInformation::RTCPPacketInformation() | ||||
|       applicationName(0), | ||||
|       applicationData(), | ||||
|       applicationLength(0), | ||||
|       reportBlock(false), | ||||
|       fractionLost(0), | ||||
|       roundTripTime(0), | ||||
|       lastReceivedExtendedHighSeqNum(0), | ||||
|       jitter(0), | ||||
|       rtt(0), | ||||
|       interArrivalJitter(0), | ||||
|       sliPictureId(0), | ||||
|       rpsiPictureId(0), | ||||
| @@ -95,16 +91,11 @@ RTCPPacketInformation::AddNACKPacket(const uint16_t packetID) | ||||
| } | ||||
|  | ||||
| void | ||||
| RTCPPacketInformation::AddReportInfo(const uint8_t fraction, | ||||
|                                      const uint16_t rtt, | ||||
|                                      const uint32_t extendedHighSeqNum, | ||||
|                                      const uint32_t j) | ||||
| RTCPPacketInformation::AddReportInfo( | ||||
|     const RTCPReportBlockInformation& report_block_info) | ||||
| { | ||||
|     reportBlock = true; | ||||
|     fractionLost = fraction; | ||||
|     roundTripTime = rtt; | ||||
|     jitter = j; | ||||
|     lastReceivedExtendedHighSeqNum = extendedHighSeqNum; | ||||
|   this->rtt = report_block_info.RTT; | ||||
|   report_blocks.push_back(report_block_info.remoteReceiveBlock); | ||||
| } | ||||
|  | ||||
| RTCPReportBlockInformation::RTCPReportBlockInformation(): | ||||
|   | ||||
| @@ -11,7 +11,6 @@ | ||||
| #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_HELP_H_ | ||||
| #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_HELP_H_ | ||||
|  | ||||
| #include <list> | ||||
|  | ||||
| #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"  // RTCPReportBlock | ||||
| #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" | ||||
| @@ -24,58 +23,6 @@ namespace webrtc { | ||||
| namespace RTCPHelp | ||||
| { | ||||
|  | ||||
| class RTCPPacketInformation | ||||
| { | ||||
| public: | ||||
|     RTCPPacketInformation(); | ||||
|     ~RTCPPacketInformation(); | ||||
|  | ||||
|     void AddVoIPMetric(const RTCPVoIPMetric*  metric); | ||||
|  | ||||
|     void AddApplicationData(const uint8_t* data, | ||||
|                             const uint16_t size); | ||||
|  | ||||
|     void AddNACKPacket(const uint16_t packetID); | ||||
|     void ResetNACKPacketIdArray(); | ||||
|  | ||||
|     void AddReportInfo(const uint8_t fractionLost, | ||||
|                        const uint16_t rtt, | ||||
|                        const uint32_t extendedHighSeqNum, | ||||
|                        const uint32_t jitter); | ||||
|  | ||||
|     uint32_t  rtcpPacketTypeFlags; // RTCPPacketTypeFlags bit field | ||||
|     uint32_t  remoteSSRC; | ||||
|  | ||||
|     std::list<uint16_t> nackSequenceNumbers; | ||||
|  | ||||
|     uint8_t   applicationSubType; | ||||
|     uint32_t  applicationName; | ||||
|     uint8_t*  applicationData; | ||||
|     uint16_t  applicationLength; | ||||
|  | ||||
|     bool            reportBlock; | ||||
|     uint8_t   fractionLost; | ||||
|     uint16_t  roundTripTime; | ||||
|     uint32_t  lastReceivedExtendedHighSeqNum; | ||||
|     uint32_t  jitter; | ||||
|  | ||||
|     uint32_t  interArrivalJitter; | ||||
|  | ||||
|     uint8_t   sliPictureId; | ||||
|     uint64_t  rpsiPictureId; | ||||
|     uint32_t  receiverEstimatedMaxBitrate; | ||||
|  | ||||
|     uint32_t ntp_secs; | ||||
|     uint32_t ntp_frac; | ||||
|     uint32_t rtp_timestamp; | ||||
|  | ||||
|     RTCPVoIPMetric*  VoIPMetric; | ||||
|  | ||||
| private: | ||||
|     DISALLOW_COPY_AND_ASSIGN(RTCPPacketInformation); | ||||
| }; | ||||
|  | ||||
|  | ||||
| class RTCPReportBlockInformation | ||||
| { | ||||
| public: | ||||
| @@ -94,6 +41,51 @@ public: | ||||
|     uint32_t    numAverageCalcs; | ||||
| }; | ||||
|  | ||||
| class RTCPPacketInformation | ||||
| { | ||||
| public: | ||||
|     RTCPPacketInformation(); | ||||
|     ~RTCPPacketInformation(); | ||||
|  | ||||
|     void AddVoIPMetric(const RTCPVoIPMetric*  metric); | ||||
|  | ||||
|     void AddApplicationData(const uint8_t* data, | ||||
|                             const uint16_t size); | ||||
|  | ||||
|     void AddNACKPacket(const uint16_t packetID); | ||||
|     void ResetNACKPacketIdArray(); | ||||
|  | ||||
|     void AddReportInfo(const RTCPReportBlockInformation& report_block_info); | ||||
|  | ||||
|     uint32_t  rtcpPacketTypeFlags; // RTCPPacketTypeFlags bit field | ||||
|     uint32_t  remoteSSRC; | ||||
|  | ||||
|     std::list<uint16_t> nackSequenceNumbers; | ||||
|  | ||||
|     uint8_t   applicationSubType; | ||||
|     uint32_t  applicationName; | ||||
|     uint8_t*  applicationData; | ||||
|     uint16_t  applicationLength; | ||||
|  | ||||
|     ReportBlockList report_blocks; | ||||
|     uint16_t rtt; | ||||
|  | ||||
|     uint32_t  interArrivalJitter; | ||||
|  | ||||
|     uint8_t   sliPictureId; | ||||
|     uint64_t  rpsiPictureId; | ||||
|     uint32_t  receiverEstimatedMaxBitrate; | ||||
|  | ||||
|     uint32_t ntp_secs; | ||||
|     uint32_t ntp_frac; | ||||
|     uint32_t rtp_timestamp; | ||||
|  | ||||
|     RTCPVoIPMetric*  VoIPMetric; | ||||
|  | ||||
| private: | ||||
|     DISALLOW_COPY_AND_ASSIGN(RTCPPacketInformation); | ||||
| }; | ||||
|  | ||||
| class RTCPReceiveInformation | ||||
| { | ||||
| public: | ||||
|   | ||||
| @@ -33,6 +33,20 @@ class PacketBuilder { | ||||
|  public: | ||||
|   static const int kMaxPacketSize = 1024; | ||||
|  | ||||
|   struct ReportBlock { | ||||
|     ReportBlock(uint32_t ssrc, uint32_t extended_max, uint8_t fraction_loss, | ||||
|                 uint32_t cumulative_loss) | ||||
|         : ssrc(ssrc), | ||||
|           extended_max(extended_max), | ||||
|           fraction_loss(fraction_loss), | ||||
|           cumulative_loss(cumulative_loss) {} | ||||
|  | ||||
|     uint32_t ssrc; | ||||
|     uint32_t extended_max; | ||||
|     uint8_t fraction_loss; | ||||
|     uint32_t cumulative_loss; | ||||
|   }; | ||||
|  | ||||
|   PacketBuilder() | ||||
|       : pos_(0), | ||||
|         pos_of_len_(0) { | ||||
| @@ -42,7 +56,7 @@ class PacketBuilder { | ||||
|   void Add8(uint8_t byte) { | ||||
|     EXPECT_LT(pos_, kMaxPacketSize - 1); | ||||
|     buffer_[pos_] = byte; | ||||
|     ++ pos_; | ||||
|     ++pos_; | ||||
|   } | ||||
|  | ||||
|   void Add16(uint16_t word) { | ||||
| @@ -93,11 +107,30 @@ class PacketBuilder { | ||||
|   } | ||||
|  | ||||
|   void AddRrPacket(uint32_t sender_ssrc, uint32_t rtp_ssrc, | ||||
|                    uint32_t extended_max) { | ||||
|     AddRtcpHeader(201, 1); | ||||
|                    uint32_t extended_max, uint8_t fraction_loss, | ||||
|                    uint32_t cumulative_loss) { | ||||
|     ReportBlock report_block(rtp_ssrc, extended_max, fraction_loss, | ||||
|                              cumulative_loss); | ||||
|     std::list<ReportBlock> report_block_vector(&report_block, | ||||
|                                                &report_block + 1); | ||||
|     AddRrPacketMultipleReportBlocks(sender_ssrc, report_block_vector); | ||||
|   } | ||||
|  | ||||
|   void AddRrPacketMultipleReportBlocks( | ||||
|       uint32_t sender_ssrc, const std::list<ReportBlock>& report_blocks) { | ||||
|     AddRtcpHeader(201, report_blocks.size()); | ||||
|     Add32(sender_ssrc); | ||||
|     for (std::list<ReportBlock>::const_iterator it = report_blocks.begin(); | ||||
|          it != report_blocks.end(); ++it) { | ||||
|       AddReportBlock(it->ssrc, it->extended_max, it->fraction_loss, | ||||
|                      it->cumulative_loss); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   void AddReportBlock(uint32_t rtp_ssrc, uint32_t extended_max, | ||||
|                       uint8_t fraction_loss, uint32_t cumulative_loss) { | ||||
|     Add32(rtp_ssrc); | ||||
|     Add32(0);  // No loss. | ||||
|     Add32((fraction_loss << 24) + cumulative_loss); | ||||
|     Add32(extended_max); | ||||
|     Add32(0);  // Jitter. | ||||
|     Add32(0);  // Last SR. | ||||
| @@ -211,12 +244,8 @@ class RtcpReceiverTest : public ::testing::Test { | ||||
|     rtcp_packet_info_.applicationSubType = | ||||
|         rtcpPacketInformation.applicationSubType; | ||||
|     rtcp_packet_info_.applicationName = rtcpPacketInformation.applicationName; | ||||
|     rtcp_packet_info_.reportBlock = rtcpPacketInformation.reportBlock; | ||||
|     rtcp_packet_info_.fractionLost = rtcpPacketInformation.fractionLost; | ||||
|     rtcp_packet_info_.roundTripTime = rtcpPacketInformation.roundTripTime; | ||||
|     rtcp_packet_info_.lastReceivedExtendedHighSeqNum = | ||||
|         rtcpPacketInformation.lastReceivedExtendedHighSeqNum; | ||||
|     rtcp_packet_info_.jitter = rtcpPacketInformation.jitter; | ||||
|     rtcp_packet_info_.report_blocks = rtcpPacketInformation.report_blocks; | ||||
|     rtcp_packet_info_.rtt = rtcpPacketInformation.rtt; | ||||
|     rtcp_packet_info_.interArrivalJitter = | ||||
|         rtcpPacketInformation.interArrivalJitter; | ||||
|     rtcp_packet_info_.sliPictureId = rtcpPacketInformation.sliPictureId; | ||||
| @@ -263,7 +292,9 @@ TEST_F(RtcpReceiverTest, ReceiveReportTimeout) { | ||||
|   const uint32_t kSourceSsrc = 0x40506; | ||||
|   const int64_t kRtcpIntervalMs = 1000; | ||||
|  | ||||
|   rtcp_receiver_->SetSSRC(kSourceSsrc); | ||||
|   std::set<uint32_t> ssrcs; | ||||
|   ssrcs.insert(kSourceSsrc); | ||||
|   rtcp_receiver_->SetSsrcs(kSourceSsrc, ssrcs); | ||||
|  | ||||
|   uint32_t sequence_number = 1234; | ||||
|   system_clock_.AdvanceTimeMilliseconds(3 * kRtcpIntervalMs); | ||||
| @@ -274,7 +305,7 @@ TEST_F(RtcpReceiverTest, ReceiveReportTimeout) { | ||||
|  | ||||
|   // Add a RR and advance the clock just enough to not trigger a timeout. | ||||
|   PacketBuilder p1; | ||||
|   p1.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number); | ||||
|   p1.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number, 0, 0); | ||||
|   EXPECT_EQ(0, InjectRtcpPacket(p1.packet(), p1.length())); | ||||
|   system_clock_.AdvanceTimeMilliseconds(3 * kRtcpIntervalMs - 1); | ||||
|   EXPECT_FALSE(rtcp_receiver_->RtcpRrTimeout(kRtcpIntervalMs)); | ||||
| @@ -283,7 +314,7 @@ TEST_F(RtcpReceiverTest, ReceiveReportTimeout) { | ||||
|   // Add a RR with the same extended max as the previous RR to trigger a | ||||
|   // sequence number timeout, but not a RR timeout. | ||||
|   PacketBuilder p2; | ||||
|   p2.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number); | ||||
|   p2.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number, 0, 0); | ||||
|   EXPECT_EQ(0, InjectRtcpPacket(p2.packet(), p2.length())); | ||||
|   system_clock_.AdvanceTimeMilliseconds(2); | ||||
|   EXPECT_FALSE(rtcp_receiver_->RtcpRrTimeout(kRtcpIntervalMs)); | ||||
| @@ -301,7 +332,7 @@ TEST_F(RtcpReceiverTest, ReceiveReportTimeout) { | ||||
|   // Add a new RR with increase sequence number to reset timers. | ||||
|   PacketBuilder p3; | ||||
|   sequence_number++; | ||||
|   p2.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number); | ||||
|   p2.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number, 0, 0); | ||||
|   EXPECT_EQ(0, InjectRtcpPacket(p2.packet(), p2.length())); | ||||
|   EXPECT_FALSE(rtcp_receiver_->RtcpRrTimeout(kRtcpIntervalMs)); | ||||
|   EXPECT_FALSE(rtcp_receiver_->RtcpRrSequenceNumberTimeout(kRtcpIntervalMs)); | ||||
| @@ -309,7 +340,7 @@ TEST_F(RtcpReceiverTest, ReceiveReportTimeout) { | ||||
|   // Verify we can get a timeout again once we've received new RR. | ||||
|   system_clock_.AdvanceTimeMilliseconds(2 * kRtcpIntervalMs); | ||||
|   PacketBuilder p4; | ||||
|   p4.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number); | ||||
|   p4.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number, 0, 0); | ||||
|   EXPECT_EQ(0, InjectRtcpPacket(p4.packet(), p4.length())); | ||||
|   system_clock_.AdvanceTimeMilliseconds(kRtcpIntervalMs + 1); | ||||
|   EXPECT_FALSE(rtcp_receiver_->RtcpRrTimeout(kRtcpIntervalMs)); | ||||
| @@ -323,11 +354,47 @@ TEST_F(RtcpReceiverTest, TmmbrReceivedWithNoIncomingPacket) { | ||||
|   EXPECT_EQ(-1, rtcp_receiver_->TMMBRReceived(0, 0, NULL)); | ||||
| } | ||||
|  | ||||
| TEST_F(RtcpReceiverTest, TwoReportBlocks) { | ||||
|   const uint32_t kSenderSsrc = 0x10203; | ||||
|   const int kNumSsrcs = 2; | ||||
|   const uint32_t kSourceSsrcs[kNumSsrcs] = {0x40506, 0x50607}; | ||||
|   uint32_t sequence_numbers[kNumSsrcs] = {10, 12423}; | ||||
|  | ||||
|   std::set<uint32_t> ssrcs(kSourceSsrcs, kSourceSsrcs + kNumSsrcs); | ||||
|   rtcp_receiver_->SetSsrcs(kSourceSsrcs[0], ssrcs); | ||||
|  | ||||
|   PacketBuilder packet; | ||||
|   std::list<PacketBuilder::ReportBlock> report_blocks; | ||||
|   report_blocks.push_back(PacketBuilder::ReportBlock( | ||||
|       kSourceSsrcs[0], sequence_numbers[0], 10, 5)); | ||||
|   report_blocks.push_back(PacketBuilder::ReportBlock( | ||||
|       kSourceSsrcs[1], sequence_numbers[1], 0, 0)); | ||||
|   packet.AddRrPacketMultipleReportBlocks(kSenderSsrc, report_blocks); | ||||
|   EXPECT_EQ(0, InjectRtcpPacket(packet.packet(), packet.length())); | ||||
|   ASSERT_EQ(2u, rtcp_packet_info_.report_blocks.size()); | ||||
|   EXPECT_EQ(10, rtcp_packet_info_.report_blocks.front().fractionLost); | ||||
|   EXPECT_EQ(0, rtcp_packet_info_.report_blocks.back().fractionLost); | ||||
|  | ||||
|   PacketBuilder packet2; | ||||
|   report_blocks.clear(); | ||||
|   report_blocks.push_back(PacketBuilder::ReportBlock( | ||||
|       kSourceSsrcs[0], sequence_numbers[0], 0, 0)); | ||||
|   report_blocks.push_back(PacketBuilder::ReportBlock( | ||||
|       kSourceSsrcs[1], sequence_numbers[1], 20, 10)); | ||||
|   packet2.AddRrPacketMultipleReportBlocks(kSenderSsrc, report_blocks); | ||||
|   EXPECT_EQ(0, InjectRtcpPacket(packet2.packet(), packet2.length())); | ||||
|   ASSERT_EQ(2u, rtcp_packet_info_.report_blocks.size()); | ||||
|   EXPECT_EQ(0, rtcp_packet_info_.report_blocks.front().fractionLost); | ||||
|   EXPECT_EQ(20, rtcp_packet_info_.report_blocks.back().fractionLost); | ||||
| } | ||||
|  | ||||
| TEST_F(RtcpReceiverTest, TmmbrPacketAccepted) { | ||||
|   const uint32_t kMediaFlowSsrc = 0x2040608; | ||||
|   const uint32_t kSenderSsrc = 0x10203; | ||||
|   const uint32_t kMediaRecipientSsrc = 0x101; | ||||
|   rtcp_receiver_->SetSSRC(kMediaFlowSsrc);  // Matches "media source" above. | ||||
|   std::set<uint32_t> ssrcs; | ||||
|   ssrcs.insert(kMediaFlowSsrc);  // Matches "media source" above. | ||||
|   rtcp_receiver_->SetSsrcs(kMediaFlowSsrc, ssrcs); | ||||
|  | ||||
|   PacketBuilder p; | ||||
|   p.AddSrPacket(kSenderSsrc); | ||||
| @@ -362,7 +429,9 @@ TEST_F(RtcpReceiverTest, TmmbrPacketNotForUsIgnored) { | ||||
|   p.Add32(kOtherMediaFlowSsrc);  // This SSRC is not what we're sending. | ||||
|   p.AddTmmbrBandwidth(30000, 0, 0); | ||||
|  | ||||
|   rtcp_receiver_->SetSSRC(kMediaFlowSsrc); | ||||
|   std::set<uint32_t> ssrcs; | ||||
|   ssrcs.insert(kMediaFlowSsrc); | ||||
|   rtcp_receiver_->SetSsrcs(kMediaFlowSsrc, ssrcs); | ||||
|   EXPECT_EQ(0, InjectRtcpPacket(p.packet(), p.length())); | ||||
|   EXPECT_EQ(0, rtcp_receiver_->TMMBRReceived(0, 0, NULL)); | ||||
| } | ||||
| @@ -371,7 +440,9 @@ TEST_F(RtcpReceiverTest, TmmbrPacketZeroRateIgnored) { | ||||
|   const uint32_t kMediaFlowSsrc = 0x2040608; | ||||
|   const uint32_t kSenderSsrc = 0x10203; | ||||
|   const uint32_t kMediaRecipientSsrc = 0x101; | ||||
|   rtcp_receiver_->SetSSRC(kMediaFlowSsrc);  // Matches "media source" above. | ||||
|   std::set<uint32_t> ssrcs; | ||||
|   ssrcs.insert(kMediaFlowSsrc);  // Matches "media source" above. | ||||
|   rtcp_receiver_->SetSsrcs(kMediaFlowSsrc, ssrcs); | ||||
|  | ||||
|   PacketBuilder p; | ||||
|   p.AddSrPacket(kSenderSsrc); | ||||
| @@ -390,7 +461,9 @@ TEST_F(RtcpReceiverTest, TmmbrThreeConstraintsTimeOut) { | ||||
|   const uint32_t kMediaFlowSsrc = 0x2040608; | ||||
|   const uint32_t kSenderSsrc = 0x10203; | ||||
|   const uint32_t kMediaRecipientSsrc = 0x101; | ||||
|   rtcp_receiver_->SetSSRC(kMediaFlowSsrc);  // Matches "media source" above. | ||||
|   std::set<uint32_t> ssrcs; | ||||
|   ssrcs.insert(kMediaFlowSsrc);  // Matches "media source" above. | ||||
|   rtcp_receiver_->SetSsrcs(kMediaFlowSsrc, ssrcs); | ||||
|  | ||||
|   // Inject 3 packets "from" kMediaRecipientSsrc, Ssrc+1, Ssrc+2. | ||||
|   // The times of arrival are starttime + 0, starttime + 5 and starttime + 10. | ||||
|   | ||||
| @@ -246,12 +246,8 @@ class TestTransport : public Transport, | ||||
|     rtcp_packet_info_.applicationSubType = | ||||
|         rtcpPacketInformation.applicationSubType; | ||||
|     rtcp_packet_info_.applicationName = rtcpPacketInformation.applicationName; | ||||
|     rtcp_packet_info_.reportBlock = rtcpPacketInformation.reportBlock; | ||||
|     rtcp_packet_info_.fractionLost = rtcpPacketInformation.fractionLost; | ||||
|     rtcp_packet_info_.roundTripTime = rtcpPacketInformation.roundTripTime; | ||||
|     rtcp_packet_info_.lastReceivedExtendedHighSeqNum = | ||||
|         rtcpPacketInformation.lastReceivedExtendedHighSeqNum; | ||||
|     rtcp_packet_info_.jitter = rtcpPacketInformation.jitter; | ||||
|     rtcp_packet_info_.report_blocks = rtcpPacketInformation.report_blocks; | ||||
|     rtcp_packet_info_.rtt = rtcpPacketInformation.rtt; | ||||
|     rtcp_packet_info_.interArrivalJitter = | ||||
|         rtcpPacketInformation.interArrivalJitter; | ||||
|     rtcp_packet_info_.sliPictureId = rtcpPacketInformation.sliPictureId; | ||||
|   | ||||
| @@ -111,10 +111,10 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const Configuration& configuration) | ||||
|                                        configuration.rtcp_feedback); | ||||
|   rtcp_sender_.RegisterSendTransport(configuration.outgoing_transport); | ||||
|  | ||||
|   // Make sure that RTCP objects are aware of our SSRC | ||||
|   // Make sure that RTCP objects are aware of our SSRC. | ||||
|   uint32_t SSRC = rtp_sender_.SSRC(); | ||||
|   rtcp_sender_.SetSSRC(SSRC); | ||||
|   rtcp_receiver_.SetSSRC(SSRC); | ||||
|   SetRtcpReceiverSsrcs(SSRC); | ||||
|  | ||||
|   WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id_, "%s created", __FUNCTION__); | ||||
| } | ||||
| @@ -261,6 +261,8 @@ int32_t ModuleRtpRtcpImpl::Process() { | ||||
| int32_t ModuleRtpRtcpImpl::SetRTXSendStatus(RtxMode mode, bool set_ssrc, | ||||
|                                             uint32_t ssrc) { | ||||
|   rtp_sender_.SetRTXStatus(mode, set_ssrc, ssrc); | ||||
|  | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| @@ -410,8 +412,9 @@ int32_t ModuleRtpRtcpImpl::SetSSRC(const uint32_t ssrc) { | ||||
|   WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id_, "SetSSRC(%d)", ssrc); | ||||
|  | ||||
|   rtp_sender_.SetSSRC(ssrc); | ||||
|   rtcp_receiver_.SetSSRC(ssrc); | ||||
|   rtcp_sender_.SetSSRC(ssrc); | ||||
|   SetRtcpReceiverSsrcs(ssrc); | ||||
|  | ||||
|   return 0;  // TODO(pwestin): change to void. | ||||
| } | ||||
|  | ||||
| @@ -510,8 +513,9 @@ int32_t ModuleRtpRtcpImpl::SetSendingStatus(const bool sending) { | ||||
|     // Make sure that RTCP objects are aware of our SSRC (it could have changed | ||||
|     // Due to collision) | ||||
|     uint32_t SSRC = rtp_sender_.SSRC(); | ||||
|     rtcp_receiver_.SetSSRC(SSRC); | ||||
|     rtcp_sender_.SetSSRC(SSRC); | ||||
|     SetRtcpReceiverSsrcs(SSRC); | ||||
|  | ||||
|     return 0; | ||||
|   } | ||||
|   return 0; | ||||
| @@ -1459,7 +1463,7 @@ void ModuleRtpRtcpImpl::SetRemoteSSRC(const uint32_t ssrc) { | ||||
|     } | ||||
|     // Change local SSRC and inform all objects about the new SSRC. | ||||
|     rtcp_sender_.SetSSRC(new_ssrc); | ||||
|     rtcp_receiver_.SetSSRC(new_ssrc); | ||||
|     SetRtcpReceiverSsrcs(new_ssrc); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -1587,4 +1591,17 @@ int64_t ModuleRtpRtcpImpl::RtcpReportInterval() { | ||||
|   else | ||||
|     return RTCP_INTERVAL_VIDEO_MS; | ||||
| } | ||||
|  | ||||
| void ModuleRtpRtcpImpl::SetRtcpReceiverSsrcs(uint32_t main_ssrc) { | ||||
|   std::set<uint32_t> ssrcs; | ||||
|   ssrcs.insert(main_ssrc); | ||||
|   RtxMode rtx_mode = kRtxOff; | ||||
|   uint32_t rtx_ssrc = 0; | ||||
|   int rtx_payload_type = 0; | ||||
|   rtp_sender_.RTXStatus(&rtx_mode, &rtx_ssrc, &rtx_payload_type); | ||||
|   if (rtx_mode != kRtxOff) | ||||
|     ssrcs.insert(rtx_ssrc); | ||||
|   rtcp_receiver_.SetSsrcs(main_ssrc, ssrcs); | ||||
| } | ||||
|  | ||||
| }  // Namespace webrtc | ||||
|   | ||||
| @@ -377,6 +377,7 @@ class ModuleRtpRtcpImpl : public RtpRtcp { | ||||
|  | ||||
|  private: | ||||
|   int64_t RtcpReportInterval(); | ||||
|   void SetRtcpReceiverSsrcs(uint32_t main_ssrc); | ||||
|  | ||||
|   int32_t             id_; | ||||
|   const bool                audio_; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 stefan@webrtc.org
					stefan@webrtc.org