diff --git a/test/call_test.cc b/test/call_test.cc index 7d782503da..805829e3c5 100644 --- a/test/call_test.cc +++ b/test/call_test.cc @@ -166,6 +166,7 @@ void CallTest::RunBaseTest(BaseTest* test) { int height = kDefaultHeight; int frame_rate = kDefaultFramerate; test->ModifyVideoCaptureStartResolution(&width, &height, &frame_rate); + test->ModifyVideoDegradationPreference(°radation_preference_); CreateFrameGeneratorCapturer(frame_rate, width, height); test->OnFrameGeneratorCapturerCreated(frame_generator_capturer_); } @@ -783,6 +784,9 @@ void BaseTest::ModifyVideoCaptureStartResolution(int* width, int* heigt, int* frame_rate) {} +void BaseTest::ModifyVideoDegradationPreference( + DegradationPreference* degradation_preference) {} + void BaseTest::OnVideoStreamsCreated( VideoSendStream* send_stream, const std::vector& receive_streams) {} diff --git a/test/call_test.h b/test/call_test.h index 674244ec6c..5050282000 100644 --- a/test/call_test.h +++ b/test/call_test.h @@ -263,6 +263,9 @@ class BaseTest : public RtpRtcpObserver { virtual void ModifyVideoCaptureStartResolution(int* width, int* heigt, int* frame_rate); + virtual void ModifyVideoDegradationPreference( + DegradationPreference* degradation_preference); + virtual void OnVideoStreamsCreated( VideoSendStream* send_stream, const std::vector& receive_streams); diff --git a/video/BUILD.gn b/video/BUILD.gn index bc8b5a5804..824f1c15ec 100644 --- a/video/BUILD.gn +++ b/video/BUILD.gn @@ -411,6 +411,7 @@ if (rtc_include_tests) { defines = [] sources = [ "call_stats_unittest.cc", + "cpu_scaling_tests.cc", "encoder_rtcp_feedback_unittest.cc", "end_to_end_tests/bandwidth_tests.cc", "end_to_end_tests/call_operation_tests.cc", diff --git a/video/cpu_scaling_tests.cc b/video/cpu_scaling_tests.cc new file mode 100644 index 0000000000..608f05e052 --- /dev/null +++ b/video/cpu_scaling_tests.cc @@ -0,0 +1,131 @@ +/* + * Copyright (c) 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 "test/call_test.h" +#include "test/field_trial.h" +#include "test/frame_generator_capturer.h" + +namespace webrtc { +namespace { +constexpr int kWidth = 1280; +constexpr int kHeight = 720; +constexpr int kFps = 28; +} // namespace + +// Minimal normal usage at start, then 60s overuse. +class CpuOveruseTest : public test::CallTest { + protected: + CpuOveruseTest() + : field_trials_("WebRTC-ForceSimulatedOveruseIntervalMs/1-60000-60000/") { + } + + void RunTestAndCheckForAdaptation( + const DegradationPreference& degradation_preference, + bool expect_adaptation); + + test::ScopedFieldTrials field_trials_; +}; + +void CpuOveruseTest::RunTestAndCheckForAdaptation( + const DegradationPreference& degradation_preference, + bool expect_adaptation) { + class OveruseObserver + : public test::SendTest, + public test::FrameGeneratorCapturer::SinkWantsObserver { + public: + OveruseObserver(const DegradationPreference& degradation_preference, + bool expect_adaptation) + : SendTest(expect_adaptation ? kLongTimeoutMs : kDefaultTimeoutMs), + degradation_preference_(degradation_preference), + expect_adaptation_(expect_adaptation) {} + + private: + void OnFrameGeneratorCapturerCreated( + test::FrameGeneratorCapturer* frame_generator_capturer) override { + frame_generator_capturer->SetSinkWantsObserver(this); + // Set initial resolution. + frame_generator_capturer->ChangeResolution(kWidth, kHeight); + } + + // Called when FrameGeneratorCapturer::AddOrUpdateSink is called. + void OnSinkWantsChanged(rtc::VideoSinkInterface* sink, + const rtc::VideoSinkWants& wants) override { + if (wants.max_pixel_count == std::numeric_limits::max() && + wants.max_framerate_fps == kFps) { + // Max configured framerate is initially set. + return; + } + switch (degradation_preference_) { + case DegradationPreference::MAINTAIN_FRAMERATE: + EXPECT_LT(wants.max_pixel_count, kWidth * kHeight); + observation_complete_.Set(); + break; + case DegradationPreference::MAINTAIN_RESOLUTION: + EXPECT_LT(wants.max_framerate_fps, kFps); + observation_complete_.Set(); + break; + case DegradationPreference::BALANCED: + if (wants.max_pixel_count == std::numeric_limits::max() && + wants.max_framerate_fps == std::numeric_limits::max()) { + // |adapt_counters_| map in VideoStreamEncoder is reset when + // balanced mode is set. + break; + } + EXPECT_TRUE(wants.max_pixel_count < kWidth * kHeight || + wants.max_framerate_fps < kFps); + observation_complete_.Set(); + break; + default: + RTC_NOTREACHED(); + } + } + + void ModifyVideoConfigs( + VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { + EXPECT_FALSE(encoder_config->simulcast_layers.empty()); + encoder_config->simulcast_layers[0].max_framerate = kFps; + } + + void ModifyVideoDegradationPreference( + DegradationPreference* degradation_preference) override { + *degradation_preference = degradation_preference_; + } + + void PerformTest() override { + EXPECT_EQ(expect_adaptation_, Wait()) + << "Timed out while waiting for a scale down."; + } + + const DegradationPreference degradation_preference_; + const bool expect_adaptation_; + } test(degradation_preference, expect_adaptation); + + RunBaseTest(&test); +} + +TEST_F(CpuOveruseTest, AdaptsDownInResolutionOnOveruse) { + RunTestAndCheckForAdaptation(DegradationPreference::MAINTAIN_FRAMERATE, true); +} + +TEST_F(CpuOveruseTest, AdaptsDownInFpsOnOveruse) { + RunTestAndCheckForAdaptation(DegradationPreference::MAINTAIN_RESOLUTION, + true); +} + +TEST_F(CpuOveruseTest, AdaptsDownInResolutionOrFpsOnOveruse) { + RunTestAndCheckForAdaptation(DegradationPreference::BALANCED, true); +} + +TEST_F(CpuOveruseTest, NoAdaptDownOnOveruse) { + RunTestAndCheckForAdaptation(DegradationPreference::DISABLED, false); +} +} // namespace webrtc