[Overuse] Initial version of VideoStreamAdapter (Restrictor moved).

This CL simply moves the VideoSourceRestrictor from being an inner class
of OveruseFrameDetectorResourceAdaptationModule to a new class,
VideoStreamAdapter.

In follow-up CLs, the responsibility of determining what the next step
for adapting up or down should also be moved to the VideoStreamAdapter.

The end-goal is that the VideoStreamAdapter takes care of "can adapt?"
and "do adapt!" type of logic so that a multi-stream aware adaptation
module can decide which stream (adapter) to adapt, and the adapter can
take care of the nitty gritty details of doing so.

In this CL the "can?"/"do!" part is realized but not the logic for
determining what the next step up or down is, and the class interface
needs improvement.

This CL also sets up the video/adaptation/ subdirectory and moves the
AdaptationCounters class here. Other adaptation-related classes (e.g.
the module and its resources) should move into this directory as well
in the future.

Bug: webrtc:11393
Change-Id: I2c12c1281eca854c62791abb65f0aca47a119726
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/169542
Reviewed-by: Evan Shrubsole <eshr@google.com>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Henrik Andreassson <henrika@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30705}
This commit is contained in:
Henrik Boström
2020-03-06 10:41:25 +01:00
committed by Commit Bot
parent f351cfffe2
commit efbec9a304
15 changed files with 540 additions and 283 deletions

View File

