aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenrik Boström <hbos@webrtc.org>2020-04-29 16:46:30 +0200
committerCommit Bot <commit-bot@chromium.org>2020-04-29 15:59:14 +0000
commit722fa4d50924ba35bd5bf76283222c43af23cdab (patch)
tree1dc9df71498230a874c824403bce31a81e90bc21
parentbb826c9142e370574335a0529d45cd4a6b3a0c19 (diff)
downloadwebrtc-722fa4d50924ba35bd5bf76283222c43af23cdab.tar.gz
[Adaptation] Misc tests for processor, input provider and restrictions.
This CL adds miscellaneous unit tests for the ResourceAdaptationProcessor, the VideoSourceRestrictions comparators and the VideoStreamInputStateProvider. Bug: webrtc:11172 Change-Id: If95f69644aaf2b43e3b19d5729bedef0b438c77b Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/174101 Reviewed-by: Evan Shrubsole <eshr@google.com> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Commit-Queue: Henrik Boström <hbos@webrtc.org> Cr-Commit-Position: refs/heads/master@{#31147}
-rw-r--r--call/adaptation/BUILD.gn7
-rw-r--r--call/adaptation/resource_adaptation_processor_unittest.cc257
-rw-r--r--call/adaptation/test/fake_frame_rate_provider.cc27
-rw-r--r--call/adaptation/test/fake_frame_rate_provider.h57
-rw-r--r--call/adaptation/test/fake_resource.cc29
-rw-r--r--call/adaptation/test/fake_resource.h13
-rw-r--r--call/adaptation/video_source_restrictions_unittest.cc73
-rw-r--r--call/adaptation/video_stream_adapter.cc7
-rw-r--r--call/adaptation/video_stream_input_state.cc10
-rw-r--r--call/adaptation/video_stream_input_state.h6
-rw-r--r--call/adaptation/video_stream_input_state_provider.cc3
-rw-r--r--call/adaptation/video_stream_input_state_provider_unittest.cc53
-rw-r--r--video/adaptation/quality_scaler_resource.cc4
-rw-r--r--video/adaptation/video_stream_encoder_resource_manager.h3
14 files changed, 531 insertions, 18 deletions
diff --git a/call/adaptation/BUILD.gn b/call/adaptation/BUILD.gn
index 94656cf0a9..deac3156d6 100644
--- a/call/adaptation/BUILD.gn
+++ b/call/adaptation/BUILD.gn
@@ -47,8 +47,11 @@ if (rtc_include_tests) {
testonly = true
sources = [
+ "resource_adaptation_processor_unittest.cc",
"resource_unittest.cc",
+ "video_source_restrictions_unittest.cc",
"video_stream_adapter_unittest.cc",
+ "video_stream_input_state_provider_unittest.cc",
]
deps = [
":resource_adaptation",
@@ -68,12 +71,16 @@ if (rtc_include_tests) {
testonly = true
sources = [
+ "test/fake_frame_rate_provider.cc",
+ "test/fake_frame_rate_provider.h",
"test/fake_resource.cc",
"test/fake_resource.h",
]
deps = [
":resource_adaptation",
+ "../../api/video:video_stream_encoder",
"../../rtc_base:rtc_base_approved",
+ "../../test:test_support",
]
}
}
diff --git a/call/adaptation/resource_adaptation_processor_unittest.cc b/call/adaptation/resource_adaptation_processor_unittest.cc
new file mode 100644
index 0000000000..2e26dbec72
--- /dev/null
+++ b/call/adaptation/resource_adaptation_processor_unittest.cc
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2020 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 "call/adaptation/resource_adaptation_processor.h"
+
+#include "api/video/video_adaptation_counters.h"
+#include "call/adaptation/resource.h"
+#include "call/adaptation/resource_adaptation_processor_interface.h"
+#include "call/adaptation/test/fake_frame_rate_provider.h"
+#include "call/adaptation/test/fake_resource.h"
+#include "call/adaptation/video_source_restrictions.h"
+#include "call/adaptation/video_stream_input_state_provider.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+
+namespace {
+
+const int kDefaultFrameRate = 30;
+const int kDefaultFrameSize = 1280 * 720;
+
+class ResourceAdaptationProcessorListenerForTesting
+ : public ResourceAdaptationProcessorListener {
+ public:
+ ResourceAdaptationProcessorListenerForTesting()
+ : restrictions_updated_count_(0),
+ restrictions_(),
+ adaptation_counters_(),
+ reason_(nullptr) {}
+ ~ResourceAdaptationProcessorListenerForTesting() override {}
+
+ size_t restrictions_updated_count() const {
+ return restrictions_updated_count_;
+ }
+ const VideoSourceRestrictions& restrictions() const { return restrictions_; }
+ const VideoAdaptationCounters& adaptation_counters() const {
+ return adaptation_counters_;
+ }
+ const Resource* reason() const { return reason_; }
+
+ // ResourceAdaptationProcessorListener implementation.
+ void OnVideoSourceRestrictionsUpdated(
+ VideoSourceRestrictions restrictions,
+ const VideoAdaptationCounters& adaptation_counters,
+ const Resource* reason) override {
+ ++restrictions_updated_count_;
+ restrictions_ = restrictions;
+ adaptation_counters_ = adaptation_counters;
+ reason_ = reason;
+ }
+
+ private:
+ size_t restrictions_updated_count_;
+ VideoSourceRestrictions restrictions_;
+ VideoAdaptationCounters adaptation_counters_;
+ const Resource* reason_;
+};
+
+class ResourceAdaptationProcessorTest : public ::testing::Test {
+ public:
+ ResourceAdaptationProcessorTest()
+ : frame_rate_provider_(),
+ input_state_provider_(&frame_rate_provider_),
+ resource_("FakeResource"),
+ processor_(&input_state_provider_,
+ /*encoder_stats_observer=*/&frame_rate_provider_) {
+ processor_.AddAdaptationListener(&processor_listener_);
+ processor_.AddResource(&resource_);
+ }
+ ~ResourceAdaptationProcessorTest() override {
+ processor_.StopResourceAdaptation();
+ }
+
+ void SetInputStates(bool has_input, int fps, int frame_size) {
+ input_state_provider_.OnHasInputChanged(has_input);
+ frame_rate_provider_.set_fps(fps);
+ input_state_provider_.OnFrameSizeObserved(frame_size);
+ }
+
+ void RestrictSource(VideoSourceRestrictions restrictions) {
+ SetInputStates(
+ true, restrictions.max_frame_rate().value_or(kDefaultFrameRate),
+ restrictions.target_pixels_per_frame().has_value()
+ ? restrictions.target_pixels_per_frame().value()
+ : restrictions.max_pixels_per_frame().value_or(kDefaultFrameSize));
+ }
+
+ protected:
+ FakeFrameRateProvider frame_rate_provider_;
+ VideoStreamInputStateProvider input_state_provider_;
+ FakeResource resource_;
+ ResourceAdaptationProcessor processor_;
+ ResourceAdaptationProcessorListenerForTesting processor_listener_;
+};
+
+} // namespace
+
+TEST_F(ResourceAdaptationProcessorTest, DisabledByDefault) {
+ EXPECT_EQ(DegradationPreference::DISABLED,
+ processor_.degradation_preference());
+ EXPECT_EQ(DegradationPreference::DISABLED,
+ processor_.effective_degradation_preference());
+ SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
+ processor_.StartResourceAdaptation();
+ // Adaptation does not happen when disabled.
+ resource_.set_usage_state(ResourceUsageState::kOveruse);
+ EXPECT_EQ(0u, processor_listener_.restrictions_updated_count());
+}
+
+TEST_F(ResourceAdaptationProcessorTest, InsufficientInput) {
+ processor_.SetDegradationPreference(
+ DegradationPreference::MAINTAIN_FRAMERATE);
+ processor_.StartResourceAdaptation();
+ // Adaptation does not happen if input is insufficient.
+ // When frame size is missing (OnFrameSizeObserved not called yet).
+ input_state_provider_.OnHasInputChanged(true);
+ resource_.set_usage_state(ResourceUsageState::kOveruse);
+ EXPECT_EQ(0u, processor_listener_.restrictions_updated_count());
+ // When "has input" is missing.
+ SetInputStates(false, kDefaultFrameRate, kDefaultFrameSize);
+ resource_.set_usage_state(ResourceUsageState::kOveruse);
+ EXPECT_EQ(0u, processor_listener_.restrictions_updated_count());
+ // Note: frame rate cannot be missing, if unset it is 0.
+}
+
+// These tests verify that restrictions are applied, but not exactly how much
+// the source is restricted. This ensures that the VideoStreamAdapter is wired
+// up correctly but not exactly how the VideoStreamAdapter generates
+// restrictions. For that, see video_stream_adapter_unittest.cc.
+TEST_F(ResourceAdaptationProcessorTest,
+ OveruseTriggersRestrictingResolutionInMaintainFrameRate) {
+ processor_.SetDegradationPreference(
+ DegradationPreference::MAINTAIN_FRAMERATE);
+ processor_.StartResourceAdaptation();
+ SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
+ resource_.set_usage_state(ResourceUsageState::kOveruse);
+ EXPECT_EQ(1u, processor_listener_.restrictions_updated_count());
+ EXPECT_TRUE(
+ processor_listener_.restrictions().max_pixels_per_frame().has_value());
+}
+
+TEST_F(ResourceAdaptationProcessorTest,
+ OveruseTriggersRestrictingFrameRateInMaintainResolution) {
+ processor_.SetDegradationPreference(
+ DegradationPreference::MAINTAIN_RESOLUTION);
+ processor_.StartResourceAdaptation();
+ SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
+ resource_.set_usage_state(ResourceUsageState::kOveruse);
+ EXPECT_EQ(1u, processor_listener_.restrictions_updated_count());
+ EXPECT_TRUE(processor_listener_.restrictions().max_frame_rate().has_value());
+}
+
+TEST_F(ResourceAdaptationProcessorTest,
+ OveruseTriggersRestrictingFrameRateAndResolutionInBalanced) {
+ processor_.SetDegradationPreference(DegradationPreference::BALANCED);
+ processor_.StartResourceAdaptation();
+ SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
+ // Adapting multiple times eventually resticts both frame rate and resolution.
+ // Exactly many times we need to adapt depends on BalancedDegradationSettings,
+ // VideoStreamAdapter and default input states. This test requires it to be
+ // achieved within 4 adaptations.
+ for (size_t i = 0; i < 4; ++i) {
+ resource_.set_usage_state(ResourceUsageState::kOveruse);
+ EXPECT_EQ(i + 1, processor_listener_.restrictions_updated_count());
+ RestrictSource(processor_listener_.restrictions());
+ }
+ EXPECT_TRUE(
+ processor_listener_.restrictions().max_pixels_per_frame().has_value());
+ EXPECT_TRUE(processor_listener_.restrictions().max_frame_rate().has_value());
+}
+
+TEST_F(ResourceAdaptationProcessorTest, AwaitingPreviousAdaptation) {
+ processor_.SetDegradationPreference(
+ DegradationPreference::MAINTAIN_FRAMERATE);
+ processor_.StartResourceAdaptation();
+ SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
+ resource_.set_usage_state(ResourceUsageState::kOveruse);
+ EXPECT_EQ(1u, processor_listener_.restrictions_updated_count());
+ // If we don't restrict the source then adaptation will not happen again due
+ // to "awaiting previous adaptation". This prevents "double-adapt".
+ resource_.set_usage_state(ResourceUsageState::kOveruse);
+ EXPECT_EQ(1u, processor_listener_.restrictions_updated_count());
+}
+
+TEST_F(ResourceAdaptationProcessorTest, CannotAdaptUpWhenUnrestricted) {
+ processor_.SetDegradationPreference(
+ DegradationPreference::MAINTAIN_FRAMERATE);
+ processor_.StartResourceAdaptation();
+ SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
+ resource_.set_usage_state(ResourceUsageState::kUnderuse);
+ EXPECT_EQ(0u, processor_listener_.restrictions_updated_count());
+}
+
+TEST_F(ResourceAdaptationProcessorTest, UnderuseTakesUsBackToUnrestricted) {
+ processor_.SetDegradationPreference(
+ DegradationPreference::MAINTAIN_FRAMERATE);
+ processor_.StartResourceAdaptation();
+ SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
+ resource_.set_usage_state(ResourceUsageState::kOveruse);
+ EXPECT_EQ(1u, processor_listener_.restrictions_updated_count());
+ RestrictSource(processor_listener_.restrictions());
+ resource_.set_usage_state(ResourceUsageState::kUnderuse);
+ EXPECT_EQ(2u, processor_listener_.restrictions_updated_count());
+ EXPECT_EQ(VideoSourceRestrictions(), processor_listener_.restrictions());
+}
+
+TEST_F(ResourceAdaptationProcessorTest, ResourcesCanPreventAdaptingUp) {
+ processor_.SetDegradationPreference(
+ DegradationPreference::MAINTAIN_FRAMERATE);
+ processor_.StartResourceAdaptation();
+ SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
+ // Adapt down so that we can adapt up.
+ resource_.set_usage_state(ResourceUsageState::kOveruse);
+ EXPECT_EQ(1u, processor_listener_.restrictions_updated_count());
+ RestrictSource(processor_listener_.restrictions());
+ // Adapting up is prevented.
+ resource_.set_is_adaptation_up_allowed(false);
+ resource_.set_usage_state(ResourceUsageState::kUnderuse);
+ EXPECT_EQ(1u, processor_listener_.restrictions_updated_count());
+}
+
+TEST_F(ResourceAdaptationProcessorTest, AdaptingTriggersOnAdaptationApplied) {
+ processor_.SetDegradationPreference(
+ DegradationPreference::MAINTAIN_FRAMERATE);
+ processor_.StartResourceAdaptation();
+ SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
+ resource_.set_usage_state(ResourceUsageState::kOveruse);
+ EXPECT_EQ(1u, resource_.num_adaptations_applied());
+}
+
+TEST_F(ResourceAdaptationProcessorTest, AdaptingClearsResourceUsageState) {
+ processor_.SetDegradationPreference(
+ DegradationPreference::MAINTAIN_FRAMERATE);
+ processor_.StartResourceAdaptation();
+ SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
+ resource_.set_usage_state(ResourceUsageState::kOveruse);
+ EXPECT_EQ(1u, processor_listener_.restrictions_updated_count());
+ EXPECT_FALSE(resource_.usage_state().has_value());
+}
+
+TEST_F(ResourceAdaptationProcessorTest,
+ FailingAdaptingAlsoClearsResourceUsageState) {
+ processor_.SetDegradationPreference(DegradationPreference::DISABLED);
+ processor_.StartResourceAdaptation();
+ resource_.set_usage_state(ResourceUsageState::kOveruse);
+ EXPECT_EQ(0u, processor_listener_.restrictions_updated_count());
+ EXPECT_FALSE(resource_.usage_state().has_value());
+}
+
+} // namespace webrtc
diff --git a/call/adaptation/test/fake_frame_rate_provider.cc b/call/adaptation/test/fake_frame_rate_provider.cc
new file mode 100644
index 0000000000..65fee6a7ba
--- /dev/null
+++ b/call/adaptation/test/fake_frame_rate_provider.cc
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020 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 "call/adaptation/test/fake_frame_rate_provider.h"
+
+#include "test/gmock.h"
+
+using ::testing::Return;
+
+namespace webrtc {
+
+FakeFrameRateProvider::FakeFrameRateProvider() {
+ set_fps(0);
+}
+
+void FakeFrameRateProvider::set_fps(int fps) {
+ EXPECT_CALL(*this, GetInputFrameRate()).WillRepeatedly(Return(fps));
+}
+
+} // namespace webrtc
diff --git a/call/adaptation/test/fake_frame_rate_provider.h b/call/adaptation/test/fake_frame_rate_provider.h
new file mode 100644
index 0000000000..a08e162321
--- /dev/null
+++ b/call/adaptation/test/fake_frame_rate_provider.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2020 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.
+ */
+
+#ifndef CALL_ADAPTATION_TEST_FAKE_FRAME_RATE_PROVIDER_H_
+#define CALL_ADAPTATION_TEST_FAKE_FRAME_RATE_PROVIDER_H_
+
+#include <string>
+#include <vector>
+
+#include "api/video/video_stream_encoder_observer.h"
+#include "test/gmock.h"
+
+namespace webrtc {
+
+class MockVideoStreamEncoderObserver : public VideoStreamEncoderObserver {
+ public:
+ MOCK_METHOD2(OnEncodedFrameTimeMeasured, void(int, int));
+ MOCK_METHOD2(OnIncomingFrame, void(int, int));
+ MOCK_METHOD2(OnSendEncodedImage,
+ void(const EncodedImage&, const CodecSpecificInfo*));
+ MOCK_METHOD1(OnEncoderImplementationChanged, void(const std::string&));
+ MOCK_METHOD1(OnFrameDropped, void(DropReason));
+ MOCK_METHOD2(OnEncoderReconfigured,
+ void(const VideoEncoderConfig&,
+ const std::vector<VideoStream>&));
+ MOCK_METHOD3(OnAdaptationChanged,
+ void(VideoAdaptationReason,
+ const VideoAdaptationCounters&,
+ const VideoAdaptationCounters&));
+ MOCK_METHOD0(ClearAdaptationStats, void());
+ MOCK_METHOD2(UpdateAdaptationSettings,
+ void(AdaptationSettings, AdaptationSettings));
+ MOCK_METHOD0(OnMinPixelLimitReached, void());
+ MOCK_METHOD0(OnInitialQualityResolutionAdaptDown, void());
+ MOCK_METHOD1(OnSuspendChange, void(bool));
+ MOCK_METHOD2(OnBitrateAllocationUpdated,
+ void(const VideoCodec&, const VideoBitrateAllocation&));
+ MOCK_METHOD1(OnEncoderInternalScalerUpdate, void(bool));
+ MOCK_CONST_METHOD0(GetInputFrameRate, int());
+};
+
+class FakeFrameRateProvider : public MockVideoStreamEncoderObserver {
+ public:
+ FakeFrameRateProvider();
+ void set_fps(int fps);
+};
+
+} // namespace webrtc
+
+#endif // CALL_ADAPTATION_TEST_FAKE_FRAME_RATE_PROVIDER_H_
diff --git a/call/adaptation/test/fake_resource.cc b/call/adaptation/test/fake_resource.cc
index dc2d8c5df9..bd7ad5431f 100644
--- a/call/adaptation/test/fake_resource.cc
+++ b/call/adaptation/test/fake_resource.cc
@@ -15,7 +15,10 @@
namespace webrtc {
FakeResource::FakeResource(std::string name)
- : Resource(), name_(std::move(name)) {}
+ : Resource(),
+ name_(std::move(name)),
+ is_adaptation_up_allowed_(true),
+ num_adaptations_applied_(0) {}
FakeResource::~FakeResource() {}
@@ -23,4 +26,28 @@ void FakeResource::set_usage_state(ResourceUsageState usage_state) {
OnResourceUsageStateMeasured(usage_state);
}
+void FakeResource::set_is_adaptation_up_allowed(bool is_adaptation_up_allowed) {
+ is_adaptation_up_allowed_ = is_adaptation_up_allowed;
+}
+
+size_t FakeResource::num_adaptations_applied() const {
+ return num_adaptations_applied_;
+}
+
+bool FakeResource::IsAdaptationUpAllowed(
+ const VideoStreamInputState& input_state,
+ const VideoSourceRestrictions& restrictions_before,
+ const VideoSourceRestrictions& restrictions_after,
+ const Resource& reason_resource) const {
+ return is_adaptation_up_allowed_;
+}
+
+void FakeResource::OnAdaptationApplied(
+ const VideoStreamInputState& input_state,
+ const VideoSourceRestrictions& restrictions_before,
+ const VideoSourceRestrictions& restrictions_after,
+ const Resource& reason_resource) {
+ ++num_adaptations_applied_;
+}
+
} // namespace webrtc
diff --git a/call/adaptation/test/fake_resource.h b/call/adaptation/test/fake_resource.h
index 2e1dc1b550..0d9b1f46bb 100644
--- a/call/adaptation/test/fake_resource.h
+++ b/call/adaptation/test/fake_resource.h
@@ -24,11 +24,24 @@ class FakeResource : public Resource {
~FakeResource() override;
void set_usage_state(ResourceUsageState usage_state);
+ void set_is_adaptation_up_allowed(bool is_adaptation_up_allowed);
+ size_t num_adaptations_applied() const;
+ // Resource implementation.
std::string name() const override { return name_; }
+ bool IsAdaptationUpAllowed(const VideoStreamInputState& input_state,
+ const VideoSourceRestrictions& restrictions_before,
+ const VideoSourceRestrictions& restrictions_after,
+ const Resource& reason_resource) const override;
+ void OnAdaptationApplied(const VideoStreamInputState& input_state,
+ const VideoSourceRestrictions& restrictions_before,
+ const VideoSourceRestrictions& restrictions_after,
+ const Resource& reason_resource) override;
private:
const std::string name_;
+ bool is_adaptation_up_allowed_;
+ size_t num_adaptations_applied_;
};
} // namespace webrtc
diff --git a/call/adaptation/video_source_restrictions_unittest.cc b/call/adaptation/video_source_restrictions_unittest.cc
new file mode 100644
index 0000000000..eeb4b1d7fd
--- /dev/null
+++ b/call/adaptation/video_source_restrictions_unittest.cc
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2020 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 "call/adaptation/video_source_restrictions.h"
+
+#include "test/gtest.h"
+
+namespace webrtc {
+
+namespace {
+
+VideoSourceRestrictions RestrictionsFromMaxPixelsPerFrame(
+ size_t max_pixels_per_frame) {
+ return VideoSourceRestrictions(max_pixels_per_frame, absl::nullopt,
+ absl::nullopt);
+}
+
+VideoSourceRestrictions RestrictionsFromMaxFrameRate(double max_frame_rate) {
+ return VideoSourceRestrictions(absl::nullopt, absl::nullopt, max_frame_rate);
+}
+
+} // namespace
+
+TEST(VideoSourceRestrictionsTest, DidIncreaseResolution) {
+ // smaller restrictions -> larger restrictions
+ EXPECT_TRUE(DidIncreaseResolution(RestrictionsFromMaxPixelsPerFrame(10),
+ RestrictionsFromMaxPixelsPerFrame(11)));
+ // unrestricted -> restricted
+ EXPECT_FALSE(DidIncreaseResolution(VideoSourceRestrictions(),
+ RestrictionsFromMaxPixelsPerFrame(10)));
+ // restricted -> unrestricted
+ EXPECT_TRUE(DidIncreaseResolution(RestrictionsFromMaxPixelsPerFrame(10),
+ VideoSourceRestrictions()));
+ // restricted -> equally restricted
+ EXPECT_FALSE(DidIncreaseResolution(RestrictionsFromMaxPixelsPerFrame(10),
+ RestrictionsFromMaxPixelsPerFrame(10)));
+ // unrestricted -> unrestricted
+ EXPECT_FALSE(DidIncreaseResolution(VideoSourceRestrictions(),
+ VideoSourceRestrictions()));
+ // larger restrictions -> smaller restrictions
+ EXPECT_FALSE(DidIncreaseResolution(RestrictionsFromMaxPixelsPerFrame(10),
+ RestrictionsFromMaxPixelsPerFrame(9)));
+}
+
+TEST(VideoSourceRestrictionsTest, DidDecreaseFrameRate) {
+ // samller restrictions -> larger restrictions
+ EXPECT_FALSE(DidDecreaseFrameRate(RestrictionsFromMaxFrameRate(10),
+ RestrictionsFromMaxFrameRate(11)));
+ // unrestricted -> restricted
+ EXPECT_TRUE(DidDecreaseFrameRate(VideoSourceRestrictions(),
+ RestrictionsFromMaxFrameRate(10)));
+ // restricted -> unrestricted
+ EXPECT_FALSE(DidDecreaseFrameRate(RestrictionsFromMaxFrameRate(10),
+ VideoSourceRestrictions()));
+ // restricted -> equally restricted
+ EXPECT_FALSE(DidDecreaseFrameRate(RestrictionsFromMaxFrameRate(10),
+ RestrictionsFromMaxFrameRate(10)));
+ // unrestricted -> unrestricted
+ EXPECT_FALSE(DidDecreaseFrameRate(VideoSourceRestrictions(),
+ VideoSourceRestrictions()));
+ // larger restrictions -> samller restrictions
+ EXPECT_TRUE(DidDecreaseFrameRate(RestrictionsFromMaxFrameRate(10),
+ RestrictionsFromMaxFrameRate(9)));
+}
+
+} // namespace webrtc
diff --git a/call/adaptation/video_stream_adapter.cc b/call/adaptation/video_stream_adapter.cc
index 62330e945f..b224e3e4d2 100644
--- a/call/adaptation/video_stream_adapter.cc
+++ b/call/adaptation/video_stream_adapter.cc
@@ -433,7 +433,7 @@ Adaptation VideoStreamAdapter::GetAdaptationUp() const {
}
case DegradationPreference::MAINTAIN_RESOLUTION: {
// Scale up framerate.
- int target_fps = input_state_.frames_per_second().value();
+ int target_fps = input_state_.frames_per_second();
if (source_restrictor_->adaptation_counters().fps_adaptations == 1) {
RTC_LOG(LS_INFO) << "Removing framerate down-scaling setting.";
target_fps = std::numeric_limits<int>::max();
@@ -505,8 +505,7 @@ Adaptation VideoStreamAdapter::GetAdaptationDown() const {
min_pixel_limit_reached);
}
case DegradationPreference::MAINTAIN_RESOLUTION: {
- int target_fps =
- GetLowerFrameRateThan(input_state_.frames_per_second().value());
+ int target_fps = GetLowerFrameRateThan(input_state_.frames_per_second());
if (!source_restrictor_->CanDecreaseFrameRateTo(target_fps)) {
return Adaptation(adaptation_validation_id_,
Adaptation::Status::kLimitReached);
@@ -542,7 +541,7 @@ void VideoStreamAdapter::ApplyAdaptation(const Adaptation& adaptation) {
// adapting again before this adaptation has had an effect.
last_adaptation_request_.emplace(AdaptationRequest{
input_state_.frame_size_pixels().value(),
- input_state_.frames_per_second().value(),
+ input_state_.frames_per_second(),
AdaptationRequest::GetModeFromAdaptationAction(adaptation.step().type)});
// Adapt!
source_restrictor_->ApplyAdaptationStep(adaptation.step(),
diff --git a/call/adaptation/video_stream_input_state.cc b/call/adaptation/video_stream_input_state.cc
index 1827334b21..dc3315e6d0 100644
--- a/call/adaptation/video_stream_input_state.cc
+++ b/call/adaptation/video_stream_input_state.cc
@@ -17,7 +17,7 @@ namespace webrtc {
VideoStreamInputState::VideoStreamInputState()
: has_input_(false),
frame_size_pixels_(absl::nullopt),
- frames_per_second_(absl::nullopt),
+ frames_per_second_(0),
video_codec_type_(VideoCodecType::kVideoCodecGeneric),
min_pixels_per_frame_(kDefaultMinPixelsPerFrame) {}
@@ -30,8 +30,7 @@ void VideoStreamInputState::set_frame_size_pixels(
frame_size_pixels_ = frame_size_pixels;
}
-void VideoStreamInputState::set_frames_per_second(
- absl::optional<int> frames_per_second) {
+void VideoStreamInputState::set_frames_per_second(int frames_per_second) {
frames_per_second_ = frames_per_second;
}
@@ -52,7 +51,7 @@ absl::optional<int> VideoStreamInputState::frame_size_pixels() const {
return frame_size_pixels_;
}
-absl::optional<int> VideoStreamInputState::frames_per_second() const {
+int VideoStreamInputState::frames_per_second() const {
return frames_per_second_;
}
@@ -65,8 +64,7 @@ int VideoStreamInputState::min_pixels_per_frame() const {
}
bool VideoStreamInputState::HasInputFrameSizeAndFramesPerSecond() const {
- return has_input_ && frame_size_pixels_.has_value() &&
- frames_per_second_.has_value();
+ return has_input_ && frame_size_pixels_.has_value();
}
} // namespace webrtc
diff --git a/call/adaptation/video_stream_input_state.h b/call/adaptation/video_stream_input_state.h
index ef80405e75..af0d7c78e9 100644
--- a/call/adaptation/video_stream_input_state.h
+++ b/call/adaptation/video_stream_input_state.h
@@ -24,13 +24,13 @@ class VideoStreamInputState {
void set_has_input(bool has_input);
void set_frame_size_pixels(absl::optional<int> frame_size_pixels);
- void set_frames_per_second(absl::optional<int> frames_per_second);
+ void set_frames_per_second(int frames_per_second);
void set_video_codec_type(VideoCodecType video_codec_type);
void set_min_pixels_per_frame(int min_pixels_per_frame);
bool has_input() const;
absl::optional<int> frame_size_pixels() const;
- absl::optional<int> frames_per_second() const;
+ int frames_per_second() const;
VideoCodecType video_codec_type() const;
int min_pixels_per_frame() const;
@@ -39,7 +39,7 @@ class VideoStreamInputState {
private:
bool has_input_;
absl::optional<int> frame_size_pixels_;
- absl::optional<int> frames_per_second_;
+ int frames_per_second_;
VideoCodecType video_codec_type_;
int min_pixels_per_frame_;
};
diff --git a/call/adaptation/video_stream_input_state_provider.cc b/call/adaptation/video_stream_input_state_provider.cc
index 2548a4802b..eac30bbfac 100644
--- a/call/adaptation/video_stream_input_state_provider.cc
+++ b/call/adaptation/video_stream_input_state_provider.cc
@@ -40,8 +40,7 @@ VideoStreamInputState VideoStreamInputStateProvider::InputState() {
// GetInputFrameRate() is thread-safe.
int input_fps = frame_rate_provider_->GetInputFrameRate();
rtc::CritScope lock(&crit_);
- input_state_.set_frames_per_second(
- input_fps >= 0 ? absl::optional<int>(input_fps) : absl::nullopt);
+ input_state_.set_frames_per_second(input_fps);
return input_state_;
}
diff --git a/call/adaptation/video_stream_input_state_provider_unittest.cc b/call/adaptation/video_stream_input_state_provider_unittest.cc
new file mode 100644
index 0000000000..49c662c581
--- /dev/null
+++ b/call/adaptation/video_stream_input_state_provider_unittest.cc
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2020 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 "call/adaptation/video_stream_input_state_provider.h"
+
+#include <utility>
+
+#include "api/video_codecs/video_encoder.h"
+#include "call/adaptation/encoder_settings.h"
+#include "call/adaptation/test/fake_frame_rate_provider.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+
+TEST(VideoStreamInputStateProviderTest, DefaultValues) {
+ FakeFrameRateProvider frame_rate_provider;
+ VideoStreamInputStateProvider input_state_provider(&frame_rate_provider);
+ VideoStreamInputState input_state = input_state_provider.InputState();
+ EXPECT_EQ(false, input_state.has_input());
+ EXPECT_EQ(absl::nullopt, input_state.frame_size_pixels());
+ EXPECT_EQ(0, input_state.frames_per_second());
+ EXPECT_EQ(VideoCodecType::kVideoCodecGeneric, input_state.video_codec_type());
+ EXPECT_EQ(kDefaultMinPixelsPerFrame, input_state.min_pixels_per_frame());
+}
+
+TEST(VideoStreamInputStateProviderTest, ValuesSet) {
+ FakeFrameRateProvider frame_rate_provider;
+ VideoStreamInputStateProvider input_state_provider(&frame_rate_provider);
+ input_state_provider.OnHasInputChanged(true);
+ input_state_provider.OnFrameSizeObserved(42);
+ frame_rate_provider.set_fps(123);
+ VideoEncoder::EncoderInfo encoder_info;
+ encoder_info.scaling_settings.min_pixels_per_frame = 1337;
+ VideoEncoderConfig encoder_config;
+ encoder_config.codec_type = VideoCodecType::kVideoCodecVP9;
+ input_state_provider.OnEncoderSettingsChanged(EncoderSettings(
+ std::move(encoder_info), std::move(encoder_config), VideoCodec()));
+ VideoStreamInputState input_state = input_state_provider.InputState();
+ EXPECT_EQ(true, input_state.has_input());
+ EXPECT_EQ(42, input_state.frame_size_pixels());
+ EXPECT_EQ(123, input_state.frames_per_second());
+ EXPECT_EQ(VideoCodecType::kVideoCodecVP9, input_state.video_codec_type());
+ EXPECT_EQ(1337, input_state.min_pixels_per_frame());
+}
+
+} // namespace webrtc
diff --git a/video/adaptation/quality_scaler_resource.cc b/video/adaptation/quality_scaler_resource.cc
index 4369baa092..3f32fa2ce6 100644
--- a/video/adaptation/quality_scaler_resource.cc
+++ b/video/adaptation/quality_scaler_resource.cc
@@ -116,8 +116,8 @@ void QualityScalerResource::OnAdaptationApplied(
DidDecreaseFrameRate(restrictions_before, restrictions_after)) {
absl::optional<int> min_diff = BalancedDegradationSettings().MinFpsDiff(
input_state.frame_size_pixels().value());
- if (min_diff && input_state.frames_per_second().value() > 0) {
- int fps_diff = input_state.frames_per_second().value() -
+ if (min_diff && input_state.frames_per_second() > 0) {
+ int fps_diff = input_state.frames_per_second() -
restrictions_after.max_frame_rate().value();
if (fps_diff < min_diff.value()) {
clear_qp_samples = false;
diff --git a/video/adaptation/video_stream_encoder_resource_manager.h b/video/adaptation/video_stream_encoder_resource_manager.h
index 740865baba..61b1506627 100644
--- a/video/adaptation/video_stream_encoder_resource_manager.h
+++ b/video/adaptation/video_stream_encoder_resource_manager.h
@@ -164,6 +164,9 @@ class VideoStreamEncoderResourceManager
void ResetActiveCounts();
std::string ActiveCountsToString() const;
+ // TODO(hbos): Consider moving all of the manager's resources into separate
+ // files for testability.
+
// Does not trigger adaptations, only prevents adapting up based on
// |active_counts_|.
class PreventAdaptUpDueToActiveCounts final : public Resource {