/* * Copyright 2018 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include #include "call/test/mock_bitrate_allocator.h" #include "call/test/mock_rtp_transport_controller_send.h" #include "logging/rtc_event_log/rtc_event_log.h" #include "modules/video_coding/fec_controller_default.h" #include "rtc_base/experiments/alr_experiment.h" #include "rtc_base/task_queue_for_test.h" #include "test/field_trial.h" #include "test/gmock.h" #include "test/gtest.h" #include "test/mock_transport.h" #include "video/test/mock_video_stream_encoder.h" #include "video/video_send_stream_impl.h" namespace webrtc { namespace internal { namespace { using testing::NiceMock; using testing::StrictMock; using testing::ReturnRef; using testing::Return; using testing::Invoke; using testing::_; constexpr int64_t kDefaultInitialBitrateBps = 333000; const double kDefaultBitratePriority = 0.5; const float kAlrProbingExperimentPaceMultiplier = 1.0f; std::string GetAlrProbingExperimentString() { return std::string( AlrExperimentSettings::kScreenshareProbingBweExperimentName) + "/1.0,2875,80,40,-60,3/"; } } // namespace class VideoSendStreamImplTest : public ::testing::Test { protected: VideoSendStreamImplTest() : clock_(1000 * 1000 * 1000), config_(&transport_), send_delay_stats_(&clock_), retransmission_limiter_(&clock_, 1000), test_queue_("test_queue"), process_thread_(ProcessThread::Create("test_thread")), call_stats_(&clock_, process_thread_.get()), stats_proxy_(&clock_, config_, VideoEncoderConfig::ContentType::kRealtimeVideo) { config_.rtp.ssrcs.push_back(8080); config_.rtp.payload_type = 1; EXPECT_CALL(transport_controller_, keepalive_config()) .WillRepeatedly(ReturnRef(keepalive_config_)); EXPECT_CALL(transport_controller_, packet_router()) .WillRepeatedly(Return(&packet_router_)); } ~VideoSendStreamImplTest() {} std::unique_ptr CreateVideoSendStreamImpl( int initial_encoder_max_bitrate, double initial_encoder_bitrate_priority, VideoEncoderConfig::ContentType content_type) { EXPECT_CALL(bitrate_allocator_, GetStartBitrate(_)) .WillOnce(Return(123000)); std::map suspended_ssrcs; std::map suspended_payload_states; return rtc::MakeUnique( &stats_proxy_, &test_queue_, &call_stats_, &transport_controller_, &bitrate_allocator_, &send_delay_stats_, &video_stream_encoder_, &event_log_, &config_, initial_encoder_max_bitrate, initial_encoder_bitrate_priority, suspended_ssrcs, suspended_payload_states, content_type, rtc::MakeUnique(&clock_), &retransmission_limiter_); } protected: NiceMock transport_; NiceMock transport_controller_; NiceMock bitrate_allocator_; NiceMock video_stream_encoder_; SimulatedClock clock_; RtcEventLogNullImpl event_log_; VideoSendStream::Config config_; SendDelayStats send_delay_stats_; RateLimiter retransmission_limiter_; rtc::test::TaskQueueForTest test_queue_; std::unique_ptr process_thread_; CallStats call_stats_; SendStatisticsProxy stats_proxy_; PacketRouter packet_router_; RtpKeepAliveConfig keepalive_config_; }; TEST_F(VideoSendStreamImplTest, RegistersAsBitrateObserverOnStart) { test_queue_.SendTask([this] { config_.track_id = "test"; const bool kSuspend = false; config_.suspend_below_min_bitrate = kSuspend; auto vss_impl = CreateVideoSendStreamImpl( kDefaultInitialBitrateBps, kDefaultBitratePriority, VideoEncoderConfig::ContentType::kRealtimeVideo); EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _)) .WillOnce(Invoke( [&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) { EXPECT_EQ(config.min_bitrate_bps, 0u); EXPECT_EQ(config.max_bitrate_bps, kDefaultInitialBitrateBps); EXPECT_EQ(config.pad_up_bitrate_bps, 0u); EXPECT_EQ(config.enforce_min_bitrate, !kSuspend); EXPECT_EQ(config.track_id, "test"); EXPECT_EQ(config.bitrate_priority, kDefaultBitratePriority); EXPECT_EQ(config.has_packet_feedback, false); })); vss_impl->Start(); EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get())).Times(1); vss_impl->Stop(); }); } TEST_F(VideoSendStreamImplTest, ReportFeedbackAvailability) { test_queue_.SendTask([this] { config_.rtp.extensions.emplace_back( RtpExtension::kTransportSequenceNumberUri, RtpExtension::kTransportSequenceNumberDefaultId); auto vss_impl = CreateVideoSendStreamImpl( kDefaultInitialBitrateBps, kDefaultBitratePriority, VideoEncoderConfig::ContentType::kRealtimeVideo); EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _)) .WillOnce(Invoke( [&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) { EXPECT_EQ(config.has_packet_feedback, true); })); vss_impl->Start(); EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get())).Times(1); vss_impl->Stop(); }); } TEST_F(VideoSendStreamImplTest, SetsScreensharePacingFactorWithFeedback) { test::ScopedFieldTrials alr_experiment(GetAlrProbingExperimentString()); test_queue_.SendTask([this] { config_.rtp.extensions.emplace_back( RtpExtension::kTransportSequenceNumberUri, RtpExtension::kTransportSequenceNumberDefaultId); EXPECT_CALL(transport_controller_, SetPacingFactor(kAlrProbingExperimentPaceMultiplier)) .Times(1); auto vss_impl = CreateVideoSendStreamImpl( kDefaultInitialBitrateBps, kDefaultBitratePriority, VideoEncoderConfig::ContentType::kScreen); vss_impl->Start(); vss_impl->Stop(); }); } TEST_F(VideoSendStreamImplTest, DoesNotSetPacingFactorWithoutFeedback) { test::ScopedFieldTrials alr_experiment(GetAlrProbingExperimentString()); test_queue_.SendTask([this] { EXPECT_CALL(transport_controller_, SetPacingFactor(_)).Times(0); auto vss_impl = CreateVideoSendStreamImpl( kDefaultInitialBitrateBps, kDefaultBitratePriority, VideoEncoderConfig::ContentType::kScreen); vss_impl->Start(); vss_impl->Stop(); }); } } // namespace internal } // namespace webrtc