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> |
11 #include <list> | 11 #include <list> |
12 #include <map> | 12 #include <map> |
13 #include <memory> | 13 #include <memory> |
14 #include <sstream> | 14 #include <sstream> |
15 #include <string> | 15 #include <string> |
16 #include <vector> | 16 #include <vector> |
17 | 17 |
18 #include "webrtc/base/checks.h" | 18 #include "webrtc/base/checks.h" |
19 #include "webrtc/base/event.h" | 19 #include "webrtc/base/event.h" |
20 #include "webrtc/base/file.h" | 20 #include "webrtc/base/file.h" |
21 #include "webrtc/base/optional.h" | 21 #include "webrtc/base/optional.h" |
| 22 #include "webrtc/base/random.h" |
22 #include "webrtc/base/rate_limiter.h" | 23 #include "webrtc/base/rate_limiter.h" |
23 #include "webrtc/call/call.h" | 24 #include "webrtc/call/call.h" |
24 #include "webrtc/common_video/include/frame_callback.h" | 25 #include "webrtc/common_video/include/frame_callback.h" |
25 #include "webrtc/logging/rtc_event_log/rtc_event_log.h" | 26 #include "webrtc/logging/rtc_event_log/rtc_event_log.h" |
26 #include "webrtc/media/base/fakevideorenderer.h" | 27 #include "webrtc/media/base/fakevideorenderer.h" |
27 #include "webrtc/modules/include/module_common_types.h" | 28 #include "webrtc/modules/include/module_common_types.h" |
28 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" | 29 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" |
29 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | 30 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
30 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h" | 31 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h" |
31 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h" | 32 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h" |
(...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
701 } test; | 702 } test; |
702 | 703 |
703 RunBaseTest(&test); | 704 RunBaseTest(&test); |
704 } | 705 } |
705 | 706 |
706 TEST_P(EndToEndTest, CanReceiveFlexfec) { | 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 FlexfecRenderObserver() | 711 FlexfecRenderObserver() |
711 : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {} | 712 : EndToEndTest(kDefaultTimeoutMs), random_(0xcafef00d1) {} |
712 | 713 |
713 size_t GetNumFlexfecStreams() const override { return 1; } | 714 size_t GetNumFlexfecStreams() const override { return 1; } |
714 | 715 |
715 private: | 716 private: |
716 Action OnSendRtp(const uint8_t* packet, size_t length) override { | 717 Action OnSendRtp(const uint8_t* packet, size_t length) override { |
717 rtc::CritScope lock(&crit_); | 718 rtc::CritScope lock(&crit_); |
718 RTPHeader header; | 719 RTPHeader header; |
719 EXPECT_TRUE(parser_->Parse(packet, length, &header)); | 720 EXPECT_TRUE(parser_->Parse(packet, length, &header)); |
720 | 721 |
721 uint8_t payload_type = header.payloadType; | 722 uint8_t payload_type = header.payloadType; |
722 if (payload_type != kFakeVideoSendPayloadType) { | 723 if (payload_type != kFakeVideoSendPayloadType) { |
723 EXPECT_EQ(kFlexfecPayloadType, payload_type); | 724 EXPECT_EQ(kFlexfecPayloadType, payload_type); |
724 } | 725 } |
725 | 726 |
726 auto seq_num_it = protected_sequence_numbers_.find(header.sequenceNumber); | 727 // Is this a retransmitted media packet? From the perspective of FEC, this |
727 if (seq_num_it != protected_sequence_numbers_.end()) { | 728 // packet is then no longer dropped, so remove it from the list of |
728 // Retransmitted packet, should not count. | 729 // dropped packets. |
729 protected_sequence_numbers_.erase(seq_num_it); | 730 if (payload_type == kFakeVideoSendPayloadType) { |
730 auto ts_it = protected_timestamps_.find(header.timestamp); | 731 auto seq_num_it = dropped_sequence_numbers_.find(header.sequenceNumber); |
731 EXPECT_NE(ts_it, protected_timestamps_.end()); | 732 if (seq_num_it != dropped_sequence_numbers_.end()) { |
732 protected_timestamps_.erase(ts_it); | 733 dropped_sequence_numbers_.erase(seq_num_it); |
733 return SEND_PACKET; | 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 } |
734 } | 740 } |
735 | 741 |
736 switch (state_) { | 742 // Simulate 5% packet loss. Record what media packets, and corresponding |
737 case kFirstPacket: | 743 // timestamps, that were dropped. |
738 state_ = kDropEveryOtherPacketUntilFlexfec; | 744 if (random_.Rand(1, 100) <= 5) { |
739 break; | 745 if (payload_type == kFakeVideoSendPayloadType) { |
740 case kDropEveryOtherPacketUntilFlexfec: | 746 dropped_sequence_numbers_.insert(header.sequenceNumber); |
741 if (payload_type == kFlexfecPayloadType) { | 747 dropped_timestamps_.insert(header.timestamp); |
742 state_ = kDropNextMediaPacket; | 748 } |
743 return SEND_PACKET; | 749 |
744 } | 750 return DROP_PACKET; |
745 if (header.sequenceNumber % 2 == 0) | |
746 return DROP_PACKET; | |
747 break; | |
748 case kDropNextMediaPacket: | |
749 if (payload_type == kFakeVideoSendPayloadType) { | |
750 protected_sequence_numbers_.insert(header.sequenceNumber); | |
751 protected_timestamps_.insert(header.timestamp); | |
752 state_ = kDropEveryOtherPacketUntilFlexfec; | |
753 return DROP_PACKET; | |
754 } | |
755 break; | |
756 } | 751 } |
757 | 752 |
758 return SEND_PACKET; | 753 return SEND_PACKET; |
759 } | 754 } |
760 | 755 |
761 void OnFrame(const VideoFrame& video_frame) override { | 756 void OnFrame(const VideoFrame& video_frame) override { |
762 rtc::CritScope lock(&crit_); | 757 rtc::CritScope lock(&crit_); |
763 // Rendering frame with timestamp of packet that was dropped -> FEC | 758 // Rendering frame with timestamp of packet that was dropped -> FEC |
764 // protection worked. | 759 // protection worked. |
765 auto it = protected_timestamps_.find(video_frame.timestamp()); | 760 auto it = dropped_timestamps_.find(video_frame.timestamp()); |
766 if (it != protected_timestamps_.end()) | 761 if (it != dropped_timestamps_.end()) |
767 observation_complete_.Set(); | 762 observation_complete_.Set(); |
768 } | 763 } |
769 | 764 |
770 enum { | |
771 kFirstPacket, | |
772 kDropEveryOtherPacketUntilFlexfec, | |
773 kDropNextMediaPacket, | |
774 } state_; | |
775 | |
776 void ModifyVideoConfigs( | 765 void ModifyVideoConfigs( |
777 VideoSendStream::Config* send_config, | 766 VideoSendStream::Config* send_config, |
778 std::vector<VideoReceiveStream::Config>* receive_configs, | 767 std::vector<VideoReceiveStream::Config>* receive_configs, |
779 VideoEncoderConfig* encoder_config) override { | 768 VideoEncoderConfig* encoder_config) override { |
780 (*receive_configs)[0].renderer = this; | 769 (*receive_configs)[0].renderer = this; |
781 } | 770 } |
782 | 771 |
783 void PerformTest() override { | 772 void PerformTest() override { |
784 EXPECT_TRUE(Wait()) | 773 EXPECT_TRUE(Wait()) |
785 << "Timed out waiting for dropped frames to be rendered."; | 774 << "Timed out waiting for dropped frames to be rendered."; |
786 } | 775 } |
787 | 776 |
788 rtc::CriticalSection crit_; | 777 rtc::CriticalSection crit_; |
789 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_); | 778 std::set<uint32_t> dropped_sequence_numbers_ GUARDED_BY(crit_); |
790 // Since several packets can have the same timestamp a multiset is used | 779 // Since several packets can have the same timestamp a multiset is used |
791 // instead of a set. | 780 // instead of a set. |
792 std::multiset<uint32_t> protected_timestamps_ GUARDED_BY(crit_); | 781 std::multiset<uint32_t> dropped_timestamps_ GUARDED_BY(crit_); |
| 782 Random random_; |
793 } test; | 783 } test; |
794 | 784 |
795 RunBaseTest(&test); | 785 RunBaseTest(&test); |
796 } | 786 } |
797 | 787 |
798 TEST_P(EndToEndTest, ReceivedUlpfecPacketsNotNacked) { | 788 TEST_P(EndToEndTest, ReceivedUlpfecPacketsNotNacked) { |
799 class UlpfecNackObserver : public test::EndToEndTest { | 789 class UlpfecNackObserver : public test::EndToEndTest { |
800 public: | 790 public: |
801 UlpfecNackObserver() | 791 UlpfecNackObserver() |
802 : EndToEndTest(kDefaultTimeoutMs), | 792 : EndToEndTest(kDefaultTimeoutMs), |
(...skipping 3267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4070 std::unique_ptr<VideoEncoder> encoder_; | 4060 std::unique_ptr<VideoEncoder> encoder_; |
4071 std::unique_ptr<VideoDecoder> decoder_; | 4061 std::unique_ptr<VideoDecoder> decoder_; |
4072 rtc::CriticalSection crit_; | 4062 rtc::CriticalSection crit_; |
4073 int recorded_frames_ GUARDED_BY(crit_); | 4063 int recorded_frames_ GUARDED_BY(crit_); |
4074 } test(this); | 4064 } test(this); |
4075 | 4065 |
4076 RunBaseTest(&test); | 4066 RunBaseTest(&test); |
4077 } | 4067 } |
4078 | 4068 |
4079 } // namespace webrtc | 4069 } // namespace webrtc |
OLD | NEW |