[Adaptation] Prep Resource for api/ move. Introduce VSE-Resource.

This CL is in preparation for moving Resource to the api/ folder. It
does not move it, but makes it such that the moving CL can be a pure
move.

In order to do this, we must stop depending on rtc_base/rtc::TaskQueue
in favor of api/webrtc::TaskQueueBase.

There are also other rtc_base/ dependencies that we do not want to
expose to the api/ folder, like critical sections and thread
annotations which are not publically exposed. To get around this, we
make Resource an abstract interface and move all of the base class
functionality into a new non-api/ class: VideoStreamEncoderResource.

The Resource now has Register/UnregisterAdaptationTaskQueue() methods.
By explicitly unregistering, we can ensure validity of the pointer even
if the Resource outlives the PeerConnection. While public interface
methods are only to be called on the adaptation task queue, posting to
the task queue happens off-queue, so a |lock_| is introduced to guard
it.

Bug: webrtc:11525
Change-Id: I50b3a30960cdec9032016c779b47001c01dad32f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/176320
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@{#31402}
This commit is contained in:
Henrik Boström
2020-06-01 17:59:05 +02:00
committed by Commit Bot
parent 3a2be87b80
commit 5cc28b0c6a
20 changed files with 442 additions and 185 deletions

View File

@ -30,6 +30,7 @@ rtc_library("resource_adaptation") {
deps = [ deps = [
"../../api:rtp_parameters", "../../api:rtp_parameters",
"../../api:scoped_refptr", "../../api:scoped_refptr",
"../../api/task_queue:task_queue",
"../../api/video:video_adaptation", "../../api/video:video_adaptation",
"../../api/video:video_frame", "../../api/video:video_frame",
"../../api/video:video_stream_encoder", "../../api/video:video_stream_encoder",
@ -86,9 +87,14 @@ if (rtc_include_tests) {
] ]
deps = [ deps = [
":resource_adaptation", ":resource_adaptation",
"../../api:scoped_refptr",
"../../api/task_queue:task_queue",
"../../api/video:video_stream_encoder", "../../api/video:video_stream_encoder",
"../../rtc_base:rtc_base_approved", "../../rtc_base:rtc_base_approved",
"../../rtc_base/synchronization:sequence_checker",
"../../rtc_base/task_utils:to_queued_task",
"../../test:test_support", "../../test:test_support",
"//third_party/abseil-cpp/absl/types:optional",
] ]
} }
} }

View File

@ -26,77 +26,8 @@ const char* ResourceUsageStateToString(ResourceUsageState usage_state) {
ResourceListener::~ResourceListener() {} ResourceListener::~ResourceListener() {}
Resource::Resource() Resource::Resource() {}
: encoder_queue_(nullptr),
resource_adaptation_queue_(nullptr),
usage_state_(absl::nullopt),
listener_(nullptr) {}
Resource::~Resource() { Resource::~Resource() {}
RTC_DCHECK(!listener_)
<< "There is a listener depending on a Resource being destroyed.";
}
void Resource::Initialize(rtc::TaskQueue* encoder_queue,
rtc::TaskQueue* resource_adaptation_queue) {
RTC_DCHECK(!encoder_queue_);
RTC_DCHECK(encoder_queue);
RTC_DCHECK(!resource_adaptation_queue_);
RTC_DCHECK(resource_adaptation_queue);
encoder_queue_ = encoder_queue;
resource_adaptation_queue_ = resource_adaptation_queue;
}
void Resource::SetResourceListener(ResourceListener* listener) {
RTC_DCHECK(resource_adaptation_queue_);
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
// If you want to change listener you need to unregister the old listener by
// setting it to null first.
RTC_DCHECK(!listener_ || !listener) << "A listener is already set";
listener_ = listener;
}
absl::optional<ResourceUsageState> Resource::usage_state() const {
RTC_DCHECK(resource_adaptation_queue_);
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
return usage_state_;
}
void Resource::ClearUsageState() {
RTC_DCHECK(resource_adaptation_queue_);
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
usage_state_ = absl::nullopt;
}
bool Resource::IsAdaptationUpAllowed(
const VideoStreamInputState& input_state,
const VideoSourceRestrictions& restrictions_before,
const VideoSourceRestrictions& restrictions_after,
rtc::scoped_refptr<Resource> reason_resource) const {
return true;
}
void Resource::OnAdaptationApplied(
const VideoStreamInputState& input_state,
const VideoSourceRestrictions& restrictions_before,
const VideoSourceRestrictions& restrictions_after,
rtc::scoped_refptr<Resource> reason_resource) {}
rtc::TaskQueue* Resource::encoder_queue() const {
return encoder_queue_;
}
rtc::TaskQueue* Resource::resource_adaptation_queue() const {
return resource_adaptation_queue_;
}
void Resource::OnResourceUsageStateMeasured(ResourceUsageState usage_state) {
RTC_DCHECK(resource_adaptation_queue_);
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
usage_state_ = usage_state;
if (!listener_)
return;
listener_->OnResourceUsageStateMeasured(this);
}
} // namespace webrtc } // namespace webrtc

View File

@ -16,10 +16,10 @@
#include "absl/types/optional.h" #include "absl/types/optional.h"
#include "api/scoped_refptr.h" #include "api/scoped_refptr.h"
#include "api/task_queue/task_queue_base.h"
#include "call/adaptation/video_source_restrictions.h" #include "call/adaptation/video_source_restrictions.h"
#include "call/adaptation/video_stream_input_state.h" #include "call/adaptation/video_stream_input_state.h"
#include "rtc_base/ref_count.h" #include "rtc_base/ref_count.h"
#include "rtc_base/task_queue.h"
namespace webrtc { namespace webrtc {
@ -44,49 +44,62 @@ class ResourceListener {
rtc::scoped_refptr<Resource> resource) = 0; rtc::scoped_refptr<Resource> resource) = 0;
}; };
// A Resource monitors an implementation-specific system resource. It may report
// kOveruse or kUnderuse when resource usage is high or low enough that we
// should perform some sort of mitigation to fulfil the resource's constraints.
//
// All methods defined in this interface, except RegisterAdaptationTaskQueue(),
// MUST be invoked on the resource adaptation task queue.
//
// Usage measurements may be performed on an implementation-specific task queue.
// The Resource is reference counted to prevent use-after-free when posting
// between task queues. As such, the implementation MUST NOT make any
// assumptions about which task queue Resource is destructed on.
class Resource : public rtc::RefCountInterface { class Resource : public rtc::RefCountInterface {
public: public:
// By default, usage_state() is null until a measurement is made.
Resource(); Resource();
// Destruction may happen on any task queue.
~Resource() override; ~Resource() override;
void Initialize(rtc::TaskQueue* encoder_queue, // Provides a pointer to the adaptation task queue. After this call, all
rtc::TaskQueue* resource_adaptation_queue); // methods defined in this interface, including
// UnregisterAdaptationTaskQueue() MUST be invoked on the adaptation task
// queue. Registering the adaptation task queue may, however, happen off the
// adaptation task queue.
virtual void RegisterAdaptationTaskQueue(
TaskQueueBase* resource_adaptation_queue) = 0;
// Signals that the adaptation task queue is no longer safe to use. No
// assumptions must be made as to whether or not tasks in-flight will run.
virtual void UnregisterAdaptationTaskQueue() = 0;
void SetResourceListener(ResourceListener* listener); // The listeners MUST be informed any time UsageState() changes.
virtual void SetResourceListener(ResourceListener* listener) = 0;
absl::optional<ResourceUsageState> usage_state() const; virtual std::string Name() const = 0;
void ClearUsageState(); // Within a single task running on the adaptation task queue, UsageState()
// MUST return the same value every time it is called.
// TODO(https://crbug.com/webrtc/11618): Remove the UsageState() getter in
// favor of passing the use usage state directly to the ResourceListener. This
// gets rid of this strange requirement of having to return the same thing
// every time.
virtual absl::optional<ResourceUsageState> UsageState() const = 0;
// Invalidates current usage measurements, i.e. in response to the system load
// changing. Example: an adaptation was just applied.
virtual void ClearUsageState() = 0;
// This method allows the Resource to reject a proposed adaptation in the "up" // This method allows the Resource to reject a proposed adaptation in the "up"
// direction if it predicts this would cause overuse of this resource. The // direction if it predicts this would cause overuse of this resource.
// default implementation unconditionally returns true (= allowed).
virtual bool IsAdaptationUpAllowed( virtual bool IsAdaptationUpAllowed(
const VideoStreamInputState& input_state, const VideoStreamInputState& input_state,
const VideoSourceRestrictions& restrictions_before, const VideoSourceRestrictions& restrictions_before,
const VideoSourceRestrictions& restrictions_after, const VideoSourceRestrictions& restrictions_after,
rtc::scoped_refptr<Resource> reason_resource) const; rtc::scoped_refptr<Resource> reason_resource) const = 0;
virtual void OnAdaptationApplied( virtual void OnAdaptationApplied(
const VideoStreamInputState& input_state, const VideoStreamInputState& input_state,
const VideoSourceRestrictions& restrictions_before, const VideoSourceRestrictions& restrictions_before,
const VideoSourceRestrictions& restrictions_after, const VideoSourceRestrictions& restrictions_after,
rtc::scoped_refptr<Resource> reason_resource); rtc::scoped_refptr<Resource> reason_resource) = 0;
virtual std::string name() const = 0;
protected:
rtc::TaskQueue* encoder_queue() const;
rtc::TaskQueue* resource_adaptation_queue() const;
// Updates the usage state and informs all registered listeners.
void OnResourceUsageStateMeasured(ResourceUsageState usage_state);
private:
rtc::TaskQueue* encoder_queue_;
rtc::TaskQueue* resource_adaptation_queue_;
absl::optional<ResourceUsageState> usage_state_
RTC_GUARDED_BY(resource_adaptation_queue_);
ResourceListener* listener_ RTC_GUARDED_BY(resource_adaptation_queue_);
}; };
} // namespace webrtc } // namespace webrtc

