[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}
This commit is contained in:
parent
bb826c9142
commit
722fa4d509
@ -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",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
257
call/adaptation/resource_adaptation_processor_unittest.cc
Normal file
257
call/adaptation/resource_adaptation_processor_unittest.cc
Normal file
@ -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
|
||||
27
call/adaptation/test/fake_frame_rate_provider.cc
Normal file
27
call/adaptation/test/fake_frame_rate_provider.cc
Normal file
@ -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
|
||||
57
call/adaptation/test/fake_frame_rate_provider.h
Normal file
57
call/adaptation/test/fake_frame_rate_provider.h
Normal file
@ -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_
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
73
call/adaptation/video_source_restrictions_unittest.cc
Normal file
73
call/adaptation/video_source_restrictions_unittest.cc
Normal file
@ -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
|
||||
@ -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(),
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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_;
|
||||
};
|
||||
|
||||
@ -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_;
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
@ -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;
|
||||
|
||||
@ -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 {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user