Chromium Code Reviews| 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..271c8e053dbff07fd8bf12d62a3533453e1f69ca 100644 |
| --- a/webrtc/video/end_to_end_tests.cc |
| +++ b/webrtc/video/end_to_end_tests.cc |
| @@ -666,6 +666,93 @@ TEST_F(EndToEndTest, CanReceiveUlpfec) { |
| 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); |
| + } |
| + |
| + if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) { |
|
stefan-webrtc
2016/11/15 14:21:44
I prefer find() over count as it's cheaper.
brandtr
2016/11/15 14:29:47
Done.
|
| + // Retransmitted packet, should not count. |
| + protected_sequence_numbers_.erase(header.sequenceNumber); |
|
stefan-webrtc
2016/11/15 14:21:44
And then you can erase what you found here.
brandtr
2016/11/15 14:29:47
Done.
|
| + EXPECT_GT(protected_timestamps_.count(header.timestamp), 0u); |
| + protected_timestamps_.erase(header.timestamp); |
| + 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. |
| + if (protected_timestamps_.count(video_frame.timestamp()) != 0) |
| + 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 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, ReceivedUlpfecPacketsNotNacked) { |
| class UlpfecNackObserver : public test::EndToEndTest { |
| public: |
| @@ -3709,6 +3796,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 +3814,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 +3835,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 { |