 Chromium Code Reviews
 Chromium Code Reviews Issue 2625633003:
  Let FlexfecReceiveStreamImpl send RTCP RRs.  (Closed)
    
  
    Issue 2625633003:
  Let FlexfecReceiveStreamImpl send RTCP RRs.  (Closed) 
  | OLD | NEW | 
|---|---|
| 1 /* | 1 /* | 
| 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 
| 3 * | 3 * | 
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license | 
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source | 
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found | 
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may | 
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. | 
| 9 */ | 9 */ | 
| 10 #include <algorithm> | 10 #include <algorithm> | 
| (...skipping 686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 697 rtc::CriticalSection crit_; | 697 rtc::CriticalSection crit_; | 
| 698 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_); | 698 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_); | 
| 699 // Since several packets can have the same timestamp a multiset is used | 699 // Since several packets can have the same timestamp a multiset is used | 
| 700 // instead of a set. | 700 // instead of a set. | 
| 701 std::multiset<uint32_t> protected_timestamps_ GUARDED_BY(crit_); | 701 std::multiset<uint32_t> protected_timestamps_ GUARDED_BY(crit_); | 
| 702 } test; | 702 } test; | 
| 703 | 703 | 
| 704 RunBaseTest(&test); | 704 RunBaseTest(&test); | 
| 705 } | 705 } | 
| 706 | 706 | 
| 707 TEST_P(EndToEndTest, CanReceiveFlexfec) { | 707 class FlexfecRenderObserver : public test::EndToEndTest, | 
| 708 class FlexfecRenderObserver : public test::EndToEndTest, | 708 public rtc::VideoSinkInterface<VideoFrame> { | 
| 709 public rtc::VideoSinkInterface<VideoFrame> { | 709 public: | 
| 710 public: | 710 static constexpr uint32_t kVideoLocalSsrc = 123; | 
| 711 FlexfecRenderObserver() | 711 static constexpr uint32_t kFlexfecLocalSsrc = 456; | 
| 712 : EndToEndTest(kDefaultTimeoutMs), random_(0xcafef00d1) {} | |
| 713 | 712 | 
| 714 size_t GetNumFlexfecStreams() const override { return 1; } | 713 explicit FlexfecRenderObserver(bool expect_flexfec_rtcp) | 
| 714 : test::EndToEndTest(test::CallTest::kDefaultTimeoutMs), | |
| 715 expect_flexfec_rtcp_(expect_flexfec_rtcp), | |
| 716 received_flexfec_rtcp_(false), | |
| 717 random_(0xcafef00d1) {} | |
| 715 | 718 | 
| 716 private: | 719 size_t GetNumFlexfecStreams() const override { return 1; } | 
| 717 Action OnSendRtp(const uint8_t* packet, size_t length) override { | |
| 718 rtc::CritScope lock(&crit_); | |
| 719 RTPHeader header; | |
| 720 EXPECT_TRUE(parser_->Parse(packet, length, &header)); | |
| 721 | 720 | 
| 722 uint8_t payload_type = header.payloadType; | 721 private: | 
| 723 if (payload_type != kFakeVideoSendPayloadType) { | 722 Action OnSendRtp(const uint8_t* packet, size_t length) override { | 
| 724 EXPECT_EQ(kFlexfecPayloadType, payload_type); | 723 rtc::CritScope lock(&crit_); | 
| 724 RTPHeader header; | |
| 725 EXPECT_TRUE(parser_->Parse(packet, length, &header)); | |
| 726 | |
| 727 uint8_t payload_type = header.payloadType; | |
| 728 if (payload_type != test::CallTest::kFakeVideoSendPayloadType) { | |
| 729 EXPECT_EQ(test::CallTest::kFlexfecPayloadType, payload_type); | |
| 730 } | |
| 731 | |
| 732 // Is this a retransmitted media packet? From the perspective of FEC, this | |
| 733 // packet is then no longer dropped, so remove it from the list of | |
| 734 // dropped packets. | |
| 735 if (payload_type == test::CallTest::kFakeVideoSendPayloadType) { | |
| 736 auto seq_num_it = dropped_sequence_numbers_.find(header.sequenceNumber); | |
| 737 if (seq_num_it != dropped_sequence_numbers_.end()) { | |
| 738 dropped_sequence_numbers_.erase(seq_num_it); | |
| 739 auto ts_it = dropped_timestamps_.find(header.timestamp); | |
| 740 EXPECT_NE(ts_it, dropped_timestamps_.end()); | |
| 741 dropped_timestamps_.erase(ts_it); | |
| 742 | |
| 743 return SEND_PACKET; | |
| 744 } | |
| 745 } | |
| 746 | |
| 747 // Simulate 5% packet loss. Record what media packets, and corresponding | |
| 748 // timestamps, that were dropped. | |
| 749 if (random_.Rand(1, 100) <= 5) { | |
| 750 if (payload_type == test::CallTest::kFakeVideoSendPayloadType) { | |
| 751 dropped_sequence_numbers_.insert(header.sequenceNumber); | |
| 752 dropped_timestamps_.insert(header.timestamp); | |
| 725 } | 753 } | 
| 726 | 754 | 
| 727 // Is this a retransmitted media packet? From the perspective of FEC, this | 755 return DROP_PACKET; | 
| 728 // packet is then no longer dropped, so remove it from the list of | |
| 729 // dropped packets. | |
| 730 if (payload_type == kFakeVideoSendPayloadType) { | |
| 731 auto seq_num_it = dropped_sequence_numbers_.find(header.sequenceNumber); | |
| 732 if (seq_num_it != dropped_sequence_numbers_.end()) { | |
| 733 dropped_sequence_numbers_.erase(seq_num_it); | |
| 734 auto ts_it = dropped_timestamps_.find(header.timestamp); | |
| 735 EXPECT_NE(ts_it, dropped_timestamps_.end()); | |
| 736 dropped_timestamps_.erase(ts_it); | |
| 737 | |
| 738 return SEND_PACKET; | |
| 739 } | |
| 740 } | |
| 741 | |
| 742 // Simulate 5% packet loss. Record what media packets, and corresponding | |
| 743 // timestamps, that were dropped. | |
| 744 if (random_.Rand(1, 100) <= 5) { | |
| 745 if (payload_type == kFakeVideoSendPayloadType) { | |
| 746 dropped_sequence_numbers_.insert(header.sequenceNumber); | |
| 747 dropped_timestamps_.insert(header.timestamp); | |
| 748 } | |
| 749 | |
| 750 return DROP_PACKET; | |
| 751 } | |
| 752 | |
| 753 return SEND_PACKET; | |
| 754 } | 756 } | 
| 755 | 757 | 
| 756 void OnFrame(const VideoFrame& video_frame) override { | 758 return SEND_PACKET; | 
| 757 rtc::CritScope lock(&crit_); | 759 } | 
| 758 // Rendering frame with timestamp of packet that was dropped -> FEC | 760 | 
| 759 // protection worked. | 761 Action OnReceiveRtcp(const uint8_t* data, size_t length) override { | 
| 760 auto it = dropped_timestamps_.find(video_frame.timestamp()); | 762 test::RtcpPacketParser parser; | 
| 761 if (it != dropped_timestamps_.end()) | 763 | 
| 762 observation_complete_.Set(); | 764 parser.Parse(data, length); | 
| 765 if (parser.sender_ssrc() == kFlexfecLocalSsrc) { | |
| 766 received_flexfec_rtcp_ = true; | |
| 
danilchap
2017/01/11 12:13:07
probably set to true only if (!report_blocks.empty
 
brandtr
2017/01/11 12:25:36
Yes, this is better, as it requires the EXPECTs be
 | |
| 767 | |
| 768 EXPECT_EQ(1, parser.receiver_report()->num_packets()); | |
| 769 const std::vector<rtcp::ReportBlock>& report_blocks = | |
| 770 parser.receiver_report()->report_blocks(); | |
| 771 if (!report_blocks.empty()) { | |
| 
brandtr
2017/01/11 10:47:52
This check is needed because the newly created RTP
 
danilchap
2017/01/11 12:13:07
should be correct, not so sure if reasonable.
quo
 
brandtr
2017/01/11 12:25:36
Acknowledged.
 | |
| 772 EXPECT_EQ(1U, report_blocks.size()); | |
| 773 EXPECT_EQ(test::CallTest::kFlexfecSendSsrc, | |
| 774 report_blocks[0].source_ssrc()); | |
| 775 } | |
| 763 } | 776 } | 
| 764 | 777 | 
| 765 void ModifyVideoConfigs( | 778 return SEND_PACKET; | 
| 766 VideoSendStream::Config* send_config, | 779 } | 
| 767 std::vector<VideoReceiveStream::Config>* receive_configs, | 780 | 
| 768 VideoEncoderConfig* encoder_config) override { | 781 void OnFrame(const VideoFrame& video_frame) override { | 
| 769 (*receive_configs)[0].renderer = this; | 782 rtc::CritScope lock(&crit_); | 
| 783 // Rendering frame with timestamp of packet that was dropped -> FEC | |
| 784 // protection worked. | |
| 785 auto it = dropped_timestamps_.find(video_frame.timestamp()); | |
| 786 if (it != dropped_timestamps_.end()) { | |
| 787 if (!expect_flexfec_rtcp_ || received_flexfec_rtcp_) { | |
| 788 observation_complete_.Set(); | |
| 789 } | |
| 770 } | 790 } | 
| 791 } | |
| 771 | 792 | 
| 772 void PerformTest() override { | 793 void ModifyVideoConfigs( | 
| 773 EXPECT_TRUE(Wait()) | 794 VideoSendStream::Config* send_config, | 
| 774 << "Timed out waiting for dropped frames to be rendered."; | 795 std::vector<VideoReceiveStream::Config>* receive_configs, | 
| 775 } | 796 VideoEncoderConfig* encoder_config) override { | 
| 797 (*receive_configs)[0].rtp.local_ssrc = kVideoLocalSsrc; | |
| 798 (*receive_configs)[0].renderer = this; | |
| 799 } | |
| 776 | 800 | 
| 777 rtc::CriticalSection crit_; | 801 void ModifyFlexfecConfigs( | 
| 778 std::set<uint32_t> dropped_sequence_numbers_ GUARDED_BY(crit_); | 802 std::vector<FlexfecReceiveStream::Config>* receive_configs) override { | 
| 779 // Since several packets can have the same timestamp a multiset is used | 803 (*receive_configs)[0].local_ssrc = kFlexfecLocalSsrc; | 
| 780 // instead of a set. | 804 } | 
| 781 std::multiset<uint32_t> dropped_timestamps_ GUARDED_BY(crit_); | |
| 782 Random random_; | |
| 783 } test; | |
| 784 | 805 | 
| 806 void PerformTest() override { | |
| 807 EXPECT_TRUE(Wait()) | |
| 808 << "Timed out waiting for dropped frames to be rendered."; | |
| 809 } | |
| 810 | |
| 811 rtc::CriticalSection crit_; | |
| 812 std::set<uint32_t> dropped_sequence_numbers_ GUARDED_BY(crit_); | |
| 813 // Since several packets can have the same timestamp a multiset is used | |
| 814 // instead of a set. | |
| 815 std::multiset<uint32_t> dropped_timestamps_ GUARDED_BY(crit_); | |
| 816 bool expect_flexfec_rtcp_; | |
| 817 bool received_flexfec_rtcp_; | |
| 818 Random random_; | |
| 819 }; | |
| 820 | |
| 821 TEST_P(EndToEndTest, ReceivesFlexfec) { | |
| 822 FlexfecRenderObserver test(false); | |
| 785 RunBaseTest(&test); | 823 RunBaseTest(&test); | 
| 786 } | 824 } | 
| 787 | 825 | 
| 826 TEST_P(EndToEndTest, ReceivesFlexfecAndSendsCorrespondingRtcp) { | |
| 827 FlexfecRenderObserver test(true); | |
| 828 RunBaseTest(&test); | |
| 829 } | |
| 830 | |
| 788 TEST_P(EndToEndTest, ReceivedUlpfecPacketsNotNacked) { | 831 TEST_P(EndToEndTest, ReceivedUlpfecPacketsNotNacked) { | 
| 789 class UlpfecNackObserver : public test::EndToEndTest { | 832 class UlpfecNackObserver : public test::EndToEndTest { | 
| 790 public: | 833 public: | 
| 791 UlpfecNackObserver() | 834 UlpfecNackObserver() | 
| 792 : EndToEndTest(kDefaultTimeoutMs), | 835 : EndToEndTest(kDefaultTimeoutMs), | 
| 793 state_(kFirstPacket), | 836 state_(kFirstPacket), | 
| 794 ulpfec_sequence_number_(0), | 837 ulpfec_sequence_number_(0), | 
| 795 has_last_sequence_number_(false), | 838 has_last_sequence_number_(false), | 
| 796 last_sequence_number_(0), | 839 last_sequence_number_(0), | 
| 797 encoder_(VP8Encoder::Create()), | 840 encoder_(VP8Encoder::Create()), | 
| (...skipping 3267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4065 std::unique_ptr<VideoEncoder> encoder_; | 4108 std::unique_ptr<VideoEncoder> encoder_; | 
| 4066 std::unique_ptr<VideoDecoder> decoder_; | 4109 std::unique_ptr<VideoDecoder> decoder_; | 
| 4067 rtc::CriticalSection crit_; | 4110 rtc::CriticalSection crit_; | 
| 4068 int recorded_frames_ GUARDED_BY(crit_); | 4111 int recorded_frames_ GUARDED_BY(crit_); | 
| 4069 } test(this); | 4112 } test(this); | 
| 4070 | 4113 | 
| 4071 RunBaseTest(&test); | 4114 RunBaseTest(&test); | 
| 4072 } | 4115 } | 
| 4073 | 4116 | 
| 4074 } // namespace webrtc | 4117 } // namespace webrtc | 
| OLD | NEW |