View File

@ -195,8 +195,8 @@ void ResourceAdaptationProcessor::MaybeUpdateVideoSourceRestrictions(
void ResourceAdaptationProcessor::OnResourceUsageStateMeasured( void ResourceAdaptationProcessor::OnResourceUsageStateMeasured(
rtc::scoped_refptr<Resource> resource) { rtc::scoped_refptr<Resource> resource) {
RTC_DCHECK_RUN_ON(&sequence_checker_); RTC_DCHECK_RUN_ON(&sequence_checker_);
RTC_DCHECK(resource->usage_state().has_value()); RTC_DCHECK(resource->UsageState().has_value());
ResourceUsageState usage_state = resource->usage_state().value(); ResourceUsageState usage_state = resource->UsageState().value();
MitigationResultAndLogMessage result_and_message; MitigationResultAndLogMessage result_and_message;
switch (usage_state) { switch (usage_state) {
case ResourceUsageState::kOveruse: case ResourceUsageState::kOveruse:
@ -214,7 +214,7 @@ void ResourceAdaptationProcessor::OnResourceUsageStateMeasured(
// successfully adapted since - don't log to avoid spam. // successfully adapted since - don't log to avoid spam.
return; return;
} }
RTC_LOG(INFO) << "Resource \"" << resource->name() << "\" signalled " RTC_LOG(INFO) << "Resource \"" << resource->Name() << "\" signalled "
<< ResourceUsageStateToString(usage_state) << ". " << ResourceUsageStateToString(usage_state) << ". "
<< result_and_message.message; << result_and_message.message;
if (result_and_message.result == MitigationResult::kAdaptationApplied) { if (result_and_message.result == MitigationResult::kAdaptationApplied) {
@ -289,7 +289,7 @@ ResourceAdaptationProcessor::OnResourceUnderuse(
restrictions_after, reason_resource)) { restrictions_after, reason_resource)) {
processing_in_progress_ = false; processing_in_progress_ = false;
rtc::StringBuilder message; rtc::StringBuilder message;
message << "Not adapting up because resource \"" << resource->name() message << "Not adapting up because resource \"" << resource->Name()
<< "\" disallowed it"; << "\" disallowed it";
return MitigationResultAndLogMessage( return MitigationResultAndLogMessage(
MitigationResult::kRejectedByResource, message.Release()); MitigationResult::kRejectedByResource, message.Release());

View File

@ -70,16 +70,16 @@ class ResourceAdaptationProcessorTest : public ::testing::Test {
public: public:
ResourceAdaptationProcessorTest() ResourceAdaptationProcessorTest()
: resource_adaptation_queue_("ResourceAdaptationQueue"), : resource_adaptation_queue_("ResourceAdaptationQueue"),
encoder_queue_("EncoderQueue"),
frame_rate_provider_(), frame_rate_provider_(),
input_state_provider_(&frame_rate_provider_), input_state_provider_(&frame_rate_provider_),
resource_(new FakeResource("FakeResource")), resource_(FakeResource::Create("FakeResource")),
other_resource_(new FakeResource("OtherFakeResource")), other_resource_(FakeResource::Create("OtherFakeResource")),
processor_(std::make_unique<ResourceAdaptationProcessor>( processor_(std::make_unique<ResourceAdaptationProcessor>(
&input_state_provider_, &input_state_provider_,
/*encoder_stats_observer=*/&frame_rate_provider_)) { /*encoder_stats_observer=*/&frame_rate_provider_)) {
resource_->Initialize(&encoder_queue_, &resource_adaptation_queue_); resource_->RegisterAdaptationTaskQueue(resource_adaptation_queue_.Get());
other_resource_->Initialize(&encoder_queue_, &resource_adaptation_queue_); other_resource_->RegisterAdaptationTaskQueue(
resource_adaptation_queue_.Get());
rtc::Event event; rtc::Event event;
resource_adaptation_queue_.PostTask([this, &event] { resource_adaptation_queue_.PostTask([this, &event] {
processor_->InitializeOnResourceAdaptationQueue(); processor_->InitializeOnResourceAdaptationQueue();
@ -119,7 +119,6 @@ class ResourceAdaptationProcessorTest : public ::testing::Test {
protected: protected:
TaskQueueForTest resource_adaptation_queue_; TaskQueueForTest resource_adaptation_queue_;
TaskQueueForTest encoder_queue_;
FakeFrameRateProvider frame_rate_provider_; FakeFrameRateProvider frame_rate_provider_;
VideoStreamInputStateProvider input_state_provider_; VideoStreamInputStateProvider input_state_provider_;
rtc::scoped_refptr<FakeResource> resource_; rtc::scoped_refptr<FakeResource> resource_;
@ -397,7 +396,7 @@ TEST_F(ResourceAdaptationProcessorTest, AdaptingClearsResourceUsageState) {
SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize); SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
resource_->set_usage_state(ResourceUsageState::kOveruse); resource_->set_usage_state(ResourceUsageState::kOveruse);
EXPECT_EQ(1u, processor_listener_.restrictions_updated_count()); EXPECT_EQ(1u, processor_listener_.restrictions_updated_count());
EXPECT_FALSE(resource_->usage_state().has_value()); EXPECT_FALSE(resource_->UsageState().has_value());
}, },
RTC_FROM_HERE); RTC_FROM_HERE);
} }
@ -410,7 +409,7 @@ TEST_F(ResourceAdaptationProcessorTest,
processor_->StartResourceAdaptation(); processor_->StartResourceAdaptation();
resource_->set_usage_state(ResourceUsageState::kOveruse); resource_->set_usage_state(ResourceUsageState::kOveruse);
EXPECT_EQ(0u, processor_listener_.restrictions_updated_count()); EXPECT_EQ(0u, processor_listener_.restrictions_updated_count());
EXPECT_FALSE(resource_->usage_state().has_value()); EXPECT_FALSE(resource_->UsageState().has_value());
}, },
RTC_FROM_HERE); RTC_FROM_HERE);
} }

View File

@ -36,15 +36,14 @@ class ResourceTest : public ::testing::Test {
public: public:
ResourceTest() ResourceTest()
: resource_adaptation_queue_("ResourceAdaptationQueue"), : resource_adaptation_queue_("ResourceAdaptationQueue"),
encoder_queue_("EncoderQueue"), fake_resource_(FakeResource::Create("FakeResource")) {
fake_resource_(new FakeResource("FakeResource")) { fake_resource_->RegisterAdaptationTaskQueue(
fake_resource_->Initialize(&encoder_queue_, &resource_adaptation_queue_); resource_adaptation_queue_.Get());
} }
protected: protected:
const std::unique_ptr<TaskQueueFactory> task_queue_factory_; const std::unique_ptr<TaskQueueFactory> task_queue_factory_;
TaskQueueForTest resource_adaptation_queue_; TaskQueueForTest resource_adaptation_queue_;
TaskQueueForTest encoder_queue_;
rtc::scoped_refptr<FakeResource> fake_resource_; rtc::scoped_refptr<FakeResource> fake_resource_;
}; };
@ -56,7 +55,7 @@ TEST_F(ResourceTest, RegisteringListenerReceivesCallbacks) {
EXPECT_CALL(resource_listener, OnResourceUsageStateMeasured(_)) EXPECT_CALL(resource_listener, OnResourceUsageStateMeasured(_))
.Times(1) .Times(1)
.WillOnce([](rtc::scoped_refptr<Resource> resource) { .WillOnce([](rtc::scoped_refptr<Resource> resource) {
EXPECT_EQ(ResourceUsageState::kOveruse, resource->usage_state()); EXPECT_EQ(ResourceUsageState::kOveruse, resource->UsageState());
}); });
fake_resource_->set_usage_state(ResourceUsageState::kOveruse); fake_resource_->set_usage_state(ResourceUsageState::kOveruse);
fake_resource_->SetResourceListener(nullptr); fake_resource_->SetResourceListener(nullptr);

View File

@ -10,35 +10,95 @@
#include "call/adaptation/test/fake_resource.h" #include "call/adaptation/test/fake_resource.h"
#include <algorithm>
#include <utility> #include <utility>
#include "rtc_base/ref_counted_object.h"
#include "rtc_base/task_utils/to_queued_task.h"
namespace webrtc { namespace webrtc {
// static
rtc::scoped_refptr<FakeResource> FakeResource::Create(std::string name) {
return new rtc::RefCountedObject<FakeResource>(name);
}
FakeResource::FakeResource(std::string name) FakeResource::FakeResource(std::string name)
: rtc::RefCountedObject<Resource>(), : Resource(),
lock_(),
name_(std::move(name)), name_(std::move(name)),
resource_adaptation_queue_(nullptr),
is_adaptation_up_allowed_(true), is_adaptation_up_allowed_(true),
num_adaptations_applied_(0) {} num_adaptations_applied_(0),
usage_state_(absl::nullopt),
listener_(nullptr) {}
FakeResource::~FakeResource() {} FakeResource::~FakeResource() {}
void FakeResource::set_usage_state(ResourceUsageState usage_state) { void FakeResource::set_usage_state(ResourceUsageState usage_state) {
OnResourceUsageStateMeasured(usage_state); if (!resource_adaptation_queue_->IsCurrent()) {
resource_adaptation_queue_->PostTask(ToQueuedTask(
[this_ref = rtc::scoped_refptr<FakeResource>(this), usage_state] {
this_ref->set_usage_state(usage_state);
}));
return;
}
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
usage_state_ = usage_state;
if (listener_) {
listener_->OnResourceUsageStateMeasured(this);
}
} }
void FakeResource::set_is_adaptation_up_allowed(bool is_adaptation_up_allowed) { void FakeResource::set_is_adaptation_up_allowed(bool is_adaptation_up_allowed) {
rtc::CritScope crit(&lock_);
is_adaptation_up_allowed_ = is_adaptation_up_allowed; is_adaptation_up_allowed_ = is_adaptation_up_allowed;
} }
size_t FakeResource::num_adaptations_applied() const { size_t FakeResource::num_adaptations_applied() const {
rtc::CritScope crit(&lock_);
return num_adaptations_applied_; return num_adaptations_applied_;
} }
void FakeResource::RegisterAdaptationTaskQueue(
TaskQueueBase* resource_adaptation_queue) {
RTC_DCHECK(!resource_adaptation_queue_);
RTC_DCHECK(resource_adaptation_queue);
resource_adaptation_queue_ = resource_adaptation_queue;
}
void FakeResource::UnregisterAdaptationTaskQueue() {
RTC_DCHECK(resource_adaptation_queue_);
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
resource_adaptation_queue_ = nullptr;
}
void FakeResource::SetResourceListener(ResourceListener* listener) {
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
listener_ = listener;
}
std::string FakeResource::Name() const {
return name_;
}
absl::optional<ResourceUsageState> FakeResource::UsageState() const {
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
return usage_state_;
}
void FakeResource::ClearUsageState() {
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
usage_state_ = absl::nullopt;
}
bool FakeResource::IsAdaptationUpAllowed( bool FakeResource::IsAdaptationUpAllowed(
const VideoStreamInputState& input_state, const VideoStreamInputState& input_state,
const VideoSourceRestrictions& restrictions_before, const VideoSourceRestrictions& restrictions_before,
const VideoSourceRestrictions& restrictions_after, const VideoSourceRestrictions& restrictions_after,
rtc::scoped_refptr<Resource> reason_resource) const { rtc::scoped_refptr<Resource> reason_resource) const {
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
rtc::CritScope crit(&lock_);
return is_adaptation_up_allowed_; return is_adaptation_up_allowed_;
} }
@ -47,6 +107,8 @@ void FakeResource::OnAdaptationApplied(
const VideoSourceRestrictions& restrictions_before, const VideoSourceRestrictions& restrictions_before,
const VideoSourceRestrictions& restrictions_after, const VideoSourceRestrictions& restrictions_after,
rtc::scoped_refptr<Resource> reason_resource) { rtc::scoped_refptr<Resource> reason_resource) {
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
rtc::CritScope crit(&lock_);
++num_adaptations_applied_; ++num_adaptations_applied_;
} }

View File

@ -12,15 +12,22 @@
#define CALL_ADAPTATION_TEST_FAKE_RESOURCE_H_ #define CALL_ADAPTATION_TEST_FAKE_RESOURCE_H_
#include <string> #include <string>
#include <vector>
#include "absl/types/optional.h"
#include "api/scoped_refptr.h"
#include "api/task_queue/task_queue_base.h"
#include "call/adaptation/resource.h" #include "call/adaptation/resource.h"
#include "rtc_base/ref_counted_object.h" #include "rtc_base/critical_section.h"
#include "rtc_base/synchronization/sequence_checker.h"
namespace webrtc { namespace webrtc {
// Fake resource used for testing. // Fake resource used for testing.
class FakeResource : public rtc::RefCountedObject<Resource> { class FakeResource : public Resource {
public: public:
static rtc::scoped_refptr<FakeResource> Create(std::string name);
explicit FakeResource(std::string name); explicit FakeResource(std::string name);
~FakeResource() override; ~FakeResource() override;
@ -29,7 +36,13 @@ class FakeResource : public rtc::RefCountedObject<Resource> {
size_t num_adaptations_applied() const; size_t num_adaptations_applied() const;
// Resource implementation. // Resource implementation.
std::string name() const override { return name_; } void RegisterAdaptationTaskQueue(
TaskQueueBase* resource_adaptation_queue) override;
void UnregisterAdaptationTaskQueue() override;
void SetResourceListener(ResourceListener* listener) override;
std::string Name() const override;
absl::optional<ResourceUsageState> UsageState() const override;
void ClearUsageState() override;
bool IsAdaptationUpAllowed( bool IsAdaptationUpAllowed(
const VideoStreamInputState& input_state, const VideoStreamInputState& input_state,
const VideoSourceRestrictions& restrictions_before, const VideoSourceRestrictions& restrictions_before,
@ -42,9 +55,14 @@ class FakeResource : public rtc::RefCountedObject<Resource> {
rtc::scoped_refptr<Resource> reason_resource) override; rtc::scoped_refptr<Resource> reason_resource) override;
private: private:
rtc::CriticalSection lock_;
const std::string name_; const std::string name_;
bool is_adaptation_up_allowed_; TaskQueueBase* resource_adaptation_queue_;
size_t num_adaptations_applied_; bool is_adaptation_up_allowed_ RTC_GUARDED_BY(lock_);
size_t num_adaptations_applied_ RTC_GUARDED_BY(lock_);
absl::optional<ResourceUsageState> usage_state_
RTC_GUARDED_BY(resource_adaptation_queue_);
ResourceListener* listener_ RTC_GUARDED_BY(resource_adaptation_queue_);
}; };
} // namespace webrtc } // namespace webrtc

View File

@ -16,6 +16,8 @@ rtc_library("video_adaptation") {
"overuse_frame_detector.h", "overuse_frame_detector.h",
"quality_scaler_resource.cc", "quality_scaler_resource.cc",
"quality_scaler_resource.h", "quality_scaler_resource.h",
"video_stream_encoder_resource.cc",
"video_stream_encoder_resource.h",
"video_stream_encoder_resource_manager.cc", "video_stream_encoder_resource_manager.cc",
"video_stream_encoder_resource_manager.h", "video_stream_encoder_resource_manager.h",
] ]
@ -44,6 +46,7 @@ rtc_library("video_adaptation") {
"../../rtc_base/experiments:quality_scaler_settings", "../../rtc_base/experiments:quality_scaler_settings",
"../../rtc_base/synchronization:sequence_checker", "../../rtc_base/synchronization:sequence_checker",
"../../rtc_base/task_utils:repeating_task", "../../rtc_base/task_utils:repeating_task",
"../../rtc_base/task_utils:to_queued_task",
"../../system_wrappers:field_trial", "../../system_wrappers:field_trial",
"../../system_wrappers:system_wrappers", "../../system_wrappers:system_wrappers",
"//third_party/abseil-cpp/absl/algorithm:container", "//third_party/abseil-cpp/absl/algorithm:container",

View File

@ -15,18 +15,28 @@
#include "api/video/video_adaptation_reason.h" #include "api/video/video_adaptation_reason.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/ref_counted_object.h"
namespace webrtc { namespace webrtc {
// static
rtc::scoped_refptr<EncodeUsageResource> EncodeUsageResource::Create(
std::unique_ptr<OveruseFrameDetector> overuse_detector) {
return new rtc::RefCountedObject<EncodeUsageResource>(
std::move(overuse_detector));
}
EncodeUsageResource::EncodeUsageResource( EncodeUsageResource::EncodeUsageResource(
std::unique_ptr<OveruseFrameDetector> overuse_detector) std::unique_ptr<OveruseFrameDetector> overuse_detector)
: rtc::RefCountedObject<Resource>(), : VideoStreamEncoderResource("EncoderUsageResource"),
overuse_detector_(std::move(overuse_detector)), overuse_detector_(std::move(overuse_detector)),
is_started_(false), is_started_(false),
target_frame_rate_(absl::nullopt) { target_frame_rate_(absl::nullopt) {
RTC_DCHECK(overuse_detector_); RTC_DCHECK(overuse_detector_);
} }
EncodeUsageResource::~EncodeUsageResource() {}
bool EncodeUsageResource::is_started() const { bool EncodeUsageResource::is_started() const {
RTC_DCHECK_RUN_ON(encoder_queue()); RTC_DCHECK_RUN_ON(encoder_queue());
return is_started_; return is_started_;
@ -81,7 +91,7 @@ void EncodeUsageResource::AdaptUp() {
RTC_DCHECK_RUN_ON(encoder_queue()); RTC_DCHECK_RUN_ON(encoder_queue());
// Reference counting guarantees that this object is still alive by the time // Reference counting guarantees that this object is still alive by the time
// the task is executed. // the task is executed.
resource_adaptation_queue()->PostTask( MaybePostTaskToResourceAdaptationQueue(
[this_ref = rtc::scoped_refptr<EncodeUsageResource>(this)] { [this_ref = rtc::scoped_refptr<EncodeUsageResource>(this)] {
RTC_DCHECK_RUN_ON(this_ref->resource_adaptation_queue()); RTC_DCHECK_RUN_ON(this_ref->resource_adaptation_queue());
this_ref->OnResourceUsageStateMeasured(ResourceUsageState::kUnderuse); this_ref->OnResourceUsageStateMeasured(ResourceUsageState::kUnderuse);
@ -92,7 +102,7 @@ void EncodeUsageResource::AdaptDown() {
RTC_DCHECK_RUN_ON(encoder_queue()); RTC_DCHECK_RUN_ON(encoder_queue());
// Reference counting guarantees that this object is still alive by the time // Reference counting guarantees that this object is still alive by the time
// the task is executed. // the task is executed.
resource_adaptation_queue()->PostTask( MaybePostTaskToResourceAdaptationQueue(
[this_ref = rtc::scoped_refptr<EncodeUsageResource>(this)] { [this_ref = rtc::scoped_refptr<EncodeUsageResource>(this)] {
RTC_DCHECK_RUN_ON(this_ref->resource_adaptation_queue()); RTC_DCHECK_RUN_ON(this_ref->resource_adaptation_queue());
this_ref->OnResourceUsageStateMeasured(ResourceUsageState::kOveruse); this_ref->OnResourceUsageStateMeasured(ResourceUsageState::kOveruse);

View File

@ -15,11 +15,13 @@
#include <string> #include <string>
#include "absl/types/optional.h" #include "absl/types/optional.h"
#include "api/scoped_refptr.h"
#include "api/video/video_adaptation_reason.h" #include "api/video/video_adaptation_reason.h"
#include "call/adaptation/resource.h" #include "call/adaptation/resource.h"
#include "rtc_base/ref_counted_object.h" #include "rtc_base/ref_counted_object.h"
#include "rtc_base/task_queue.h" #include "rtc_base/task_queue.h"
#include "video/adaptation/overuse_frame_detector.h" #include "video/adaptation/overuse_frame_detector.h"
#include "video/adaptation/video_stream_encoder_resource.h"
namespace webrtc { namespace webrtc {
@ -28,11 +30,15 @@ namespace webrtc {
// indirectly by usage in the ResourceAdaptationProcessor (which is only tested // indirectly by usage in the ResourceAdaptationProcessor (which is only tested
// because of its usage in VideoStreamEncoder); all tests are currently in // because of its usage in VideoStreamEncoder); all tests are currently in
// video_stream_encoder_unittest.cc. // video_stream_encoder_unittest.cc.
class EncodeUsageResource : public rtc::RefCountedObject<Resource>, class EncodeUsageResource : public VideoStreamEncoderResource,
public OveruseFrameDetectorObserverInterface { public OveruseFrameDetectorObserverInterface {
public: public:
static rtc::scoped_refptr<EncodeUsageResource> Create(
std::unique_ptr<OveruseFrameDetector> overuse_detector);
explicit EncodeUsageResource( explicit EncodeUsageResource(
std::unique_ptr<OveruseFrameDetector> overuse_detector); std::unique_ptr<OveruseFrameDetector> overuse_detector);
~EncodeUsageResource() override;
bool is_started() const; bool is_started() const;
@ -51,8 +57,6 @@ class EncodeUsageResource : public rtc::RefCountedObject<Resource>,
void AdaptUp() override; void AdaptUp() override;
void AdaptDown() override; void AdaptDown() override;
std::string name() const override { return "EncoderUsageResource"; }
private: private:
int TargetFrameRateAsInt(); int TargetFrameRateAsInt();

View File

@ -13,6 +13,8 @@
#include <utility> #include <utility>
#include "rtc_base/experiments/balanced_degradation_settings.h" #include "rtc_base/experiments/balanced_degradation_settings.h"
#include "rtc_base/ref_counted_object.h"
#include "rtc_base/task_utils/to_queued_task.h"
#include "rtc_base/time_utils.h" #include "rtc_base/time_utils.h"
namespace webrtc { namespace webrtc {
@ -23,8 +25,13 @@ const int64_t kUnderuseDueToDisabledCooldownMs = 1000;
} // namespace } // namespace
// static
rtc::scoped_refptr<QualityScalerResource> QualityScalerResource::Create() {
return new rtc::RefCountedObject<QualityScalerResource>();
}
QualityScalerResource::QualityScalerResource() QualityScalerResource::QualityScalerResource()
: rtc::RefCountedObject<Resource>(), : VideoStreamEncoderResource("QualityScalerResource"),
quality_scaler_(nullptr), quality_scaler_(nullptr),
last_underuse_due_to_disabled_timestamp_ms_(absl::nullopt), last_underuse_due_to_disabled_timestamp_ms_(absl::nullopt),
num_handled_callbacks_(0), num_handled_callbacks_(0),
@ -95,7 +102,7 @@ void QualityScalerResource::OnEncodeCompleted(const EncodedImage& encoded_image,
timestamp_ms - last_underuse_due_to_disabled_timestamp_ms_.value() >= timestamp_ms - last_underuse_due_to_disabled_timestamp_ms_.value() >=
kUnderuseDueToDisabledCooldownMs) { kUnderuseDueToDisabledCooldownMs) {
last_underuse_due_to_disabled_timestamp_ms_ = timestamp_ms; last_underuse_due_to_disabled_timestamp_ms_ = timestamp_ms;
resource_adaptation_queue()->PostTask( MaybePostTaskToResourceAdaptationQueue(
[this_ref = rtc::scoped_refptr<QualityScalerResource>(this)] { [this_ref = rtc::scoped_refptr<QualityScalerResource>(this)] {
RTC_DCHECK_RUN_ON(this_ref->resource_adaptation_queue()); RTC_DCHECK_RUN_ON(this_ref->resource_adaptation_queue());
this_ref->OnResourceUsageStateMeasured( this_ref->OnResourceUsageStateMeasured(
@ -126,7 +133,7 @@ void QualityScalerResource::OnReportQpUsageHigh(
size_t callback_id = QueuePendingCallback(callback); size_t callback_id = QueuePendingCallback(callback);
// Reference counting guarantees that this object is still alive by the time // Reference counting guarantees that this object is still alive by the time
// the task is executed. // the task is executed.
resource_adaptation_queue()->PostTask( MaybePostTaskToResourceAdaptationQueue(
[this_ref = rtc::scoped_refptr<QualityScalerResource>(this), [this_ref = rtc::scoped_refptr<QualityScalerResource>(this),
callback_id] { callback_id] {
RTC_DCHECK_RUN_ON(this_ref->resource_adaptation_queue()); RTC_DCHECK_RUN_ON(this_ref->resource_adaptation_queue());
@ -146,7 +153,7 @@ void QualityScalerResource::OnReportQpUsageLow(
size_t callback_id = QueuePendingCallback(callback); size_t callback_id = QueuePendingCallback(callback);
// Reference counting guarantees that this object is still alive by the time // Reference counting guarantees that this object is still alive by the time
// the task is executed. // the task is executed.
resource_adaptation_queue()->PostTask( MaybePostTaskToResourceAdaptationQueue(
[this_ref = rtc::scoped_refptr<QualityScalerResource>(this), [this_ref = rtc::scoped_refptr<QualityScalerResource>(this),
callback_id] { callback_id] {
RTC_DCHECK_RUN_ON(this_ref->resource_adaptation_queue()); RTC_DCHECK_RUN_ON(this_ref->resource_adaptation_queue());
@ -206,8 +213,8 @@ void QualityScalerResource::HandlePendingCallback(size_t callback_id,
// Reference counting guarantees that this object is still alive by the time // Reference counting guarantees that this object is still alive by the time
// the task is executed. // the task is executed.
encoder_queue()->PostTask( encoder_queue()->PostTask(
[this_ref = rtc::scoped_refptr<QualityScalerResource>(this), callback_id, ToQueuedTask([this_ref = rtc::scoped_refptr<QualityScalerResource>(this),
clear_qp_samples] { callback_id, clear_qp_samples] {
RTC_DCHECK_RUN_ON(this_ref->encoder_queue()); RTC_DCHECK_RUN_ON(this_ref->encoder_queue());
if (this_ref->num_handled_callbacks_ >= callback_id) { if (this_ref->num_handled_callbacks_ >= callback_id) {
// The callback with this ID has already been handled. // The callback with this ID has already been handled.
@ -220,7 +227,7 @@ void QualityScalerResource::HandlePendingCallback(size_t callback_id,
clear_qp_samples); clear_qp_samples);
++this_ref->num_handled_callbacks_; ++this_ref->num_handled_callbacks_;
this_ref->pending_callbacks_.pop(); this_ref->pending_callbacks_.pop();
}); }));
} }
void QualityScalerResource::AbortPendingCallbacks() { void QualityScalerResource::AbortPendingCallbacks() {

View File

@ -16,6 +16,7 @@
#include <string> #include <string>
#include "absl/types/optional.h" #include "absl/types/optional.h"
#include "api/scoped_refptr.h"
#include "api/video/video_adaptation_reason.h" #include "api/video/video_adaptation_reason.h"
#include "api/video_codecs/video_encoder.h" #include "api/video_codecs/video_encoder.h"
#include "call/adaptation/resource.h" #include "call/adaptation/resource.h"
@ -24,13 +25,16 @@
#include "rtc_base/critical_section.h" #include "rtc_base/critical_section.h"
#include "rtc_base/ref_counted_object.h" #include "rtc_base/ref_counted_object.h"
#include "rtc_base/task_queue.h" #include "rtc_base/task_queue.h"
#include "video/adaptation/video_stream_encoder_resource.h"
namespace webrtc { namespace webrtc {
// Handles interaction with the QualityScaler. // Handles interaction with the QualityScaler.
class QualityScalerResource : public rtc::RefCountedObject<Resource>, class QualityScalerResource : public VideoStreamEncoderResource,
public QualityScalerQpUsageHandlerInterface { public QualityScalerQpUsageHandlerInterface {
public: public:
static rtc::scoped_refptr<QualityScalerResource> Create();
QualityScalerResource(); QualityScalerResource();
~QualityScalerResource() override; ~QualityScalerResource() override;
@ -56,9 +60,7 @@ class QualityScalerResource : public rtc::RefCountedObject<Resource>,
rtc::scoped_refptr<QualityScalerQpUsageHandlerCallbackInterface> callback) rtc::scoped_refptr<QualityScalerQpUsageHandlerCallbackInterface> callback)
override; override;
std::string name() const override { return "QualityScalerResource"; } // VideoStreamEncoderResource implementation.
// Resource implementation.
void OnAdaptationApplied( void OnAdaptationApplied(
const VideoStreamInputState& input_state, const VideoStreamInputState& input_state,
const VideoSourceRestrictions& restrictions_before, const VideoSourceRestrictions& restrictions_before,
@ -81,9 +83,9 @@ class QualityScalerResource : public rtc::RefCountedObject<Resource>,
absl::optional<int64_t> last_underuse_due_to_disabled_timestamp_ms_ absl::optional<int64_t> last_underuse_due_to_disabled_timestamp_ms_
RTC_GUARDED_BY(encoder_queue()); RTC_GUARDED_BY(encoder_queue());
// Every OnReportQpUsageHigh/Low() operation has a callback that MUST be // Every OnReportQpUsageHigh/Low() operation has a callback that MUST be
// invoked on the |encoder_queue_|. Because usage measurements are reported on // invoked on the encoder_queue(). Because usage measurements are reported on
// the |encoder_queue_| but handled by the processor on the the // the encoder_queue() but handled by the processor on the the
// |resource_adaptation_queue_|, handling a measurement entails a task queue // resource_adaptation_queue_(), handling a measurement entails a task queue
// "ping" round-trip. Multiple callbacks in-flight is thus possible. // "ping" round-trip. Multiple callbacks in-flight is thus possible.
size_t num_handled_callbacks_ RTC_GUARDED_BY(encoder_queue()); size_t num_handled_callbacks_ RTC_GUARDED_BY(encoder_queue());
std::queue<rtc::scoped_refptr<QualityScalerQpUsageHandlerCallbackInterface>> std::queue<rtc::scoped_refptr<QualityScalerQpUsageHandlerCallbackInterface>>

View File

@ -74,9 +74,10 @@ class QualityScalerResourceTest : public ::testing::Test {
encoder_queue_(task_queue_factory_->CreateTaskQueue( encoder_queue_(task_queue_factory_->CreateTaskQueue(
"EncoderQueue", "EncoderQueue",
TaskQueueFactory::Priority::NORMAL)), TaskQueueFactory::Priority::NORMAL)),
quality_scaler_resource_(new QualityScalerResource()) { quality_scaler_resource_(QualityScalerResource::Create()) {
quality_scaler_resource_->Initialize(&encoder_queue_, quality_scaler_resource_->RegisterEncoderTaskQueue(encoder_queue_.Get());
&resource_adaptation_queue_); quality_scaler_resource_->RegisterAdaptationTaskQueue(
resource_adaptation_queue_.Get());
rtc::Event event; rtc::Event event;
encoder_queue_.PostTask([this, &event] { encoder_queue_.PostTask([this, &event] {
quality_scaler_resource_->StartCheckForOveruse( quality_scaler_resource_->StartCheckForOveruse(

View File

@ -0,0 +1,112 @@
/*
* 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_encoder_resource.h"
#include <algorithm>
#include <utility>
namespace webrtc {
VideoStreamEncoderResource::VideoStreamEncoderResource(std::string name)
: lock_(),
name_(std::move(name)),
encoder_queue_(nullptr),
resource_adaptation_queue_(nullptr),
usage_state_(absl::nullopt),
listener_(nullptr) {}
VideoStreamEncoderResource::~VideoStreamEncoderResource() {
RTC_DCHECK(!listener_)
<< "There is a listener depending on a VideoStreamEncoderResource being "
<< "destroyed.";
}
void VideoStreamEncoderResource::RegisterEncoderTaskQueue(
TaskQueueBase* encoder_queue) {
RTC_DCHECK(!encoder_queue_);
RTC_DCHECK(encoder_queue);
encoder_queue_ = encoder_queue;
}
void VideoStreamEncoderResource::RegisterAdaptationTaskQueue(
TaskQueueBase* resource_adaptation_queue) {
rtc::CritScope crit(&lock_);
RTC_DCHECK(!resource_adaptation_queue_);
RTC_DCHECK(resource_adaptation_queue);
resource_adaptation_queue_ = resource_adaptation_queue;
}
void VideoStreamEncoderResource::UnregisterAdaptationTaskQueue() {
rtc::CritScope crit(&lock_);
RTC_DCHECK(resource_adaptation_queue_);
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
resource_adaptation_queue_ = nullptr;
}
void VideoStreamEncoderResource::SetResourceListener(
ResourceListener* listener) {
RTC_DCHECK_RUN_ON(resource_adaptation_queue());
// If you want to change listener you need to unregister the old listener by
// setting it to null first.
RTC_DCHECK(!listener_ || !listener) << "A listener is already set";
listener_ = listener;
}
std::string VideoStreamEncoderResource::Name() const {
return name_;
}
absl::optional<ResourceUsageState> VideoStreamEncoderResource::UsageState()
const {
RTC_DCHECK_RUN_ON(resource_adaptation_queue());
return usage_state_;
}
void VideoStreamEncoderResource::ClearUsageState() {
RTC_DCHECK_RUN_ON(resource_adaptation_queue());
usage_state_ = absl::nullopt;
}
bool VideoStreamEncoderResource::IsAdaptationUpAllowed(
const VideoStreamInputState& input_state,
const VideoSourceRestrictions& restrictions_before,
const VideoSourceRestrictions& restrictions_after,
rtc::scoped_refptr<Resource> reason_resource) const {
return true;
}
void VideoStreamEncoderResource::OnAdaptationApplied(
const VideoStreamInputState& input_state,
const VideoSourceRestrictions& restrictions_before,
const VideoSourceRestrictions& restrictions_after,
rtc::scoped_refptr<Resource> reason_resource) {}
void VideoStreamEncoderResource::OnResourceUsageStateMeasured(
ResourceUsageState usage_state) {
RTC_DCHECK_RUN_ON(resource_adaptation_queue());
usage_state_ = usage_state;
if (listener_) {
listener_->OnResourceUsageStateMeasured(this);
}
}
TaskQueueBase* VideoStreamEncoderResource::encoder_queue() const {
return encoder_queue_;
}
TaskQueueBase* VideoStreamEncoderResource::resource_adaptation_queue() const {
rtc::CritScope crit(&lock_);
RTC_DCHECK(resource_adaptation_queue_);
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
return resource_adaptation_queue_;
}
} // namespace webrtc

View File

@ -0,0 +1,86 @@
/*
* 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_ENCODER_RESOURCE_H_
#define VIDEO_ADAPTATION_VIDEO_STREAM_ENCODER_RESOURCE_H_
#include <string>
#include <vector>
#include "absl/types/optional.h"
#include "api/task_queue/task_queue_base.h"
#include "call/adaptation/resource.h"
#include "rtc_base/critical_section.h"
#include "rtc_base/synchronization/sequence_checker.h"
namespace webrtc {
class VideoStreamEncoderResource : public Resource {
public:
~VideoStreamEncoderResource() override;
// Registering task queues must be performed as part of initialization.
void RegisterEncoderTaskQueue(TaskQueueBase* encoder_queue);
// Resource implementation.
void RegisterAdaptationTaskQueue(
TaskQueueBase* resource_adaptation_queue) override;
void UnregisterAdaptationTaskQueue() override;
void SetResourceListener(ResourceListener* listener) override;
std::string Name() const override;
absl::optional<ResourceUsageState> UsageState() const override;
void ClearUsageState() override;
// Default implementations, may be overriden again by child classes.
bool IsAdaptationUpAllowed(
const VideoStreamInputState& input_state,
const VideoSourceRestrictions& restrictions_before,
const VideoSourceRestrictions& restrictions_after,
rtc::scoped_refptr<Resource> reason_resource) const override;
void OnAdaptationApplied(
const VideoStreamInputState& input_state,
const VideoSourceRestrictions& restrictions_before,
const VideoSourceRestrictions& restrictions_after,
rtc::scoped_refptr<Resource> reason_resource) override;
protected:
explicit VideoStreamEncoderResource(std::string name);
void OnResourceUsageStateMeasured(ResourceUsageState usage_state);
// The caller is responsible for ensuring the task queue is still valid.
TaskQueueBase* encoder_queue() const;
// Validity of returned pointer is ensured by only allowing this method to be
// called on the adaptation task queue. Designed for use with RTC_GUARDED_BY.
// For posting from a different queue, use
// MaybePostTaskToResourceAdaptationQueue() instead, which only posts if the
// task queue is currently registered.
TaskQueueBase* resource_adaptation_queue() const;
template <typename Closure>
void MaybePostTaskToResourceAdaptationQueue(Closure&& closure) {
rtc::CritScope crit(&lock_);
if (!resource_adaptation_queue_)
return;
resource_adaptation_queue_->PostTask(ToQueuedTask(closure));
}
private:
rtc::CriticalSection lock_;
const std::string name_;
// Treated as const after initialization.
TaskQueueBase* encoder_queue_;
TaskQueueBase* resource_adaptation_queue_ RTC_GUARDED_BY(lock_);
absl::optional<ResourceUsageState> usage_state_
RTC_GUARDED_BY(resource_adaptation_queue());
ResourceListener* listener_ RTC_GUARDED_BY(resource_adaptation_queue());
};
} // namespace webrtc
#endif // VIDEO_ADAPTATION_VIDEO_STREAM_ENCODER_RESOURCE_H_

View File

@ -26,6 +26,7 @@
#include "call/adaptation/video_source_restrictions.h" #include "call/adaptation/video_source_restrictions.h"
#include "rtc_base/logging.h" #include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h" #include "rtc_base/numerics/safe_conversions.h"
#include "rtc_base/ref_counted_object.h"
#include "rtc_base/strings/string_builder.h" #include "rtc_base/strings/string_builder.h"
#include "rtc_base/time_utils.h" #include "rtc_base/time_utils.h"
@ -140,7 +141,8 @@ class VideoStreamEncoderResourceManager::InitialFrameDropper {
VideoStreamEncoderResourceManager::PreventAdaptUpDueToActiveCounts:: VideoStreamEncoderResourceManager::PreventAdaptUpDueToActiveCounts::
PreventAdaptUpDueToActiveCounts(VideoStreamEncoderResourceManager* manager) PreventAdaptUpDueToActiveCounts(VideoStreamEncoderResourceManager* manager)
: rtc::RefCountedObject<Resource>(), : rtc::RefCountedObject<VideoStreamEncoderResource>(
"PreventAdaptUpDueToActiveCounts"),
manager_(manager), manager_(manager),
adaptation_processor_(nullptr) {} adaptation_processor_(nullptr) {}
@ -187,7 +189,8 @@ VideoStreamEncoderResourceManager::
PreventIncreaseResolutionDueToBitrateResource:: PreventIncreaseResolutionDueToBitrateResource::
PreventIncreaseResolutionDueToBitrateResource( PreventIncreaseResolutionDueToBitrateResource(
VideoStreamEncoderResourceManager* manager) VideoStreamEncoderResourceManager* manager)
: rtc::RefCountedObject<Resource>(), : rtc::RefCountedObject<VideoStreamEncoderResource>(
"PreventIncreaseResolutionDueToBitrateResource"),
manager_(manager), manager_(manager),
encoder_settings_(absl::nullopt), encoder_settings_(absl::nullopt),
encoder_target_bitrate_bps_(absl::nullopt) {} encoder_target_bitrate_bps_(absl::nullopt) {}
@ -196,7 +199,7 @@ void VideoStreamEncoderResourceManager::
PreventIncreaseResolutionDueToBitrateResource::OnEncoderSettingsUpdated( PreventIncreaseResolutionDueToBitrateResource::OnEncoderSettingsUpdated(
absl::optional<EncoderSettings> encoder_settings) { absl::optional<EncoderSettings> encoder_settings) {
RTC_DCHECK_RUN_ON(encoder_queue()); RTC_DCHECK_RUN_ON(encoder_queue());
resource_adaptation_queue()->PostTask( MaybePostTaskToResourceAdaptationQueue(
[this_ref = [this_ref =
rtc::scoped_refptr<PreventIncreaseResolutionDueToBitrateResource>( rtc::scoped_refptr<PreventIncreaseResolutionDueToBitrateResource>(
this), this),
@ -211,7 +214,7 @@ void VideoStreamEncoderResourceManager::
OnEncoderTargetBitrateUpdated( OnEncoderTargetBitrateUpdated(
absl::optional<uint32_t> encoder_target_bitrate_bps) { absl::optional<uint32_t> encoder_target_bitrate_bps) {
RTC_DCHECK_RUN_ON(encoder_queue()); RTC_DCHECK_RUN_ON(encoder_queue());
resource_adaptation_queue()->PostTask( MaybePostTaskToResourceAdaptationQueue(
[this_ref = [this_ref =
rtc::scoped_refptr<PreventIncreaseResolutionDueToBitrateResource>( rtc::scoped_refptr<PreventIncreaseResolutionDueToBitrateResource>(
this), this),
@ -258,7 +261,8 @@ bool VideoStreamEncoderResourceManager::
VideoStreamEncoderResourceManager::PreventAdaptUpInBalancedResource:: VideoStreamEncoderResourceManager::PreventAdaptUpInBalancedResource::
PreventAdaptUpInBalancedResource(VideoStreamEncoderResourceManager* manager) PreventAdaptUpInBalancedResource(VideoStreamEncoderResourceManager* manager)
: rtc::RefCountedObject<Resource>(), : rtc::RefCountedObject<VideoStreamEncoderResource>(
"PreventAdaptUpInBalancedResource"),
manager_(manager), manager_(manager),
adaptation_processor_(nullptr), adaptation_processor_(nullptr),
encoder_target_bitrate_bps_(absl::nullopt) {} encoder_target_bitrate_bps_(absl::nullopt) {}
@ -274,7 +278,7 @@ void VideoStreamEncoderResourceManager::PreventAdaptUpInBalancedResource::
OnEncoderTargetBitrateUpdated( OnEncoderTargetBitrateUpdated(
absl::optional<uint32_t> encoder_target_bitrate_bps) { absl::optional<uint32_t> encoder_target_bitrate_bps) {
RTC_DCHECK_RUN_ON(encoder_queue()); RTC_DCHECK_RUN_ON(encoder_queue());
resource_adaptation_queue()->PostTask( MaybePostTaskToResourceAdaptationQueue(
[this_ref = rtc::scoped_refptr<PreventAdaptUpInBalancedResource>(this), [this_ref = rtc::scoped_refptr<PreventAdaptUpInBalancedResource>(this),
encoder_target_bitrate_bps] { encoder_target_bitrate_bps] {
RTC_DCHECK_RUN_ON(this_ref->resource_adaptation_queue()); RTC_DCHECK_RUN_ON(this_ref->resource_adaptation_queue());
@ -328,8 +332,8 @@ VideoStreamEncoderResourceManager::VideoStreamEncoderResourceManager(
prevent_adapt_up_in_balanced_resource_( prevent_adapt_up_in_balanced_resource_(
new PreventAdaptUpInBalancedResource(this)), new PreventAdaptUpInBalancedResource(this)),
encode_usage_resource_( encode_usage_resource_(
new EncodeUsageResource(std::move(overuse_detector))), EncodeUsageResource::Create(std::move(overuse_detector))),
quality_scaler_resource_(new QualityScalerResource()), quality_scaler_resource_(QualityScalerResource::Create()),
encoder_queue_(nullptr), encoder_queue_(nullptr),
resource_adaptation_queue_(nullptr), resource_adaptation_queue_(nullptr),
input_state_provider_(input_state_provider), input_state_provider_(input_state_provider),
@ -370,16 +374,24 @@ void VideoStreamEncoderResourceManager::Initialize(
RTC_DCHECK(resource_adaptation_queue); RTC_DCHECK(resource_adaptation_queue);
encoder_queue_ = encoder_queue; encoder_queue_ = encoder_queue;
resource_adaptation_queue_ = resource_adaptation_queue; resource_adaptation_queue_ = resource_adaptation_queue;
prevent_adapt_up_due_to_active_counts_->Initialize( prevent_adapt_up_due_to_active_counts_->RegisterEncoderTaskQueue(
encoder_queue_, resource_adaptation_queue_); encoder_queue_->Get());
prevent_increase_resolution_due_to_bitrate_resource_->Initialize( prevent_adapt_up_due_to_active_counts_->RegisterAdaptationTaskQueue(
encoder_queue_, resource_adaptation_queue_); resource_adaptation_queue_->Get());
prevent_adapt_up_in_balanced_resource_->Initialize( prevent_increase_resolution_due_to_bitrate_resource_
encoder_queue_, resource_adaptation_queue_); ->RegisterEncoderTaskQueue(encoder_queue_->Get());
encode_usage_resource_->Initialize(encoder_queue_, prevent_increase_resolution_due_to_bitrate_resource_
resource_adaptation_queue_); ->RegisterAdaptationTaskQueue(resource_adaptation_queue_->Get());
quality_scaler_resource_->Initialize(encoder_queue_, prevent_adapt_up_in_balanced_resource_->RegisterEncoderTaskQueue(
resource_adaptation_queue_); encoder_queue_->Get());
prevent_adapt_up_in_balanced_resource_->RegisterAdaptationTaskQueue(
resource_adaptation_queue_->Get());
encode_usage_resource_->RegisterEncoderTaskQueue(encoder_queue_->Get());
encode_usage_resource_->RegisterAdaptationTaskQueue(
resource_adaptation_queue_->Get());
quality_scaler_resource_->RegisterEncoderTaskQueue(encoder_queue_->Get());
quality_scaler_resource_->RegisterAdaptationTaskQueue(
resource_adaptation_queue_->Get());
} }
void VideoStreamEncoderResourceManager::SetAdaptationProcessor( void VideoStreamEncoderResourceManager::SetAdaptationProcessor(
@ -428,7 +440,7 @@ void VideoStreamEncoderResourceManager::MapResourceToReason(
[resource](const ResourceAndReason& r) { [resource](const ResourceAndReason& r) {
return r.resource == resource; return r.resource == resource;
}) == resources_.end()) }) == resources_.end())
<< "Resource " << resource->name() << " already was inserted"; << "Resource " << resource->Name() << " already was inserted";
resources_.emplace_back(resource, reason); resources_.emplace_back(resource, reason);
} }
@ -616,7 +628,7 @@ VideoAdaptationReason VideoStreamEncoderResourceManager::GetReasonFromResource(
return r.resource == resource; return r.resource == resource;
}); });
RTC_DCHECK(registered_resource != resources_.end()) RTC_DCHECK(registered_resource != resources_.end())
<< resource->name() << " not found."; << resource->Name() << " not found.";
return registered_resource->reason; return registered_resource->reason;
} }

View File

@ -43,6 +43,7 @@
#include "video/adaptation/encode_usage_resource.h" #include "video/adaptation/encode_usage_resource.h"
#include "video/adaptation/overuse_frame_detector.h" #include "video/adaptation/overuse_frame_detector.h"
#include "video/adaptation/quality_scaler_resource.h" #include "video/adaptation/quality_scaler_resource.h"
#include "video/adaptation/video_stream_encoder_resource.h"
namespace webrtc { namespace webrtc {
@ -178,7 +179,7 @@ class VideoStreamEncoderResourceManager
// Does not trigger adaptations, only prevents adapting up based on // Does not trigger adaptations, only prevents adapting up based on
// |active_counts_|. // |active_counts_|.
class PreventAdaptUpDueToActiveCounts final class PreventAdaptUpDueToActiveCounts final
: public rtc::RefCountedObject<Resource> { : public rtc::RefCountedObject<VideoStreamEncoderResource> {
public: public:
explicit PreventAdaptUpDueToActiveCounts( explicit PreventAdaptUpDueToActiveCounts(
VideoStreamEncoderResourceManager* manager); VideoStreamEncoderResourceManager* manager);
@ -188,9 +189,6 @@ class VideoStreamEncoderResourceManager
ResourceAdaptationProcessorInterface* adaptation_processor); ResourceAdaptationProcessorInterface* adaptation_processor);
// Resource overrides. // Resource overrides.
std::string name() const override {
return "PreventAdaptUpDueToActiveCounts";
}
bool IsAdaptationUpAllowed( bool IsAdaptationUpAllowed(
const VideoStreamInputState& input_state, const VideoStreamInputState& input_state,
const VideoSourceRestrictions& restrictions_before, const VideoSourceRestrictions& restrictions_before,
@ -207,7 +205,7 @@ class VideoStreamEncoderResourceManager
// Does not trigger adaptations, only prevents adapting up resolution. // Does not trigger adaptations, only prevents adapting up resolution.
class PreventIncreaseResolutionDueToBitrateResource final class PreventIncreaseResolutionDueToBitrateResource final
: public rtc::RefCountedObject<Resource> { : public rtc::RefCountedObject<VideoStreamEncoderResource> {
public: public:
explicit PreventIncreaseResolutionDueToBitrateResource( explicit PreventIncreaseResolutionDueToBitrateResource(
VideoStreamEncoderResourceManager* manager); VideoStreamEncoderResourceManager* manager);
@ -219,9 +217,6 @@ class VideoStreamEncoderResourceManager
absl::optional<uint32_t> encoder_target_bitrate_bps); absl::optional<uint32_t> encoder_target_bitrate_bps);
// Resource overrides. // Resource overrides.
std::string name() const override {
return "PreventIncreaseResolutionDueToBitrateResource";
}
bool IsAdaptationUpAllowed( bool IsAdaptationUpAllowed(
const VideoStreamInputState& input_state, const VideoStreamInputState& input_state,
const VideoSourceRestrictions& restrictions_before, const VideoSourceRestrictions& restrictions_before,
@ -240,7 +235,7 @@ class VideoStreamEncoderResourceManager
// Does not trigger adaptations, only prevents adapting up in BALANCED. // Does not trigger adaptations, only prevents adapting up in BALANCED.
class PreventAdaptUpInBalancedResource final class PreventAdaptUpInBalancedResource final
: public rtc::RefCountedObject<Resource> { : public rtc::RefCountedObject<VideoStreamEncoderResource> {
public: public:
explicit PreventAdaptUpInBalancedResource( explicit PreventAdaptUpInBalancedResource(
VideoStreamEncoderResourceManager* manager); VideoStreamEncoderResourceManager* manager);
@ -252,9 +247,6 @@ class VideoStreamEncoderResourceManager
absl::optional<uint32_t> encoder_target_bitrate_bps); absl::optional<uint32_t> encoder_target_bitrate_bps);
// Resource overrides. // Resource overrides.
std::string name() const override {
return "PreventAdaptUpInBalancedResource";
}
bool IsAdaptationUpAllowed( bool IsAdaptationUpAllowed(
const VideoStreamInputState& input_state, const VideoStreamInputState& input_state,
const VideoSourceRestrictions& restrictions_before, const VideoSourceRestrictions& restrictions_before,

View File

@ -1698,7 +1698,7 @@ void VideoStreamEncoder::OnVideoSourceRestrictionsUpdated(
const VideoAdaptationCounters& adaptation_counters, const VideoAdaptationCounters& adaptation_counters,
rtc::scoped_refptr<Resource> reason) { rtc::scoped_refptr<Resource> reason) {
RTC_DCHECK_RUN_ON(&resource_adaptation_queue_); RTC_DCHECK_RUN_ON(&resource_adaptation_queue_);
std::string resource_name = reason ? reason->name() : "<null>"; std::string resource_name = reason ? reason->Name() : "<null>";
RTC_LOG(INFO) << "Updating sink restrictions from " << resource_name << " to " RTC_LOG(INFO) << "Updating sink restrictions from " << resource_name << " to "
<< restrictions.ToString(); << restrictions.ToString();
video_source_sink_controller_.SetRestrictions(std::move(restrictions)); video_source_sink_controller_.SetRestrictions(std::move(restrictions));

View File

@ -316,12 +316,12 @@ class VideoStreamEncoderUnderTest : public VideoStreamEncoder {
overuse_detector_proxy_ = overuse_detector_proxy_ =
new CpuOveruseDetectorProxy(stats_proxy)), new CpuOveruseDetectorProxy(stats_proxy)),
task_queue_factory), task_queue_factory),
fake_cpu_resource_(new FakeResource("FakeResource[CPU]")), fake_cpu_resource_(FakeResource::Create("FakeResource[CPU]")),
fake_quality_resource_(new FakeResource("FakeResource[QP]")) { fake_quality_resource_(FakeResource::Create("FakeResource[QP]")) {
fake_cpu_resource_->Initialize(encoder_queue(), fake_cpu_resource_->RegisterAdaptationTaskQueue(
resource_adaptation_queue()); resource_adaptation_queue()->Get());
fake_quality_resource_->Initialize(encoder_queue(), fake_quality_resource_->RegisterAdaptationTaskQueue(
resource_adaptation_queue()); resource_adaptation_queue()->Get());
InjectAdaptationResource(fake_quality_resource_, InjectAdaptationResource(fake_quality_resource_,
VideoAdaptationReason::kQuality); VideoAdaptationReason::kQuality);
InjectAdaptationResource(fake_cpu_resource_, VideoAdaptationReason::kCpu); InjectAdaptationResource(fake_cpu_resource_, VideoAdaptationReason::kCpu);