| Index: webrtc/video/end_to_end_tests.cc
|
| diff --git a/webrtc/video/end_to_end_tests.cc b/webrtc/video/end_to_end_tests.cc
|
| index 946d81d5df7405f5f53ea7a3df5053d60e59d9fe..502851bbcee267c09dfa18fcadc2994097cafee1 100644
|
| --- a/webrtc/video/end_to_end_tests.cc
|
| +++ b/webrtc/video/end_to_end_tests.cc
|
| @@ -705,84 +705,126 @@ TEST_P(EndToEndTest, CanReceiveUlpfec) {
|
| RunBaseTest(&test);
|
| }
|
|
|
| -TEST_P(EndToEndTest, CanReceiveFlexfec) {
|
| - class FlexfecRenderObserver : public test::EndToEndTest,
|
| - public rtc::VideoSinkInterface<VideoFrame> {
|
| - public:
|
| - FlexfecRenderObserver()
|
| - : EndToEndTest(kDefaultTimeoutMs), random_(0xcafef00d1) {}
|
| +class FlexfecRenderObserver : public test::EndToEndTest,
|
| + public rtc::VideoSinkInterface<VideoFrame> {
|
| + public:
|
| + static constexpr uint32_t kVideoLocalSsrc = 123;
|
| + static constexpr uint32_t kFlexfecLocalSsrc = 456;
|
|
|
| - size_t GetNumFlexfecStreams() const override { return 1; }
|
| + explicit FlexfecRenderObserver(bool expect_flexfec_rtcp)
|
| + : test::EndToEndTest(test::CallTest::kDefaultTimeoutMs),
|
| + expect_flexfec_rtcp_(expect_flexfec_rtcp),
|
| + received_flexfec_rtcp_(false),
|
| + random_(0xcafef00d1) {}
|
|
|
| - private:
|
| - Action OnSendRtp(const uint8_t* packet, size_t length) override {
|
| - rtc::CritScope lock(&crit_);
|
| - RTPHeader header;
|
| - EXPECT_TRUE(parser_->Parse(packet, length, &header));
|
| + size_t GetNumFlexfecStreams() const override { return 1; }
|
|
|
| - uint8_t payload_type = header.payloadType;
|
| - if (payload_type != kFakeVideoSendPayloadType) {
|
| - EXPECT_EQ(kFlexfecPayloadType, payload_type);
|
| - }
|
| + private:
|
| + Action OnSendRtp(const uint8_t* packet, size_t length) override {
|
| + rtc::CritScope lock(&crit_);
|
| + RTPHeader header;
|
| + EXPECT_TRUE(parser_->Parse(packet, length, &header));
|
|
|
| - // Is this a retransmitted media packet? From the perspective of FEC, this
|
| - // packet is then no longer dropped, so remove it from the list of
|
| - // dropped packets.
|
| - if (payload_type == kFakeVideoSendPayloadType) {
|
| - auto seq_num_it = dropped_sequence_numbers_.find(header.sequenceNumber);
|
| - if (seq_num_it != dropped_sequence_numbers_.end()) {
|
| - dropped_sequence_numbers_.erase(seq_num_it);
|
| - auto ts_it = dropped_timestamps_.find(header.timestamp);
|
| - EXPECT_NE(ts_it, dropped_timestamps_.end());
|
| - dropped_timestamps_.erase(ts_it);
|
| + uint8_t payload_type = header.payloadType;
|
| + if (payload_type != test::CallTest::kFakeVideoSendPayloadType) {
|
| + EXPECT_EQ(test::CallTest::kFlexfecPayloadType, payload_type);
|
| + }
|
|
|
| - return SEND_PACKET;
|
| - }
|
| - }
|
| + // Is this a retransmitted media packet? From the perspective of FEC, this
|
| + // packet is then no longer dropped, so remove it from the list of
|
| + // dropped packets.
|
| + if (payload_type == test::CallTest::kFakeVideoSendPayloadType) {
|
| + auto seq_num_it = dropped_sequence_numbers_.find(header.sequenceNumber);
|
| + if (seq_num_it != dropped_sequence_numbers_.end()) {
|
| + dropped_sequence_numbers_.erase(seq_num_it);
|
| + auto ts_it = dropped_timestamps_.find(header.timestamp);
|
| + EXPECT_NE(ts_it, dropped_timestamps_.end());
|
| + dropped_timestamps_.erase(ts_it);
|
|
|
| - // Simulate 5% packet loss. Record what media packets, and corresponding
|
| - // timestamps, that were dropped.
|
| - if (random_.Rand(1, 100) <= 5) {
|
| - if (payload_type == kFakeVideoSendPayloadType) {
|
| - dropped_sequence_numbers_.insert(header.sequenceNumber);
|
| - dropped_timestamps_.insert(header.timestamp);
|
| - }
|
| + return SEND_PACKET;
|
| + }
|
| + }
|
|
|
| - return DROP_PACKET;
|
| + // Simulate 5% packet loss. Record what media packets, and corresponding
|
| + // timestamps, that were dropped.
|
| + if (random_.Rand(1, 100) <= 5) {
|
| + if (payload_type == test::CallTest::kFakeVideoSendPayloadType) {
|
| + dropped_sequence_numbers_.insert(header.sequenceNumber);
|
| + dropped_timestamps_.insert(header.timestamp);
|
| }
|
|
|
| - return SEND_PACKET;
|
| + return DROP_PACKET;
|
| }
|
|
|
| - void OnFrame(const VideoFrame& video_frame) override {
|
| - rtc::CritScope lock(&crit_);
|
| - // Rendering frame with timestamp of packet that was dropped -> FEC
|
| - // protection worked.
|
| - auto it = dropped_timestamps_.find(video_frame.timestamp());
|
| - if (it != dropped_timestamps_.end())
|
| - observation_complete_.Set();
|
| - }
|
| + return SEND_PACKET;
|
| + }
|
|
|
| - void ModifyVideoConfigs(
|
| - VideoSendStream::Config* send_config,
|
| - std::vector<VideoReceiveStream::Config>* receive_configs,
|
| - VideoEncoderConfig* encoder_config) override {
|
| - (*receive_configs)[0].renderer = this;
|
| + Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
|
| + test::RtcpPacketParser parser;
|
| +
|
| + parser.Parse(data, length);
|
| + if (parser.sender_ssrc() == kFlexfecLocalSsrc) {
|
| + EXPECT_EQ(1, parser.receiver_report()->num_packets());
|
| + const std::vector<rtcp::ReportBlock>& report_blocks =
|
| + parser.receiver_report()->report_blocks();
|
| + if (!report_blocks.empty()) {
|
| + EXPECT_EQ(1U, report_blocks.size());
|
| + EXPECT_EQ(test::CallTest::kFlexfecSendSsrc,
|
| + report_blocks[0].source_ssrc());
|
| + received_flexfec_rtcp_ = true;
|
| + }
|
| }
|
|
|
| - void PerformTest() override {
|
| - EXPECT_TRUE(Wait())
|
| - << "Timed out waiting for dropped frames to be rendered.";
|
| + return SEND_PACKET;
|
| + }
|
| +
|
| + void OnFrame(const VideoFrame& video_frame) override {
|
| + rtc::CritScope lock(&crit_);
|
| + // Rendering frame with timestamp of packet that was dropped -> FEC
|
| + // protection worked.
|
| + auto it = dropped_timestamps_.find(video_frame.timestamp());
|
| + if (it != dropped_timestamps_.end()) {
|
| + if (!expect_flexfec_rtcp_ || received_flexfec_rtcp_) {
|
| + observation_complete_.Set();
|
| + }
|
| }
|
| + }
|
|
|
| - rtc::CriticalSection crit_;
|
| - std::set<uint32_t> dropped_sequence_numbers_ GUARDED_BY(crit_);
|
| - // Since several packets can have the same timestamp a multiset is used
|
| - // instead of a set.
|
| - std::multiset<uint32_t> dropped_timestamps_ GUARDED_BY(crit_);
|
| - Random random_;
|
| - } test;
|
| + void ModifyVideoConfigs(
|
| + VideoSendStream::Config* send_config,
|
| + std::vector<VideoReceiveStream::Config>* receive_configs,
|
| + VideoEncoderConfig* encoder_config) override {
|
| + (*receive_configs)[0].rtp.local_ssrc = kVideoLocalSsrc;
|
| + (*receive_configs)[0].renderer = this;
|
| + }
|
| +
|
| + void ModifyFlexfecConfigs(
|
| + std::vector<FlexfecReceiveStream::Config>* receive_configs) override {
|
| + (*receive_configs)[0].local_ssrc = kFlexfecLocalSsrc;
|
| + }
|
| +
|
| + void PerformTest() override {
|
| + EXPECT_TRUE(Wait())
|
| + << "Timed out waiting for dropped frames to be rendered.";
|
| + }
|
| +
|
| + rtc::CriticalSection crit_;
|
| + std::set<uint32_t> dropped_sequence_numbers_ GUARDED_BY(crit_);
|
| + // Since several packets can have the same timestamp a multiset is used
|
| + // instead of a set.
|
| + std::multiset<uint32_t> dropped_timestamps_ GUARDED_BY(crit_);
|
| + bool expect_flexfec_rtcp_;
|
| + bool received_flexfec_rtcp_;
|
| + Random random_;
|
| +};
|
| +
|
| +TEST_P(EndToEndTest, ReceivesFlexfec) {
|
| + FlexfecRenderObserver test(false);
|
| + RunBaseTest(&test);
|
| +}
|
|
|
| +TEST_P(EndToEndTest, ReceivesFlexfecAndSendsCorrespondingRtcp) {
|
| + FlexfecRenderObserver test(true);
|
| RunBaseTest(&test);
|
| }
|
|
|
|
|