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 52ff43e11d37a353482d60bc3d1600c4111d30c2..fff5b0e5e6121fbb9416acfce2e38ba605036436 100644 |
--- a/webrtc/video/end_to_end_tests.cc |
+++ b/webrtc/video/end_to_end_tests.cc |
@@ -655,7 +655,97 @@ TEST_F(EndToEndTest, CanReceiveUlpfec) { |
void PerformTest() override { |
EXPECT_TRUE(Wait()) |
- << "Timed out waiting for dropped frames frames to be rendered."; |
+ << "Timed out waiting for dropped frames to be rendered."; |
+ } |
+ |
+ rtc::CriticalSection crit_; |
+ std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_); |
+ std::set<uint32_t> protected_timestamps_ GUARDED_BY(crit_); |
+ } test; |
+ |
+ RunBaseTest(&test); |
+} |
+ |
+TEST_F(EndToEndTest, CanReceiveFlexfec) { |
+ class FlexfecRenderObserver : public test::EndToEndTest, |
+ public rtc::VideoSinkInterface<VideoFrame> { |
+ public: |
+ FlexfecRenderObserver() |
+ : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {} |
+ |
+ size_t GetNumFlexfecStreams() const override { return 1; } |
+ |
+ private: |
+ Action OnSendRtp(const uint8_t* packet, size_t length) override { |
+ rtc::CritScope lock(&crit_); |
+ RTPHeader header; |
+ EXPECT_TRUE(parser_->Parse(packet, length, &header)); |
+ |
+ uint8_t payload_type = header.payloadType; |
+ if (payload_type != kFakeVideoSendPayloadType) { |
+ EXPECT_EQ(kFlexfecPayloadType, payload_type); |
+ } |
+ |
+ auto seq_num_it = protected_sequence_numbers_.find(header.sequenceNumber); |
+ if (seq_num_it != protected_sequence_numbers_.end()) { |
+ // Retransmitted packet, should not count. |
+ protected_sequence_numbers_.erase(seq_num_it); |
+ auto ts_it = protected_timestamps_.find(header.timestamp); |
+ EXPECT_NE(ts_it, protected_timestamps_.end()); |
+ protected_timestamps_.erase(ts_it); |
+ return SEND_PACKET; |
+ } |
+ |
+ switch (state_) { |
+ case kFirstPacket: |
+ state_ = kDropEveryOtherPacketUntilFlexfec; |
+ break; |
+ case kDropEveryOtherPacketUntilFlexfec: |
+ if (payload_type == kFlexfecPayloadType) { |
+ state_ = kDropNextMediaPacket; |
+ return SEND_PACKET; |
+ } |
+ if (header.sequenceNumber % 2 == 0) |
+ return DROP_PACKET; |
+ break; |
+ case kDropNextMediaPacket: |
+ if (payload_type == kFakeVideoSendPayloadType) { |
+ protected_sequence_numbers_.insert(header.sequenceNumber); |
+ protected_timestamps_.insert(header.timestamp); |
+ state_ = kDropEveryOtherPacketUntilFlexfec; |
+ return DROP_PACKET; |
+ } |
+ break; |
+ } |
+ |
+ 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 = protected_timestamps_.find(video_frame.timestamp()); |
+ if (it != protected_timestamps_.end()) |
+ observation_complete_.Set(); |
+ } |
+ |
+ enum { |
+ kFirstPacket, |
+ kDropEveryOtherPacketUntilFlexfec, |
+ kDropNextMediaPacket, |
+ } state_; |
+ |
+ void ModifyVideoConfigs( |
+ VideoSendStream::Config* send_config, |
+ std::vector<VideoReceiveStream::Config>* receive_configs, |
+ VideoEncoderConfig* encoder_config) override { |
+ (*receive_configs)[0].renderer = this; |
+ } |
+ |
+ void PerformTest() override { |
+ EXPECT_TRUE(Wait()) |
+ << "Timed out waiting for dropped frames to be rendered."; |
} |
rtc::CriticalSection crit_; |
@@ -3709,6 +3799,13 @@ void VerifyEmptyUlpfecConfig(const UlpfecConfig& config) { |
<< "Enabling RTX in ULPFEC requires rtpmap: rtx negotiation."; |
} |
+void VerifyEmptyFlexfecConfig(const FlexfecConfig& config) { |
+ EXPECT_EQ(-1, config.flexfec_payload_type) |
+ << "Enabling FlexFEC requires rtpmap: flexfec negotiation."; |
+ EXPECT_TRUE(config.protected_media_ssrcs.empty()) |
+ << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation."; |
+} |
+ |
TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) { |
VideoSendStream::Config default_send_config(nullptr); |
EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms) |
@@ -3720,9 +3817,10 @@ TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) { |
VerifyEmptyNackConfig(default_send_config.rtp.nack); |
VerifyEmptyUlpfecConfig(default_send_config.rtp.ulpfec); |
+ VerifyEmptyFlexfecConfig(default_send_config.rtp.flexfec); |
} |
-TEST_F(EndToEndTest, VerifyDefaultReceiveConfigParameters) { |
+TEST_F(EndToEndTest, VerifyDefaultVideoReceiveConfigParameters) { |
VideoReceiveStream::Config default_receive_config(nullptr); |
EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode) |
<< "Reduced-size RTCP require rtcp-rsize to be negotiated."; |
@@ -3740,6 +3838,11 @@ TEST_F(EndToEndTest, VerifyDefaultReceiveConfigParameters) { |
VerifyEmptyUlpfecConfig(default_receive_config.rtp.ulpfec); |
} |
+TEST_F(EndToEndTest, VerifyDefaultFlexfecReceiveConfigParameters) { |
+ FlexfecReceiveStream::Config default_receive_config; |
+ VerifyEmptyFlexfecConfig(default_receive_config); |
+} |
+ |
TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) { |
static const int kExtensionId = 8; |
class TransportSequenceNumberTest : public test::EndToEndTest { |