[Adaptation] Remove Resource::UsageState() and ClearUsageState().
ResourceListener::OnResourceUsageStateMeasured() now takes ResourceUsageState as argument, making Resource::UsageState() superfluous. With the existing "fire-and-forget" behavior of always clearing usage state on reacting to a signal, there is no longer a need to call ClearUsageState() so this too is removed. (We may want to have a callback in the future to hint to the Resource that it is a good idea to clear internal measurement samples, i.e. because the load of the system is about to change, but we can revisit that when we need it.) Moving the usage state to the callback has the benefit of getting rid of the assumption that UsageState() has to return the same value every time it is called in the same task. This CL is also the final nail in the coffin for Resource needing to know about the adaptation task queue: ResourceAdaptationProcessor's ResourceListener now takes care of posting to the adaptation task queue. To support this, the processor's SequenceChecker is replaced by a TaskQueueBase pointer. Bug: webrtc:11525, webrtc:11618 Change-Id: I2277e71cc3759c85b62465020935603f03792c94 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/176376 Commit-Queue: Henrik Boström <hbos@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Evan Shrubsole <eshr@google.com> Cr-Commit-Position: refs/heads/master@{#31416}
This commit is contained in:

committed by
Commit Bot

parent
3b641675de
commit
39ab1b547c
@ -45,6 +45,7 @@ rtc_library("resource_adaptation") {
|
|||||||
"../../rtc_base:rtc_task_queue",
|
"../../rtc_base:rtc_task_queue",
|
||||||
"../../rtc_base/experiments:balanced_degradation_settings",
|
"../../rtc_base/experiments:balanced_degradation_settings",
|
||||||
"../../rtc_base/synchronization:sequence_checker",
|
"../../rtc_base/synchronization:sequence_checker",
|
||||||
|
"../../rtc_base/task_utils:to_queued_task",
|
||||||
"//third_party/abseil-cpp/absl/algorithm:container",
|
"//third_party/abseil-cpp/absl/algorithm:container",
|
||||||
"//third_party/abseil-cpp/absl/types:optional",
|
"//third_party/abseil-cpp/absl/types:optional",
|
||||||
]
|
]
|
||||||
@ -70,6 +71,7 @@ if (rtc_include_tests) {
|
|||||||
"../../api/video:video_adaptation",
|
"../../api/video:video_adaptation",
|
||||||
"../../api/video_codecs:video_codecs_api",
|
"../../api/video_codecs:video_codecs_api",
|
||||||
"../../rtc_base:checks",
|
"../../rtc_base:checks",
|
||||||
|
"../../rtc_base:gunit_helpers",
|
||||||
"../../rtc_base:rtc_base_approved",
|
"../../rtc_base:rtc_base_approved",
|
||||||
"../../rtc_base:rtc_task_queue",
|
"../../rtc_base:rtc_task_queue",
|
||||||
"../../rtc_base:task_queue_for_test",
|
"../../rtc_base:task_queue_for_test",
|
||||||
|
@ -12,11 +12,8 @@
|
|||||||
#define CALL_ADAPTATION_RESOURCE_H_
|
#define CALL_ADAPTATION_RESOURCE_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#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"
|
||||||
@ -38,20 +35,18 @@ class ResourceListener {
|
|||||||
public:
|
public:
|
||||||
virtual ~ResourceListener();
|
virtual ~ResourceListener();
|
||||||
|
|
||||||
// Informs the listener of a new measurement of resource usage. This means
|
|
||||||
// that |resource->usage_state()| is now up-to-date.
|
|
||||||
virtual void OnResourceUsageStateMeasured(
|
virtual void OnResourceUsageStateMeasured(
|
||||||
rtc::scoped_refptr<Resource> resource) = 0;
|
rtc::scoped_refptr<Resource> resource,
|
||||||
|
ResourceUsageState usage_state) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A Resource monitors an implementation-specific system resource. It may report
|
// A Resource monitors an implementation-specific resource. It may report
|
||||||
// kOveruse or kUnderuse when resource usage is high or low enough that we
|
// 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.
|
// should perform some sort of mitigation to fulfil the resource's constraints.
|
||||||
//
|
//
|
||||||
// All methods defined in this interface, except SetResourceListener(), MUST be
|
// The methods on this interface are invoked on the adaptation task queue.
|
||||||
// invoked on the resource adaptation task queue.
|
// Resource usage measurements may be performed on an any 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
|
// The Resource is reference counted to prevent use-after-free when posting
|
||||||
// between task queues. As such, the implementation MUST NOT make any
|
// between task queues. As such, the implementation MUST NOT make any
|
||||||
// assumptions about which task queue Resource is destructed on.
|
// assumptions about which task queue Resource is destructed on.
|
||||||
@ -62,18 +57,9 @@ class Resource : public rtc::RefCountInterface {
|
|||||||
~Resource() override;
|
~Resource() override;
|
||||||
|
|
||||||
virtual std::string Name() const = 0;
|
virtual std::string Name() const = 0;
|
||||||
// The listener MUST be informed any time UsageState() changes.
|
// The |listener| may be informed of resource usage measurements on any task
|
||||||
|
// queue, but not after this method is invoked with the null argument.
|
||||||
virtual void SetResourceListener(ResourceListener* listener) = 0;
|
virtual void SetResourceListener(ResourceListener* listener) = 0;
|
||||||
// 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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -16,10 +16,47 @@
|
|||||||
|
|
||||||
#include "absl/algorithm/container.h"
|
#include "absl/algorithm/container.h"
|
||||||
#include "rtc_base/logging.h"
|
#include "rtc_base/logging.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/task_utils/to_queued_task.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
ResourceAdaptationProcessor::ResourceListenerDelegate::ResourceListenerDelegate(
|
||||||
|
ResourceAdaptationProcessor* processor)
|
||||||
|
: resource_adaptation_queue_(nullptr), processor_(processor) {}
|
||||||
|
|
||||||
|
void ResourceAdaptationProcessor::ResourceListenerDelegate::
|
||||||
|
SetResourceAdaptationQueue(TaskQueueBase* resource_adaptation_queue) {
|
||||||
|
RTC_DCHECK(!resource_adaptation_queue_);
|
||||||
|
RTC_DCHECK(resource_adaptation_queue);
|
||||||
|
resource_adaptation_queue_ = resource_adaptation_queue;
|
||||||
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceAdaptationProcessor::ResourceListenerDelegate::
|
||||||
|
OnProcessorDestroyed() {
|
||||||
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
|
processor_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceAdaptationProcessor::ResourceListenerDelegate::
|
||||||
|
OnResourceUsageStateMeasured(rtc::scoped_refptr<Resource> resource,
|
||||||
|
ResourceUsageState usage_state) {
|
||||||
|
if (!resource_adaptation_queue_->IsCurrent()) {
|
||||||
|
resource_adaptation_queue_->PostTask(ToQueuedTask(
|
||||||
|
[this_ref = rtc::scoped_refptr<ResourceListenerDelegate>(this),
|
||||||
|
resource, usage_state] {
|
||||||
|
this_ref->OnResourceUsageStateMeasured(resource, usage_state);
|
||||||
|
}));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
|
if (processor_) {
|
||||||
|
processor_->OnResourceUsageStateMeasured(resource, usage_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ResourceAdaptationProcessor::MitigationResultAndLogMessage::
|
ResourceAdaptationProcessor::MitigationResultAndLogMessage::
|
||||||
MitigationResultAndLogMessage()
|
MitigationResultAndLogMessage()
|
||||||
: result(MitigationResult::kAdaptationApplied), message() {}
|
: result(MitigationResult::kAdaptationApplied), message() {}
|
||||||
@ -31,7 +68,9 @@ ResourceAdaptationProcessor::MitigationResultAndLogMessage::
|
|||||||
ResourceAdaptationProcessor::ResourceAdaptationProcessor(
|
ResourceAdaptationProcessor::ResourceAdaptationProcessor(
|
||||||
VideoStreamInputStateProvider* input_state_provider,
|
VideoStreamInputStateProvider* input_state_provider,
|
||||||
VideoStreamEncoderObserver* encoder_stats_observer)
|
VideoStreamEncoderObserver* encoder_stats_observer)
|
||||||
: sequence_checker_(),
|
: resource_adaptation_queue_(nullptr),
|
||||||
|
resource_listener_delegate_(
|
||||||
|
new rtc::RefCountedObject<ResourceListenerDelegate>(this)),
|
||||||
is_resource_adaptation_enabled_(false),
|
is_resource_adaptation_enabled_(false),
|
||||||
input_state_provider_(input_state_provider),
|
input_state_provider_(input_state_provider),
|
||||||
encoder_stats_observer_(encoder_stats_observer),
|
encoder_stats_observer_(encoder_stats_observer),
|
||||||
@ -42,12 +81,10 @@ ResourceAdaptationProcessor::ResourceAdaptationProcessor(
|
|||||||
stream_adapter_(std::make_unique<VideoStreamAdapter>()),
|
stream_adapter_(std::make_unique<VideoStreamAdapter>()),
|
||||||
last_reported_source_restrictions_(),
|
last_reported_source_restrictions_(),
|
||||||
previous_mitigation_results_(),
|
previous_mitigation_results_(),
|
||||||
processing_in_progress_(false) {
|
processing_in_progress_(false) {}
|
||||||
sequence_checker_.Detach();
|
|
||||||
}
|
|
||||||
|
|
||||||
ResourceAdaptationProcessor::~ResourceAdaptationProcessor() {
|
ResourceAdaptationProcessor::~ResourceAdaptationProcessor() {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
RTC_DCHECK(!is_resource_adaptation_enabled_);
|
RTC_DCHECK(!is_resource_adaptation_enabled_);
|
||||||
RTC_DCHECK(restrictions_listeners_.empty())
|
RTC_DCHECK(restrictions_listeners_.empty())
|
||||||
<< "There are restrictions listener(s) depending on a "
|
<< "There are restrictions listener(s) depending on a "
|
||||||
@ -61,38 +98,43 @@ ResourceAdaptationProcessor::~ResourceAdaptationProcessor() {
|
|||||||
RTC_DCHECK(adaptation_listeners_.empty())
|
RTC_DCHECK(adaptation_listeners_.empty())
|
||||||
<< "There are listener(s) attached to a ResourceAdaptationProcessor "
|
<< "There are listener(s) attached to a ResourceAdaptationProcessor "
|
||||||
<< "being destroyed.";
|
<< "being destroyed.";
|
||||||
|
resource_listener_delegate_->OnProcessorDestroyed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceAdaptationProcessor::InitializeOnResourceAdaptationQueue() {
|
void ResourceAdaptationProcessor::SetResourceAdaptationQueue(
|
||||||
// Allows |sequence_checker_| to attach to the resource adaptation queue.
|
TaskQueueBase* resource_adaptation_queue) {
|
||||||
// The caller is responsible for ensuring that this is the current queue.
|
RTC_DCHECK(!resource_adaptation_queue_);
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK(resource_adaptation_queue);
|
||||||
|
resource_adaptation_queue_ = resource_adaptation_queue;
|
||||||
|
resource_listener_delegate_->SetResourceAdaptationQueue(
|
||||||
|
resource_adaptation_queue);
|
||||||
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
}
|
}
|
||||||
|
|
||||||
DegradationPreference ResourceAdaptationProcessor::degradation_preference()
|
DegradationPreference ResourceAdaptationProcessor::degradation_preference()
|
||||||
const {
|
const {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
return degradation_preference_;
|
return degradation_preference_;
|
||||||
}
|
}
|
||||||
|
|
||||||
DegradationPreference
|
DegradationPreference
|
||||||
ResourceAdaptationProcessor::effective_degradation_preference() const {
|
ResourceAdaptationProcessor::effective_degradation_preference() const {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
return effective_degradation_preference_;
|
return effective_degradation_preference_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceAdaptationProcessor::StartResourceAdaptation() {
|
void ResourceAdaptationProcessor::StartResourceAdaptation() {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
if (is_resource_adaptation_enabled_)
|
if (is_resource_adaptation_enabled_)
|
||||||
return;
|
return;
|
||||||
for (const auto& resource : resources_) {
|
for (const auto& resource : resources_) {
|
||||||
resource->SetResourceListener(this);
|
resource->SetResourceListener(resource_listener_delegate_);
|
||||||
}
|
}
|
||||||
is_resource_adaptation_enabled_ = true;
|
is_resource_adaptation_enabled_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceAdaptationProcessor::StopResourceAdaptation() {
|
void ResourceAdaptationProcessor::StopResourceAdaptation() {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
if (!is_resource_adaptation_enabled_)
|
if (!is_resource_adaptation_enabled_)
|
||||||
return;
|
return;
|
||||||
for (const auto& resource : resources_) {
|
for (const auto& resource : resources_) {
|
||||||
@ -103,7 +145,7 @@ void ResourceAdaptationProcessor::StopResourceAdaptation() {
|
|||||||
|
|
||||||
void ResourceAdaptationProcessor::AddRestrictionsListener(
|
void ResourceAdaptationProcessor::AddRestrictionsListener(
|
||||||
VideoSourceRestrictionsListener* restrictions_listener) {
|
VideoSourceRestrictionsListener* restrictions_listener) {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
RTC_DCHECK(std::find(restrictions_listeners_.begin(),
|
RTC_DCHECK(std::find(restrictions_listeners_.begin(),
|
||||||
restrictions_listeners_.end(),
|
restrictions_listeners_.end(),
|
||||||
restrictions_listener) == restrictions_listeners_.end());
|
restrictions_listener) == restrictions_listeners_.end());
|
||||||
@ -112,7 +154,7 @@ void ResourceAdaptationProcessor::AddRestrictionsListener(
|
|||||||
|
|
||||||
void ResourceAdaptationProcessor::RemoveRestrictionsListener(
|
void ResourceAdaptationProcessor::RemoveRestrictionsListener(
|
||||||
VideoSourceRestrictionsListener* restrictions_listener) {
|
VideoSourceRestrictionsListener* restrictions_listener) {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
auto it = std::find(restrictions_listeners_.begin(),
|
auto it = std::find(restrictions_listeners_.begin(),
|
||||||
restrictions_listeners_.end(), restrictions_listener);
|
restrictions_listeners_.end(), restrictions_listener);
|
||||||
RTC_DCHECK(it != restrictions_listeners_.end());
|
RTC_DCHECK(it != restrictions_listeners_.end());
|
||||||
@ -121,7 +163,7 @@ void ResourceAdaptationProcessor::RemoveRestrictionsListener(
|
|||||||
|
|
||||||
void ResourceAdaptationProcessor::AddResource(
|
void ResourceAdaptationProcessor::AddResource(
|
||||||
rtc::scoped_refptr<Resource> resource) {
|
rtc::scoped_refptr<Resource> resource) {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
// TODO(hbos): Allow adding resources while |is_resource_adaptation_enabled_|
|
// TODO(hbos): Allow adding resources while |is_resource_adaptation_enabled_|
|
||||||
// by registering as a listener of the resource on adding it.
|
// by registering as a listener of the resource on adding it.
|
||||||
RTC_DCHECK(!is_resource_adaptation_enabled_);
|
RTC_DCHECK(!is_resource_adaptation_enabled_);
|
||||||
@ -132,7 +174,7 @@ void ResourceAdaptationProcessor::AddResource(
|
|||||||
|
|
||||||
void ResourceAdaptationProcessor::RemoveResource(
|
void ResourceAdaptationProcessor::RemoveResource(
|
||||||
rtc::scoped_refptr<Resource> resource) {
|
rtc::scoped_refptr<Resource> resource) {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
// TODO(hbos): Allow removing resources while
|
// TODO(hbos): Allow removing resources while
|
||||||
// |is_resource_adaptation_enabled_| by unregistering as a listener of the
|
// |is_resource_adaptation_enabled_| by unregistering as a listener of the
|
||||||
// resource on removing it.
|
// resource on removing it.
|
||||||
@ -144,7 +186,7 @@ void ResourceAdaptationProcessor::RemoveResource(
|
|||||||
|
|
||||||
void ResourceAdaptationProcessor::AddAdaptationConstraint(
|
void ResourceAdaptationProcessor::AddAdaptationConstraint(
|
||||||
AdaptationConstraint* adaptation_constraint) {
|
AdaptationConstraint* adaptation_constraint) {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
RTC_DCHECK(std::find(adaptation_constraints_.begin(),
|
RTC_DCHECK(std::find(adaptation_constraints_.begin(),
|
||||||
adaptation_constraints_.end(),
|
adaptation_constraints_.end(),
|
||||||
adaptation_constraint) == adaptation_constraints_.end());
|
adaptation_constraint) == adaptation_constraints_.end());
|
||||||
@ -153,7 +195,7 @@ void ResourceAdaptationProcessor::AddAdaptationConstraint(
|
|||||||
|
|
||||||
void ResourceAdaptationProcessor::RemoveAdaptationConstraint(
|
void ResourceAdaptationProcessor::RemoveAdaptationConstraint(
|
||||||
AdaptationConstraint* adaptation_constraint) {
|
AdaptationConstraint* adaptation_constraint) {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
auto it = std::find(adaptation_constraints_.begin(),
|
auto it = std::find(adaptation_constraints_.begin(),
|
||||||
adaptation_constraints_.end(), adaptation_constraint);
|
adaptation_constraints_.end(), adaptation_constraint);
|
||||||
RTC_DCHECK(it != adaptation_constraints_.end());
|
RTC_DCHECK(it != adaptation_constraints_.end());
|
||||||
@ -162,7 +204,7 @@ void ResourceAdaptationProcessor::RemoveAdaptationConstraint(
|
|||||||
|
|
||||||
void ResourceAdaptationProcessor::AddAdaptationListener(
|
void ResourceAdaptationProcessor::AddAdaptationListener(
|
||||||
AdaptationListener* adaptation_listener) {
|
AdaptationListener* adaptation_listener) {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
RTC_DCHECK(std::find(adaptation_listeners_.begin(),
|
RTC_DCHECK(std::find(adaptation_listeners_.begin(),
|
||||||
adaptation_listeners_.end(),
|
adaptation_listeners_.end(),
|
||||||
adaptation_listener) == adaptation_listeners_.end());
|
adaptation_listener) == adaptation_listeners_.end());
|
||||||
@ -171,7 +213,7 @@ void ResourceAdaptationProcessor::AddAdaptationListener(
|
|||||||
|
|
||||||
void ResourceAdaptationProcessor::RemoveAdaptationListener(
|
void ResourceAdaptationProcessor::RemoveAdaptationListener(
|
||||||
AdaptationListener* adaptation_listener) {
|
AdaptationListener* adaptation_listener) {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
auto it = std::find(adaptation_listeners_.begin(),
|
auto it = std::find(adaptation_listeners_.begin(),
|
||||||
adaptation_listeners_.end(), adaptation_listener);
|
adaptation_listeners_.end(), adaptation_listener);
|
||||||
RTC_DCHECK(it != adaptation_listeners_.end());
|
RTC_DCHECK(it != adaptation_listeners_.end());
|
||||||
@ -180,19 +222,19 @@ void ResourceAdaptationProcessor::RemoveAdaptationListener(
|
|||||||
|
|
||||||
void ResourceAdaptationProcessor::SetDegradationPreference(
|
void ResourceAdaptationProcessor::SetDegradationPreference(
|
||||||
DegradationPreference degradation_preference) {
|
DegradationPreference degradation_preference) {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
degradation_preference_ = degradation_preference;
|
degradation_preference_ = degradation_preference;
|
||||||
MaybeUpdateEffectiveDegradationPreference();
|
MaybeUpdateEffectiveDegradationPreference();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceAdaptationProcessor::SetIsScreenshare(bool is_screenshare) {
|
void ResourceAdaptationProcessor::SetIsScreenshare(bool is_screenshare) {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
is_screenshare_ = is_screenshare;
|
is_screenshare_ = is_screenshare;
|
||||||
MaybeUpdateEffectiveDegradationPreference();
|
MaybeUpdateEffectiveDegradationPreference();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceAdaptationProcessor::MaybeUpdateEffectiveDegradationPreference() {
|
void ResourceAdaptationProcessor::MaybeUpdateEffectiveDegradationPreference() {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
effective_degradation_preference_ =
|
effective_degradation_preference_ =
|
||||||
(is_screenshare_ &&
|
(is_screenshare_ &&
|
||||||
degradation_preference_ == DegradationPreference::BALANCED)
|
degradation_preference_ == DegradationPreference::BALANCED)
|
||||||
@ -203,7 +245,7 @@ void ResourceAdaptationProcessor::MaybeUpdateEffectiveDegradationPreference() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ResourceAdaptationProcessor::ResetVideoSourceRestrictions() {
|
void ResourceAdaptationProcessor::ResetVideoSourceRestrictions() {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
RTC_LOG(INFO) << "Resetting restrictions";
|
RTC_LOG(INFO) << "Resetting restrictions";
|
||||||
stream_adapter_->ClearRestrictions();
|
stream_adapter_->ClearRestrictions();
|
||||||
adaptations_counts_by_resource_.clear();
|
adaptations_counts_by_resource_.clear();
|
||||||
@ -212,7 +254,7 @@ void ResourceAdaptationProcessor::ResetVideoSourceRestrictions() {
|
|||||||
|
|
||||||
void ResourceAdaptationProcessor::MaybeUpdateVideoSourceRestrictions(
|
void ResourceAdaptationProcessor::MaybeUpdateVideoSourceRestrictions(
|
||||||
rtc::scoped_refptr<Resource> reason) {
|
rtc::scoped_refptr<Resource> reason) {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
VideoSourceRestrictions new_source_restrictions =
|
VideoSourceRestrictions new_source_restrictions =
|
||||||
FilterRestrictionsByDegradationPreference(
|
FilterRestrictionsByDegradationPreference(
|
||||||
stream_adapter_->source_restrictions(),
|
stream_adapter_->source_restrictions(),
|
||||||
@ -235,10 +277,9 @@ 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_);
|
ResourceUsageState usage_state) {
|
||||||
RTC_DCHECK(resource->UsageState().has_value());
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
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:
|
||||||
@ -269,7 +310,7 @@ void ResourceAdaptationProcessor::OnResourceUsageStateMeasured(
|
|||||||
|
|
||||||
bool ResourceAdaptationProcessor::HasSufficientInputForAdaptation(
|
bool ResourceAdaptationProcessor::HasSufficientInputForAdaptation(
|
||||||
const VideoStreamInputState& input_state) const {
|
const VideoStreamInputState& input_state) const {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
return input_state.HasInputFrameSizeAndFramesPerSecond() &&
|
return input_state.HasInputFrameSizeAndFramesPerSecond() &&
|
||||||
(effective_degradation_preference_ !=
|
(effective_degradation_preference_ !=
|
||||||
DegradationPreference::MAINTAIN_RESOLUTION ||
|
DegradationPreference::MAINTAIN_RESOLUTION ||
|
||||||
@ -279,16 +320,9 @@ bool ResourceAdaptationProcessor::HasSufficientInputForAdaptation(
|
|||||||
ResourceAdaptationProcessor::MitigationResultAndLogMessage
|
ResourceAdaptationProcessor::MitigationResultAndLogMessage
|
||||||
ResourceAdaptationProcessor::OnResourceUnderuse(
|
ResourceAdaptationProcessor::OnResourceUnderuse(
|
||||||
rtc::scoped_refptr<Resource> reason_resource) {
|
rtc::scoped_refptr<Resource> reason_resource) {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
RTC_DCHECK(!processing_in_progress_);
|
RTC_DCHECK(!processing_in_progress_);
|
||||||
processing_in_progress_ = true;
|
processing_in_progress_ = true;
|
||||||
// Clear all usage states. In order to re-run adaptation logic, resources need
|
|
||||||
// to provide new resource usage measurements.
|
|
||||||
// TODO(hbos): Support not unconditionally clearing usage states by having the
|
|
||||||
// ResourceAdaptationProcessor check in on its resources at certain intervals.
|
|
||||||
for (const auto& resource : resources_) {
|
|
||||||
resource->ClearUsageState();
|
|
||||||
}
|
|
||||||
if (effective_degradation_preference_ == DegradationPreference::DISABLED) {
|
if (effective_degradation_preference_ == DegradationPreference::DISABLED) {
|
||||||
processing_in_progress_ = false;
|
processing_in_progress_ = false;
|
||||||
return MitigationResultAndLogMessage(
|
return MitigationResultAndLogMessage(
|
||||||
@ -358,16 +392,9 @@ ResourceAdaptationProcessor::OnResourceUnderuse(
|
|||||||
ResourceAdaptationProcessor::MitigationResultAndLogMessage
|
ResourceAdaptationProcessor::MitigationResultAndLogMessage
|
||||||
ResourceAdaptationProcessor::OnResourceOveruse(
|
ResourceAdaptationProcessor::OnResourceOveruse(
|
||||||
rtc::scoped_refptr<Resource> reason_resource) {
|
rtc::scoped_refptr<Resource> reason_resource) {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
RTC_DCHECK(!processing_in_progress_);
|
RTC_DCHECK(!processing_in_progress_);
|
||||||
processing_in_progress_ = true;
|
processing_in_progress_ = true;
|
||||||
// Clear all usage states. In order to re-run adaptation logic, resources need
|
|
||||||
// to provide new resource usage measurements.
|
|
||||||
// TODO(hbos): Support not unconditionally clearing usage states by having the
|
|
||||||
// ResourceAdaptationProcessor check in on its resources at certain intervals.
|
|
||||||
for (const auto& resource : resources_) {
|
|
||||||
resource->ClearUsageState();
|
|
||||||
}
|
|
||||||
if (effective_degradation_preference_ == DegradationPreference::DISABLED) {
|
if (effective_degradation_preference_ == DegradationPreference::DISABLED) {
|
||||||
processing_in_progress_ = false;
|
processing_in_progress_ = false;
|
||||||
return MitigationResultAndLogMessage(
|
return MitigationResultAndLogMessage(
|
||||||
@ -419,7 +446,7 @@ ResourceAdaptationProcessor::OnResourceOveruse(
|
|||||||
|
|
||||||
void ResourceAdaptationProcessor::TriggerAdaptationDueToFrameDroppedDueToSize(
|
void ResourceAdaptationProcessor::TriggerAdaptationDueToFrameDroppedDueToSize(
|
||||||
rtc::scoped_refptr<Resource> reason_resource) {
|
rtc::scoped_refptr<Resource> reason_resource) {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
RTC_LOG(INFO) << "TriggerAdaptationDueToFrameDroppedDueToSize called";
|
RTC_LOG(INFO) << "TriggerAdaptationDueToFrameDroppedDueToSize called";
|
||||||
VideoAdaptationCounters counters_before =
|
VideoAdaptationCounters counters_before =
|
||||||
stream_adapter_->adaptation_counters();
|
stream_adapter_->adaptation_counters();
|
||||||
@ -439,7 +466,7 @@ void ResourceAdaptationProcessor::TriggerAdaptationDueToFrameDroppedDueToSize(
|
|||||||
|
|
||||||
void ResourceAdaptationProcessor::UpdateResourceDegradationCounts(
|
void ResourceAdaptationProcessor::UpdateResourceDegradationCounts(
|
||||||
rtc::scoped_refptr<Resource> resource) {
|
rtc::scoped_refptr<Resource> resource) {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
RTC_DCHECK(resource);
|
RTC_DCHECK(resource);
|
||||||
int delta = stream_adapter_->adaptation_counters().Total();
|
int delta = stream_adapter_->adaptation_counters().Total();
|
||||||
for (const auto& adaptations : adaptations_counts_by_resource_) {
|
for (const auto& adaptations : adaptations_counts_by_resource_) {
|
||||||
@ -453,7 +480,7 @@ void ResourceAdaptationProcessor::UpdateResourceDegradationCounts(
|
|||||||
|
|
||||||
bool ResourceAdaptationProcessor::IsResourceAllowedToAdaptUp(
|
bool ResourceAdaptationProcessor::IsResourceAllowedToAdaptUp(
|
||||||
rtc::scoped_refptr<Resource> resource) const {
|
rtc::scoped_refptr<Resource> resource) const {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
RTC_DCHECK(resource);
|
RTC_DCHECK(resource);
|
||||||
const auto& adaptations = adaptations_counts_by_resource_.find(resource);
|
const auto& adaptations = adaptations_counts_by_resource_.find(resource);
|
||||||
return adaptations != adaptations_counts_by_resource_.end() &&
|
return adaptations != adaptations_counts_by_resource_.end() &&
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "absl/types/optional.h"
|
#include "absl/types/optional.h"
|
||||||
#include "api/rtp_parameters.h"
|
#include "api/rtp_parameters.h"
|
||||||
#include "api/scoped_refptr.h"
|
#include "api/scoped_refptr.h"
|
||||||
|
#include "api/task_queue/task_queue_base.h"
|
||||||
#include "api/video/video_frame.h"
|
#include "api/video/video_frame.h"
|
||||||
#include "api/video/video_stream_encoder_observer.h"
|
#include "api/video/video_stream_encoder_observer.h"
|
||||||
#include "call/adaptation/adaptation_constraint.h"
|
#include "call/adaptation/adaptation_constraint.h"
|
||||||
@ -29,7 +30,6 @@
|
|||||||
#include "call/adaptation/video_stream_adapter.h"
|
#include "call/adaptation/video_stream_adapter.h"
|
||||||
#include "call/adaptation/video_stream_input_state.h"
|
#include "call/adaptation/video_stream_input_state.h"
|
||||||
#include "call/adaptation/video_stream_input_state_provider.h"
|
#include "call/adaptation/video_stream_input_state_provider.h"
|
||||||
#include "rtc_base/synchronization/sequence_checker.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
@ -57,7 +57,8 @@ class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
|
|||||||
VideoStreamEncoderObserver* encoder_stats_observer);
|
VideoStreamEncoderObserver* encoder_stats_observer);
|
||||||
~ResourceAdaptationProcessor() override;
|
~ResourceAdaptationProcessor() override;
|
||||||
|
|
||||||
void InitializeOnResourceAdaptationQueue() override;
|
void SetResourceAdaptationQueue(
|
||||||
|
TaskQueueBase* resource_adaptation_queue) override;
|
||||||
|
|
||||||
// ResourceAdaptationProcessorInterface implementation.
|
// ResourceAdaptationProcessorInterface implementation.
|
||||||
DegradationPreference degradation_preference() const override;
|
DegradationPreference degradation_preference() const override;
|
||||||
@ -86,8 +87,8 @@ class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
|
|||||||
|
|
||||||
// ResourceListener implementation.
|
// ResourceListener implementation.
|
||||||
// Triggers OnResourceUnderuse() or OnResourceOveruse().
|
// Triggers OnResourceUnderuse() or OnResourceOveruse().
|
||||||
void OnResourceUsageStateMeasured(
|
void OnResourceUsageStateMeasured(rtc::scoped_refptr<Resource> resource,
|
||||||
rtc::scoped_refptr<Resource> resource) override;
|
ResourceUsageState usage_state) override;
|
||||||
|
|
||||||
// May trigger 1-2 adaptations. It is meant to reduce resolution but this is
|
// May trigger 1-2 adaptations. It is meant to reduce resolution but this is
|
||||||
// not guaranteed. It may adapt frame rate, which does not address the issue.
|
// not guaranteed. It may adapt frame rate, which does not address the issue.
|
||||||
@ -99,6 +100,27 @@ class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
|
|||||||
bool HasSufficientInputForAdaptation(
|
bool HasSufficientInputForAdaptation(
|
||||||
const VideoStreamInputState& input_state) const;
|
const VideoStreamInputState& input_state) const;
|
||||||
|
|
||||||
|
// If resource usage measurements happens off the adaptation task queue, this
|
||||||
|
// class takes care of posting the measurement for the processor to handle it
|
||||||
|
// on the adaptation task queue.
|
||||||
|
class ResourceListenerDelegate : public rtc::RefCountInterface,
|
||||||
|
public ResourceListener {
|
||||||
|
public:
|
||||||
|
explicit ResourceListenerDelegate(ResourceAdaptationProcessor* processor);
|
||||||
|
|
||||||
|
void SetResourceAdaptationQueue(TaskQueueBase* resource_adaptation_queue);
|
||||||
|
void OnProcessorDestroyed();
|
||||||
|
|
||||||
|
// ResourceListener implementation.
|
||||||
|
void OnResourceUsageStateMeasured(rtc::scoped_refptr<Resource> resource,
|
||||||
|
ResourceUsageState usage_state) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
TaskQueueBase* resource_adaptation_queue_;
|
||||||
|
ResourceAdaptationProcessor* processor_
|
||||||
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
|
};
|
||||||
|
|
||||||
enum class MitigationResult {
|
enum class MitigationResult {
|
||||||
kDisabled,
|
kDisabled,
|
||||||
kInsufficientInput,
|
kInsufficientInput,
|
||||||
@ -141,39 +163,41 @@ class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
|
|||||||
// restrictions rather than just the counters.
|
// restrictions rather than just the counters.
|
||||||
bool IsResourceAllowedToAdaptUp(rtc::scoped_refptr<Resource> resource) const;
|
bool IsResourceAllowedToAdaptUp(rtc::scoped_refptr<Resource> resource) const;
|
||||||
|
|
||||||
webrtc::SequenceChecker sequence_checker_;
|
TaskQueueBase* resource_adaptation_queue_;
|
||||||
bool is_resource_adaptation_enabled_ RTC_GUARDED_BY(sequence_checker_);
|
rtc::scoped_refptr<ResourceListenerDelegate> resource_listener_delegate_;
|
||||||
|
bool is_resource_adaptation_enabled_
|
||||||
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
// Input and output.
|
// Input and output.
|
||||||
VideoStreamInputStateProvider* const input_state_provider_
|
VideoStreamInputStateProvider* const input_state_provider_
|
||||||
RTC_GUARDED_BY(sequence_checker_);
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
VideoStreamEncoderObserver* const encoder_stats_observer_
|
VideoStreamEncoderObserver* const encoder_stats_observer_
|
||||||
RTC_GUARDED_BY(sequence_checker_);
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
std::vector<VideoSourceRestrictionsListener*> restrictions_listeners_
|
std::vector<VideoSourceRestrictionsListener*> restrictions_listeners_
|
||||||
RTC_GUARDED_BY(sequence_checker_);
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
std::vector<rtc::scoped_refptr<Resource>> resources_
|
std::vector<rtc::scoped_refptr<Resource>> resources_
|
||||||
RTC_GUARDED_BY(sequence_checker_);
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
std::vector<AdaptationConstraint*> adaptation_constraints_
|
std::vector<AdaptationConstraint*> adaptation_constraints_
|
||||||
RTC_GUARDED_BY(sequence_checker_);
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
std::vector<AdaptationListener*> adaptation_listeners_
|
std::vector<AdaptationListener*> adaptation_listeners_
|
||||||
RTC_GUARDED_BY(sequence_checker_);
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
// Purely used for statistics, does not ensure mapped resources stay alive.
|
// Purely used for statistics, does not ensure mapped resources stay alive.
|
||||||
std::map<const Resource*, int> adaptations_counts_by_resource_
|
std::map<const Resource*, int> adaptations_counts_by_resource_
|
||||||
RTC_GUARDED_BY(sequence_checker_);
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
// Adaptation strategy settings.
|
// Adaptation strategy settings.
|
||||||
DegradationPreference degradation_preference_
|
DegradationPreference degradation_preference_
|
||||||
RTC_GUARDED_BY(sequence_checker_);
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
DegradationPreference effective_degradation_preference_
|
DegradationPreference effective_degradation_preference_
|
||||||
RTC_GUARDED_BY(sequence_checker_);
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
bool is_screenshare_ RTC_GUARDED_BY(sequence_checker_);
|
bool is_screenshare_ RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
// Responsible for generating and applying possible adaptations.
|
// Responsible for generating and applying possible adaptations.
|
||||||
const std::unique_ptr<VideoStreamAdapter> stream_adapter_
|
const std::unique_ptr<VideoStreamAdapter> stream_adapter_
|
||||||
RTC_GUARDED_BY(sequence_checker_);
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
VideoSourceRestrictions last_reported_source_restrictions_
|
VideoSourceRestrictions last_reported_source_restrictions_
|
||||||
RTC_GUARDED_BY(sequence_checker_);
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
// Keeps track of previous mitigation results per resource since the last
|
// Keeps track of previous mitigation results per resource since the last
|
||||||
// successful adaptation. Used to avoid RTC_LOG spam.
|
// successful adaptation. Used to avoid RTC_LOG spam.
|
||||||
std::map<Resource*, MitigationResult> previous_mitigation_results_
|
std::map<Resource*, MitigationResult> previous_mitigation_results_
|
||||||
RTC_GUARDED_BY(sequence_checker_);
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
// Prevents recursion.
|
// Prevents recursion.
|
||||||
//
|
//
|
||||||
// This is used to prevent triggering resource adaptation in the process of
|
// This is used to prevent triggering resource adaptation in the process of
|
||||||
@ -185,7 +209,7 @@ class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
|
|||||||
// Resource::OnAdaptationApplied() ->
|
// Resource::OnAdaptationApplied() ->
|
||||||
// Resource::OnResourceUsageStateMeasured() ->
|
// Resource::OnResourceUsageStateMeasured() ->
|
||||||
// ResourceAdaptationProcessor::OnResourceOveruse() // Boom, not allowed.
|
// ResourceAdaptationProcessor::OnResourceOveruse() // Boom, not allowed.
|
||||||
bool processing_in_progress_ RTC_GUARDED_BY(sequence_checker_);
|
bool processing_in_progress_ RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "absl/types/optional.h"
|
#include "absl/types/optional.h"
|
||||||
#include "api/rtp_parameters.h"
|
#include "api/rtp_parameters.h"
|
||||||
#include "api/scoped_refptr.h"
|
#include "api/scoped_refptr.h"
|
||||||
|
#include "api/task_queue/task_queue_base.h"
|
||||||
#include "api/video/video_adaptation_counters.h"
|
#include "api/video/video_adaptation_counters.h"
|
||||||
#include "api/video/video_frame.h"
|
#include "api/video/video_frame.h"
|
||||||
#include "call/adaptation/adaptation_constraint.h"
|
#include "call/adaptation/adaptation_constraint.h"
|
||||||
@ -21,7 +22,6 @@
|
|||||||
#include "call/adaptation/encoder_settings.h"
|
#include "call/adaptation/encoder_settings.h"
|
||||||
#include "call/adaptation/resource.h"
|
#include "call/adaptation/resource.h"
|
||||||
#include "call/adaptation/video_source_restrictions.h"
|
#include "call/adaptation/video_source_restrictions.h"
|
||||||
#include "rtc_base/task_queue.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
@ -48,7 +48,8 @@ class ResourceAdaptationProcessorInterface {
|
|||||||
public:
|
public:
|
||||||
virtual ~ResourceAdaptationProcessorInterface();
|
virtual ~ResourceAdaptationProcessorInterface();
|
||||||
|
|
||||||
virtual void InitializeOnResourceAdaptationQueue() = 0;
|
virtual void SetResourceAdaptationQueue(
|
||||||
|
TaskQueueBase* resource_adaptation_queue) = 0;
|
||||||
|
|
||||||
virtual DegradationPreference degradation_preference() const = 0;
|
virtual DegradationPreference degradation_preference() const = 0;
|
||||||
// Reinterprets "balanced + screenshare" as "maintain-resolution".
|
// Reinterprets "balanced + screenshare" as "maintain-resolution".
|
||||||
|
@ -20,7 +20,9 @@
|
|||||||
#include "call/adaptation/test/fake_resource.h"
|
#include "call/adaptation/test/fake_resource.h"
|
||||||
#include "call/adaptation/video_source_restrictions.h"
|
#include "call/adaptation/video_source_restrictions.h"
|
||||||
#include "call/adaptation/video_stream_input_state_provider.h"
|
#include "call/adaptation/video_stream_input_state_provider.h"
|
||||||
|
#include "rtc_base/critical_section.h"
|
||||||
#include "rtc_base/event.h"
|
#include "rtc_base/event.h"
|
||||||
|
#include "rtc_base/gunit.h"
|
||||||
#include "rtc_base/task_queue_for_test.h"
|
#include "rtc_base/task_queue_for_test.h"
|
||||||
#include "test/gtest.h"
|
#include "test/gtest.h"
|
||||||
|
|
||||||
@ -30,6 +32,7 @@ namespace {
|
|||||||
|
|
||||||
const int kDefaultFrameRate = 30;
|
const int kDefaultFrameRate = 30;
|
||||||
const int kDefaultFrameSize = 1280 * 720;
|
const int kDefaultFrameSize = 1280 * 720;
|
||||||
|
const int kDefaultTimeoutMs = 5000;
|
||||||
|
|
||||||
class VideoSourceRestrictionsListenerForTesting
|
class VideoSourceRestrictionsListenerForTesting
|
||||||
: public VideoSourceRestrictionsListener {
|
: public VideoSourceRestrictionsListener {
|
||||||
@ -42,19 +45,28 @@ class VideoSourceRestrictionsListenerForTesting
|
|||||||
~VideoSourceRestrictionsListenerForTesting() override {}
|
~VideoSourceRestrictionsListenerForTesting() override {}
|
||||||
|
|
||||||
size_t restrictions_updated_count() const {
|
size_t restrictions_updated_count() const {
|
||||||
|
rtc::CritScope crit(&lock_);
|
||||||
return restrictions_updated_count_;
|
return restrictions_updated_count_;
|
||||||
}
|
}
|
||||||
const VideoSourceRestrictions& restrictions() const { return restrictions_; }
|
VideoSourceRestrictions restrictions() const {
|
||||||
const VideoAdaptationCounters& adaptation_counters() const {
|
rtc::CritScope crit(&lock_);
|
||||||
|
return restrictions_;
|
||||||
|
}
|
||||||
|
VideoAdaptationCounters adaptation_counters() const {
|
||||||
|
rtc::CritScope crit(&lock_);
|
||||||
return adaptation_counters_;
|
return adaptation_counters_;
|
||||||
}
|
}
|
||||||
rtc::scoped_refptr<Resource> reason() const { return reason_; }
|
rtc::scoped_refptr<Resource> reason() const {
|
||||||
|
rtc::CritScope crit(&lock_);
|
||||||
|
return reason_;
|
||||||
|
}
|
||||||
|
|
||||||
// VideoSourceRestrictionsListener implementation.
|
// VideoSourceRestrictionsListener implementation.
|
||||||
void OnVideoSourceRestrictionsUpdated(
|
void OnVideoSourceRestrictionsUpdated(
|
||||||
VideoSourceRestrictions restrictions,
|
VideoSourceRestrictions restrictions,
|
||||||
const VideoAdaptationCounters& adaptation_counters,
|
const VideoAdaptationCounters& adaptation_counters,
|
||||||
rtc::scoped_refptr<Resource> reason) override {
|
rtc::scoped_refptr<Resource> reason) override {
|
||||||
|
rtc::CritScope crit(&lock_);
|
||||||
++restrictions_updated_count_;
|
++restrictions_updated_count_;
|
||||||
restrictions_ = restrictions;
|
restrictions_ = restrictions;
|
||||||
adaptation_counters_ = adaptation_counters;
|
adaptation_counters_ = adaptation_counters;
|
||||||
@ -62,10 +74,11 @@ class VideoSourceRestrictionsListenerForTesting
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t restrictions_updated_count_;
|
rtc::CriticalSection lock_;
|
||||||
VideoSourceRestrictions restrictions_;
|
size_t restrictions_updated_count_ RTC_GUARDED_BY(lock_);
|
||||||
VideoAdaptationCounters adaptation_counters_;
|
VideoSourceRestrictions restrictions_ RTC_GUARDED_BY(lock_);
|
||||||
rtc::scoped_refptr<Resource> reason_;
|
VideoAdaptationCounters adaptation_counters_ RTC_GUARDED_BY(lock_);
|
||||||
|
rtc::scoped_refptr<Resource> reason_ RTC_GUARDED_BY(lock_);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResourceAdaptationProcessorTest : public ::testing::Test {
|
class ResourceAdaptationProcessorTest : public ::testing::Test {
|
||||||
@ -81,31 +94,26 @@ class ResourceAdaptationProcessorTest : public ::testing::Test {
|
|||||||
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_)) {
|
||||||
rtc::Event event;
|
resource_adaptation_queue_.SendTask(
|
||||||
resource_adaptation_queue_.PostTask([this, &event] {
|
[this] {
|
||||||
processor_->InitializeOnResourceAdaptationQueue();
|
processor_->SetResourceAdaptationQueue(
|
||||||
processor_->AddRestrictionsListener(&restrictions_listener_);
|
resource_adaptation_queue_.Get());
|
||||||
processor_->AddResource(resource_);
|
processor_->AddRestrictionsListener(&restrictions_listener_);
|
||||||
processor_->AddResource(other_resource_);
|
processor_->AddResource(resource_);
|
||||||
processor_->AddAdaptationConstraint(&adaptation_constraint_);
|
processor_->AddResource(other_resource_);
|
||||||
processor_->AddAdaptationListener(&adaptation_listener_);
|
processor_->AddAdaptationConstraint(&adaptation_constraint_);
|
||||||
event.Set();
|
processor_->AddAdaptationListener(&adaptation_listener_);
|
||||||
});
|
},
|
||||||
event.Wait(rtc::Event::kForever);
|
RTC_FROM_HERE);
|
||||||
}
|
}
|
||||||
~ResourceAdaptationProcessorTest() override {
|
~ResourceAdaptationProcessorTest() override {
|
||||||
rtc::Event event;
|
resource_adaptation_queue_.SendTask(
|
||||||
resource_adaptation_queue_.PostTask([this, &event] {
|
[this] {
|
||||||
processor_->StopResourceAdaptation();
|
if (processor_) {
|
||||||
processor_->RemoveRestrictionsListener(&restrictions_listener_);
|
DestroyProcessor();
|
||||||
processor_->RemoveResource(resource_);
|
}
|
||||||
processor_->RemoveResource(other_resource_);
|
},
|
||||||
processor_->RemoveAdaptationConstraint(&adaptation_constraint_);
|
RTC_FROM_HERE);
|
||||||
processor_->RemoveAdaptationListener(&adaptation_listener_);
|
|
||||||
processor_.reset();
|
|
||||||
event.Set();
|
|
||||||
});
|
|
||||||
event.Wait(rtc::Event::kForever);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetInputStates(bool has_input, int fps, int frame_size) {
|
void SetInputStates(bool has_input, int fps, int frame_size) {
|
||||||
@ -122,6 +130,17 @@ class ResourceAdaptationProcessorTest : public ::testing::Test {
|
|||||||
: restrictions.max_pixels_per_frame().value_or(kDefaultFrameSize));
|
: restrictions.max_pixels_per_frame().value_or(kDefaultFrameSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DestroyProcessor() {
|
||||||
|
RTC_DCHECK_RUN_ON(&resource_adaptation_queue_);
|
||||||
|
processor_->StopResourceAdaptation();
|
||||||
|
processor_->RemoveRestrictionsListener(&restrictions_listener_);
|
||||||
|
processor_->RemoveResource(resource_);
|
||||||
|
processor_->RemoveResource(other_resource_);
|
||||||
|
processor_->RemoveAdaptationConstraint(&adaptation_constraint_);
|
||||||
|
processor_->RemoveAdaptationListener(&adaptation_listener_);
|
||||||
|
processor_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TaskQueueForTest resource_adaptation_queue_;
|
TaskQueueForTest resource_adaptation_queue_;
|
||||||
FakeFrameRateProvider frame_rate_provider_;
|
FakeFrameRateProvider frame_rate_provider_;
|
||||||
@ -394,33 +413,6 @@ TEST_F(ResourceAdaptationProcessorTest, AdaptingTriggersOnAdaptationApplied) {
|
|||||||
RTC_FROM_HERE);
|
RTC_FROM_HERE);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResourceAdaptationProcessorTest, AdaptingClearsResourceUsageState) {
|
|
||||||
resource_adaptation_queue_.SendTask(
|
|
||||||
[this] {
|
|
||||||
processor_->SetDegradationPreference(
|
|
||||||
DegradationPreference::MAINTAIN_FRAMERATE);
|
|
||||||
processor_->StartResourceAdaptation();
|
|
||||||
SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
|
|
||||||
resource_->SetUsageState(ResourceUsageState::kOveruse);
|
|
||||||
EXPECT_EQ(1u, restrictions_listener_.restrictions_updated_count());
|
|
||||||
EXPECT_FALSE(resource_->UsageState().has_value());
|
|
||||||
},
|
|
||||||
RTC_FROM_HERE);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(ResourceAdaptationProcessorTest,
|
|
||||||
FailingAdaptingAlsoClearsResourceUsageState) {
|
|
||||||
resource_adaptation_queue_.SendTask(
|
|
||||||
[this] {
|
|
||||||
processor_->SetDegradationPreference(DegradationPreference::DISABLED);
|
|
||||||
processor_->StartResourceAdaptation();
|
|
||||||
resource_->SetUsageState(ResourceUsageState::kOveruse);
|
|
||||||
EXPECT_EQ(0u, restrictions_listener_.restrictions_updated_count());
|
|
||||||
EXPECT_FALSE(resource_->UsageState().has_value());
|
|
||||||
},
|
|
||||||
RTC_FROM_HERE);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(ResourceAdaptationProcessorTest,
|
TEST_F(ResourceAdaptationProcessorTest,
|
||||||
AdaptsDownWhenOtherResourceIsAlwaysUnderused) {
|
AdaptsDownWhenOtherResourceIsAlwaysUnderused) {
|
||||||
resource_adaptation_queue_.SendTask(
|
resource_adaptation_queue_.SendTask(
|
||||||
@ -447,4 +439,46 @@ TEST_F(ResourceAdaptationProcessorTest,
|
|||||||
RTC_FROM_HERE);
|
RTC_FROM_HERE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ResourceAdaptationProcessorTest,
|
||||||
|
TriggerOveruseNotOnAdaptationTaskQueue) {
|
||||||
|
resource_adaptation_queue_.SendTask(
|
||||||
|
[this] {
|
||||||
|
processor_->SetDegradationPreference(
|
||||||
|
DegradationPreference::MAINTAIN_FRAMERATE);
|
||||||
|
processor_->StartResourceAdaptation();
|
||||||
|
SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
|
||||||
|
},
|
||||||
|
RTC_FROM_HERE);
|
||||||
|
resource_->SetUsageState(ResourceUsageState::kOveruse);
|
||||||
|
EXPECT_EQ_WAIT(1u, restrictions_listener_.restrictions_updated_count(),
|
||||||
|
kDefaultTimeoutMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ResourceAdaptationProcessorTest,
|
||||||
|
DestroyProcessorWhileResourceListenerDelegateHasTaskInFlight) {
|
||||||
|
resource_adaptation_queue_.SendTask(
|
||||||
|
[this] {
|
||||||
|
processor_->SetDegradationPreference(
|
||||||
|
DegradationPreference::MAINTAIN_FRAMERATE);
|
||||||
|
processor_->StartResourceAdaptation();
|
||||||
|
SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
|
||||||
|
},
|
||||||
|
RTC_FROM_HERE);
|
||||||
|
// Block the destruction of the processor. This ensures that the adaptation
|
||||||
|
// queue is blocked until the ResourceListenerDelegate has had time to post
|
||||||
|
// its task.
|
||||||
|
rtc::Event destroy_processor_event;
|
||||||
|
resource_adaptation_queue_.PostTask([this, &destroy_processor_event] {
|
||||||
|
destroy_processor_event.Wait(rtc::Event::kForever);
|
||||||
|
DestroyProcessor();
|
||||||
|
});
|
||||||
|
resource_->SetUsageState(ResourceUsageState::kOveruse);
|
||||||
|
// Unblock destruction and delegate task.
|
||||||
|
destroy_processor_event.Set();
|
||||||
|
resource_adaptation_queue_.WaitForPreviouslyPostedTasks();
|
||||||
|
// Because the processor was destroyed by the time the delegate's task ran,
|
||||||
|
// the overuse signal must not have been handled.
|
||||||
|
EXPECT_EQ(0u, restrictions_listener_.restrictions_updated_count());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -26,7 +26,8 @@ class MockResourceListener : public ResourceListener {
|
|||||||
public:
|
public:
|
||||||
MOCK_METHOD(void,
|
MOCK_METHOD(void,
|
||||||
OnResourceUsageStateMeasured,
|
OnResourceUsageStateMeasured,
|
||||||
(rtc::scoped_refptr<Resource> resource),
|
(rtc::scoped_refptr<Resource> resource,
|
||||||
|
ResourceUsageState usage_state),
|
||||||
(override));
|
(override));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -41,10 +42,11 @@ class ResourceTest : public ::testing::Test {
|
|||||||
TEST_F(ResourceTest, RegisteringListenerReceivesCallbacks) {
|
TEST_F(ResourceTest, RegisteringListenerReceivesCallbacks) {
|
||||||
StrictMock<MockResourceListener> resource_listener;
|
StrictMock<MockResourceListener> resource_listener;
|
||||||
fake_resource_->SetResourceListener(&resource_listener);
|
fake_resource_->SetResourceListener(&resource_listener);
|
||||||
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->UsageState());
|
ResourceUsageState usage_state) {
|
||||||
|
EXPECT_EQ(ResourceUsageState::kOveruse, usage_state);
|
||||||
});
|
});
|
||||||
fake_resource_->SetUsageState(ResourceUsageState::kOveruse);
|
fake_resource_->SetUsageState(ResourceUsageState::kOveruse);
|
||||||
fake_resource_->SetResourceListener(nullptr);
|
fake_resource_->SetResourceListener(nullptr);
|
||||||
@ -54,7 +56,7 @@ TEST_F(ResourceTest, UnregisteringListenerStopsCallbacks) {
|
|||||||
StrictMock<MockResourceListener> resource_listener;
|
StrictMock<MockResourceListener> resource_listener;
|
||||||
fake_resource_->SetResourceListener(&resource_listener);
|
fake_resource_->SetResourceListener(&resource_listener);
|
||||||
fake_resource_->SetResourceListener(nullptr);
|
fake_resource_->SetResourceListener(nullptr);
|
||||||
EXPECT_CALL(resource_listener, OnResourceUsageStateMeasured(_)).Times(0);
|
EXPECT_CALL(resource_listener, OnResourceUsageStateMeasured(_, _)).Times(0);
|
||||||
fake_resource_->SetUsageState(ResourceUsageState::kOveruse);
|
fake_resource_->SetUsageState(ResourceUsageState::kOveruse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,17 +23,13 @@ rtc::scoped_refptr<FakeResource> FakeResource::Create(std::string name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FakeResource::FakeResource(std::string name)
|
FakeResource::FakeResource(std::string name)
|
||||||
: Resource(),
|
: Resource(), name_(std::move(name)), listener_(nullptr) {}
|
||||||
name_(std::move(name)),
|
|
||||||
listener_(nullptr),
|
|
||||||
usage_state_(absl::nullopt) {}
|
|
||||||
|
|
||||||
FakeResource::~FakeResource() {}
|
FakeResource::~FakeResource() {}
|
||||||
|
|
||||||
void FakeResource::SetUsageState(ResourceUsageState usage_state) {
|
void FakeResource::SetUsageState(ResourceUsageState usage_state) {
|
||||||
usage_state_ = usage_state;
|
|
||||||
if (listener_) {
|
if (listener_) {
|
||||||
listener_->OnResourceUsageStateMeasured(this);
|
listener_->OnResourceUsageStateMeasured(this, usage_state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,12 +41,4 @@ void FakeResource::SetResourceListener(ResourceListener* listener) {
|
|||||||
listener_ = listener;
|
listener_ = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::optional<ResourceUsageState> FakeResource::UsageState() const {
|
|
||||||
return usage_state_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FakeResource::ClearUsageState() {
|
|
||||||
usage_state_ = absl::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -33,13 +33,10 @@ class FakeResource : public Resource {
|
|||||||
// Resource implementation.
|
// Resource implementation.
|
||||||
std::string Name() const override;
|
std::string Name() const override;
|
||||||
void SetResourceListener(ResourceListener* listener) override;
|
void SetResourceListener(ResourceListener* listener) override;
|
||||||
absl::optional<ResourceUsageState> UsageState() const override;
|
|
||||||
void ClearUsageState() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::string name_;
|
const std::string name_;
|
||||||
ResourceListener* listener_;
|
ResourceListener* listener_;
|
||||||
absl::optional<ResourceUsageState> usage_state_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -20,7 +20,6 @@ VideoStreamEncoderResource::VideoStreamEncoderResource(std::string name)
|
|||||||
name_(std::move(name)),
|
name_(std::move(name)),
|
||||||
encoder_queue_(nullptr),
|
encoder_queue_(nullptr),
|
||||||
resource_adaptation_queue_(nullptr),
|
resource_adaptation_queue_(nullptr),
|
||||||
usage_state_(absl::nullopt),
|
|
||||||
listener_(nullptr) {}
|
listener_(nullptr) {}
|
||||||
|
|
||||||
VideoStreamEncoderResource::~VideoStreamEncoderResource() {
|
VideoStreamEncoderResource::~VideoStreamEncoderResource() {
|
||||||
@ -64,23 +63,11 @@ std::string VideoStreamEncoderResource::Name() const {
|
|||||||
return name_;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VideoStreamEncoderResource::OnResourceUsageStateMeasured(
|
void VideoStreamEncoderResource::OnResourceUsageStateMeasured(
|
||||||
ResourceUsageState usage_state) {
|
ResourceUsageState usage_state) {
|
||||||
RTC_DCHECK_RUN_ON(resource_adaptation_queue());
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue());
|
||||||
usage_state_ = usage_state;
|
|
||||||
if (listener_) {
|
if (listener_) {
|
||||||
listener_->OnResourceUsageStateMeasured(this);
|
listener_->OnResourceUsageStateMeasured(this, usage_state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,8 +34,6 @@ class VideoStreamEncoderResource : public Resource {
|
|||||||
// Resource implementation.
|
// Resource implementation.
|
||||||
std::string Name() const override;
|
std::string Name() const override;
|
||||||
void SetResourceListener(ResourceListener* listener) override;
|
void SetResourceListener(ResourceListener* listener) override;
|
||||||
absl::optional<ResourceUsageState> UsageState() const override;
|
|
||||||
void ClearUsageState() override;
|
|
||||||
|
|
||||||
// Provides a pointer to the adaptation task queue. After this call, all
|
// Provides a pointer to the adaptation task queue. After this call, all
|
||||||
// methods defined in this interface, including
|
// methods defined in this interface, including
|
||||||
@ -74,8 +72,6 @@ class VideoStreamEncoderResource : public Resource {
|
|||||||
// Treated as const after initialization.
|
// Treated as const after initialization.
|
||||||
TaskQueueBase* encoder_queue_;
|
TaskQueueBase* encoder_queue_;
|
||||||
TaskQueueBase* resource_adaptation_queue_ RTC_GUARDED_BY(lock_);
|
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());
|
ResourceListener* listener_ RTC_GUARDED_BY(resource_adaptation_queue());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -284,7 +284,8 @@ VideoStreamEncoder::VideoStreamEncoder(
|
|||||||
rtc::Event initialize_processor_event;
|
rtc::Event initialize_processor_event;
|
||||||
resource_adaptation_queue_.PostTask([this, &initialize_processor_event] {
|
resource_adaptation_queue_.PostTask([this, &initialize_processor_event] {
|
||||||
RTC_DCHECK_RUN_ON(&resource_adaptation_queue_);
|
RTC_DCHECK_RUN_ON(&resource_adaptation_queue_);
|
||||||
resource_adaptation_processor_->InitializeOnResourceAdaptationQueue();
|
resource_adaptation_processor_->SetResourceAdaptationQueue(
|
||||||
|
resource_adaptation_queue_.Get());
|
||||||
stream_resource_manager_.SetAdaptationProcessor(
|
stream_resource_manager_.SetAdaptationProcessor(
|
||||||
resource_adaptation_processor_.get());
|
resource_adaptation_processor_.get());
|
||||||
resource_adaptation_processor_->AddRestrictionsListener(
|
resource_adaptation_processor_->AddRestrictionsListener(
|
||||||
|
Reference in New Issue
Block a user