diff --git a/video/video_send_stream.cc b/video/video_send_stream.cc index f3af9958f3..c1fb177428 100644 --- a/video/video_send_stream.cc +++ b/video/video_send_stream.cc @@ -49,7 +49,7 @@ namespace { const size_t kPathMTU = 1500; std::vector CreateRtpRtcpModules( - Transport* outgoing_transport, + const VideoSendStream::Config& config, RtcpIntraFrameObserver* intra_frame_callback, RtcpBandwidthObserver* bandwidth_callback, RtpTransportControllerSendInterface* transport, @@ -60,15 +60,12 @@ std::vector CreateRtpRtcpModules( RtcEventLog* event_log, RateLimiter* retransmission_rate_limiter, OverheadObserver* overhead_observer, - size_t num_modules, - RtpKeepAliveConfig keepalive_config, - RtcpIntervalConfig rtcp_interval_config) { - RTC_DCHECK_GT(num_modules, 0); + RtpKeepAliveConfig keepalive_config) { + RTC_DCHECK_GT(config.rtp.ssrcs.size(), 0); RtpRtcp::Configuration configuration; configuration.audio = false; configuration.receiver_only = false; - configuration.flexfec_sender = flexfec_sender; - configuration.outgoing_transport = outgoing_transport; + configuration.outgoing_transport = config.send_transport; configuration.intra_frame_callback = intra_frame_callback; configuration.bandwidth_callback = bandwidth_callback; configuration.transport_feedback_callback = @@ -86,9 +83,19 @@ std::vector CreateRtpRtcpModules( configuration.retransmission_rate_limiter = retransmission_rate_limiter; configuration.overhead_observer = overhead_observer; configuration.keepalive_config = keepalive_config; - configuration.rtcp_interval_config = rtcp_interval_config; + configuration.rtcp_interval_config.video_interval_ms = + config.rtcp.video_report_interval_ms; + configuration.rtcp_interval_config.audio_interval_ms = + config.rtcp.audio_report_interval_ms; std::vector modules; - for (size_t i = 0; i < num_modules; ++i) { + const std::vector& flexfec_protected_ssrcs = + config.rtp.flexfec.protected_media_ssrcs; + for (uint32_t ssrc : config.rtp.ssrcs) { + bool enable_flexfec = flexfec_sender != nullptr && + std::find(flexfec_protected_ssrcs.begin(), + flexfec_protected_ssrcs.end(), + ssrc) != flexfec_protected_ssrcs.end(); + configuration.flexfec_sender = enable_flexfec ? flexfec_sender : nullptr; RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration); rtp_rtcp->SetSendingStatus(false); rtp_rtcp->SetSendingMediaStatus(false); @@ -119,14 +126,6 @@ std::unique_ptr MaybeCreateFlexfecSender( return nullptr; } - if (config.rtp.ssrcs.size() > 1) { - RTC_LOG(LS_WARNING) - << "Both FlexFEC and simulcast are enabled. This " - "combination is however not supported by our current " - "FlexFEC implementation. Therefore disabling FlexFEC."; - return nullptr; - } - if (config.rtp.flexfec.protected_media_ssrcs.size() > 1) { RTC_LOG(LS_WARNING) << "The supplied FlexfecConfig contained multiple protected " @@ -791,7 +790,7 @@ VideoSendStreamImpl::VideoSendStreamImpl( video_stream_encoder), bandwidth_observer_(transport->GetBandwidthObserver()), rtp_rtcp_modules_(CreateRtpRtcpModules( - config_->send_transport, + *config_, &encoder_feedback_, bandwidth_observer_, transport, @@ -802,10 +801,7 @@ VideoSendStreamImpl::VideoSendStreamImpl( event_log, transport->GetRetransmissionRateLimiter(), this, - config_->rtp.ssrcs.size(), - transport->keepalive_config(), - RtcpIntervalConfig{config_->rtcp.video_report_interval_ms, - config_->rtcp.audio_report_interval_ms})), + transport->keepalive_config())), payload_router_(rtp_rtcp_modules_, config_->rtp.ssrcs, config_->encoder_settings.payload_type, diff --git a/video/video_send_stream_tests.cc b/video/video_send_stream_tests.cc index 26ac918219..7a64ac1ced 100644 --- a/video/video_send_stream_tests.cc +++ b/video/video_send_stream_tests.cc @@ -38,6 +38,7 @@ #include "test/frame_generator.h" #include "test/frame_generator_capturer.h" #include "test/frame_utils.h" +#include "test/gmock.h" #include "test/gtest.h" #include "test/null_transport.h" #include "test/rtcp_packet_parser.h" @@ -634,16 +635,19 @@ class FlexfecObserver : public test::EndToEndTest { FlexfecObserver(bool header_extensions_enabled, bool use_nack, const std::string& codec, - VideoEncoder* encoder) + VideoEncoder* encoder, + size_t num_video_streams) : EndToEndTest(VideoSendStreamTest::kDefaultTimeoutMs), encoder_(encoder), payload_name_(codec), use_nack_(use_nack), sent_media_(false), sent_flexfec_(false), - header_extensions_enabled_(header_extensions_enabled) {} + header_extensions_enabled_(header_extensions_enabled), + num_video_streams_(num_video_streams) {} size_t GetNumFlexfecStreams() const override { return 1; } + size_t GetNumVideoStreams() const override { return num_video_streams_; } private: Action OnSendRtp(const uint8_t* packet, size_t length) override { @@ -656,7 +660,9 @@ class FlexfecObserver : public test::EndToEndTest { } else { EXPECT_EQ(VideoSendStreamTest::kFakeVideoSendPayloadType, header.payloadType); - EXPECT_EQ(VideoSendStreamTest::kVideoSendSsrcs[0], header.ssrc); + EXPECT_THAT(testing::make_tuple(VideoSendStreamTest::kVideoSendSsrcs, + num_video_streams_), + testing::Contains(header.ssrc)); sent_media_ = true; } @@ -718,37 +724,44 @@ class FlexfecObserver : public test::EndToEndTest { const bool use_nack_; bool sent_media_; bool sent_flexfec_; - bool header_extensions_enabled_; + const bool header_extensions_enabled_; + const size_t num_video_streams_; }; TEST_F(VideoSendStreamTest, SupportsFlexfecVp8) { std::unique_ptr encoder(VP8Encoder::Create()); - FlexfecObserver test(false, false, "VP8", encoder.get()); + FlexfecObserver test(false, false, "VP8", encoder.get(), 1); + RunBaseTest(&test); +} + +TEST_F(VideoSendStreamTest, SupportsFlexfecSimulcastVp8) { + std::unique_ptr encoder(VP8Encoder::Create()); + FlexfecObserver test(false, false, "VP8", encoder.get(), 2); RunBaseTest(&test); } TEST_F(VideoSendStreamTest, SupportsFlexfecWithNackVp8) { std::unique_ptr encoder(VP8Encoder::Create()); - FlexfecObserver test(false, true, "VP8", encoder.get()); + FlexfecObserver test(false, true, "VP8", encoder.get(), 1); RunBaseTest(&test); } TEST_F(VideoSendStreamTest, SupportsFlexfecWithRtpExtensionsVp8) { std::unique_ptr encoder(VP8Encoder::Create()); - FlexfecObserver test(true, false, "VP8", encoder.get()); + FlexfecObserver test(true, false, "VP8", encoder.get(), 1); RunBaseTest(&test); } #if !defined(RTC_DISABLE_VP9) TEST_F(VideoSendStreamTest, SupportsFlexfecVp9) { std::unique_ptr encoder(VP9Encoder::Create()); - FlexfecObserver test(false, false, "VP9", encoder.get()); + FlexfecObserver test(false, false, "VP9", encoder.get(), 1); RunBaseTest(&test); } TEST_F(VideoSendStreamTest, SupportsFlexfecWithNackVp9) { std::unique_ptr encoder(VP9Encoder::Create()); - FlexfecObserver test(false, true, "VP9", encoder.get()); + FlexfecObserver test(false, true, "VP9", encoder.get(), 1); RunBaseTest(&test); } #endif // defined(RTC_DISABLE_VP9) @@ -756,21 +769,21 @@ TEST_F(VideoSendStreamTest, SupportsFlexfecWithNackVp9) { TEST_F(VideoSendStreamTest, SupportsFlexfecH264) { std::unique_ptr encoder( new test::FakeH264Encoder(Clock::GetRealTimeClock())); - FlexfecObserver test(false, false, "H264", encoder.get()); + FlexfecObserver test(false, false, "H264", encoder.get(), 1); RunBaseTest(&test); } TEST_F(VideoSendStreamTest, SupportsFlexfecWithNackH264) { std::unique_ptr encoder( new test::FakeH264Encoder(Clock::GetRealTimeClock())); - FlexfecObserver test(false, true, "H264", encoder.get()); + FlexfecObserver test(false, true, "H264", encoder.get(), 1); RunBaseTest(&test); } TEST_F(VideoSendStreamTest, SupportsFlexfecWithMultithreadedH264) { std::unique_ptr encoder( new test::MultithreadedFakeH264Encoder(Clock::GetRealTimeClock())); - FlexfecObserver test(false, false, "H264", encoder.get()); + FlexfecObserver test(false, false, "H264", encoder.get(), 1); RunBaseTest(&test); }