mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 13:50:40 +01:00
[Adaptation] VideoStreamAdapter broadcasts adaptations
This moves this responsibility from the ResourceAdaptaitonProcessor to the VideoStreamAdapter. A new interface for listening to adaptation changes was added, and the ResourceAdaptationProcessor now listens on the VideoStreamAdapter for those changes. This means that going forward, 1. We can do adaptations outside of resource limitations, like setting prior adaptations on a resource like initial frame dropper is designed to. 2. Adaptations can be on a different queue than the ResourceAdaptaitonProcessor's queue since updates are pushed through the listener. Bug: webrtc:11700 Change-Id: I6de0dec748dba095e702f0b9893c5afa50b51aa9 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/176859 Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Henrik Boström <hbos@webrtc.org> Commit-Queue: Evan Shrubsole <eshr@google.com> Cr-Commit-Position: refs/heads/master@{#31615}
This commit is contained in:
parent
a1888ae791
commit
ec0af26ff8
13 changed files with 337 additions and 188 deletions
|
@ -15,6 +15,8 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "absl/algorithm/container.h"
|
#include "absl/algorithm/container.h"
|
||||||
|
#include "api/video/video_adaptation_counters.h"
|
||||||
|
#include "call/adaptation/video_stream_adapter.h"
|
||||||
#include "rtc_base/logging.h"
|
#include "rtc_base/logging.h"
|
||||||
#include "rtc_base/ref_counted_object.h"
|
#include "rtc_base/ref_counted_object.h"
|
||||||
#include "rtc_base/strings/string_builder.h"
|
#include "rtc_base/strings/string_builder.h"
|
||||||
|
@ -67,7 +69,8 @@ ResourceAdaptationProcessor::MitigationResultAndLogMessage::
|
||||||
|
|
||||||
ResourceAdaptationProcessor::ResourceAdaptationProcessor(
|
ResourceAdaptationProcessor::ResourceAdaptationProcessor(
|
||||||
VideoStreamInputStateProvider* input_state_provider,
|
VideoStreamInputStateProvider* input_state_provider,
|
||||||
VideoStreamEncoderObserver* encoder_stats_observer)
|
VideoStreamEncoderObserver* encoder_stats_observer,
|
||||||
|
VideoStreamAdapter* stream_adapter)
|
||||||
: resource_adaptation_queue_(nullptr),
|
: resource_adaptation_queue_(nullptr),
|
||||||
resource_listener_delegate_(
|
resource_listener_delegate_(
|
||||||
new rtc::RefCountedObject<ResourceListenerDelegate>(this)),
|
new rtc::RefCountedObject<ResourceListenerDelegate>(this)),
|
||||||
|
@ -77,16 +80,15 @@ ResourceAdaptationProcessor::ResourceAdaptationProcessor(
|
||||||
degradation_preference_(DegradationPreference::DISABLED),
|
degradation_preference_(DegradationPreference::DISABLED),
|
||||||
effective_degradation_preference_(DegradationPreference::DISABLED),
|
effective_degradation_preference_(DegradationPreference::DISABLED),
|
||||||
is_screenshare_(false),
|
is_screenshare_(false),
|
||||||
stream_adapter_(std::make_unique<VideoStreamAdapter>()),
|
stream_adapter_(stream_adapter),
|
||||||
last_reported_source_restrictions_(),
|
last_reported_source_restrictions_(),
|
||||||
previous_mitigation_results_(),
|
previous_mitigation_results_(),
|
||||||
processing_in_progress_(false) {}
|
processing_in_progress_(false) {
|
||||||
|
RTC_DCHECK(stream_adapter_);
|
||||||
|
}
|
||||||
|
|
||||||
ResourceAdaptationProcessor::~ResourceAdaptationProcessor() {
|
ResourceAdaptationProcessor::~ResourceAdaptationProcessor() {
|
||||||
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
RTC_DCHECK(restrictions_listeners_.empty())
|
|
||||||
<< "There are restrictions listener(s) depending on a "
|
|
||||||
<< "ResourceAdaptationProcessor being destroyed.";
|
|
||||||
RTC_DCHECK(resources_.empty())
|
RTC_DCHECK(resources_.empty())
|
||||||
<< "There are resource(s) attached to a ResourceAdaptationProcessor "
|
<< "There are resource(s) attached to a ResourceAdaptationProcessor "
|
||||||
<< "being destroyed.";
|
<< "being destroyed.";
|
||||||
|
@ -96,6 +98,7 @@ 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.";
|
||||||
|
stream_adapter_->RemoveRestrictionsListener(this);
|
||||||
resource_listener_delegate_->OnProcessorDestroyed();
|
resource_listener_delegate_->OnProcessorDestroyed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,6 +110,8 @@ void ResourceAdaptationProcessor::SetResourceAdaptationQueue(
|
||||||
resource_listener_delegate_->SetResourceAdaptationQueue(
|
resource_listener_delegate_->SetResourceAdaptationQueue(
|
||||||
resource_adaptation_queue);
|
resource_adaptation_queue);
|
||||||
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
|
// Now that we have the adaptation queue we can attach as adaptation listener.
|
||||||
|
stream_adapter_->AddRestrictionsListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
DegradationPreference ResourceAdaptationProcessor::degradation_preference()
|
DegradationPreference ResourceAdaptationProcessor::degradation_preference()
|
||||||
|
@ -121,22 +126,23 @@ ResourceAdaptationProcessor::effective_degradation_preference() const {
|
||||||
return effective_degradation_preference_;
|
return effective_degradation_preference_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceAdaptationProcessor::AddRestrictionsListener(
|
void ResourceAdaptationProcessor::AddResourceLimitationsListener(
|
||||||
VideoSourceRestrictionsListener* restrictions_listener) {
|
ResourceLimitationsListener* limitations_listener) {
|
||||||
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
RTC_DCHECK(std::find(restrictions_listeners_.begin(),
|
RTC_DCHECK(std::find(resource_limitations_listeners_.begin(),
|
||||||
restrictions_listeners_.end(),
|
resource_limitations_listeners_.end(),
|
||||||
restrictions_listener) == restrictions_listeners_.end());
|
limitations_listener) ==
|
||||||
restrictions_listeners_.push_back(restrictions_listener);
|
resource_limitations_listeners_.end());
|
||||||
|
resource_limitations_listeners_.push_back(limitations_listener);
|
||||||
}
|
}
|
||||||
|
void ResourceAdaptationProcessor::RemoveResourceLimitationsListener(
|
||||||
void ResourceAdaptationProcessor::RemoveRestrictionsListener(
|
ResourceLimitationsListener* limitations_listener) {
|
||||||
VideoSourceRestrictionsListener* restrictions_listener) {
|
|
||||||
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
auto it = std::find(restrictions_listeners_.begin(),
|
auto it =
|
||||||
restrictions_listeners_.end(), restrictions_listener);
|
std::find(resource_limitations_listeners_.begin(),
|
||||||
RTC_DCHECK(it != restrictions_listeners_.end());
|
resource_limitations_listeners_.end(), limitations_listener);
|
||||||
restrictions_listeners_.erase(it);
|
RTC_DCHECK(it != resource_limitations_listeners_.end());
|
||||||
|
resource_limitations_listeners_.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceAdaptationProcessor::AddResource(
|
void ResourceAdaptationProcessor::AddResource(
|
||||||
|
@ -232,39 +238,6 @@ void ResourceAdaptationProcessor::MaybeUpdateEffectiveDegradationPreference() {
|
||||||
? DegradationPreference::MAINTAIN_RESOLUTION
|
? DegradationPreference::MAINTAIN_RESOLUTION
|
||||||
: degradation_preference_;
|
: degradation_preference_;
|
||||||
stream_adapter_->SetDegradationPreference(effective_degradation_preference_);
|
stream_adapter_->SetDegradationPreference(effective_degradation_preference_);
|
||||||
MaybeUpdateVideoSourceRestrictions(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResourceAdaptationProcessor::ResetVideoSourceRestrictions() {
|
|
||||||
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
|
||||||
RTC_LOG(INFO) << "Resetting restrictions";
|
|
||||||
stream_adapter_->ClearRestrictions();
|
|
||||||
adaptation_limits_by_resources_.clear();
|
|
||||||
for (auto restrictions_listener : restrictions_listeners_) {
|
|
||||||
restrictions_listener->OnResourceLimitationChanged(nullptr, {});
|
|
||||||
}
|
|
||||||
MaybeUpdateVideoSourceRestrictions(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResourceAdaptationProcessor::MaybeUpdateVideoSourceRestrictions(
|
|
||||||
rtc::scoped_refptr<Resource> reason) {
|
|
||||||
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
|
||||||
VideoSourceRestrictions new_source_restrictions =
|
|
||||||
FilterRestrictionsByDegradationPreference(
|
|
||||||
stream_adapter_->source_restrictions(),
|
|
||||||
effective_degradation_preference_);
|
|
||||||
if (last_reported_source_restrictions_ != new_source_restrictions) {
|
|
||||||
RTC_LOG(INFO) << "Reporting new restrictions (in "
|
|
||||||
<< DegradationPreferenceToString(
|
|
||||||
effective_degradation_preference_)
|
|
||||||
<< "): " << new_source_restrictions.ToString();
|
|
||||||
last_reported_source_restrictions_ = std::move(new_source_restrictions);
|
|
||||||
for (auto* restrictions_listener : restrictions_listeners_) {
|
|
||||||
restrictions_listener->OnVideoSourceRestrictionsUpdated(
|
|
||||||
last_reported_source_restrictions_,
|
|
||||||
stream_adapter_->adaptation_counters(), reason);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceAdaptationProcessor::OnResourceUsageStateMeasured(
|
void ResourceAdaptationProcessor::OnResourceUsageStateMeasured(
|
||||||
|
@ -386,10 +359,10 @@ ResourceAdaptationProcessor::OnResourceUnderuse(
|
||||||
MitigationResult::kNotMostLimitedResource, message.Release());
|
MitigationResult::kNotMostLimitedResource, message.Release());
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateResourceLimitations(reason_resource, peek_restrictions);
|
|
||||||
if (most_limited_resources.size() > 1) {
|
if (most_limited_resources.size() > 1) {
|
||||||
// If there are multiple most limited resources, all must signal underuse
|
// If there are multiple most limited resources, all must signal underuse
|
||||||
// before the adaptation is applied.
|
// before the adaptation is applied.
|
||||||
|
UpdateResourceLimitations(reason_resource, peek_restrictions);
|
||||||
processing_in_progress_ = false;
|
processing_in_progress_ = false;
|
||||||
rtc::StringBuilder message;
|
rtc::StringBuilder message;
|
||||||
message << "Resource \"" << reason_resource->Name()
|
message << "Resource \"" << reason_resource->Name()
|
||||||
|
@ -399,14 +372,11 @@ ResourceAdaptationProcessor::OnResourceUnderuse(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Apply adaptation.
|
// Apply adaptation.
|
||||||
stream_adapter_->ApplyAdaptation(adaptation);
|
stream_adapter_->ApplyAdaptation(adaptation, reason_resource);
|
||||||
for (auto* adaptation_listener : adaptation_listeners_) {
|
for (auto* adaptation_listener : adaptation_listeners_) {
|
||||||
adaptation_listener->OnAdaptationApplied(
|
adaptation_listener->OnAdaptationApplied(
|
||||||
input_state, restrictions_before, restrictions_after, reason_resource);
|
input_state, restrictions_before, restrictions_after, reason_resource);
|
||||||
}
|
}
|
||||||
// Update VideoSourceRestrictions based on adaptation. This also informs the
|
|
||||||
// |restrictions_listeners_|.
|
|
||||||
MaybeUpdateVideoSourceRestrictions(reason_resource);
|
|
||||||
processing_in_progress_ = false;
|
processing_in_progress_ = false;
|
||||||
rtc::StringBuilder message;
|
rtc::StringBuilder message;
|
||||||
message << "Adapted up successfully. Unfiltered adaptations: "
|
message << "Adapted up successfully. Unfiltered adaptations: "
|
||||||
|
@ -456,15 +426,11 @@ ResourceAdaptationProcessor::OnResourceOveruse(
|
||||||
stream_adapter_->PeekNextRestrictions(adaptation);
|
stream_adapter_->PeekNextRestrictions(adaptation);
|
||||||
VideoSourceRestrictions restrictions_after =
|
VideoSourceRestrictions restrictions_after =
|
||||||
peek_next_restrictions.restrictions;
|
peek_next_restrictions.restrictions;
|
||||||
UpdateResourceLimitations(reason_resource, peek_next_restrictions);
|
stream_adapter_->ApplyAdaptation(adaptation, reason_resource);
|
||||||
stream_adapter_->ApplyAdaptation(adaptation);
|
|
||||||
for (auto* adaptation_listener : adaptation_listeners_) {
|
for (auto* adaptation_listener : adaptation_listeners_) {
|
||||||
adaptation_listener->OnAdaptationApplied(
|
adaptation_listener->OnAdaptationApplied(
|
||||||
input_state, restrictions_before, restrictions_after, reason_resource);
|
input_state, restrictions_before, restrictions_after, reason_resource);
|
||||||
}
|
}
|
||||||
// Update VideoSourceRestrictions based on adaptation. This also informs the
|
|
||||||
// |restrictions_listeners_|.
|
|
||||||
MaybeUpdateVideoSourceRestrictions(reason_resource);
|
|
||||||
processing_in_progress_ = false;
|
processing_in_progress_ = false;
|
||||||
rtc::StringBuilder message;
|
rtc::StringBuilder message;
|
||||||
message << "Adapted down successfully. Unfiltered adaptations: "
|
message << "Adapted down successfully. Unfiltered adaptations: "
|
||||||
|
@ -520,17 +486,19 @@ ResourceAdaptationProcessor::FindMostLimitedResources() const {
|
||||||
|
|
||||||
void ResourceAdaptationProcessor::UpdateResourceLimitations(
|
void ResourceAdaptationProcessor::UpdateResourceLimitations(
|
||||||
rtc::scoped_refptr<Resource> reason_resource,
|
rtc::scoped_refptr<Resource> reason_resource,
|
||||||
const VideoStreamAdapter::RestrictionsWithCounters&
|
const VideoStreamAdapter::RestrictionsWithCounters& restrictions) {
|
||||||
peek_next_restrictions) {
|
auto& adaptation_limits = adaptation_limits_by_resources_[reason_resource];
|
||||||
adaptation_limits_by_resources_[reason_resource] = peek_next_restrictions;
|
if (adaptation_limits == restrictions) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
adaptation_limits = restrictions;
|
||||||
|
|
||||||
std::map<rtc::scoped_refptr<Resource>, VideoAdaptationCounters> limitations;
|
std::map<rtc::scoped_refptr<Resource>, VideoAdaptationCounters> limitations;
|
||||||
for (const auto& p : adaptation_limits_by_resources_) {
|
for (const auto& p : adaptation_limits_by_resources_) {
|
||||||
limitations.insert(std::make_pair(p.first, p.second.adaptation_counters));
|
limitations.insert(std::make_pair(p.first, p.second.adaptation_counters));
|
||||||
}
|
}
|
||||||
|
for (auto limitations_listener : resource_limitations_listeners_) {
|
||||||
for (auto restrictions_listener : restrictions_listeners_) {
|
limitations_listener->OnResourceLimitationChanged(reason_resource,
|
||||||
restrictions_listener->OnResourceLimitationChanged(reason_resource,
|
|
||||||
limitations);
|
limitations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -539,8 +507,8 @@ void ResourceAdaptationProcessor::
|
||||||
MaybeUpdateResourceLimitationsOnResourceRemoval(
|
MaybeUpdateResourceLimitationsOnResourceRemoval(
|
||||||
VideoStreamAdapter::RestrictionsWithCounters removed_limitations) {
|
VideoStreamAdapter::RestrictionsWithCounters removed_limitations) {
|
||||||
if (adaptation_limits_by_resources_.empty()) {
|
if (adaptation_limits_by_resources_.empty()) {
|
||||||
// Only the resource being removed was adapted so reset restrictions.
|
// Only the resource being removed was adapted so clear restrictions.
|
||||||
ResetVideoSourceRestrictions();
|
stream_adapter_->ClearRestrictions();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,20 +526,37 @@ void ResourceAdaptationProcessor::
|
||||||
Adaptation adapt_to = stream_adapter_->GetAdaptationTo(
|
Adaptation adapt_to = stream_adapter_->GetAdaptationTo(
|
||||||
most_limited.adaptation_counters, most_limited.restrictions);
|
most_limited.adaptation_counters, most_limited.restrictions);
|
||||||
RTC_DCHECK_EQ(adapt_to.status(), Adaptation::Status::kValid);
|
RTC_DCHECK_EQ(adapt_to.status(), Adaptation::Status::kValid);
|
||||||
stream_adapter_->ApplyAdaptation(adapt_to);
|
stream_adapter_->ApplyAdaptation(adapt_to, nullptr);
|
||||||
|
|
||||||
RTC_LOG(INFO) << "Most limited resource removed. Restoring restrictions to "
|
|
||||||
"next most limited restrictions: "
|
|
||||||
<< most_limited.restrictions.ToString() << " with counters "
|
|
||||||
<< most_limited.adaptation_counters.ToString();
|
|
||||||
|
|
||||||
MaybeUpdateVideoSourceRestrictions(nullptr);
|
|
||||||
auto input_state = input_state_provider_->InputState();
|
auto input_state = input_state_provider_->InputState();
|
||||||
for (auto* adaptation_listener : adaptation_listeners_) {
|
for (auto* adaptation_listener : adaptation_listeners_) {
|
||||||
adaptation_listener->OnAdaptationApplied(
|
adaptation_listener->OnAdaptationApplied(
|
||||||
input_state, removed_limitations.restrictions,
|
input_state, removed_limitations.restrictions,
|
||||||
most_limited.restrictions, nullptr);
|
most_limited.restrictions, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RTC_LOG(INFO) << "Most limited resource removed. Restoring restrictions to "
|
||||||
|
"next most limited restrictions: "
|
||||||
|
<< most_limited.restrictions.ToString() << " with counters "
|
||||||
|
<< most_limited.adaptation_counters.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceAdaptationProcessor::OnVideoSourceRestrictionsUpdated(
|
||||||
|
VideoSourceRestrictions restrictions,
|
||||||
|
const VideoAdaptationCounters& adaptation_counters,
|
||||||
|
rtc::scoped_refptr<Resource> reason,
|
||||||
|
const VideoSourceRestrictions& unfiltered_restrictions) {
|
||||||
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
|
if (reason) {
|
||||||
|
UpdateResourceLimitations(reason,
|
||||||
|
{unfiltered_restrictions, adaptation_counters});
|
||||||
|
} else if (adaptation_counters.Total() == 0) {
|
||||||
|
// Adaptations are cleared.
|
||||||
|
adaptation_limits_by_resources_.clear();
|
||||||
|
previous_mitigation_results_.clear();
|
||||||
|
for (auto limitations_listener : resource_limitations_listeners_) {
|
||||||
|
limitations_listener->OnResourceLimitationChanged(nullptr, {});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
|
@ -51,11 +51,13 @@ namespace webrtc {
|
||||||
// any thread but MUST subsequently be used and destroyed on a single sequence,
|
// any thread but MUST subsequently be used and destroyed on a single sequence,
|
||||||
// i.e. the "resource adaptation task queue".
|
// i.e. the "resource adaptation task queue".
|
||||||
class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
|
class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
|
||||||
|
public VideoSourceRestrictionsListener,
|
||||||
public ResourceListener {
|
public ResourceListener {
|
||||||
public:
|
public:
|
||||||
ResourceAdaptationProcessor(
|
ResourceAdaptationProcessor(
|
||||||
VideoStreamInputStateProvider* input_state_provider,
|
VideoStreamInputStateProvider* input_state_provider,
|
||||||
VideoStreamEncoderObserver* encoder_stats_observer);
|
VideoStreamEncoderObserver* encoder_stats_observer,
|
||||||
|
VideoStreamAdapter* video_stream_adapter);
|
||||||
~ResourceAdaptationProcessor() override;
|
~ResourceAdaptationProcessor() override;
|
||||||
|
|
||||||
void SetResourceAdaptationQueue(
|
void SetResourceAdaptationQueue(
|
||||||
|
@ -65,10 +67,10 @@ class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
|
||||||
DegradationPreference degradation_preference() const override;
|
DegradationPreference degradation_preference() const override;
|
||||||
DegradationPreference effective_degradation_preference() const override;
|
DegradationPreference effective_degradation_preference() const override;
|
||||||
|
|
||||||
void AddRestrictionsListener(
|
void AddResourceLimitationsListener(
|
||||||
VideoSourceRestrictionsListener* restrictions_listener) override;
|
ResourceLimitationsListener* limitations_listener) override;
|
||||||
void RemoveRestrictionsListener(
|
void RemoveResourceLimitationsListener(
|
||||||
VideoSourceRestrictionsListener* restrictions_listener) override;
|
ResourceLimitationsListener* limitations_listener) override;
|
||||||
void AddResource(rtc::scoped_refptr<Resource> resource) override;
|
void AddResource(rtc::scoped_refptr<Resource> resource) override;
|
||||||
std::vector<rtc::scoped_refptr<Resource>> GetResources() const override;
|
std::vector<rtc::scoped_refptr<Resource>> GetResources() const override;
|
||||||
void RemoveResource(rtc::scoped_refptr<Resource> resource) override;
|
void RemoveResource(rtc::scoped_refptr<Resource> resource) override;
|
||||||
|
@ -83,13 +85,19 @@ class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
|
||||||
void SetDegradationPreference(
|
void SetDegradationPreference(
|
||||||
DegradationPreference degradation_preference) override;
|
DegradationPreference degradation_preference) override;
|
||||||
void SetIsScreenshare(bool is_screenshare) override;
|
void SetIsScreenshare(bool is_screenshare) override;
|
||||||
void ResetVideoSourceRestrictions() override;
|
|
||||||
|
|
||||||
// ResourceListener implementation.
|
// ResourceListener implementation.
|
||||||
// Triggers OnResourceUnderuse() or OnResourceOveruse().
|
// Triggers OnResourceUnderuse() or OnResourceOveruse().
|
||||||
void OnResourceUsageStateMeasured(rtc::scoped_refptr<Resource> resource,
|
void OnResourceUsageStateMeasured(rtc::scoped_refptr<Resource> resource,
|
||||||
ResourceUsageState usage_state) override;
|
ResourceUsageState usage_state) override;
|
||||||
|
|
||||||
|
// VideoSourceRestrictionsListener implementation.
|
||||||
|
void OnVideoSourceRestrictionsUpdated(
|
||||||
|
VideoSourceRestrictions restrictions,
|
||||||
|
const VideoAdaptationCounters& adaptation_counters,
|
||||||
|
rtc::scoped_refptr<Resource> reason,
|
||||||
|
const VideoSourceRestrictions& unfiltered_restrictions) 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.
|
||||||
// TODO(hbos): Can we get rid of this?
|
// TODO(hbos): Can we get rid of this?
|
||||||
|
@ -149,9 +157,6 @@ class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
|
||||||
// Needs to be invoked any time |degradation_preference_| or |is_screenshare_|
|
// Needs to be invoked any time |degradation_preference_| or |is_screenshare_|
|
||||||
// changes to ensure |effective_degradation_preference_| is up-to-date.
|
// changes to ensure |effective_degradation_preference_| is up-to-date.
|
||||||
void MaybeUpdateEffectiveDegradationPreference();
|
void MaybeUpdateEffectiveDegradationPreference();
|
||||||
// If the filtered source restrictions are different than
|
|
||||||
// |last_reported_source_restrictions_|, inform the listeners.
|
|
||||||
void MaybeUpdateVideoSourceRestrictions(rtc::scoped_refptr<Resource> reason);
|
|
||||||
|
|
||||||
void UpdateResourceLimitations(
|
void UpdateResourceLimitations(
|
||||||
rtc::scoped_refptr<Resource> reason_resource,
|
rtc::scoped_refptr<Resource> reason_resource,
|
||||||
|
@ -178,7 +183,7 @@ class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
|
||||||
RTC_GUARDED_BY(resource_adaptation_queue_);
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
VideoStreamEncoderObserver* const encoder_stats_observer_
|
VideoStreamEncoderObserver* const encoder_stats_observer_
|
||||||
RTC_GUARDED_BY(resource_adaptation_queue_);
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
std::vector<VideoSourceRestrictionsListener*> restrictions_listeners_
|
std::vector<ResourceLimitationsListener*> resource_limitations_listeners_
|
||||||
RTC_GUARDED_BY(resource_adaptation_queue_);
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
std::vector<rtc::scoped_refptr<Resource>> resources_
|
std::vector<rtc::scoped_refptr<Resource>> resources_
|
||||||
RTC_GUARDED_BY(resource_adaptation_queue_);
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
|
@ -198,7 +203,7 @@ class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
|
||||||
RTC_GUARDED_BY(resource_adaptation_queue_);
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
bool is_screenshare_ RTC_GUARDED_BY(resource_adaptation_queue_);
|
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_
|
VideoStreamAdapter* const stream_adapter_
|
||||||
RTC_GUARDED_BY(resource_adaptation_queue_);
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
VideoSourceRestrictions last_reported_source_restrictions_
|
VideoSourceRestrictions last_reported_source_restrictions_
|
||||||
RTC_GUARDED_BY(resource_adaptation_queue_);
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
|
|
|
@ -12,9 +12,9 @@
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
VideoSourceRestrictionsListener::~VideoSourceRestrictionsListener() = default;
|
|
||||||
|
|
||||||
ResourceAdaptationProcessorInterface::~ResourceAdaptationProcessorInterface() =
|
ResourceAdaptationProcessorInterface::~ResourceAdaptationProcessorInterface() =
|
||||||
default;
|
default;
|
||||||
|
|
||||||
|
ResourceLimitationsListener::~ResourceLimitationsListener() = default;
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
|
@ -28,26 +28,16 @@
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
// The listener is responsible for carrying out the reconfiguration of the video
|
class ResourceLimitationsListener {
|
||||||
// source such that the VideoSourceRestrictions are fulfilled.
|
|
||||||
class VideoSourceRestrictionsListener {
|
|
||||||
public:
|
public:
|
||||||
virtual ~VideoSourceRestrictionsListener();
|
virtual ~ResourceLimitationsListener();
|
||||||
|
|
||||||
// The |restrictions| are filtered by degradation preference but not the
|
|
||||||
// |adaptation_counters|, which are currently only reported for legacy stats
|
|
||||||
// calculation purposes.
|
|
||||||
virtual void OnVideoSourceRestrictionsUpdated(
|
|
||||||
VideoSourceRestrictions restrictions,
|
|
||||||
const VideoAdaptationCounters& adaptation_counters,
|
|
||||||
rtc::scoped_refptr<Resource> reason) = 0;
|
|
||||||
|
|
||||||
// The limitations on a resource were changed. This does not mean the current
|
// The limitations on a resource were changed. This does not mean the current
|
||||||
// video restrictions have changed.
|
// video restrictions have changed.
|
||||||
virtual void OnResourceLimitationChanged(
|
virtual void OnResourceLimitationChanged(
|
||||||
rtc::scoped_refptr<Resource> resource,
|
rtc::scoped_refptr<Resource> resource,
|
||||||
const std::map<rtc::scoped_refptr<Resource>, VideoAdaptationCounters>&
|
const std::map<rtc::scoped_refptr<Resource>, VideoAdaptationCounters>&
|
||||||
resource_limitations) {}
|
resource_limitations) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The Resource Adaptation Processor is responsible for reacting to resource
|
// The Resource Adaptation Processor is responsible for reacting to resource
|
||||||
|
@ -74,10 +64,10 @@ class ResourceAdaptationProcessorInterface {
|
||||||
// with AddResource() and RemoveResource() instead. When the processor is
|
// with AddResource() and RemoveResource() instead. When the processor is
|
||||||
// multi-stream aware, stream-specific resouces will get added and removed
|
// multi-stream aware, stream-specific resouces will get added and removed
|
||||||
// over time.
|
// over time.
|
||||||
virtual void AddRestrictionsListener(
|
virtual void AddResourceLimitationsListener(
|
||||||
VideoSourceRestrictionsListener* restrictions_listener) = 0;
|
ResourceLimitationsListener* limitations_listener) = 0;
|
||||||
virtual void RemoveRestrictionsListener(
|
virtual void RemoveResourceLimitationsListener(
|
||||||
VideoSourceRestrictionsListener* restrictions_listener) = 0;
|
ResourceLimitationsListener* limitations_listener) = 0;
|
||||||
virtual void AddResource(rtc::scoped_refptr<Resource> resource) = 0;
|
virtual void AddResource(rtc::scoped_refptr<Resource> resource) = 0;
|
||||||
virtual std::vector<rtc::scoped_refptr<Resource>> GetResources() const = 0;
|
virtual std::vector<rtc::scoped_refptr<Resource>> GetResources() const = 0;
|
||||||
virtual void RemoveResource(rtc::scoped_refptr<Resource> resource) = 0;
|
virtual void RemoveResource(rtc::scoped_refptr<Resource> resource) = 0;
|
||||||
|
@ -93,7 +83,6 @@ class ResourceAdaptationProcessorInterface {
|
||||||
virtual void SetDegradationPreference(
|
virtual void SetDegradationPreference(
|
||||||
DegradationPreference degradation_preference) = 0;
|
DegradationPreference degradation_preference) = 0;
|
||||||
virtual void SetIsScreenshare(bool is_screenshare) = 0;
|
virtual void SetIsScreenshare(bool is_screenshare) = 0;
|
||||||
virtual void ResetVideoSourceRestrictions() = 0;
|
|
||||||
|
|
||||||
// May trigger one or more adaptations. It is meant to reduce resolution -
|
// May trigger one or more adaptations. It is meant to reduce resolution -
|
||||||
// useful if a frame was dropped due to its size - however, the implementation
|
// useful if a frame was dropped due to its size - however, the implementation
|
||||||
|
|
|
@ -65,7 +65,8 @@ class VideoSourceRestrictionsListenerForTesting
|
||||||
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,
|
||||||
|
const VideoSourceRestrictions& unfiltered_restrictions) override {
|
||||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
||||||
++restrictions_updated_count_;
|
++restrictions_updated_count_;
|
||||||
restrictions_ = restrictions;
|
restrictions_ = restrictions;
|
||||||
|
@ -91,11 +92,13 @@ class ResourceAdaptationProcessorTest : public ::testing::Test {
|
||||||
other_resource_(FakeResource::Create("OtherFakeResource")),
|
other_resource_(FakeResource::Create("OtherFakeResource")),
|
||||||
adaptation_constraint_("FakeAdaptationConstraint"),
|
adaptation_constraint_("FakeAdaptationConstraint"),
|
||||||
adaptation_listener_(),
|
adaptation_listener_(),
|
||||||
|
video_stream_adapter_(std::make_unique<VideoStreamAdapter>()),
|
||||||
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_,
|
||||||
|
video_stream_adapter_.get())) {
|
||||||
processor_->SetResourceAdaptationQueue(TaskQueueBase::Current());
|
processor_->SetResourceAdaptationQueue(TaskQueueBase::Current());
|
||||||
processor_->AddRestrictionsListener(&restrictions_listener_);
|
video_stream_adapter_->AddRestrictionsListener(&restrictions_listener_);
|
||||||
processor_->AddResource(resource_);
|
processor_->AddResource(resource_);
|
||||||
processor_->AddResource(other_resource_);
|
processor_->AddResource(other_resource_);
|
||||||
processor_->AddAdaptationConstraint(&adaptation_constraint_);
|
processor_->AddAdaptationConstraint(&adaptation_constraint_);
|
||||||
|
@ -122,7 +125,6 @@ class ResourceAdaptationProcessorTest : public ::testing::Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DestroyProcessor() {
|
void DestroyProcessor() {
|
||||||
processor_->RemoveRestrictionsListener(&restrictions_listener_);
|
|
||||||
if (resource_) {
|
if (resource_) {
|
||||||
processor_->RemoveResource(resource_);
|
processor_->RemoveResource(resource_);
|
||||||
}
|
}
|
||||||
|
@ -131,6 +133,7 @@ class ResourceAdaptationProcessorTest : public ::testing::Test {
|
||||||
}
|
}
|
||||||
processor_->RemoveAdaptationConstraint(&adaptation_constraint_);
|
processor_->RemoveAdaptationConstraint(&adaptation_constraint_);
|
||||||
processor_->RemoveAdaptationListener(&adaptation_listener_);
|
processor_->RemoveAdaptationListener(&adaptation_listener_);
|
||||||
|
video_stream_adapter_->RemoveRestrictionsListener(&restrictions_listener_);
|
||||||
processor_.reset();
|
processor_.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,6 +148,7 @@ class ResourceAdaptationProcessorTest : public ::testing::Test {
|
||||||
rtc::scoped_refptr<FakeResource> other_resource_;
|
rtc::scoped_refptr<FakeResource> other_resource_;
|
||||||
FakeAdaptationConstraint adaptation_constraint_;
|
FakeAdaptationConstraint adaptation_constraint_;
|
||||||
FakeAdaptationListener adaptation_listener_;
|
FakeAdaptationListener adaptation_listener_;
|
||||||
|
std::unique_ptr<VideoStreamAdapter> video_stream_adapter_;
|
||||||
std::unique_ptr<ResourceAdaptationProcessor> processor_;
|
std::unique_ptr<ResourceAdaptationProcessor> processor_;
|
||||||
VideoSourceRestrictionsListenerForTesting restrictions_listener_;
|
VideoSourceRestrictionsListenerForTesting restrictions_listener_;
|
||||||
};
|
};
|
||||||
|
@ -290,7 +294,7 @@ TEST_F(ResourceAdaptationProcessorTest,
|
||||||
resource_->SetUsageState(ResourceUsageState::kOveruse);
|
resource_->SetUsageState(ResourceUsageState::kOveruse);
|
||||||
EXPECT_EQ(1u, restrictions_listener_.restrictions_updated_count());
|
EXPECT_EQ(1u, restrictions_listener_.restrictions_updated_count());
|
||||||
|
|
||||||
processor_->ResetVideoSourceRestrictions();
|
video_stream_adapter_->ClearRestrictions();
|
||||||
EXPECT_EQ(0, restrictions_listener_.adaptation_counters().Total());
|
EXPECT_EQ(0, restrictions_listener_.adaptation_counters().Total());
|
||||||
other_resource_->SetUsageState(ResourceUsageState::kOveruse);
|
other_resource_->SetUsageState(ResourceUsageState::kOveruse);
|
||||||
EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
|
EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
|
||||||
|
|
|
@ -61,6 +61,8 @@ int GetLowerResolutionThan(int pixel_count) {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
VideoSourceRestrictionsListener::~VideoSourceRestrictionsListener() = default;
|
||||||
|
|
||||||
VideoSourceRestrictions FilterRestrictionsByDegradationPreference(
|
VideoSourceRestrictions FilterRestrictionsByDegradationPreference(
|
||||||
VideoSourceRestrictions source_restrictions,
|
VideoSourceRestrictions source_restrictions,
|
||||||
DegradationPreference degradation_preference) {
|
DegradationPreference degradation_preference) {
|
||||||
|
@ -82,28 +84,6 @@ VideoSourceRestrictions FilterRestrictionsByDegradationPreference(
|
||||||
return source_restrictions;
|
return source_restrictions;
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoAdaptationCounters FilterVideoAdaptationCountersByDegradationPreference(
|
|
||||||
VideoAdaptationCounters counters,
|
|
||||||
DegradationPreference degradation_preference) {
|
|
||||||
switch (degradation_preference) {
|
|
||||||
case DegradationPreference::BALANCED:
|
|
||||||
break;
|
|
||||||
case DegradationPreference::MAINTAIN_FRAMERATE:
|
|
||||||
counters.fps_adaptations = 0;
|
|
||||||
break;
|
|
||||||
case DegradationPreference::MAINTAIN_RESOLUTION:
|
|
||||||
counters.resolution_adaptations = 0;
|
|
||||||
break;
|
|
||||||
case DegradationPreference::DISABLED:
|
|
||||||
counters.resolution_adaptations = 0;
|
|
||||||
counters.fps_adaptations = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
RTC_NOTREACHED();
|
|
||||||
}
|
|
||||||
return counters;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(hbos): Use absl::optional<> instead?
|
// TODO(hbos): Use absl::optional<> instead?
|
||||||
int GetHigherResolutionThan(int pixel_count) {
|
int GetHigherResolutionThan(int pixel_count) {
|
||||||
return pixel_count != std::numeric_limits<int>::max()
|
return pixel_count != std::numeric_limits<int>::max()
|
||||||
|
@ -355,40 +335,73 @@ VideoStreamAdapter::VideoStreamAdapter()
|
||||||
adaptation_validation_id_(0),
|
adaptation_validation_id_(0),
|
||||||
degradation_preference_(DegradationPreference::DISABLED),
|
degradation_preference_(DegradationPreference::DISABLED),
|
||||||
input_state_(),
|
input_state_(),
|
||||||
last_adaptation_request_(absl::nullopt) {}
|
last_adaptation_request_(absl::nullopt),
|
||||||
|
last_video_source_restrictions_() {
|
||||||
|
sequence_checker_.Detach();
|
||||||
|
}
|
||||||
|
|
||||||
VideoStreamAdapter::~VideoStreamAdapter() {}
|
VideoStreamAdapter::~VideoStreamAdapter() {}
|
||||||
|
|
||||||
VideoSourceRestrictions VideoStreamAdapter::source_restrictions() const {
|
VideoSourceRestrictions VideoStreamAdapter::source_restrictions() const {
|
||||||
|
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
||||||
return source_restrictor_->source_restrictions();
|
return source_restrictor_->source_restrictions();
|
||||||
}
|
}
|
||||||
|
|
||||||
const VideoAdaptationCounters& VideoStreamAdapter::adaptation_counters() const {
|
const VideoAdaptationCounters& VideoStreamAdapter::adaptation_counters() const {
|
||||||
|
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
||||||
return source_restrictor_->adaptation_counters();
|
return source_restrictor_->adaptation_counters();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoStreamAdapter::ClearRestrictions() {
|
void VideoStreamAdapter::ClearRestrictions() {
|
||||||
|
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
||||||
// Invalidate any previously returned Adaptation.
|
// Invalidate any previously returned Adaptation.
|
||||||
|
RTC_LOG(INFO) << "Resetting restrictions";
|
||||||
++adaptation_validation_id_;
|
++adaptation_validation_id_;
|
||||||
source_restrictor_->ClearRestrictions();
|
source_restrictor_->ClearRestrictions();
|
||||||
last_adaptation_request_.reset();
|
last_adaptation_request_.reset();
|
||||||
|
BroadcastVideoRestrictionsUpdate(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoStreamAdapter::AddRestrictionsListener(
|
||||||
|
VideoSourceRestrictionsListener* restrictions_listener) {
|
||||||
|
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
||||||
|
RTC_DCHECK(std::find(restrictions_listeners_.begin(),
|
||||||
|
restrictions_listeners_.end(),
|
||||||
|
restrictions_listener) == restrictions_listeners_.end());
|
||||||
|
restrictions_listeners_.push_back(restrictions_listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoStreamAdapter::RemoveRestrictionsListener(
|
||||||
|
VideoSourceRestrictionsListener* restrictions_listener) {
|
||||||
|
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
||||||
|
auto it = std::find(restrictions_listeners_.begin(),
|
||||||
|
restrictions_listeners_.end(), restrictions_listener);
|
||||||
|
RTC_DCHECK(it != restrictions_listeners_.end());
|
||||||
|
restrictions_listeners_.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoStreamAdapter::SetDegradationPreference(
|
void VideoStreamAdapter::SetDegradationPreference(
|
||||||
DegradationPreference degradation_preference) {
|
DegradationPreference degradation_preference) {
|
||||||
|
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
||||||
if (degradation_preference_ == degradation_preference)
|
if (degradation_preference_ == degradation_preference)
|
||||||
return;
|
return;
|
||||||
// Invalidate any previously returned Adaptation.
|
// Invalidate any previously returned Adaptation.
|
||||||
++adaptation_validation_id_;
|
++adaptation_validation_id_;
|
||||||
if (degradation_preference == DegradationPreference::BALANCED ||
|
bool balanced_switch =
|
||||||
degradation_preference_ == DegradationPreference::BALANCED) {
|
degradation_preference == DegradationPreference::BALANCED ||
|
||||||
ClearRestrictions();
|
degradation_preference_ == DegradationPreference::BALANCED;
|
||||||
}
|
|
||||||
degradation_preference_ = degradation_preference;
|
degradation_preference_ = degradation_preference;
|
||||||
|
if (balanced_switch) {
|
||||||
|
// ClearRestrictions() calls BroadcastVideoRestrictionsUpdate(nullptr).
|
||||||
|
ClearRestrictions();
|
||||||
|
} else {
|
||||||
|
BroadcastVideoRestrictionsUpdate(nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoStreamAdapter::SetInput(VideoStreamInputState input_state) {
|
void VideoStreamAdapter::SetInput(VideoStreamInputState input_state) {
|
||||||
// Invalidate any previously returned Adaptation.
|
// Invalidate any previously returned Adaptation.
|
||||||
|
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
||||||
++adaptation_validation_id_;
|
++adaptation_validation_id_;
|
||||||
input_state_ = input_state;
|
input_state_ = input_state;
|
||||||
source_restrictor_->set_min_pixels_per_frame(
|
source_restrictor_->set_min_pixels_per_frame(
|
||||||
|
@ -396,6 +409,7 @@ void VideoStreamAdapter::SetInput(VideoStreamInputState input_state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Adaptation VideoStreamAdapter::GetAdaptationUp() const {
|
Adaptation VideoStreamAdapter::GetAdaptationUp() const {
|
||||||
|
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
||||||
RTC_DCHECK_NE(degradation_preference_, DegradationPreference::DISABLED);
|
RTC_DCHECK_NE(degradation_preference_, DegradationPreference::DISABLED);
|
||||||
RTC_DCHECK(input_state_.HasInputFrameSizeAndFramesPerSecond());
|
RTC_DCHECK(input_state_.HasInputFrameSizeAndFramesPerSecond());
|
||||||
// Don't adapt if we're awaiting a previous adaptation to have an effect.
|
// Don't adapt if we're awaiting a previous adaptation to have an effect.
|
||||||
|
@ -469,6 +483,7 @@ Adaptation VideoStreamAdapter::GetAdaptationUp() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
Adaptation VideoStreamAdapter::GetAdaptationDown() const {
|
Adaptation VideoStreamAdapter::GetAdaptationDown() const {
|
||||||
|
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
||||||
RTC_DCHECK_NE(degradation_preference_, DegradationPreference::DISABLED);
|
RTC_DCHECK_NE(degradation_preference_, DegradationPreference::DISABLED);
|
||||||
RTC_DCHECK(input_state_.HasInputFrameSizeAndFramesPerSecond());
|
RTC_DCHECK(input_state_.HasInputFrameSizeAndFramesPerSecond());
|
||||||
// Don't adapt if we're awaiting a previous adaptation to have an effect or
|
// Don't adapt if we're awaiting a previous adaptation to have an effect or
|
||||||
|
@ -537,11 +552,13 @@ Adaptation VideoStreamAdapter::GetAdaptationDown() const {
|
||||||
|
|
||||||
VideoStreamAdapter::RestrictionsWithCounters
|
VideoStreamAdapter::RestrictionsWithCounters
|
||||||
VideoStreamAdapter::PeekNextRestrictions(const Adaptation& adaptation) const {
|
VideoStreamAdapter::PeekNextRestrictions(const Adaptation& adaptation) const {
|
||||||
|
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
||||||
RTC_DCHECK_EQ(adaptation.validation_id_, adaptation_validation_id_);
|
RTC_DCHECK_EQ(adaptation.validation_id_, adaptation_validation_id_);
|
||||||
RTC_LOG(LS_INFO) << "PeekNextRestrictions called";
|
RTC_LOG(LS_INFO) << "PeekNextRestrictions called";
|
||||||
if (adaptation.status() != Adaptation::Status::kValid)
|
if (adaptation.status() != Adaptation::Status::kValid) {
|
||||||
return {source_restrictor_->source_restrictions(),
|
return {source_restrictor_->source_restrictions(),
|
||||||
source_restrictor_->adaptation_counters()};
|
source_restrictor_->adaptation_counters()};
|
||||||
|
}
|
||||||
VideoSourceRestrictor restrictor_copy = *source_restrictor_;
|
VideoSourceRestrictor restrictor_copy = *source_restrictor_;
|
||||||
restrictor_copy.ApplyAdaptationStep(adaptation.step(),
|
restrictor_copy.ApplyAdaptationStep(adaptation.step(),
|
||||||
degradation_preference_);
|
degradation_preference_);
|
||||||
|
@ -549,7 +566,10 @@ VideoStreamAdapter::PeekNextRestrictions(const Adaptation& adaptation) const {
|
||||||
restrictor_copy.adaptation_counters()};
|
restrictor_copy.adaptation_counters()};
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoStreamAdapter::ApplyAdaptation(const Adaptation& adaptation) {
|
void VideoStreamAdapter::ApplyAdaptation(
|
||||||
|
const Adaptation& adaptation,
|
||||||
|
rtc::scoped_refptr<Resource> resource) {
|
||||||
|
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
||||||
RTC_DCHECK_EQ(adaptation.validation_id_, adaptation_validation_id_);
|
RTC_DCHECK_EQ(adaptation.validation_id_, adaptation_validation_id_);
|
||||||
RTC_LOG(LS_INFO) << "ApplyAdaptation called";
|
RTC_LOG(LS_INFO) << "ApplyAdaptation called";
|
||||||
if (adaptation.status() != Adaptation::Status::kValid)
|
if (adaptation.status() != Adaptation::Status::kValid)
|
||||||
|
@ -562,14 +582,33 @@ void VideoStreamAdapter::ApplyAdaptation(const Adaptation& adaptation) {
|
||||||
// Adapt!
|
// Adapt!
|
||||||
source_restrictor_->ApplyAdaptationStep(adaptation.step(),
|
source_restrictor_->ApplyAdaptationStep(adaptation.step(),
|
||||||
degradation_preference_);
|
degradation_preference_);
|
||||||
|
BroadcastVideoRestrictionsUpdate(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
Adaptation VideoStreamAdapter::GetAdaptationTo(
|
Adaptation VideoStreamAdapter::GetAdaptationTo(
|
||||||
const VideoAdaptationCounters& counters,
|
const VideoAdaptationCounters& counters,
|
||||||
const VideoSourceRestrictions& restrictions) const {
|
const VideoSourceRestrictions& restrictions) const {
|
||||||
// Adapts up/down from the current levels so counters are equal.
|
// Adapts up/down from the current levels so counters are equal.
|
||||||
|
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
||||||
return Adaptation(adaptation_validation_id_,
|
return Adaptation(adaptation_validation_id_,
|
||||||
Adaptation::Step(restrictions, counters));
|
Adaptation::Step(restrictions, counters));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoStreamAdapter::BroadcastVideoRestrictionsUpdate(
|
||||||
|
const rtc::scoped_refptr<Resource>& resource) {
|
||||||
|
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
||||||
|
VideoSourceRestrictions filtered = FilterRestrictionsByDegradationPreference(
|
||||||
|
source_restrictions(), degradation_preference_);
|
||||||
|
if (last_filtered_restrictions_ == filtered) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (auto* restrictions_listener : restrictions_listeners_) {
|
||||||
|
restrictions_listener->OnVideoSourceRestrictionsUpdated(
|
||||||
|
filtered, source_restrictor_->adaptation_counters(), resource,
|
||||||
|
source_restrictions());
|
||||||
|
}
|
||||||
|
last_video_source_restrictions_ = source_restrictor_->source_restrictions();
|
||||||
|
last_filtered_restrictions_ = filtered;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#define CALL_ADAPTATION_VIDEO_STREAM_ADAPTER_H_
|
#define CALL_ADAPTATION_VIDEO_STREAM_ADAPTER_H_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "absl/types/optional.h"
|
#include "absl/types/optional.h"
|
||||||
#include "api/adaptation/resource.h"
|
#include "api/adaptation/resource.h"
|
||||||
|
@ -24,6 +25,22 @@
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
// The listener is responsible for carrying out the reconfiguration of the video
|
||||||
|
// source such that the VideoSourceRestrictions are fulfilled.
|
||||||
|
class VideoSourceRestrictionsListener {
|
||||||
|
public:
|
||||||
|
virtual ~VideoSourceRestrictionsListener();
|
||||||
|
|
||||||
|
// The |restrictions| are filtered by degradation preference but not the
|
||||||
|
// |adaptation_counters|, which are currently only reported for legacy stats
|
||||||
|
// calculation purposes.
|
||||||
|
virtual void OnVideoSourceRestrictionsUpdated(
|
||||||
|
VideoSourceRestrictions restrictions,
|
||||||
|
const VideoAdaptationCounters& adaptation_counters,
|
||||||
|
rtc::scoped_refptr<Resource> reason,
|
||||||
|
const VideoSourceRestrictions& unfiltered_restrictions) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class VideoStreamAdapter;
|
class VideoStreamAdapter;
|
||||||
|
|
||||||
extern const int kMinFrameRateFps;
|
extern const int kMinFrameRateFps;
|
||||||
|
@ -32,10 +49,6 @@ VideoSourceRestrictions FilterRestrictionsByDegradationPreference(
|
||||||
VideoSourceRestrictions source_restrictions,
|
VideoSourceRestrictions source_restrictions,
|
||||||
DegradationPreference degradation_preference);
|
DegradationPreference degradation_preference);
|
||||||
|
|
||||||
VideoAdaptationCounters FilterVideoAdaptationCountersByDegradationPreference(
|
|
||||||
VideoAdaptationCounters counters,
|
|
||||||
DegradationPreference degradation_preference);
|
|
||||||
|
|
||||||
int GetHigherResolutionThan(int pixel_count);
|
int GetHigherResolutionThan(int pixel_count);
|
||||||
|
|
||||||
// Represents one step that the VideoStreamAdapter can take when adapting the
|
// Represents one step that the VideoStreamAdapter can take when adapting the
|
||||||
|
@ -128,6 +141,11 @@ class VideoStreamAdapter {
|
||||||
const VideoAdaptationCounters& adaptation_counters() const;
|
const VideoAdaptationCounters& adaptation_counters() const;
|
||||||
void ClearRestrictions();
|
void ClearRestrictions();
|
||||||
|
|
||||||
|
void AddRestrictionsListener(
|
||||||
|
VideoSourceRestrictionsListener* restrictions_listener);
|
||||||
|
void RemoveRestrictionsListener(
|
||||||
|
VideoSourceRestrictionsListener* restrictions_listener);
|
||||||
|
|
||||||
// TODO(hbos): Setting the degradation preference should not clear
|
// TODO(hbos): Setting the degradation preference should not clear
|
||||||
// restrictions! This is not defined in the spec and is unexpected, there is a
|
// restrictions! This is not defined in the spec and is unexpected, there is a
|
||||||
// tiny risk that people would discover and rely on this behavior.
|
// tiny risk that people would discover and rely on this behavior.
|
||||||
|
@ -145,6 +163,15 @@ class VideoStreamAdapter {
|
||||||
struct RestrictionsWithCounters {
|
struct RestrictionsWithCounters {
|
||||||
VideoSourceRestrictions restrictions;
|
VideoSourceRestrictions restrictions;
|
||||||
VideoAdaptationCounters adaptation_counters;
|
VideoAdaptationCounters adaptation_counters;
|
||||||
|
|
||||||
|
bool operator==(const RestrictionsWithCounters& other) {
|
||||||
|
return restrictions == other.restrictions &&
|
||||||
|
adaptation_counters == other.adaptation_counters;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const RestrictionsWithCounters& other) {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns the restrictions that result from applying the adaptation, without
|
// Returns the restrictions that result from applying the adaptation, without
|
||||||
|
@ -152,12 +179,19 @@ class VideoStreamAdapter {
|
||||||
// are returned.
|
// are returned.
|
||||||
RestrictionsWithCounters PeekNextRestrictions(
|
RestrictionsWithCounters PeekNextRestrictions(
|
||||||
const Adaptation& adaptation) const;
|
const Adaptation& adaptation) const;
|
||||||
// Updates source_restrictions() based according to the Adaptation.
|
// Updates source_restrictions() based according to the Adaptation. These
|
||||||
void ApplyAdaptation(const Adaptation& adaptation);
|
// adaptations will be attributed to the Resource |resource| if the |resource|
|
||||||
|
// is non-null. If |resource| is null the adaptation will be changed in
|
||||||
|
// general, and thus could be adapted up in the future from other resources.
|
||||||
|
void ApplyAdaptation(const Adaptation& adaptation,
|
||||||
|
rtc::scoped_refptr<Resource> resource);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class VideoSourceRestrictor;
|
class VideoSourceRestrictor;
|
||||||
|
|
||||||
|
void BroadcastVideoRestrictionsUpdate(
|
||||||
|
const rtc::scoped_refptr<Resource>& resource);
|
||||||
|
|
||||||
// The input frame rate and resolution at the time of an adaptation in the
|
// The input frame rate and resolution at the time of an adaptation in the
|
||||||
// direction described by |mode_| (up or down).
|
// direction described by |mode_| (up or down).
|
||||||
// TODO(https://crbug.com/webrtc/11393): Can this be renamed? Can this be
|
// TODO(https://crbug.com/webrtc/11393): Can this be renamed? Can this be
|
||||||
|
@ -171,18 +205,21 @@ class VideoStreamAdapter {
|
||||||
Adaptation::StepType step_type_;
|
Adaptation::StepType step_type_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SequenceChecker sequence_checker_ RTC_GUARDED_BY(&sequence_checker_);
|
||||||
// Owner and modifier of the VideoSourceRestriction of this stream adaptor.
|
// Owner and modifier of the VideoSourceRestriction of this stream adaptor.
|
||||||
const std::unique_ptr<VideoSourceRestrictor> source_restrictor_;
|
const std::unique_ptr<VideoSourceRestrictor> source_restrictor_
|
||||||
|
RTC_GUARDED_BY(&sequence_checker_);
|
||||||
// Decides the next adaptation target in DegradationPreference::BALANCED.
|
// Decides the next adaptation target in DegradationPreference::BALANCED.
|
||||||
const BalancedDegradationSettings balanced_settings_;
|
const BalancedDegradationSettings balanced_settings_;
|
||||||
// To guard against applying adaptations that have become invalidated, an
|
// To guard against applying adaptations that have become invalidated, an
|
||||||
// Adaptation that is applied has to have a matching validation ID.
|
// Adaptation that is applied has to have a matching validation ID.
|
||||||
int adaptation_validation_id_;
|
int adaptation_validation_id_ RTC_GUARDED_BY(&sequence_checker_);
|
||||||
// When deciding the next target up or down, different strategies are used
|
// When deciding the next target up or down, different strategies are used
|
||||||
// depending on the DegradationPreference.
|
// depending on the DegradationPreference.
|
||||||
// https://w3c.github.io/mst-content-hint/#dom-rtcdegradationpreference
|
// https://w3c.github.io/mst-content-hint/#dom-rtcdegradationpreference
|
||||||
DegradationPreference degradation_preference_;
|
DegradationPreference degradation_preference_
|
||||||
VideoStreamInputState input_state_;
|
RTC_GUARDED_BY(&sequence_checker_);
|
||||||
|
VideoStreamInputState input_state_ RTC_GUARDED_BY(&sequence_checker_);
|
||||||
// The input frame rate, resolution and adaptation direction of the last
|
// The input frame rate, resolution and adaptation direction of the last
|
||||||
// ApplyAdaptationTarget(). Used to avoid adapting twice if a recent
|
// ApplyAdaptationTarget(). Used to avoid adapting twice if a recent
|
||||||
// adaptation has not had an effect on the input frame rate or resolution yet.
|
// adaptation has not had an effect on the input frame rate or resolution yet.
|
||||||
|
@ -190,7 +227,16 @@ class VideoStreamAdapter {
|
||||||
// resources intead? If we already have adapted it seems like we should wait
|
// resources intead? If we already have adapted it seems like we should wait
|
||||||
// a while before adapting again, so that we are not acting on usage
|
// a while before adapting again, so that we are not acting on usage
|
||||||
// measurements that are made obsolete/unreliable by an "ongoing" adaptation.
|
// measurements that are made obsolete/unreliable by an "ongoing" adaptation.
|
||||||
absl::optional<AdaptationRequest> last_adaptation_request_;
|
absl::optional<AdaptationRequest> last_adaptation_request_
|
||||||
|
RTC_GUARDED_BY(&sequence_checker_);
|
||||||
|
// The previous restrictions value. Starts as unrestricted.
|
||||||
|
VideoSourceRestrictions last_video_source_restrictions_
|
||||||
|
RTC_GUARDED_BY(&sequence_checker_);
|
||||||
|
VideoSourceRestrictions last_filtered_restrictions_
|
||||||
|
RTC_GUARDED_BY(&sequence_checker_);
|
||||||
|
|
||||||
|
std::vector<VideoSourceRestrictionsListener*> restrictions_listeners_
|
||||||
|
RTC_GUARDED_BY(&sequence_checker_);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
|
@ -85,7 +85,7 @@ class FakeVideoStream {
|
||||||
// Performs ApplyAdaptation() followed by SetInput() with input pixels and
|
// Performs ApplyAdaptation() followed by SetInput() with input pixels and
|
||||||
// frame rate adjusted according to the resulting restrictions.
|
// frame rate adjusted according to the resulting restrictions.
|
||||||
void ApplyAdaptation(Adaptation adaptation) {
|
void ApplyAdaptation(Adaptation adaptation) {
|
||||||
adapter_->ApplyAdaptation(adaptation);
|
adapter_->ApplyAdaptation(adaptation, nullptr);
|
||||||
// Update input pixels and fps according to the resulting restrictions.
|
// Update input pixels and fps according to the resulting restrictions.
|
||||||
auto restrictions = adapter_->source_restrictions();
|
auto restrictions = adapter_->source_restrictions();
|
||||||
if (restrictions.target_pixels_per_frame().has_value()) {
|
if (restrictions.target_pixels_per_frame().has_value()) {
|
||||||
|
@ -110,6 +110,28 @@ class FakeVideoStream {
|
||||||
int min_pixels_per_frame_;
|
int min_pixels_per_frame_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FakeVideoStreamAdapterListner : public VideoSourceRestrictionsListener {
|
||||||
|
public:
|
||||||
|
void OnVideoSourceRestrictionsUpdated(
|
||||||
|
VideoSourceRestrictions restrictions,
|
||||||
|
const VideoAdaptationCounters& adaptation_counters,
|
||||||
|
rtc::scoped_refptr<Resource> reason,
|
||||||
|
const VideoSourceRestrictions& unfiltered_restrictions) {
|
||||||
|
calls_++;
|
||||||
|
last_restrictions_ = unfiltered_restrictions;
|
||||||
|
}
|
||||||
|
|
||||||
|
int calls() const { return calls_; }
|
||||||
|
|
||||||
|
VideoSourceRestrictions last_restrictions() const {
|
||||||
|
return last_restrictions_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int calls_ = 0;
|
||||||
|
VideoSourceRestrictions last_restrictions_;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST(VideoStreamAdapterTest, NoRestrictionsByDefault) {
|
TEST(VideoStreamAdapterTest, NoRestrictionsByDefault) {
|
||||||
|
@ -126,7 +148,7 @@ TEST(VideoStreamAdapterTest, MaintainFramerate_DecreasesPixelsToThreeFifths) {
|
||||||
Adaptation adaptation = adapter.GetAdaptationDown();
|
Adaptation adaptation = adapter.GetAdaptationDown();
|
||||||
EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
|
EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
|
||||||
EXPECT_FALSE(adaptation.min_pixel_limit_reached());
|
EXPECT_FALSE(adaptation.min_pixel_limit_reached());
|
||||||
adapter.ApplyAdaptation(adaptation);
|
adapter.ApplyAdaptation(adaptation, nullptr);
|
||||||
EXPECT_EQ(static_cast<size_t>((kInputPixels * 3) / 5),
|
EXPECT_EQ(static_cast<size_t>((kInputPixels * 3) / 5),
|
||||||
adapter.source_restrictions().max_pixels_per_frame());
|
adapter.source_restrictions().max_pixels_per_frame());
|
||||||
EXPECT_EQ(absl::nullopt,
|
EXPECT_EQ(absl::nullopt,
|
||||||
|
@ -195,7 +217,7 @@ TEST(VideoStreamAdapterTest, MaintainResolution_DecreasesFpsToTwoThirds) {
|
||||||
InputState(1280 * 720, kInputFps, kDefaultMinPixelsPerFrame));
|
InputState(1280 * 720, kInputFps, kDefaultMinPixelsPerFrame));
|
||||||
Adaptation adaptation = adapter.GetAdaptationDown();
|
Adaptation adaptation = adapter.GetAdaptationDown();
|
||||||
EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
|
EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
|
||||||
adapter.ApplyAdaptation(adaptation);
|
adapter.ApplyAdaptation(adaptation, nullptr);
|
||||||
EXPECT_EQ(absl::nullopt,
|
EXPECT_EQ(absl::nullopt,
|
||||||
adapter.source_restrictions().max_pixels_per_frame());
|
adapter.source_restrictions().max_pixels_per_frame());
|
||||||
EXPECT_EQ(absl::nullopt,
|
EXPECT_EQ(absl::nullopt,
|
||||||
|
@ -275,7 +297,7 @@ TEST(VideoStreamAdapterTest, Balanced_DecreaseFrameRate) {
|
||||||
// resolution: kBalancedMediumFrameRateFps.
|
// resolution: kBalancedMediumFrameRateFps.
|
||||||
Adaptation adaptation = adapter.GetAdaptationDown();
|
Adaptation adaptation = adapter.GetAdaptationDown();
|
||||||
EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
|
EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
|
||||||
adapter.ApplyAdaptation(adaptation);
|
adapter.ApplyAdaptation(adaptation, nullptr);
|
||||||
EXPECT_EQ(absl::nullopt,
|
EXPECT_EQ(absl::nullopt,
|
||||||
adapter.source_restrictions().max_pixels_per_frame());
|
adapter.source_restrictions().max_pixels_per_frame());
|
||||||
EXPECT_EQ(absl::nullopt,
|
EXPECT_EQ(absl::nullopt,
|
||||||
|
@ -519,7 +541,7 @@ TEST(VideoStreamAdapterTest, MaintainFramerate_AwaitingPreviousAdaptationDown) {
|
||||||
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
|
||||||
adapter.SetInput(InputState(1280 * 720, 30, kDefaultMinPixelsPerFrame));
|
adapter.SetInput(InputState(1280 * 720, 30, kDefaultMinPixelsPerFrame));
|
||||||
// Adapt down once, but don't update the input.
|
// Adapt down once, but don't update the input.
|
||||||
adapter.ApplyAdaptation(adapter.GetAdaptationDown());
|
adapter.ApplyAdaptation(adapter.GetAdaptationDown(), nullptr);
|
||||||
EXPECT_EQ(1, adapter.adaptation_counters().resolution_adaptations);
|
EXPECT_EQ(1, adapter.adaptation_counters().resolution_adaptations);
|
||||||
{
|
{
|
||||||
// Having performed the adaptation, but not updated the input based on the
|
// Having performed the adaptation, but not updated the input based on the
|
||||||
|
@ -541,7 +563,7 @@ TEST(VideoStreamAdapterTest, MaintainFramerate_AwaitingPreviousAdaptationUp) {
|
||||||
fake_stream.ApplyAdaptation(adapter.GetAdaptationDown());
|
fake_stream.ApplyAdaptation(adapter.GetAdaptationDown());
|
||||||
EXPECT_EQ(2, adapter.adaptation_counters().resolution_adaptations);
|
EXPECT_EQ(2, adapter.adaptation_counters().resolution_adaptations);
|
||||||
// Adapt up once, but don't update the input.
|
// Adapt up once, but don't update the input.
|
||||||
adapter.ApplyAdaptation(adapter.GetAdaptationUp());
|
adapter.ApplyAdaptation(adapter.GetAdaptationUp(), nullptr);
|
||||||
EXPECT_EQ(1, adapter.adaptation_counters().resolution_adaptations);
|
EXPECT_EQ(1, adapter.adaptation_counters().resolution_adaptations);
|
||||||
{
|
{
|
||||||
// Having performed the adaptation, but not updated the input based on the
|
// Having performed the adaptation, but not updated the input based on the
|
||||||
|
@ -614,7 +636,7 @@ TEST(VideoStreamAdapterTest,
|
||||||
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
|
||||||
fake_stream.ApplyAdaptation(adapter.GetAdaptationDown());
|
fake_stream.ApplyAdaptation(adapter.GetAdaptationDown());
|
||||||
// Apply adaptation up but don't update input.
|
// Apply adaptation up but don't update input.
|
||||||
adapter.ApplyAdaptation(adapter.GetAdaptationUp());
|
adapter.ApplyAdaptation(adapter.GetAdaptationUp(), nullptr);
|
||||||
EXPECT_EQ(Adaptation::Status::kAwaitingPreviousAdaptation,
|
EXPECT_EQ(Adaptation::Status::kAwaitingPreviousAdaptation,
|
||||||
adapter.GetAdaptationUp().status());
|
adapter.GetAdaptationUp().status());
|
||||||
|
|
||||||
|
@ -668,7 +690,7 @@ TEST(VideoStreamAdapterTest,
|
||||||
FakeVideoStream fake_stream(&adapter, 1280 * 720, 30,
|
FakeVideoStream fake_stream(&adapter, 1280 * 720, 30,
|
||||||
kDefaultMinPixelsPerFrame);
|
kDefaultMinPixelsPerFrame);
|
||||||
// Apply adaptation but don't update the input.
|
// Apply adaptation but don't update the input.
|
||||||
adapter.ApplyAdaptation(adapter.GetAdaptationDown());
|
adapter.ApplyAdaptation(adapter.GetAdaptationDown(), nullptr);
|
||||||
EXPECT_EQ(Adaptation::Status::kAwaitingPreviousAdaptation,
|
EXPECT_EQ(Adaptation::Status::kAwaitingPreviousAdaptation,
|
||||||
adapter.GetAdaptationDown().status());
|
adapter.GetAdaptationDown().status());
|
||||||
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
|
||||||
|
@ -676,6 +698,36 @@ TEST(VideoStreamAdapterTest,
|
||||||
EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
|
EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(VideoStreamAdapterTest, RestrictionsBroadcasted) {
|
||||||
|
VideoStreamAdapter adapter;
|
||||||
|
FakeVideoStreamAdapterListner listener;
|
||||||
|
adapter.AddRestrictionsListener(&listener);
|
||||||
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
|
||||||
|
FakeVideoStream fake_stream(&adapter, 1280 * 720, 30,
|
||||||
|
kDefaultMinPixelsPerFrame);
|
||||||
|
// Not broadcast on invalid ApplyAdaptation.
|
||||||
|
{
|
||||||
|
Adaptation adaptation = adapter.GetAdaptationUp();
|
||||||
|
adapter.ApplyAdaptation(adaptation, nullptr);
|
||||||
|
EXPECT_EQ(0, listener.calls());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Broadcast on ApplyAdaptation.
|
||||||
|
{
|
||||||
|
Adaptation adaptation = adapter.GetAdaptationDown();
|
||||||
|
VideoStreamAdapter::RestrictionsWithCounters peek =
|
||||||
|
adapter.PeekNextRestrictions(adaptation);
|
||||||
|
fake_stream.ApplyAdaptation(adaptation);
|
||||||
|
EXPECT_EQ(1, listener.calls());
|
||||||
|
EXPECT_EQ(peek.restrictions, listener.last_restrictions());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Broadcast on ClearRestrictions().
|
||||||
|
adapter.ClearRestrictions();
|
||||||
|
EXPECT_EQ(2, listener.calls());
|
||||||
|
EXPECT_EQ(VideoSourceRestrictions(), listener.last_restrictions());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(VideoStreamAdapterTest, PeekNextRestrictions) {
|
TEST(VideoStreamAdapterTest, PeekNextRestrictions) {
|
||||||
VideoStreamAdapter adapter;
|
VideoStreamAdapter adapter;
|
||||||
// Any non-disabled DegradationPreference will do.
|
// Any non-disabled DegradationPreference will do.
|
||||||
|
@ -718,12 +770,24 @@ TEST(VideoStreamAdapterTest, PeekNextRestrictions) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(VideoStreamAdapterTest, PeekRestrictionsDoesNotBroadcast) {
|
||||||
|
VideoStreamAdapter adapter;
|
||||||
|
FakeVideoStreamAdapterListner listener;
|
||||||
|
adapter.AddRestrictionsListener(&listener);
|
||||||
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
|
||||||
|
FakeVideoStream fake_stream(&adapter, 1280 * 720, 30,
|
||||||
|
kDefaultMinPixelsPerFrame);
|
||||||
|
Adaptation adaptation = adapter.GetAdaptationDown();
|
||||||
|
adapter.PeekNextRestrictions(adaptation);
|
||||||
|
EXPECT_EQ(0, listener.calls());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(VideoStreamAdapterTest,
|
TEST(VideoStreamAdapterTest,
|
||||||
SetDegradationPreferenceToOrFromBalancedClearsRestrictions) {
|
SetDegradationPreferenceToOrFromBalancedClearsRestrictions) {
|
||||||
VideoStreamAdapter adapter;
|
VideoStreamAdapter adapter;
|
||||||
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
|
||||||
adapter.SetInput(InputState(1280 * 720, 30, kDefaultMinPixelsPerFrame));
|
adapter.SetInput(InputState(1280 * 720, 30, kDefaultMinPixelsPerFrame));
|
||||||
adapter.ApplyAdaptation(adapter.GetAdaptationDown());
|
adapter.ApplyAdaptation(adapter.GetAdaptationDown(), nullptr);
|
||||||
EXPECT_NE(VideoSourceRestrictions(), adapter.source_restrictions());
|
EXPECT_NE(VideoSourceRestrictions(), adapter.source_restrictions());
|
||||||
EXPECT_NE(0, adapter.adaptation_counters().Total());
|
EXPECT_NE(0, adapter.adaptation_counters().Total());
|
||||||
// Changing from non-balanced to balanced clears the restrictions.
|
// Changing from non-balanced to balanced clears the restrictions.
|
||||||
|
@ -731,7 +795,7 @@ TEST(VideoStreamAdapterTest,
|
||||||
EXPECT_EQ(VideoSourceRestrictions(), adapter.source_restrictions());
|
EXPECT_EQ(VideoSourceRestrictions(), adapter.source_restrictions());
|
||||||
EXPECT_EQ(0, adapter.adaptation_counters().Total());
|
EXPECT_EQ(0, adapter.adaptation_counters().Total());
|
||||||
// Apply adaptation again.
|
// Apply adaptation again.
|
||||||
adapter.ApplyAdaptation(adapter.GetAdaptationDown());
|
adapter.ApplyAdaptation(adapter.GetAdaptationDown(), nullptr);
|
||||||
EXPECT_NE(VideoSourceRestrictions(), adapter.source_restrictions());
|
EXPECT_NE(VideoSourceRestrictions(), adapter.source_restrictions());
|
||||||
EXPECT_NE(0, adapter.adaptation_counters().Total());
|
EXPECT_NE(0, adapter.adaptation_counters().Total());
|
||||||
// Changing from balanced to non-balanced clears the restrictions.
|
// Changing from balanced to non-balanced clears the restrictions.
|
||||||
|
@ -752,7 +816,7 @@ TEST(VideoStreamAdapterDeathTest,
|
||||||
adapter.SetInput(InputState(1280 * 720, 30, kDefaultMinPixelsPerFrame));
|
adapter.SetInput(InputState(1280 * 720, 30, kDefaultMinPixelsPerFrame));
|
||||||
Adaptation adaptation = adapter.GetAdaptationDown();
|
Adaptation adaptation = adapter.GetAdaptationDown();
|
||||||
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
|
||||||
EXPECT_DEATH(adapter.ApplyAdaptation(adaptation), "");
|
EXPECT_DEATH(adapter.ApplyAdaptation(adaptation, nullptr), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(VideoStreamAdapterDeathTest, SetInputInvalidatesAdaptations) {
|
TEST(VideoStreamAdapterDeathTest, SetInputInvalidatesAdaptations) {
|
||||||
|
|
|
@ -316,11 +316,13 @@ void VideoStreamEncoderResourceManager::Initialize(
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoStreamEncoderResourceManager::SetAdaptationProcessor(
|
void VideoStreamEncoderResourceManager::SetAdaptationProcessor(
|
||||||
ResourceAdaptationProcessorInterface* adaptation_processor) {
|
ResourceAdaptationProcessorInterface* adaptation_processor,
|
||||||
|
VideoStreamAdapter* stream_adapter) {
|
||||||
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
adaptation_processor_ = adaptation_processor;
|
adaptation_processor_ = adaptation_processor;
|
||||||
balanced_constraint_->SetAdaptationProcessor(adaptation_processor);
|
balanced_constraint_->SetAdaptationProcessor(adaptation_processor);
|
||||||
quality_scaler_resource_->SetAdaptationProcessor(adaptation_processor);
|
quality_scaler_resource_->SetAdaptationProcessor(adaptation_processor);
|
||||||
|
stream_adapter_ = stream_adapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoStreamEncoderResourceManager::SetDegradationPreferences(
|
void VideoStreamEncoderResourceManager::SetDegradationPreferences(
|
||||||
|
@ -596,7 +598,8 @@ int VideoStreamEncoderResourceManager::LastInputFrameSizeOrDefault() const {
|
||||||
void VideoStreamEncoderResourceManager::OnVideoSourceRestrictionsUpdated(
|
void VideoStreamEncoderResourceManager::OnVideoSourceRestrictionsUpdated(
|
||||||
VideoSourceRestrictions restrictions,
|
VideoSourceRestrictions restrictions,
|
||||||
const VideoAdaptationCounters& adaptation_counters,
|
const VideoAdaptationCounters& adaptation_counters,
|
||||||
rtc::scoped_refptr<Resource> reason) {
|
rtc::scoped_refptr<Resource> reason,
|
||||||
|
const VideoSourceRestrictions& unfiltered_restrictions) {
|
||||||
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
// TODO(bugs.webrtc.org/11553) Remove reason parameter and add reset callback.
|
// TODO(bugs.webrtc.org/11553) Remove reason parameter and add reset callback.
|
||||||
if (!reason && adaptation_counters.Total() == 0) {
|
if (!reason && adaptation_counters.Total() == 0) {
|
||||||
|
@ -608,7 +611,8 @@ void VideoStreamEncoderResourceManager::OnVideoSourceRestrictionsUpdated(
|
||||||
// means that if the task gets executed, |this| has not been freed yet.
|
// means that if the task gets executed, |this| has not been freed yet.
|
||||||
encoder_queue_->PostTask([this, restrictions] {
|
encoder_queue_->PostTask([this, restrictions] {
|
||||||
RTC_DCHECK_RUN_ON(encoder_queue_);
|
RTC_DCHECK_RUN_ON(encoder_queue_);
|
||||||
video_source_restrictions_ = restrictions;
|
video_source_restrictions_ = FilterRestrictionsByDegradationPreference(
|
||||||
|
restrictions, degradation_preference_);
|
||||||
MaybeUpdateTargetFrameRate();
|
MaybeUpdateTargetFrameRate();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -720,13 +724,12 @@ void VideoStreamEncoderResourceManager::OnQualityRampUp() {
|
||||||
// the adaptation queue, add logic to prevent use-after-free on |this|.
|
// the adaptation queue, add logic to prevent use-after-free on |this|.
|
||||||
resource_adaptation_queue_->PostTask([this] {
|
resource_adaptation_queue_->PostTask([this] {
|
||||||
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
|
||||||
if (!adaptation_processor_) {
|
if (!stream_adapter_) {
|
||||||
// The processor nulled before this task had a chance to execute. This
|
// The processor nulled before this task had a chance to execute. This
|
||||||
// happens if the processor is destroyed. No action needed.
|
// happens if the processor is destroyed. No action needed.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RTC_LOG(LS_INFO) << "Reset quality limitations.";
|
stream_adapter_->ClearRestrictions();
|
||||||
adaptation_processor_->ResetVideoSourceRestrictions();
|
|
||||||
});
|
});
|
||||||
quality_rampup_experiment_.reset();
|
quality_rampup_experiment_.reset();
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,7 @@ extern const int kDefaultInputPixelsHeight;
|
||||||
// ResourceAdaptationProcessor code such as the inital frame dropping.
|
// ResourceAdaptationProcessor code such as the inital frame dropping.
|
||||||
class VideoStreamEncoderResourceManager
|
class VideoStreamEncoderResourceManager
|
||||||
: public VideoSourceRestrictionsListener,
|
: public VideoSourceRestrictionsListener,
|
||||||
|
public ResourceLimitationsListener,
|
||||||
public QualityRampUpExperimentListener {
|
public QualityRampUpExperimentListener {
|
||||||
public:
|
public:
|
||||||
VideoStreamEncoderResourceManager(
|
VideoStreamEncoderResourceManager(
|
||||||
|
@ -78,7 +79,8 @@ class VideoStreamEncoderResourceManager
|
||||||
void Initialize(rtc::TaskQueue* encoder_queue,
|
void Initialize(rtc::TaskQueue* encoder_queue,
|
||||||
rtc::TaskQueue* resource_adaptation_queue);
|
rtc::TaskQueue* resource_adaptation_queue);
|
||||||
void SetAdaptationProcessor(
|
void SetAdaptationProcessor(
|
||||||
ResourceAdaptationProcessorInterface* adaptation_processor);
|
ResourceAdaptationProcessorInterface* adaptation_processor,
|
||||||
|
VideoStreamAdapter* stream_adapter);
|
||||||
|
|
||||||
// TODO(https://crbug.com/webrtc/11563): The degradation preference is a
|
// TODO(https://crbug.com/webrtc/11563): The degradation preference is a
|
||||||
// setting of the Processor, it does not belong to the Manager - can we get
|
// setting of the Processor, it does not belong to the Manager - can we get
|
||||||
|
@ -130,7 +132,8 @@ class VideoStreamEncoderResourceManager
|
||||||
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,
|
||||||
|
const VideoSourceRestrictions& unfiltered_restrictions) override;
|
||||||
void OnResourceLimitationChanged(
|
void OnResourceLimitationChanged(
|
||||||
rtc::scoped_refptr<Resource> resource,
|
rtc::scoped_refptr<Resource> resource,
|
||||||
const std::map<rtc::scoped_refptr<Resource>, VideoAdaptationCounters>&
|
const std::map<rtc::scoped_refptr<Resource>, VideoAdaptationCounters>&
|
||||||
|
@ -238,6 +241,8 @@ class VideoStreamEncoderResourceManager
|
||||||
RTC_GUARDED_BY(encoder_queue_);
|
RTC_GUARDED_BY(encoder_queue_);
|
||||||
ResourceAdaptationProcessorInterface* adaptation_processor_
|
ResourceAdaptationProcessorInterface* adaptation_processor_
|
||||||
RTC_GUARDED_BY(resource_adaptation_queue_);
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
|
VideoStreamAdapter* stream_adapter_
|
||||||
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
||||||
// Thread-safe.
|
// Thread-safe.
|
||||||
VideoStreamEncoderObserver* const encoder_stats_observer_;
|
VideoStreamEncoderObserver* const encoder_stats_observer_;
|
||||||
|
|
||||||
|
|
|
@ -256,10 +256,12 @@ VideoStreamEncoder::VideoStreamEncoder(
|
||||||
ParseAutomatincAnimationDetectionFieldTrial()),
|
ParseAutomatincAnimationDetectionFieldTrial()),
|
||||||
encoder_switch_requested_(false),
|
encoder_switch_requested_(false),
|
||||||
input_state_provider_(encoder_stats_observer),
|
input_state_provider_(encoder_stats_observer),
|
||||||
|
video_stream_adapter_(std::make_unique<VideoStreamAdapter>()),
|
||||||
resource_adaptation_processor_(
|
resource_adaptation_processor_(
|
||||||
std::make_unique<ResourceAdaptationProcessor>(
|
std::make_unique<ResourceAdaptationProcessor>(
|
||||||
&input_state_provider_,
|
&input_state_provider_,
|
||||||
encoder_stats_observer)),
|
encoder_stats_observer,
|
||||||
|
video_stream_adapter_.get())),
|
||||||
adaptation_constraints_(),
|
adaptation_constraints_(),
|
||||||
adaptation_listeners_(),
|
adaptation_listeners_(),
|
||||||
stream_resource_manager_(&input_state_provider_,
|
stream_resource_manager_(&input_state_provider_,
|
||||||
|
@ -287,10 +289,11 @@ VideoStreamEncoder::VideoStreamEncoder(
|
||||||
resource_adaptation_processor_->SetResourceAdaptationQueue(
|
resource_adaptation_processor_->SetResourceAdaptationQueue(
|
||||||
resource_adaptation_queue_.Get());
|
resource_adaptation_queue_.Get());
|
||||||
stream_resource_manager_.SetAdaptationProcessor(
|
stream_resource_manager_.SetAdaptationProcessor(
|
||||||
resource_adaptation_processor_.get());
|
resource_adaptation_processor_.get(), video_stream_adapter_.get());
|
||||||
resource_adaptation_processor_->AddRestrictionsListener(
|
resource_adaptation_processor_->AddResourceLimitationsListener(
|
||||||
&stream_resource_manager_);
|
&stream_resource_manager_);
|
||||||
resource_adaptation_processor_->AddRestrictionsListener(this);
|
video_stream_adapter_->AddRestrictionsListener(&stream_resource_manager_);
|
||||||
|
video_stream_adapter_->AddRestrictionsListener(this);
|
||||||
|
|
||||||
// Add the stream resource manager's resources to the processor.
|
// Add the stream resource manager's resources to the processor.
|
||||||
adaptation_constraints_ = stream_resource_manager_.AdaptationConstraints();
|
adaptation_constraints_ = stream_resource_manager_.AdaptationConstraints();
|
||||||
|
@ -333,10 +336,12 @@ void VideoStreamEncoder::Stop() {
|
||||||
for (auto* listener : adaptation_listeners_) {
|
for (auto* listener : adaptation_listeners_) {
|
||||||
resource_adaptation_processor_->RemoveAdaptationListener(listener);
|
resource_adaptation_processor_->RemoveAdaptationListener(listener);
|
||||||
}
|
}
|
||||||
resource_adaptation_processor_->RemoveRestrictionsListener(this);
|
video_stream_adapter_->RemoveRestrictionsListener(this);
|
||||||
resource_adaptation_processor_->RemoveRestrictionsListener(
|
video_stream_adapter_->RemoveRestrictionsListener(
|
||||||
&stream_resource_manager_);
|
&stream_resource_manager_);
|
||||||
stream_resource_manager_.SetAdaptationProcessor(nullptr);
|
resource_adaptation_processor_->RemoveResourceLimitationsListener(
|
||||||
|
&stream_resource_manager_);
|
||||||
|
stream_resource_manager_.SetAdaptationProcessor(nullptr, nullptr);
|
||||||
resource_adaptation_processor_.reset();
|
resource_adaptation_processor_.reset();
|
||||||
}
|
}
|
||||||
shutdown_adaptation_processor_event.Set();
|
shutdown_adaptation_processor_event.Set();
|
||||||
|
@ -1759,7 +1764,8 @@ bool VideoStreamEncoder::DropDueToSize(uint32_t pixel_count) const {
|
||||||
void VideoStreamEncoder::OnVideoSourceRestrictionsUpdated(
|
void VideoStreamEncoder::OnVideoSourceRestrictionsUpdated(
|
||||||
VideoSourceRestrictions restrictions,
|
VideoSourceRestrictions restrictions,
|
||||||
const VideoAdaptationCounters& adaptation_counters,
|
const VideoAdaptationCounters& adaptation_counters,
|
||||||
rtc::scoped_refptr<Resource> reason) {
|
rtc::scoped_refptr<Resource> reason,
|
||||||
|
const VideoSourceRestrictions& unfiltered_restrictions) {
|
||||||
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 "
|
||||||
|
@ -2102,8 +2108,7 @@ void VideoStreamEncoder::AddRestrictionsListenerForTesting(
|
||||||
resource_adaptation_queue_.PostTask([this, restrictions_listener, &event] {
|
resource_adaptation_queue_.PostTask([this, restrictions_listener, &event] {
|
||||||
RTC_DCHECK_RUN_ON(&resource_adaptation_queue_);
|
RTC_DCHECK_RUN_ON(&resource_adaptation_queue_);
|
||||||
RTC_DCHECK(resource_adaptation_processor_);
|
RTC_DCHECK(resource_adaptation_processor_);
|
||||||
resource_adaptation_processor_->AddRestrictionsListener(
|
video_stream_adapter_->AddRestrictionsListener(restrictions_listener);
|
||||||
restrictions_listener);
|
|
||||||
event.Set();
|
event.Set();
|
||||||
});
|
});
|
||||||
event.Wait(rtc::Event::kForever);
|
event.Wait(rtc::Event::kForever);
|
||||||
|
@ -2115,8 +2120,7 @@ void VideoStreamEncoder::RemoveRestrictionsListenerForTesting(
|
||||||
resource_adaptation_queue_.PostTask([this, restrictions_listener, &event] {
|
resource_adaptation_queue_.PostTask([this, restrictions_listener, &event] {
|
||||||
RTC_DCHECK_RUN_ON(&resource_adaptation_queue_);
|
RTC_DCHECK_RUN_ON(&resource_adaptation_queue_);
|
||||||
RTC_DCHECK(resource_adaptation_processor_);
|
RTC_DCHECK(resource_adaptation_processor_);
|
||||||
resource_adaptation_processor_->RemoveRestrictionsListener(
|
video_stream_adapter_->RemoveRestrictionsListener(restrictions_listener);
|
||||||
restrictions_listener);
|
|
||||||
event.Set();
|
event.Set();
|
||||||
});
|
});
|
||||||
event.Wait(rtc::Event::kForever);
|
event.Wait(rtc::Event::kForever);
|
||||||
|
|
|
@ -120,7 +120,8 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
|
||||||
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,
|
||||||
|
const VideoSourceRestrictions& unfiltered_restrictions) override;
|
||||||
|
|
||||||
// Used for injected test resources.
|
// Used for injected test resources.
|
||||||
// TODO(eshr): Move all adaptation tests out of VideoStreamEncoder tests.
|
// TODO(eshr): Move all adaptation tests out of VideoStreamEncoder tests.
|
||||||
|
@ -408,6 +409,9 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
|
||||||
// Provies video stream input states: current resolution and frame rate.
|
// Provies video stream input states: current resolution and frame rate.
|
||||||
// This class is thread-safe.
|
// This class is thread-safe.
|
||||||
VideoStreamInputStateProvider input_state_provider_;
|
VideoStreamInputStateProvider input_state_provider_;
|
||||||
|
|
||||||
|
std::unique_ptr<VideoStreamAdapter> video_stream_adapter_
|
||||||
|
RTC_GUARDED_BY(&resource_adaptation_queue_);
|
||||||
// Responsible for adapting input resolution or frame rate to ensure resources
|
// Responsible for adapting input resolution or frame rate to ensure resources
|
||||||
// (e.g. CPU or bandwidth) are not overused.
|
// (e.g. CPU or bandwidth) are not overused.
|
||||||
// This class is single-threaded on the resource adaptation queue.
|
// This class is single-threaded on the resource adaptation queue.
|
||||||
|
|
|
@ -205,7 +205,8 @@ class FakeVideoSourceRestrictionsListener
|
||||||
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,
|
||||||
|
const VideoSourceRestrictions& unfiltered_restrictions) override {
|
||||||
was_restrictions_updated_ = true;
|
was_restrictions_updated_ = true;
|
||||||
restrictions_updated_event_.Set();
|
restrictions_updated_event_.Set();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue