[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:
Henrik Boström 2020-04-29 16:46:30 +02:00 committed by Commit Bot
parent bb826c9142
commit 722fa4d509
14 changed files with 531 additions and 18 deletions

View File

@ -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",
]
}
}

View 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

View 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

View 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_

View File

@ -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

View File

@ -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

View 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

View File

@ -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(),

View File

@ -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

View File

@ -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_;
};

View File

@ -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_;
}

View File

@ -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

View File

@ -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;

View File

@ -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 {