[Adaptation] Move AdaptationListeners to VideoStreamAdapter
This is a step needed for multi-stream and new mitigations. It also
cleans up needing to signal adaptation changes in mutiple places
from ResourceAdaptationProcessor.
R=hbos@webrtc.org
Bug: webrtc:11754
Change-Id: Ib185dc9f66fbb4a087eb9e970c68c3f47eafb17f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/178874
Commit-Queue: Evan Shrubsole <eshr@google.com>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31684}
diff --git a/call/adaptation/resource_adaptation_processor.cc b/call/adaptation/resource_adaptation_processor.cc
index dd273ac..bea8334 100644
--- a/call/adaptation/resource_adaptation_processor.cc
+++ b/call/adaptation/resource_adaptation_processor.cc
@@ -90,9 +90,6 @@
RTC_DCHECK(adaptation_constraints_.empty())
<< "There are constaint(s) attached to a ResourceAdaptationProcessor "
<< "being destroyed.";
- RTC_DCHECK(adaptation_listeners_.empty())
- << "There are listener(s) attached to a ResourceAdaptationProcessor "
- << "being destroyed.";
stream_adapter_->RemoveRestrictionsListener(this);
resource_listener_delegate_->OnProcessorDestroyed();
}
@@ -182,24 +179,6 @@
adaptation_constraints_.erase(it);
}
-void ResourceAdaptationProcessor::AddAdaptationListener(
- AdaptationListener* adaptation_listener) {
- RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
- RTC_DCHECK(std::find(adaptation_listeners_.begin(),
- adaptation_listeners_.end(),
- adaptation_listener) == adaptation_listeners_.end());
- adaptation_listeners_.push_back(adaptation_listener);
-}
-
-void ResourceAdaptationProcessor::RemoveAdaptationListener(
- AdaptationListener* adaptation_listener) {
- RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
- auto it = std::find(adaptation_listeners_.begin(),
- adaptation_listeners_.end(), adaptation_listener);
- RTC_DCHECK(it != adaptation_listeners_.end());
- adaptation_listeners_.erase(it);
-}
-
void ResourceAdaptationProcessor::OnResourceUsageStateMeasured(
rtc::scoped_refptr<Resource> resource,
ResourceUsageState usage_state) {
@@ -308,11 +287,6 @@
}
// Apply adaptation.
stream_adapter_->ApplyAdaptation(adaptation, reason_resource);
- for (auto* adaptation_listener : adaptation_listeners_) {
- adaptation_listener->OnAdaptationApplied(
- adaptation.input_state(), restrictions_before, restrictions_after,
- reason_resource);
- }
processing_in_progress_ = false;
rtc::StringBuilder message;
message << "Adapted up successfully. Unfiltered adaptations: "
@@ -341,17 +315,9 @@
message.Release());
}
// Apply adaptation.
- VideoSourceRestrictions restrictions_before =
- stream_adapter_->source_restrictions();
- VideoSourceRestrictions restrictions_after = adaptation.restrictions();
UpdateResourceLimitations(reason_resource, adaptation.restrictions(),
adaptation.counters());
- stream_adapter_->ApplyAdaptation(adaptation, nullptr);
- for (auto* adaptation_listener : adaptation_listeners_) {
- adaptation_listener->OnAdaptationApplied(
- adaptation.input_state(), restrictions_before, restrictions_after,
- reason_resource);
- }
+ stream_adapter_->ApplyAdaptation(adaptation, reason_resource);
processing_in_progress_ = false;
rtc::StringBuilder message;
message << "Adapted down successfully. Unfiltered adaptations: "
@@ -429,11 +395,6 @@
most_limited.counters, most_limited.restrictions);
RTC_DCHECK_EQ(adapt_to.status(), Adaptation::Status::kValid);
stream_adapter_->ApplyAdaptation(adapt_to, nullptr);
- for (auto* adaptation_listener : adaptation_listeners_) {
- adaptation_listener->OnAdaptationApplied(
- adapt_to.input_state(), removed_limitations.restrictions,
- most_limited.restrictions, nullptr);
- }
RTC_LOG(INFO) << "Most limited resource removed. Restoring restrictions to "
"next most limited restrictions: "
diff --git a/call/adaptation/resource_adaptation_processor.h b/call/adaptation/resource_adaptation_processor.h
index f519fcc..9f20bdb 100644
--- a/call/adaptation/resource_adaptation_processor.h
+++ b/call/adaptation/resource_adaptation_processor.h
@@ -26,7 +26,6 @@
#include "api/video/video_frame.h"
#include "api/video/video_stream_encoder_observer.h"
#include "call/adaptation/adaptation_constraint.h"
-#include "call/adaptation/adaptation_listener.h"
#include "call/adaptation/resource_adaptation_processor_interface.h"
#include "call/adaptation/video_source_restrictions.h"
#include "call/adaptation/video_stream_adapter.h"
@@ -75,9 +74,6 @@
AdaptationConstraint* adaptation_constraint) override;
void RemoveAdaptationConstraint(
AdaptationConstraint* adaptation_constraint) override;
- void AddAdaptationListener(AdaptationListener* adaptation_listener) override;
- void RemoveAdaptationListener(
- AdaptationListener* adaptation_listener) override;
// ResourceListener implementation.
// Triggers OnResourceUnderuse() or OnResourceOveruse().
@@ -165,8 +161,6 @@
RTC_GUARDED_BY(resource_adaptation_queue_);
std::vector<AdaptationConstraint*> adaptation_constraints_
RTC_GUARDED_BY(resource_adaptation_queue_);
- std::vector<AdaptationListener*> adaptation_listeners_
- RTC_GUARDED_BY(resource_adaptation_queue_);
// Purely used for statistics, does not ensure mapped resources stay alive.
std::map<rtc::scoped_refptr<Resource>,
VideoStreamAdapter::RestrictionsWithCounters>
diff --git a/call/adaptation/resource_adaptation_processor_interface.h b/call/adaptation/resource_adaptation_processor_interface.h
index cd68441..fe500c9 100644
--- a/call/adaptation/resource_adaptation_processor_interface.h
+++ b/call/adaptation/resource_adaptation_processor_interface.h
@@ -68,10 +68,6 @@
AdaptationConstraint* adaptation_constraint) = 0;
virtual void RemoveAdaptationConstraint(
AdaptationConstraint* adaptation_constraint) = 0;
- virtual void AddAdaptationListener(
- AdaptationListener* adaptation_listener) = 0;
- virtual void RemoveAdaptationListener(
- AdaptationListener* adaptation_listener) = 0;
};
} // namespace webrtc
diff --git a/call/adaptation/resource_adaptation_processor_unittest.cc b/call/adaptation/resource_adaptation_processor_unittest.cc
index 0b16fab..42fb497 100644
--- a/call/adaptation/resource_adaptation_processor_unittest.cc
+++ b/call/adaptation/resource_adaptation_processor_unittest.cc
@@ -102,7 +102,7 @@
processor_->AddResource(resource_);
processor_->AddResource(other_resource_);
processor_->AddAdaptationConstraint(&adaptation_constraint_);
- processor_->AddAdaptationListener(&adaptation_listener_);
+ video_stream_adapter_->AddAdaptationListener(&adaptation_listener_);
}
~ResourceAdaptationProcessorTest() override {
if (processor_) {
@@ -132,7 +132,7 @@
processor_->RemoveResource(other_resource_);
}
processor_->RemoveAdaptationConstraint(&adaptation_constraint_);
- processor_->RemoveAdaptationListener(&adaptation_listener_);
+ video_stream_adapter_->RemoveAdaptationListener(&adaptation_listener_);
video_stream_adapter_->RemoveRestrictionsListener(&restrictions_listener_);
processor_.reset();
}
diff --git a/call/adaptation/video_stream_adapter.cc b/call/adaptation/video_stream_adapter.cc
index 51433ef..438b64e 100644
--- a/call/adaptation/video_stream_adapter.cc
+++ b/call/adaptation/video_stream_adapter.cc
@@ -210,7 +210,11 @@
sequence_checker_.Detach();
}
-VideoStreamAdapter::~VideoStreamAdapter() {}
+VideoStreamAdapter::~VideoStreamAdapter() {
+ RTC_DCHECK(adaptation_listeners_.empty())
+ << "There are listener(s) attached to a VideoStreamAdapter being "
+ "destroyed.";
+}
VideoSourceRestrictions VideoStreamAdapter::source_restrictions() const {
RTC_DCHECK_RUN_ON(&sequence_checker_);
@@ -230,7 +234,8 @@
current_restrictions_ = {VideoSourceRestrictions(),
VideoAdaptationCounters()};
awaiting_frame_size_change_ = absl::nullopt;
- BroadcastVideoRestrictionsUpdate(nullptr);
+ BroadcastVideoRestrictionsUpdate(input_state_provider_->InputState(),
+ nullptr);
}
void VideoStreamAdapter::AddRestrictionsListener(
@@ -251,6 +256,24 @@
restrictions_listeners_.erase(it);
}
+void VideoStreamAdapter::AddAdaptationListener(
+ AdaptationListener* adaptation_listener) {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ RTC_DCHECK(std::find(adaptation_listeners_.begin(),
+ adaptation_listeners_.end(),
+ adaptation_listener) == adaptation_listeners_.end());
+ adaptation_listeners_.push_back(adaptation_listener);
+}
+
+void VideoStreamAdapter::RemoveAdaptationListener(
+ AdaptationListener* adaptation_listener) {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ auto it = std::find(adaptation_listeners_.begin(),
+ adaptation_listeners_.end(), adaptation_listener);
+ RTC_DCHECK(it != adaptation_listeners_.end());
+ adaptation_listeners_.erase(it);
+}
+
void VideoStreamAdapter::SetDegradationPreference(
DegradationPreference degradation_preference) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
@@ -266,7 +289,8 @@
// ClearRestrictions() calls BroadcastVideoRestrictionsUpdate(nullptr).
ClearRestrictions();
} else {
- BroadcastVideoRestrictionsUpdate(nullptr);
+ BroadcastVideoRestrictionsUpdate(input_state_provider_->InputState(),
+ nullptr);
}
}
@@ -584,7 +608,7 @@
awaiting_frame_size_change_ = absl::nullopt;
}
current_restrictions_ = {adaptation.restrictions(), adaptation.counters()};
- BroadcastVideoRestrictionsUpdate(resource);
+ BroadcastVideoRestrictionsUpdate(adaptation.input_state(), resource);
}
Adaptation VideoStreamAdapter::GetAdaptationTo(
@@ -598,6 +622,7 @@
}
void VideoStreamAdapter::BroadcastVideoRestrictionsUpdate(
+ const VideoStreamInputState& input_state,
const rtc::scoped_refptr<Resource>& resource) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
VideoSourceRestrictions filtered = FilterRestrictionsByDegradationPreference(
@@ -610,6 +635,11 @@
filtered, current_restrictions_.counters, resource,
source_restrictions());
}
+ for (auto* adaptation_listener : adaptation_listeners_) {
+ adaptation_listener->OnAdaptationApplied(
+ input_state, last_video_source_restrictions_,
+ current_restrictions_.restrictions, resource);
+ }
last_video_source_restrictions_ = current_restrictions_.restrictions;
last_filtered_restrictions_ = filtered;
}
diff --git a/call/adaptation/video_stream_adapter.h b/call/adaptation/video_stream_adapter.h
index 00a52a9..f91be3c 100644
--- a/call/adaptation/video_stream_adapter.h
+++ b/call/adaptation/video_stream_adapter.h
@@ -20,6 +20,7 @@
#include "api/adaptation/resource.h"
#include "api/rtp_parameters.h"
#include "api/video/video_adaptation_counters.h"
+#include "call/adaptation/adaptation_listener.h"
#include "call/adaptation/degradation_preference_provider.h"
#include "call/adaptation/video_source_restrictions.h"
#include "call/adaptation/video_stream_input_state.h"
@@ -135,6 +136,8 @@
VideoSourceRestrictionsListener* restrictions_listener);
void RemoveRestrictionsListener(
VideoSourceRestrictionsListener* restrictions_listener);
+ void AddAdaptationListener(AdaptationListener* adaptation_listener);
+ void RemoveAdaptationListener(AdaptationListener* adaptation_listener);
// TODO(hbos): Setting the degradation preference should not clear
// restrictions! This is not defined in the spec and is unexpected, there is a
@@ -164,6 +167,7 @@
private:
void BroadcastVideoRestrictionsUpdate(
+ const VideoStreamInputState& input_state,
const rtc::scoped_refptr<Resource>& resource);
bool HasSufficientInputForAdaptation(const VideoStreamInputState& input_state)
@@ -244,6 +248,8 @@
std::vector<VideoSourceRestrictionsListener*> restrictions_listeners_
RTC_GUARDED_BY(&sequence_checker_);
+ std::vector<AdaptationListener*> adaptation_listeners_
+ RTC_GUARDED_BY(&sequence_checker_);
RestrictionsWithCounters current_restrictions_
RTC_GUARDED_BY(&sequence_checker_);
diff --git a/call/adaptation/video_stream_adapter_unittest.cc b/call/adaptation/video_stream_adapter_unittest.cc
index 86c53a9..cdda03c 100644
--- a/call/adaptation/video_stream_adapter_unittest.cc
+++ b/call/adaptation/video_stream_adapter_unittest.cc
@@ -18,7 +18,9 @@
#include "api/video_codecs/video_codec.h"
#include "api/video_codecs/video_encoder.h"
#include "api/video_codecs/video_encoder_config.h"
+#include "call/adaptation/adaptation_listener.h"
#include "call/adaptation/encoder_settings.h"
+#include "call/adaptation/test/fake_adaptation_listener.h"
#include "call/adaptation/video_source_restrictions.h"
#include "call/adaptation/video_stream_input_state.h"
#include "rtc_base/string_encode.h"
@@ -29,6 +31,10 @@
namespace webrtc {
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::SaveArg;
+
namespace {
const int kBalancedHighResolutionPixels = 1280 * 720;
@@ -145,6 +151,17 @@
VideoSourceRestrictions last_restrictions_;
};
+class MockAdaptationListener : public AdaptationListener {
+ public:
+ MOCK_METHOD(void,
+ OnAdaptationApplied,
+ (const VideoStreamInputState& input_state,
+ const VideoSourceRestrictions& restrictions_before,
+ const VideoSourceRestrictions& restrictions_after,
+ rtc::scoped_refptr<Resource> reason_resource),
+ (override));
+};
+
} // namespace
class VideoStreamAdapterTest : public ::testing::Test {
@@ -870,6 +887,26 @@
adapter_.GetAdaptDownResolution().status());
}
+TEST_F(VideoStreamAdapterTest, AdaptationListenerReceivesSignalOnAdaptation) {
+ testing::StrictMock<MockAdaptationListener> adaptation_listener;
+ adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
+ adapter_.AddAdaptationListener(&adaptation_listener);
+ input_state_provider_.SetInputState(1280 * 720, 30,
+ kDefaultMinPixelsPerFrame);
+ VideoSourceRestrictions restrictions_before;
+ VideoSourceRestrictions restrictions_after;
+ EXPECT_CALL(adaptation_listener, OnAdaptationApplied)
+ .WillOnce(DoAll(SaveArg<1>(&restrictions_before),
+ SaveArg<2>(&restrictions_after)));
+ auto adaptation = adapter_.GetAdaptationDown();
+ adapter_.ApplyAdaptation(adaptation, nullptr);
+ EXPECT_EQ(VideoSourceRestrictions(), restrictions_before);
+ EXPECT_EQ(adaptation.restrictions(), restrictions_after);
+
+ // Clean up.
+ adapter_.RemoveAdaptationListener(&adaptation_listener);
+}
+
// Death tests.
// Disabled on Android because death tests misbehave on Android, see
// base/test/gtest_util.h.
diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc
index 84b5aa3..255405e 100644
--- a/video/video_stream_encoder.cc
+++ b/video/video_stream_encoder.cc
@@ -348,7 +348,6 @@
degradation_preference_manager_(
std::make_unique<DegradationPreferenceManager>()),
adaptation_constraints_(),
- adaptation_listeners_(),
stream_resource_manager_(&input_state_provider_,
encoder_stats_observer,
clock_,
@@ -387,15 +386,14 @@
// Add the stream resource manager's resources to the processor.
adaptation_constraints_ = stream_resource_manager_.AdaptationConstraints();
- adaptation_listeners_ = stream_resource_manager_.AdaptationListeners();
for (auto& resource : stream_resource_manager_.MappedResources()) {
resource_adaptation_processor_->AddResource(resource);
}
for (auto* constraint : adaptation_constraints_) {
resource_adaptation_processor_->AddAdaptationConstraint(constraint);
}
- for (auto* listener : adaptation_listeners_) {
- resource_adaptation_processor_->AddAdaptationListener(listener);
+ for (auto* listener : stream_resource_manager_.AdaptationListeners()) {
+ video_stream_adapter_->AddAdaptationListener(listener);
}
initialize_processor_event.Set();
});
@@ -423,8 +421,8 @@
for (auto* constraint : adaptation_constraints_) {
resource_adaptation_processor_->RemoveAdaptationConstraint(constraint);
}
- for (auto* listener : adaptation_listeners_) {
- resource_adaptation_processor_->RemoveAdaptationListener(listener);
+ for (auto* listener : stream_resource_manager_.AdaptationListeners()) {
+ video_stream_adapter_->RemoveAdaptationListener(listener);
}
video_stream_adapter_->RemoveRestrictionsListener(this);
video_stream_adapter_->RemoveRestrictionsListener(
@@ -2153,23 +2151,6 @@
event.Wait(rtc::Event::kForever);
}
-void VideoStreamEncoder::InjectAdaptationListener(
- AdaptationListener* adaptation_listener) {
- rtc::Event event;
- resource_adaptation_queue_.PostTask([this, adaptation_listener, &event] {
- RTC_DCHECK_RUN_ON(&resource_adaptation_queue_);
- if (!resource_adaptation_processor_) {
- // The VideoStreamEncoder was stopped and the processor destroyed before
- // this task had a chance to execute. No action needed.
- return;
- }
- adaptation_listeners_.push_back(adaptation_listener);
- resource_adaptation_processor_->AddAdaptationListener(adaptation_listener);
- event.Set();
- });
- event.Wait(rtc::Event::kForever);
-}
-
rtc::scoped_refptr<QualityScalerResource>
VideoStreamEncoder::quality_scaler_resource_for_testing() {
RTC_DCHECK_RUN_ON(&encoder_queue_);
diff --git a/video/video_stream_encoder.h b/video/video_stream_encoder.h
index 5af0111..95d4dcb 100644
--- a/video/video_stream_encoder.h
+++ b/video/video_stream_encoder.h
@@ -129,7 +129,6 @@
void InjectAdaptationResource(rtc::scoped_refptr<Resource> resource,
VideoAdaptationReason reason);
void InjectAdaptationConstraint(AdaptationConstraint* adaptation_constraint);
- void InjectAdaptationListener(AdaptationListener* adaptation_listener);
rtc::scoped_refptr<QualityScalerResource>
quality_scaler_resource_for_testing();
@@ -423,8 +422,6 @@
std::unique_ptr<DegradationPreferenceManager> degradation_preference_manager_;
std::vector<AdaptationConstraint*> adaptation_constraints_
RTC_GUARDED_BY(&resource_adaptation_queue_);
- std::vector<AdaptationListener*> adaptation_listeners_
- RTC_GUARDED_BY(&resource_adaptation_queue_);
// Handles input, output and stats reporting related to VideoStreamEncoder
// specific resources, such as "encode usage percent" measurements and "QP
// scaling". Also involved with various mitigations such as inital frame
diff --git a/video/video_stream_encoder_unittest.cc b/video/video_stream_encoder_unittest.cc
index 6bdcbd0..6a11bf6 100644
--- a/video/video_stream_encoder_unittest.cc
+++ b/video/video_stream_encoder_unittest.cc
@@ -322,13 +322,11 @@
task_queue_factory),
fake_cpu_resource_(FakeResource::Create("FakeResource[CPU]")),
fake_quality_resource_(FakeResource::Create("FakeResource[QP]")),
- fake_adaptation_constraint_("FakeAdaptationConstraint"),
- fake_adaptation_listener_() {
+ fake_adaptation_constraint_("FakeAdaptationConstraint") {
InjectAdaptationResource(fake_quality_resource_,
VideoAdaptationReason::kQuality);
InjectAdaptationResource(fake_cpu_resource_, VideoAdaptationReason::kCpu);
InjectAdaptationConstraint(&fake_adaptation_constraint_);
- InjectAdaptationListener(&fake_adaptation_listener_);
}
void SetSourceAndWaitForRestrictionsUpdated(
@@ -435,7 +433,6 @@
rtc::scoped_refptr<FakeResource> fake_cpu_resource_;
rtc::scoped_refptr<FakeResource> fake_quality_resource_;
FakeAdaptationConstraint fake_adaptation_constraint_;
- FakeAdaptationListener fake_adaptation_listener_;
};
class VideoStreamFactory