@ -608,6 +608,7 @@ if (rtc_include_tests) {
"test:test_main", "test:test_main",
"test:video_test_common", "test:video_test_common",
"video:video_tests", "video:video_tests",
"video/adaptation:video_adaptation_tests",
] ]
data = video_engine_tests_resources data = video_engine_tests_resources
if (is_android) { if (is_android) {

View File

@ -1,2 +1,2 @@
eshr@webrtc.org
hbos@webrtc.org hbos@webrtc.org
sprang@webrtc.org

View File

@ -238,6 +238,7 @@ rtc_library("video_stream_encoder_impl") {
"../rtc_base/task_utils:repeating_task", "../rtc_base/task_utils:repeating_task",
"../system_wrappers", "../system_wrappers",
"../system_wrappers:field_trial", "../system_wrappers:field_trial",
"adaptation:video_adaptation",
"//third_party/abseil-cpp/absl/algorithm:container", "//third_party/abseil-cpp/absl/algorithm:container",
"//third_party/abseil-cpp/absl/base:core_headers", "//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/types:optional", "//third_party/abseil-cpp/absl/types:optional",
@ -621,6 +622,7 @@ if (rtc_include_tests) {
"../test:test_support", "../test:test_support",
"../test:video_test_common", "../test:video_test_common",
"../test/time_controller", "../test/time_controller",
"adaptation:video_adaptation",
"//testing/gtest", "//testing/gtest",
"//third_party/abseil-cpp/absl/algorithm:container", "//third_party/abseil-cpp/absl/algorithm:container",
"//third_party/abseil-cpp/absl/memory", "//third_party/abseil-cpp/absl/memory",

48
video/adaptation/BUILD.gn Normal file
View File

@ -0,0 +1,48 @@
# 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.
import("../../webrtc.gni")
rtc_library("video_adaptation") {
sources = [
"adaptation_counters.cc",
"adaptation_counters.h",
"video_stream_adapter.cc",
"video_stream_adapter.h",
]
deps = [
"../../call/adaptation:resource_adaptation",
"../../rtc_base:checks",
"../../rtc_base:logging",
"../../rtc_base:rtc_base_approved",
"../../rtc_base:rtc_event",
"../../rtc_base:rtc_numerics",
"//third_party/abseil-cpp/absl/types:optional",
]
}
if (rtc_include_tests) {
rtc_library("video_adaptation_tests") {
testonly = true
defines = []
sources = [ "adaptation_counters_unittest.cc" ]
deps = [
":video_adaptation",
"../../rtc_base:checks",
"../../rtc_base:logging",
"../../rtc_base:rtc_base_approved",
"../../rtc_base:rtc_event",
"../../rtc_base:rtc_numerics",
"//test:test_support",
"//testing/gtest",
"//third_party/abseil-cpp/absl/types:optional",
]
}
}

2
video/adaptation/OWNERS Normal file
View File

@ -0,0 +1,2 @@
eshr@webrtc.org
hbos@webrtc.org

View File

@ -0,0 +1,38 @@
/*
* Copyright 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 "video/adaptation/adaptation_counters.h"
namespace webrtc {
bool AdaptationCounters::operator==(const AdaptationCounters& rhs) const {
return fps_adaptations == rhs.fps_adaptations &&
resolution_adaptations == rhs.resolution_adaptations;
}
bool AdaptationCounters::operator!=(const AdaptationCounters& rhs) const {
return !(rhs == *this);
}
AdaptationCounters AdaptationCounters::operator+(
const AdaptationCounters& other) const {
return AdaptationCounters(
resolution_adaptations + other.resolution_adaptations,
fps_adaptations + other.fps_adaptations);
}
AdaptationCounters AdaptationCounters::operator-(
const AdaptationCounters& other) const {
return AdaptationCounters(
resolution_adaptations - other.resolution_adaptations,
fps_adaptations - other.fps_adaptations);
}
} // namespace webrtc

View File

@ -0,0 +1,38 @@
/*
* Copyright 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 VIDEO_ADAPTATION_ADAPTATION_COUNTERS_H_
#define VIDEO_ADAPTATION_ADAPTATION_COUNTERS_H_
namespace webrtc {
// Counts the number of adaptations have resulted due to resource overuse.
// Today we can adapt resolution and fps.
struct AdaptationCounters {
AdaptationCounters() : resolution_adaptations(0), fps_adaptations(0) {}
AdaptationCounters(int resolution_adaptations, int fps_adaptations)
: resolution_adaptations(resolution_adaptations),
fps_adaptations(fps_adaptations) {}
int Total() const { return fps_adaptations + resolution_adaptations; }
bool operator==(const AdaptationCounters& rhs) const;
bool operator!=(const AdaptationCounters& rhs) const;
AdaptationCounters operator+(const AdaptationCounters& other) const;
AdaptationCounters operator-(const AdaptationCounters& other) const;
int resolution_adaptations;
int fps_adaptations;
};
} // namespace webrtc
#endif // VIDEO_ADAPTATION_ADAPTATION_COUNTERS_H_

View File

@ -0,0 +1,50 @@
/*
* 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 "video/adaptation/adaptation_counters.h"
#include "test/gtest.h"
namespace webrtc {
TEST(AdaptationCountersTest, Addition) {
AdaptationCounters a{0, 0};
AdaptationCounters b{1, 2};
AdaptationCounters total = a + b;
EXPECT_EQ(1, total.resolution_adaptations);
EXPECT_EQ(2, total.fps_adaptations);
}
TEST(AdaptationCountersTest, Subtraction) {
AdaptationCounters a{0, 1};
AdaptationCounters b{2, 1};
AdaptationCounters diff = a - b;
EXPECT_EQ(-2, diff.resolution_adaptations);
EXPECT_EQ(0, diff.fps_adaptations);
}
TEST(AdaptationCountersTest, Equality) {
AdaptationCounters a{1, 2};
AdaptationCounters b{2, 1};
EXPECT_EQ(a, a);
EXPECT_NE(a, b);
}
TEST(AdaptationCountersTest, SelfAdditionSubtraction) {
AdaptationCounters a{1, 0};
AdaptationCounters b{0, 1};
EXPECT_EQ(a, a + b - b);
EXPECT_EQ(a, b + a - b);
EXPECT_EQ(a, a - b + b);
EXPECT_EQ(a, b - b + a);
}
} // namespace webrtc

View File

@ -0,0 +1,245 @@
/*
* Copyright 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 "video/adaptation/video_stream_adapter.h"
#include <algorithm>
#include <limits>
#include "absl/types/optional.h"
#include "rtc_base/constructor_magic.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"
namespace webrtc {
// VideoSourceRestrictor is responsible for keeping track of current
// VideoSourceRestrictions. It suggests higher and lower frame rates and
// resolutions (used by "maintain-resolution" and "maintain-framerate"), but is
// ultimately not reponsible for determining when or how we should adapt up or
// down (e.g. "balanced" mode also uses BalancedDegradationPreference).
class VideoStreamAdapter::VideoSourceRestrictor {
public:
// For frame rate, the steps we take are 2/3 (down) and 3/2 (up).
static int GetLowerFrameRateThan(int fps) {
RTC_DCHECK(fps != std::numeric_limits<int>::max());
return (fps * 2) / 3;
}
// TODO(hbos): Use absl::optional<> instead?
static int GetHigherFrameRateThan(int fps) {
return fps != std::numeric_limits<int>::max()
? (fps * 3) / 2
: std::numeric_limits<int>::max();
}
// For resolution, the steps we take are 3/5 (down) and 5/3 (up).
// Notice the asymmetry of which restriction property is set depending on if
// we are adapting up or down:
// - DecreaseResolution() sets the max_pixels_per_frame() to the desired
// target and target_pixels_per_frame() to null.
// - IncreaseResolutionTo() sets the target_pixels_per_frame() to the desired
// target, and max_pixels_per_frame() is set according to
// GetIncreasedMaxPixelsWanted().
static int GetLowerResolutionThan(int pixel_count) {
RTC_DCHECK(pixel_count != std::numeric_limits<int>::max());
return (pixel_count * 3) / 5;
}
// TODO(hbos): Use absl::optional<> instead?
static int GetHigherResolutionThan(int pixel_count) {
return pixel_count != std::numeric_limits<int>::max()
? (pixel_count * 5) / 3
: std::numeric_limits<int>::max();
}
VideoSourceRestrictor() {}
VideoSourceRestrictions source_restrictions() const {
return source_restrictions_;
}
const AdaptationCounters& adaptation_counters() const { return adaptations_; }
void ClearRestrictions() {
source_restrictions_ = VideoSourceRestrictions();
adaptations_ = AdaptationCounters();
}
bool CanDecreaseResolutionTo(int target_pixels, int min_pixels_per_frame) {
int max_pixels_per_frame = rtc::dchecked_cast<int>(
source_restrictions_.max_pixels_per_frame().value_or(
std::numeric_limits<int>::max()));
return target_pixels < max_pixels_per_frame &&
target_pixels >= min_pixels_per_frame;
}
void DecreaseResolutionTo(int target_pixels, int min_pixels_per_frame) {
RTC_DCHECK(CanDecreaseResolutionTo(target_pixels, min_pixels_per_frame));
RTC_LOG(LS_INFO) << "Scaling down resolution, max pixels: "
<< target_pixels;
source_restrictions_.set_max_pixels_per_frame(
target_pixels != std::numeric_limits<int>::max()
? absl::optional<size_t>(target_pixels)
: absl::nullopt);
source_restrictions_.set_target_pixels_per_frame(absl::nullopt);
++adaptations_.resolution_adaptations;
}
bool CanIncreaseResolutionTo(int target_pixels) {
int max_pixels_wanted = GetIncreasedMaxPixelsWanted(target_pixels);
int max_pixels_per_frame = rtc::dchecked_cast<int>(
source_restrictions_.max_pixels_per_frame().value_or(
std::numeric_limits<int>::max()));
return max_pixels_wanted > max_pixels_per_frame;
}
void IncreaseResolutionTo(int target_pixels) {
RTC_DCHECK(CanIncreaseResolutionTo(target_pixels));
int max_pixels_wanted = GetIncreasedMaxPixelsWanted(target_pixels);
RTC_LOG(LS_INFO) << "Scaling up resolution, max pixels: "
<< max_pixels_wanted;
source_restrictions_.set_max_pixels_per_frame(
max_pixels_wanted != std::numeric_limits<int>::max()
? absl::optional<size_t>(max_pixels_wanted)
: absl::nullopt);
source_restrictions_.set_target_pixels_per_frame(
max_pixels_wanted != std::numeric_limits<int>::max()
? absl::optional<size_t>(target_pixels)
: absl::nullopt);
--adaptations_.resolution_adaptations;
RTC_DCHECK_GE(adaptations_.resolution_adaptations, 0);
}
bool CanDecreaseFrameRateTo(int max_frame_rate) {
const int fps_wanted = std::max(kMinFramerateFps, max_frame_rate);
return fps_wanted < rtc::dchecked_cast<int>(
source_restrictions_.max_frame_rate().value_or(
std::numeric_limits<int>::max()));
}
void DecreaseFrameRateTo(int max_frame_rate) {
RTC_DCHECK(CanDecreaseFrameRateTo(max_frame_rate));
max_frame_rate = std::max(kMinFramerateFps, max_frame_rate);
RTC_LOG(LS_INFO) << "Scaling down framerate: " << max_frame_rate;
source_restrictions_.set_max_frame_rate(
max_frame_rate != std::numeric_limits<int>::max()
? absl::optional<double>(max_frame_rate)
: absl::nullopt);
++adaptations_.fps_adaptations;
}
bool CanIncreaseFrameRateTo(int max_frame_rate) {
return max_frame_rate > rtc::dchecked_cast<int>(
source_restrictions_.max_frame_rate().value_or(
std::numeric_limits<int>::max()));
}
void IncreaseFrameRateTo(int max_frame_rate) {
RTC_DCHECK(CanIncreaseFrameRateTo(max_frame_rate));
RTC_LOG(LS_INFO) << "Scaling up framerate: " << max_frame_rate;
source_restrictions_.set_max_frame_rate(
max_frame_rate != std::numeric_limits<int>::max()
? absl::optional<double>(max_frame_rate)
: absl::nullopt);
--adaptations_.fps_adaptations;
RTC_DCHECK_GE(adaptations_.fps_adaptations, 0);
}
private:
static int GetIncreasedMaxPixelsWanted(int target_pixels) {
if (target_pixels == std::numeric_limits<int>::max())
return std::numeric_limits<int>::max();
// When we decrease resolution, we go down to at most 3/5 of current pixels.
// Thus to increase resolution, we need 3/5 to get back to where we started.
// When going up, the desired max_pixels_per_frame() has to be significantly
// higher than the target because the source's native resolutions might not
// match the target. We pick 12/5 of the target.
//
// (This value was historically 4 times the old target, which is (3/5)*4 of
// the new target - or 12/5 - assuming the target is adjusted according to
// the above steps.)
RTC_DCHECK(target_pixels != std::numeric_limits<int>::max());
return (target_pixels * 12) / 5;
}
VideoSourceRestrictions source_restrictions_;
AdaptationCounters adaptations_;
RTC_DISALLOW_COPY_AND_ASSIGN(VideoSourceRestrictor);
};
const int VideoStreamAdapter::kMinFramerateFps = 2;
// static
int VideoStreamAdapter::GetLowerFrameRateThan(int fps) {
return VideoSourceRestrictor::GetLowerFrameRateThan(fps);
}
// static
int VideoStreamAdapter::GetHigherFrameRateThan(int fps) {
return VideoSourceRestrictor::GetHigherFrameRateThan(fps);
}
// static
int VideoStreamAdapter::GetLowerResolutionThan(int pixel_count) {
return VideoSourceRestrictor::GetLowerResolutionThan(pixel_count);
}
// static
int VideoStreamAdapter::GetHigherResolutionThan(int pixel_count) {
return VideoSourceRestrictor::GetHigherResolutionThan(pixel_count);
}
VideoStreamAdapter::VideoStreamAdapter()
: source_restrictor_(std::make_unique<VideoSourceRestrictor>()) {}
VideoStreamAdapter::~VideoStreamAdapter() {}
VideoSourceRestrictions VideoStreamAdapter::source_restrictions() const {
return source_restrictor_->source_restrictions();
}
const AdaptationCounters& VideoStreamAdapter::adaptation_counters() const {
return source_restrictor_->adaptation_counters();
}
void VideoStreamAdapter::ClearRestrictions() {
source_restrictor_->ClearRestrictions();
}
bool VideoStreamAdapter::CanDecreaseResolutionTo(int target_pixels,
int min_pixels_per_frame) {
return source_restrictor_->CanDecreaseResolutionTo(target_pixels,
min_pixels_per_frame);
}
void VideoStreamAdapter::DecreaseResolutionTo(int target_pixels,
int min_pixels_per_frame) {
source_restrictor_->DecreaseResolutionTo(target_pixels, min_pixels_per_frame);
}
bool VideoStreamAdapter::CanIncreaseResolutionTo(int target_pixels) {
return source_restrictor_->CanIncreaseResolutionTo(target_pixels);
}
void VideoStreamAdapter::IncreaseResolutionTo(int target_pixels) {
source_restrictor_->IncreaseResolutionTo(target_pixels);
}
bool VideoStreamAdapter::CanDecreaseFrameRateTo(int max_frame_rate) {
return source_restrictor_->CanDecreaseFrameRateTo(max_frame_rate);
}
void VideoStreamAdapter::DecreaseFrameRateTo(int max_frame_rate) {
source_restrictor_->DecreaseFrameRateTo(max_frame_rate);
}
bool VideoStreamAdapter::CanIncreaseFrameRateTo(int max_frame_rate) {
return source_restrictor_->CanIncreaseFrameRateTo(max_frame_rate);
}
void VideoStreamAdapter::IncreaseFrameRateTo(int max_frame_rate) {
source_restrictor_->IncreaseFrameRateTo(max_frame_rate);
}
} // namespace webrtc

View File

@ -0,0 +1,66 @@
/*
* Copyright 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 VIDEO_ADAPTATION_VIDEO_STREAM_ADAPTER_H_
#define VIDEO_ADAPTATION_VIDEO_STREAM_ADAPTER_H_
#include <memory>
#include "call/adaptation/video_source_restrictions.h"
#include "video/adaptation/adaptation_counters.h"
namespace webrtc {
// Owns the VideoSourceRestriction for a single stream and is responsible for
// adapting it up or down when told to do so. This class serves the following
// purposes:
// 1. Keep track of a stream's restrictions.
// 2. Provide valid ways to adapt up or down the stream's restrictions.
// 3. Modify the stream's restrictions in one of the valid ways.
class VideoStreamAdapter {
public:
static const int kMinFramerateFps;
static int GetLowerFrameRateThan(int fps);
static int GetHigherFrameRateThan(int fps);
static int GetLowerResolutionThan(int pixel_count);
static int GetHigherResolutionThan(int pixel_count);
VideoStreamAdapter();
~VideoStreamAdapter();
// TODO(hbos): Why isn't this const?
VideoSourceRestrictions source_restrictions() const;
const AdaptationCounters& adaptation_counters() const;
void ClearRestrictions();
// "Can adapt?" and "do adapt!" methods.
// TODO(https://crbug.com/webrtc/11393): Make the adapter responsible for
// deciding what the next step are, i.e. taking on degradation preference
// logic. Then, these can be expressed either as CanAdaptUp() and DoAdaptUp()
// or as GetNextRestrictionsUp() and ApplyRestrictions().
bool CanDecreaseResolutionTo(int target_pixels, int min_pixels_per_frame);
void DecreaseResolutionTo(int target_pixels, int min_pixels_per_frame);
bool CanIncreaseResolutionTo(int target_pixels);
void IncreaseResolutionTo(int target_pixels);
bool CanDecreaseFrameRateTo(int max_frame_rate);
void DecreaseFrameRateTo(int max_frame_rate);
bool CanIncreaseFrameRateTo(int max_frame_rate);
void IncreaseFrameRateTo(int max_frame_rate);
private:
class VideoSourceRestrictor;
const std::unique_ptr<VideoSourceRestrictor> source_restrictor_;
};
} // namespace webrtc
#endif // VIDEO_ADAPTATION_VIDEO_STREAM_ADAPTER_H_

View File

@ -26,6 +26,8 @@ namespace webrtc {
// indirectly by usage in the OveruseFrameDetectorResourceAdaptationModule // indirectly by usage in the OveruseFrameDetectorResourceAdaptationModule
// (which is only tested because of its usage in VideoStreamEncoder); all tests // (which is only tested because of its usage in VideoStreamEncoder); all tests
// are currently in video_stream_encoder_unittest.cc. // are currently in video_stream_encoder_unittest.cc.
// TODO(https://crbug.com/webrtc/11222): Move this class to the
// video/adaptation/ subdirectory.
class EncodeUsageResource : public Resource, class EncodeUsageResource : public Resource,
public AdaptationObserverInterface { public AdaptationObserverInterface {
public: public:

View File

@ -32,8 +32,6 @@ namespace webrtc {
namespace { namespace {
const int kMinFramerateFps = 2;
bool IsResolutionScalingEnabled(DegradationPreference degradation_preference) { bool IsResolutionScalingEnabled(DegradationPreference degradation_preference) {
return degradation_preference == DegradationPreference::MAINTAIN_FRAMERATE || return degradation_preference == DegradationPreference::MAINTAIN_FRAMERATE ||
degradation_preference == DegradationPreference::BALANCED; degradation_preference == DegradationPreference::BALANCED;
@ -68,9 +66,9 @@ VideoSourceRestrictions ApplyDegradationPreference(
} }
// Returns AdaptationCounters where constraints that don't apply to the // Returns AdaptationCounters where constraints that don't apply to the
// degradation preference are cleared. This behaviour must reflect that of // degredation preference are cleared. This behaviour must reflect that of
// ApplyDegradationPreference for SourceRestrictions. Any changed to that // ApplyDegredationPreference for SourceRestrictions. Any to that method must
// method must also change this one. // also change this one.
AdaptationCounters ApplyDegradationPreference( AdaptationCounters ApplyDegradationPreference(
AdaptationCounters counters, AdaptationCounters counters,
DegradationPreference degradation_preference) { DegradationPreference degradation_preference) {
@ -95,180 +93,6 @@ AdaptationCounters ApplyDegradationPreference(
} // namespace } // namespace
bool AdaptationCounters::operator==(const AdaptationCounters& rhs) const {
return fps_adaptations == rhs.fps_adaptations &&
resolution_adaptations == rhs.resolution_adaptations;
}
bool AdaptationCounters::operator!=(const AdaptationCounters& rhs) const {
return !(rhs == *this);
}
AdaptationCounters AdaptationCounters::operator+(
const AdaptationCounters& other) const {
return AdaptationCounters(
resolution_adaptations + other.resolution_adaptations,
fps_adaptations + other.fps_adaptations);
}
AdaptationCounters AdaptationCounters::operator-(
const AdaptationCounters& other) const {
return AdaptationCounters(
resolution_adaptations - other.resolution_adaptations,
fps_adaptations - other.fps_adaptations);
}
// VideoSourceRestrictor is responsible for keeping track of current
// VideoSourceRestrictions and how to modify them in response to adapting up or
// down. It is not reponsible for determining when we should adapt up or down -
// for that, see
// OveruseFrameDetectorResourceAdaptationModule::OnResourceUnderuse() and
// OnResourceOveruse() - only how to modify the source/sink restrictions when
// this happens. Note that it is also not responsible for reconfigruring the
// source/sink, it is only a keeper of desired restrictions.
class OveruseFrameDetectorResourceAdaptationModule::VideoSourceRestrictor {
public:
// For frame rate, the steps we take are 2/3 (down) and 3/2 (up).
static int GetLowerFrameRateThan(int fps) {
RTC_DCHECK(fps != std::numeric_limits<int>::max());
return (fps * 2) / 3;
}
// TODO(hbos): Use absl::optional<> instead?
static int GetHigherFrameRateThan(int fps) {
return fps != std::numeric_limits<int>::max()
? (fps * 3) / 2
: std::numeric_limits<int>::max();
}
// For resolution, the steps we take are 3/5 (down) and 5/3 (up).
// Notice the asymmetry of which restriction property is set depending on if
// we are adapting up or down:
// - DecreaseResolution() sets the max_pixels_per_frame() to the desired
// target and target_pixels_per_frame() to null.
// - IncreaseResolutionTo() sets the target_pixels_per_frame() to the desired
// target, and max_pixels_per_frame() is set according to
// GetIncreasedMaxPixelsWanted().
static int GetLowerResolutionThan(int pixel_count) {
RTC_DCHECK(pixel_count != std::numeric_limits<int>::max());
return (pixel_count * 3) / 5;
}
// TODO(hbos): Use absl::optional<> instead?
static int GetHigherResolutionThan(int pixel_count) {
return pixel_count != std::numeric_limits<int>::max()
? (pixel_count * 5) / 3
: std::numeric_limits<int>::max();
}
VideoSourceRestrictor() {}
VideoSourceRestrictions source_restrictions() {
return source_restrictions_;
}
const AdaptationCounters& adaptation_counters() const { return adaptations_; }
void ClearRestrictions() {
source_restrictions_ = VideoSourceRestrictions();
adaptations_ = AdaptationCounters();
}
bool CanDecreaseResolutionTo(int target_pixels, int min_pixels_per_frame) {
int max_pixels_per_frame = rtc::dchecked_cast<int>(
source_restrictions_.max_pixels_per_frame().value_or(
std::numeric_limits<int>::max()));
return target_pixels < max_pixels_per_frame &&
target_pixels >= min_pixels_per_frame;
}
void DecreaseResolutionTo(int target_pixels, int min_pixels_per_frame) {
RTC_DCHECK(CanDecreaseResolutionTo(target_pixels, min_pixels_per_frame));
RTC_LOG(LS_INFO) << "Scaling down resolution, max pixels: "
<< target_pixels;
source_restrictions_.set_max_pixels_per_frame(
target_pixels != std::numeric_limits<int>::max()
? absl::optional<size_t>(target_pixels)
: absl::nullopt);
source_restrictions_.set_target_pixels_per_frame(absl::nullopt);
++adaptations_.resolution_adaptations;
}
bool CanIncreaseResolutionTo(int target_pixels) {
int max_pixels_wanted = GetIncreasedMaxPixelsWanted(target_pixels);
int max_pixels_per_frame = rtc::dchecked_cast<int>(
source_restrictions_.max_pixels_per_frame().value_or(
std::numeric_limits<int>::max()));
return max_pixels_wanted > max_pixels_per_frame;
}
void IncreaseResolutionTo(int target_pixels) {
RTC_DCHECK(CanIncreaseResolutionTo(target_pixels));
int max_pixels_wanted = GetIncreasedMaxPixelsWanted(target_pixels);
RTC_LOG(LS_INFO) << "Scaling up resolution, max pixels: "
<< max_pixels_wanted;
source_restrictions_.set_max_pixels_per_frame(
max_pixels_wanted != std::numeric_limits<int>::max()
? absl::optional<size_t>(max_pixels_wanted)
: absl::nullopt);
source_restrictions_.set_target_pixels_per_frame(
max_pixels_wanted != std::numeric_limits<int>::max()
? absl::optional<size_t>(target_pixels)
: absl::nullopt);
--adaptations_.resolution_adaptations;
RTC_DCHECK_GE(adaptations_.resolution_adaptations, 0);
}
bool CanDecreaseFrameRateTo(int max_frame_rate) {
const int fps_wanted = std::max(kMinFramerateFps, max_frame_rate);
return fps_wanted < rtc::dchecked_cast<int>(
source_restrictions_.max_frame_rate().value_or(
std::numeric_limits<int>::max()));
}
void DecreaseFrameRateTo(int max_frame_rate) {
RTC_DCHECK(CanDecreaseFrameRateTo(max_frame_rate));
max_frame_rate = std::max(kMinFramerateFps, max_frame_rate);
RTC_LOG(LS_INFO) << "Scaling down framerate: " << max_frame_rate;
source_restrictions_.set_max_frame_rate(
max_frame_rate != std::numeric_limits<int>::max()
? absl::optional<double>(max_frame_rate)
: absl::nullopt);
++adaptations_.fps_adaptations;
}
bool CanIncreaseFrameRateTo(int max_frame_rate) {
return max_frame_rate > rtc::dchecked_cast<int>(
source_restrictions_.max_frame_rate().value_or(
std::numeric_limits<int>::max()));
}
void IncreaseFrameRateTo(int max_frame_rate) {
RTC_DCHECK(CanIncreaseFrameRateTo(max_frame_rate));
RTC_LOG(LS_INFO) << "Scaling up framerate: " << max_frame_rate;
source_restrictions_.set_max_frame_rate(
max_frame_rate != std::numeric_limits<int>::max()
? absl::optional<double>(max_frame_rate)
: absl::nullopt);
--adaptations_.fps_adaptations;
RTC_DCHECK_GE(adaptations_.fps_adaptations, 0);
}
private:
static int GetIncreasedMaxPixelsWanted(int target_pixels) {
if (target_pixels == std::numeric_limits<int>::max())
return std::numeric_limits<int>::max();
// When we decrease resolution, we go down to at most 3/5 of current pixels.
// Thus to increase resolution, we need 3/5 to get back to where we started.
// When going up, the desired max_pixels_per_frame() has to be significantly
// higher than the target because the source's native resolutions might not
// match the target. We pick 12/5 of the target.
//
// (This value was historically 4 times the old target, which is (3/5)*4 of
// the new target - or 12/5 - assuming the target is adjusted according to
// the above steps.)
RTC_DCHECK(target_pixels != std::numeric_limits<int>::max());
return (target_pixels * 12) / 5;
}
VideoSourceRestrictions source_restrictions_;
AdaptationCounters adaptations_;
RTC_DISALLOW_COPY_AND_ASSIGN(VideoSourceRestrictor);
};
class OveruseFrameDetectorResourceAdaptationModule::InitialFrameDropper { class OveruseFrameDetectorResourceAdaptationModule::InitialFrameDropper {
public: public:
explicit InitialFrameDropper(QualityScalerResource* quality_scaler_resource) explicit InitialFrameDropper(QualityScalerResource* quality_scaler_resource)
@ -359,7 +183,7 @@ OveruseFrameDetectorResourceAdaptationModule::
degradation_preference_(DegradationPreference::DISABLED), degradation_preference_(DegradationPreference::DISABLED),
balanced_settings_(), balanced_settings_(),
last_adaptation_request_(absl::nullopt), last_adaptation_request_(absl::nullopt),
source_restrictor_(std::make_unique<VideoSourceRestrictor>()), stream_adapter_(std::make_unique<VideoStreamAdapter>()),
encode_usage_resource_( encode_usage_resource_(
std::make_unique<EncodeUsageResource>(std::move(overuse_detector))), std::make_unique<EncodeUsageResource>(std::move(overuse_detector))),
quality_scaler_resource_(std::make_unique<QualityScalerResource>()), quality_scaler_resource_(std::make_unique<QualityScalerResource>()),
@ -442,7 +266,7 @@ void OveruseFrameDetectorResourceAdaptationModule::SetDegradationPreference(
last_adaptation_request_.reset(); last_adaptation_request_.reset();
if (degradation_preference == DegradationPreference::BALANCED || if (degradation_preference == DegradationPreference::BALANCED ||
degradation_preference_ == DegradationPreference::BALANCED) { degradation_preference_ == DegradationPreference::BALANCED) {
source_restrictor_->ClearRestrictions(); stream_adapter_->ClearRestrictions();
active_counts_.fill(AdaptationCounters()); active_counts_.fill(AdaptationCounters());
} }
} }
@ -484,7 +308,7 @@ void OveruseFrameDetectorResourceAdaptationModule::SetEncoderRates(
void OveruseFrameDetectorResourceAdaptationModule:: void OveruseFrameDetectorResourceAdaptationModule::
ResetVideoSourceRestrictions() { ResetVideoSourceRestrictions() {
last_adaptation_request_.reset(); last_adaptation_request_.reset();
source_restrictor_->ClearRestrictions(); stream_adapter_->ClearRestrictions();
active_counts_.fill(AdaptationCounters()); active_counts_.fill(AdaptationCounters());
MaybeUpdateVideoSourceRestrictions(); MaybeUpdateVideoSourceRestrictions();
} }
@ -495,16 +319,15 @@ void OveruseFrameDetectorResourceAdaptationModule::OnFrame(
} }
void OveruseFrameDetectorResourceAdaptationModule::OnFrameDroppedDueToSize() { void OveruseFrameDetectorResourceAdaptationModule::OnFrameDroppedDueToSize() {
AdaptationCounters counters_before = AdaptationCounters counters_before = stream_adapter_->adaptation_counters();
source_restrictor_->adaptation_counters();
OnResourceOveruse(AdaptationObserverInterface::AdaptReason::kQuality); OnResourceOveruse(AdaptationObserverInterface::AdaptReason::kQuality);
if (degradation_preference() == DegradationPreference::BALANCED && if (degradation_preference() == DegradationPreference::BALANCED &&
source_restrictor_->adaptation_counters().fps_adaptations > stream_adapter_->adaptation_counters().fps_adaptations >
counters_before.fps_adaptations) { counters_before.fps_adaptations) {
// Adapt framerate in same step as resolution. // Adapt framerate in same step as resolution.
OnResourceOveruse(AdaptationObserverInterface::AdaptReason::kQuality); OnResourceOveruse(AdaptationObserverInterface::AdaptReason::kQuality);
} }
if (source_restrictor_->adaptation_counters().resolution_adaptations > if (stream_adapter_->adaptation_counters().resolution_adaptations >
counters_before.resolution_adaptations) { counters_before.resolution_adaptations) {
encoder_stats_observer_->OnInitialQualityResolutionAdaptDown(); encoder_stats_observer_->OnInitialQualityResolutionAdaptDown();
} }
@ -677,7 +500,7 @@ OveruseFrameDetectorResourceAdaptationModule::GetAdaptUpTarget(
// Attempt to increase target frame rate. // Attempt to increase target frame rate.
int target_fps = int target_fps =
balanced_settings_.MaxFps(GetVideoCodecTypeOrGeneric(), input_pixels); balanced_settings_.MaxFps(GetVideoCodecTypeOrGeneric(), input_pixels);
if (source_restrictor_->CanIncreaseFrameRateTo(target_fps)) { if (stream_adapter_->CanIncreaseFrameRateTo(target_fps)) {
return AdaptationTarget(AdaptationAction::kIncreaseFrameRate, return AdaptationTarget(AdaptationAction::kIncreaseFrameRate,
target_fps); target_fps);
} }
@ -702,14 +525,13 @@ OveruseFrameDetectorResourceAdaptationModule::GetAdaptUpTarget(
} }
// Attempt to increase pixel count. // Attempt to increase pixel count.
int target_pixels = input_pixels; int target_pixels = input_pixels;
if (source_restrictor_->adaptation_counters().resolution_adaptations == if (stream_adapter_->adaptation_counters().resolution_adaptations == 1) {
1) {
RTC_LOG(LS_INFO) << "Removing resolution down-scaling setting."; RTC_LOG(LS_INFO) << "Removing resolution down-scaling setting.";
target_pixels = std::numeric_limits<int>::max(); target_pixels = std::numeric_limits<int>::max();
} }
target_pixels = target_pixels =
VideoSourceRestrictor::GetHigherResolutionThan(target_pixels); VideoStreamAdapter::GetHigherResolutionThan(target_pixels);
if (!source_restrictor_->CanIncreaseResolutionTo(target_pixels)) if (!stream_adapter_->CanIncreaseResolutionTo(target_pixels))
return absl::nullopt; return absl::nullopt;
return AdaptationTarget(AdaptationAction::kIncreaseResolution, return AdaptationTarget(AdaptationAction::kIncreaseResolution,
target_pixels); target_pixels);
@ -717,12 +539,12 @@ OveruseFrameDetectorResourceAdaptationModule::GetAdaptUpTarget(
case DegradationPreference::MAINTAIN_RESOLUTION: { case DegradationPreference::MAINTAIN_RESOLUTION: {
// Scale up framerate. // Scale up framerate.
int target_fps = input_fps; int target_fps = input_fps;
if (source_restrictor_->adaptation_counters().fps_adaptations == 1) { if (stream_adapter_->adaptation_counters().fps_adaptations == 1) {
RTC_LOG(LS_INFO) << "Removing framerate down-scaling setting."; RTC_LOG(LS_INFO) << "Removing framerate down-scaling setting.";
target_fps = std::numeric_limits<int>::max(); target_fps = std::numeric_limits<int>::max();
} }
target_fps = VideoSourceRestrictor::GetHigherFrameRateThan(target_fps); target_fps = VideoStreamAdapter::GetHigherFrameRateThan(target_fps);
if (!source_restrictor_->CanIncreaseFrameRateTo(target_fps)) if (!stream_adapter_->CanIncreaseFrameRateTo(target_fps))
return absl::nullopt; return absl::nullopt;
return AdaptationTarget(AdaptationAction::kIncreaseFrameRate, target_fps); return AdaptationTarget(AdaptationAction::kIncreaseFrameRate, target_fps);
} }
@ -755,8 +577,8 @@ OveruseFrameDetectorResourceAdaptationModule::GetAdaptDownTarget(
DegradationPreference::MAINTAIN_RESOLUTION) { DegradationPreference::MAINTAIN_RESOLUTION) {
// TODO(hbos): This usage of |last_adaptation_was_down| looks like a mistake // TODO(hbos): This usage of |last_adaptation_was_down| looks like a mistake
// - delete it. // - delete it.
if (input_fps <= 0 || if (input_fps <= 0 || (last_adaptation_was_down &&
(last_adaptation_was_down && input_fps < kMinFramerateFps)) { input_fps < VideoStreamAdapter::kMinFramerateFps)) {
return absl::nullopt; return absl::nullopt;
} }
} }
@ -775,7 +597,7 @@ OveruseFrameDetectorResourceAdaptationModule::GetAdaptDownTarget(
// Try scale down framerate, if lower. // Try scale down framerate, if lower.
int target_fps = int target_fps =
balanced_settings_.MinFps(GetVideoCodecTypeOrGeneric(), input_pixels); balanced_settings_.MinFps(GetVideoCodecTypeOrGeneric(), input_pixels);
if (source_restrictor_->CanDecreaseFrameRateTo(target_fps)) { if (stream_adapter_->CanDecreaseFrameRateTo(target_fps)) {
return AdaptationTarget(AdaptationAction::kDecreaseFrameRate, return AdaptationTarget(AdaptationAction::kDecreaseFrameRate,
target_fps); target_fps);
} }
@ -785,22 +607,22 @@ OveruseFrameDetectorResourceAdaptationModule::GetAdaptDownTarget(
case DegradationPreference::MAINTAIN_FRAMERATE: { case DegradationPreference::MAINTAIN_FRAMERATE: {
// Scale down resolution. // Scale down resolution.
int target_pixels = int target_pixels =
VideoSourceRestrictor::GetLowerResolutionThan(input_pixels); VideoStreamAdapter::GetLowerResolutionThan(input_pixels);
// TODO(https://crbug.com/webrtc/11222): Move this logic to // TODO(https://crbug.com/webrtc/11222): Move this logic to
// ApplyAdaptationTarget() or elsewhere - simply checking which adaptation // ApplyAdaptationTarget() or elsewhere - simply checking which adaptation
// target is available should not have side-effects. // target is available should not have side-effects.
if (target_pixels < min_pixels_per_frame) if (target_pixels < min_pixels_per_frame)
encoder_stats_observer_->OnMinPixelLimitReached(); encoder_stats_observer_->OnMinPixelLimitReached();
if (!source_restrictor_->CanDecreaseResolutionTo(target_pixels, if (!stream_adapter_->CanDecreaseResolutionTo(target_pixels,
min_pixels_per_frame)) { min_pixels_per_frame)) {
return absl::nullopt; return absl::nullopt;
} }
return AdaptationTarget(AdaptationAction::kDecreaseResolution, return AdaptationTarget(AdaptationAction::kDecreaseResolution,
target_pixels); target_pixels);
} }
case DegradationPreference::MAINTAIN_RESOLUTION: { case DegradationPreference::MAINTAIN_RESOLUTION: {
int target_fps = VideoSourceRestrictor::GetLowerFrameRateThan(input_fps); int target_fps = VideoStreamAdapter::GetLowerFrameRateThan(input_fps);
if (!source_restrictor_->CanDecreaseFrameRateTo(target_fps)) if (!stream_adapter_->CanDecreaseFrameRateTo(target_fps))
return absl::nullopt; return absl::nullopt;
return AdaptationTarget(AdaptationAction::kDecreaseFrameRate, target_fps); return AdaptationTarget(AdaptationAction::kDecreaseFrameRate, target_fps);
} }
@ -816,28 +638,26 @@ void OveruseFrameDetectorResourceAdaptationModule::ApplyAdaptationTarget(
AdaptationObserverInterface::AdaptReason reason) { AdaptationObserverInterface::AdaptReason reason) {
switch (target.action) { switch (target.action) {
case AdaptationAction::kIncreaseResolution: case AdaptationAction::kIncreaseResolution:
source_restrictor_->IncreaseResolutionTo(target.value); stream_adapter_->IncreaseResolutionTo(target.value);
return; return;
case AdaptationAction::kDecreaseResolution: case AdaptationAction::kDecreaseResolution:
source_restrictor_->DecreaseResolutionTo(target.value, stream_adapter_->DecreaseResolutionTo(target.value, min_pixels_per_frame);
min_pixels_per_frame);
return; return;
case AdaptationAction::kIncreaseFrameRate: case AdaptationAction::kIncreaseFrameRate:
source_restrictor_->IncreaseFrameRateTo(target.value); stream_adapter_->IncreaseFrameRateTo(target.value);
// TODO(https://crbug.com/webrtc/11222): Don't adapt in two steps. // TODO(https://crbug.com/webrtc/11222): Don't adapt in two steps.
// GetAdaptUpTarget() should tell us the correct value, but BALANCED logic // GetAdaptUpTarget() should tell us the correct value, but BALANCED logic
// in DecrementFramerate() makes it hard to predict whether this will be // in DecrementFramerate() makes it hard to predict whether this will be
// the last step. Remove the dependency on GetConstAdaptCounter(). // the last step. Remove the dependency on GetConstAdaptCounter().
if (EffectiveDegradationPreference() == DegradationPreference::BALANCED && if (EffectiveDegradationPreference() == DegradationPreference::BALANCED &&
source_restrictor_->adaptation_counters().fps_adaptations == 0 && stream_adapter_->adaptation_counters().fps_adaptations == 0 &&
target.value != std::numeric_limits<int>::max()) { target.value != std::numeric_limits<int>::max()) {
RTC_LOG(LS_INFO) << "Removing framerate down-scaling setting."; RTC_LOG(LS_INFO) << "Removing framerate down-scaling setting.";
source_restrictor_->IncreaseFrameRateTo( stream_adapter_->IncreaseFrameRateTo(std::numeric_limits<int>::max());
std::numeric_limits<int>::max());
} }
return; return;
case AdaptationAction::kDecreaseFrameRate: case AdaptationAction::kDecreaseFrameRate:
source_restrictor_->DecreaseFrameRateTo(target.value); stream_adapter_->DecreaseFrameRateTo(target.value);
return; return;
} }
} }
@ -956,7 +776,7 @@ int OveruseFrameDetectorResourceAdaptationModule::MinPixelsPerFrame() const {
void OveruseFrameDetectorResourceAdaptationModule:: void OveruseFrameDetectorResourceAdaptationModule::
MaybeUpdateVideoSourceRestrictions() { MaybeUpdateVideoSourceRestrictions() {
VideoSourceRestrictions new_restrictions = ApplyDegradationPreference( VideoSourceRestrictions new_restrictions = ApplyDegradationPreference(
source_restrictor_->source_restrictions(), degradation_preference_); stream_adapter_->source_restrictions(), degradation_preference_);
if (video_source_restrictions_ != new_restrictions) { if (video_source_restrictions_ != new_restrictions) {
video_source_restrictions_ = std::move(new_restrictions); video_source_restrictions_ = std::move(new_restrictions);
adaptation_listener_->OnVideoSourceRestrictionsUpdated( adaptation_listener_->OnVideoSourceRestrictionsUpdated(
@ -977,7 +797,7 @@ void OveruseFrameDetectorResourceAdaptationModule::
// module. This is used to make sure overuse detection doesn't needlessly // module. This is used to make sure overuse detection doesn't needlessly
// trigger in low and/or variable framerate scenarios. // trigger in low and/or variable framerate scenarios.
absl::optional<double> target_frame_rate = absl::optional<double> target_frame_rate =
ApplyDegradationPreference(source_restrictor_->source_restrictions(), ApplyDegradationPreference(stream_adapter_->source_restrictions(),
degradation_preference_) degradation_preference_)
.max_frame_rate(); .max_frame_rate();
if (!target_frame_rate.has_value() || if (!target_frame_rate.has_value() ||
@ -1052,7 +872,7 @@ void OveruseFrameDetectorResourceAdaptationModule::UpdateAdaptationStats(
AdaptationCounters& active_count = active_counts_[reason]; AdaptationCounters& active_count = active_counts_[reason];
AdaptationCounters& other_active = active_counts_[(reason + 1) % 2]; AdaptationCounters& other_active = active_counts_[(reason + 1) % 2];
const AdaptationCounters total_counts = const AdaptationCounters total_counts =
source_restrictor_->adaptation_counters(); stream_adapter_->adaptation_counters();
OnAdaptationCountChanged(total_counts, &active_count, &other_active); OnAdaptationCountChanged(total_counts, &active_count, &other_active);
@ -1126,7 +946,7 @@ bool OveruseFrameDetectorResourceAdaptationModule::CanAdaptUpResolution(
encoder_settings_.has_value() encoder_settings_.has_value()
? GetEncoderBitrateLimits( ? GetEncoderBitrateLimits(
encoder_settings_->encoder_info(), encoder_settings_->encoder_info(),
VideoSourceRestrictor::GetHigherResolutionThan(pixels)) VideoStreamAdapter::GetHigherResolutionThan(pixels))
: absl::nullopt; : absl::nullopt;
if (!bitrate_limits.has_value() || bitrate_bps == 0) { if (!bitrate_limits.has_value() || bitrate_bps == 0) {
return true; // No limit configured or bitrate provided. return true; // No limit configured or bitrate provided.

View File

@ -32,32 +32,14 @@
#include "rtc_base/experiments/quality_scaler_settings.h" #include "rtc_base/experiments/quality_scaler_settings.h"
#include "rtc_base/strings/string_builder.h" #include "rtc_base/strings/string_builder.h"
#include "system_wrappers/include/clock.h" #include "system_wrappers/include/clock.h"
#include "video/adaptation/adaptation_counters.h"
#include "video/adaptation/video_stream_adapter.h"
#include "video/encode_usage_resource.h" #include "video/encode_usage_resource.h"
#include "video/overuse_frame_detector.h" #include "video/overuse_frame_detector.h"
#include "video/quality_scaler_resource.h" #include "video/quality_scaler_resource.h"
namespace webrtc { namespace webrtc {
// Counts the number of adaptations have resulted due to resource overuse.
// Today we can adapt resolution and fps.
struct AdaptationCounters {
AdaptationCounters() : resolution_adaptations(0), fps_adaptations(0) {}
AdaptationCounters(int resolution_adaptations, int fps_adaptations)
: resolution_adaptations(resolution_adaptations),
fps_adaptations(fps_adaptations) {}
int Total() const { return fps_adaptations + resolution_adaptations; }
bool operator==(const AdaptationCounters& rhs) const;
bool operator!=(const AdaptationCounters& rhs) const;
AdaptationCounters operator+(const AdaptationCounters& other) const;
AdaptationCounters operator-(const AdaptationCounters& other) const;
int resolution_adaptations;
int fps_adaptations;
};
class VideoStreamEncoder; class VideoStreamEncoder;
// This class is used by the VideoStreamEncoder and is responsible for adapting // This class is used by the VideoStreamEncoder and is responsible for adapting
@ -70,10 +52,8 @@ class VideoStreamEncoder;
// TODO(hbos): Add unittests specific to this class, it is currently only tested // TODO(hbos): Add unittests specific to this class, it is currently only tested
// indirectly in video_stream_encoder_unittest.cc and other tests exercising // indirectly in video_stream_encoder_unittest.cc and other tests exercising
// VideoStreamEncoder. // VideoStreamEncoder.
// TODO(hbos): Create and implement an abstract interface // TODO(https://crbug.com/webrtc/11222): Rename this class to something more
// ResourceAdaptationModuleInterface and make this class inherit it. Use the // appropriate and move it to the video/adaptation/ subdirectory.
// generic interface in VideoStreamEncoder, unblocking other modules from being
// implemented and used.
class OveruseFrameDetectorResourceAdaptationModule class OveruseFrameDetectorResourceAdaptationModule
: public ResourceAdaptationModuleInterface, : public ResourceAdaptationModuleInterface,
public ResourceListener { public ResourceListener {
@ -250,7 +230,7 @@ class OveruseFrameDetectorResourceAdaptationModule
// or AdaptDown signal. // or AdaptDown signal.
absl::optional<AdaptationRequest> last_adaptation_request_; absl::optional<AdaptationRequest> last_adaptation_request_;
// Keeps track of source restrictions that this adaptation module outputs. // Keeps track of source restrictions that this adaptation module outputs.
const std::unique_ptr<VideoSourceRestrictor> source_restrictor_; const std::unique_ptr<VideoStreamAdapter> stream_adapter_;
const std::unique_ptr<EncodeUsageResource> encode_usage_resource_; const std::unique_ptr<EncodeUsageResource> encode_usage_resource_;
const std::unique_ptr<QualityScalerResource> quality_scaler_resource_; const std::unique_ptr<QualityScalerResource> quality_scaler_resource_;
const std::unique_ptr<InitialFrameDropper> initial_frame_dropper_; const std::unique_ptr<InitialFrameDropper> initial_frame_dropper_;

View File

@ -12,42 +12,10 @@
#include "test/gmock.h" #include "test/gmock.h"
#include "test/gtest.h" #include "test/gtest.h"
#include "video/adaptation/adaptation_counters.h"
namespace webrtc { namespace webrtc {
TEST(AdaptationCountersTest, Addition) {
AdaptationCounters a;
AdaptationCounters b(1, 2);
AdaptationCounters total = a + b;
EXPECT_EQ(1, total.resolution_adaptations);
EXPECT_EQ(2, total.fps_adaptations);
}
TEST(AdaptationCountersTest, Subtraction) {
AdaptationCounters a(0, 1);
AdaptationCounters b(2, 1);
AdaptationCounters diff = a - b;
EXPECT_EQ(-2, diff.resolution_adaptations);
EXPECT_EQ(0, diff.fps_adaptations);
}
TEST(AdaptationCountersTest, Equality) {
AdaptationCounters a(1, 2);
AdaptationCounters b(2, 1);
EXPECT_EQ(a, a);
EXPECT_NE(a, b);
}
TEST(AdaptationCountersTest, SelfAdditionSubtraction) {
AdaptationCounters a(1, 0);
AdaptationCounters b(0, 1);
EXPECT_EQ(a, a + b - b);
EXPECT_EQ(a, b + a - b);
EXPECT_EQ(a, a - b + b);
EXPECT_EQ(a, b - b + a);
}
TEST(OveruseFrameDetectorResourceAdaptationModuleTest, TEST(OveruseFrameDetectorResourceAdaptationModuleTest,
FirstAdaptationDown_Fps) { FirstAdaptationDown_Fps) {
AdaptationCounters cpu; AdaptationCounters cpu;
@ -108,11 +76,9 @@ TEST(OveruseFrameDetectorResourceAdaptationModuleTest,
AdaptationCounters qp(1, 0); AdaptationCounters qp(1, 0);
AdaptationCounters total(0, 1); AdaptationCounters total(0, 1);
// CPU adaptation for resolution, but no // CPU adaptation for resolution, but no resolution adaptation left from CPU.
// resolution adaptation left from CPU. // We then borrow the resolution adaptation from qp, and give qp the fps
// We then borrow the resolution // adaptation from CPU.
// adaptation from qp, and give qp the
// fps adaptation from CPU.
OveruseFrameDetectorResourceAdaptationModule::OnAdaptationCountChanged( OveruseFrameDetectorResourceAdaptationModule::OnAdaptationCountChanged(
total, &cpu, &qp); total, &cpu, &qp);
@ -127,11 +93,8 @@ TEST(OveruseFrameDetectorResourceAdaptationModuleTest, AdaptUpWithBorrow_Fps) {
AdaptationCounters qp(0, 1); AdaptationCounters qp(0, 1);
AdaptationCounters total(1, 0); AdaptationCounters total(1, 0);
// CPU adaptation for fps, but no // CPU adaptation for fps, but no fps adaptation left from CPU. We then borrow
// fps adaptation left from CPU. We // the fps adaptation from qp, and give qp the resolution adaptation from CPU.
// then borrow the fps adaptation
// from qp, and give qp the
// resolution adaptation from CPU.
OveruseFrameDetectorResourceAdaptationModule::OnAdaptationCountChanged( OveruseFrameDetectorResourceAdaptationModule::OnAdaptationCountChanged(
total, &cpu, &qp); total, &cpu, &qp);

View File

@ -25,6 +25,8 @@ namespace webrtc {
// indirectly by usage in the OveruseFrameDetectorResourceAdaptationModule // indirectly by usage in the OveruseFrameDetectorResourceAdaptationModule
// (which is only tested because of its usage in VideoStreamEncoder); all tests // (which is only tested because of its usage in VideoStreamEncoder); all tests
// are currently in video_stream_encoder_unittest.cc. // are currently in video_stream_encoder_unittest.cc.
// TODO(https://crbug.com/webrtc/11222): Move this class to the
// video/adaptation/ subdirectory.
class QualityScalerResource : public Resource, class QualityScalerResource : public Resource,
public AdaptationObserverInterface { public AdaptationObserverInterface {
public: public: