[Adaptation] Move min pixel limit logic out of adaptation processor

This is in preperation for eventual multi-stream and multi-mitigation
adaptation. This logic only applied to a single stream and thus is
better fit in the VideoStreamAdapter.

Bug: webrtc:11754
Change-Id: Icc5c7920038c82b574f4b5f7efbc92698691076f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/181585
Commit-Queue: Evan Shrubsole <eshr@google.com>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31944}
This commit is contained in:
Evan Shrubsole 2020-08-17 11:10:45 +02:00 committed by Commit Bot
parent fcf5e7b131
commit d73d421565
7 changed files with 43 additions and 60 deletions

View File

@ -69,12 +69,10 @@ ResourceAdaptationProcessor::MitigationResultAndLogMessage::
: result(result), message(std::move(message)) {}
ResourceAdaptationProcessor::ResourceAdaptationProcessor(
VideoStreamEncoderObserver* encoder_stats_observer,
VideoStreamAdapter* stream_adapter)
: resource_adaptation_queue_(nullptr),
resource_listener_delegate_(
new rtc::RefCountedObject<ResourceListenerDelegate>(this)),
encoder_stats_observer_(encoder_stats_observer),
resources_(),
stream_adapter_(stream_adapter),
last_reported_source_restrictions_(),
@ -302,9 +300,6 @@ ResourceAdaptationProcessor::OnResourceOveruse(
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
// How can this stream be adapted up?
Adaptation adaptation = stream_adapter_->GetAdaptationDown();
if (adaptation.min_pixel_limit_reached()) {
encoder_stats_observer_->OnMinPixelLimitReached();
}
if (adaptation.status() == Adaptation::Status::kLimitReached) {
// Add resource as most limited.
VideoStreamAdapter::RestrictionsWithCounters restrictions;

View File

@ -54,8 +54,7 @@ class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
public VideoSourceRestrictionsListener,
public ResourceListener {
public:
ResourceAdaptationProcessor(
VideoStreamEncoderObserver* encoder_stats_observer,
explicit ResourceAdaptationProcessor(
VideoStreamAdapter* video_stream_adapter);
~ResourceAdaptationProcessor() override;
@ -147,8 +146,6 @@ class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
TaskQueueBase* resource_adaptation_queue_;
rtc::scoped_refptr<ResourceListenerDelegate> resource_listener_delegate_;
// Input and output.
VideoStreamEncoderObserver* const encoder_stats_observer_
RTC_GUARDED_BY(resource_adaptation_queue_);
mutable Mutex resources_lock_;
std::vector<rtc::scoped_refptr<Resource>> resources_
RTC_GUARDED_BY(resources_lock_);

View File

@ -89,9 +89,9 @@ class ResourceAdaptationProcessorTest : public ::testing::Test {
resource_(FakeResource::Create("FakeResource")),
other_resource_(FakeResource::Create("OtherFakeResource")),
video_stream_adapter_(
std::make_unique<VideoStreamAdapter>(&input_state_provider_)),
std::make_unique<VideoStreamAdapter>(&input_state_provider_,
&frame_rate_provider_)),
processor_(std::make_unique<ResourceAdaptationProcessor>(
/*encoder_stats_observer=*/&frame_rate_provider_,
video_stream_adapter_.get())) {
processor_->SetResourceAdaptationQueue(TaskQueueBase::Current());
video_stream_adapter_->AddRestrictionsListener(&restrictions_listener_);

View File

@ -108,6 +108,12 @@ bool CanIncreaseFrameRateTo(int max_frame_rate,
std::numeric_limits<int>::max()));
}
bool MinPixelLimitReached(const VideoStreamInputState& input_state) {
return input_state.frame_size_pixels().has_value() &&
GetLowerResolutionThan(input_state.frame_size_pixels().value()) <
input_state.min_pixels_per_frame();
}
} // namespace
VideoSourceRestrictionsListener::~VideoSourceRestrictionsListener() = default;
@ -161,23 +167,15 @@ const char* Adaptation::StatusToString(Adaptation::Status status) {
Adaptation::Adaptation(int validation_id,
VideoSourceRestrictions restrictions,
VideoAdaptationCounters counters,
VideoStreamInputState input_state,
bool min_pixel_limit_reached)
VideoStreamInputState input_state)
: validation_id_(validation_id),
status_(Status::kValid),
min_pixel_limit_reached_(min_pixel_limit_reached),
input_state_(std::move(input_state)),
restrictions_(std::move(restrictions)),
counters_(std::move(counters)) {}
Adaptation::Adaptation(int validation_id,
Status invalid_status,
VideoStreamInputState input_state,
bool min_pixel_limit_reached)
: validation_id_(validation_id),
status_(invalid_status),
min_pixel_limit_reached_(min_pixel_limit_reached),
input_state_(std::move(input_state)) {
Adaptation::Adaptation(int validation_id, Status invalid_status)
: validation_id_(validation_id), status_(invalid_status) {
RTC_DCHECK_NE(status_, Status::kValid);
}
@ -185,10 +183,6 @@ Adaptation::Status Adaptation::status() const {
return status_;
}
bool Adaptation::min_pixel_limit_reached() const {
return min_pixel_limit_reached_;
}
const VideoStreamInputState& Adaptation::input_state() const {
return input_state_;
}
@ -202,14 +196,16 @@ const VideoAdaptationCounters& Adaptation::counters() const {
}
VideoStreamAdapter::VideoStreamAdapter(
VideoStreamInputStateProvider* input_state_provider)
VideoStreamInputStateProvider* input_state_provider,
VideoStreamEncoderObserver* encoder_stats_observer)
: input_state_provider_(input_state_provider),
balanced_settings_(),
encoder_stats_observer_(encoder_stats_observer),
adaptation_validation_id_(0),
degradation_preference_(DegradationPreference::DISABLED),
awaiting_frame_size_change_(absl::nullopt),
last_video_source_restrictions_() {
awaiting_frame_size_change_(absl::nullopt) {
sequence_checker_.Detach();
RTC_DCHECK(input_state_provider_);
RTC_DCHECK(encoder_stats_observer_);
}
VideoStreamAdapter::~VideoStreamAdapter() {
@ -299,17 +295,11 @@ void VideoStreamAdapter::SetDegradationPreference(
struct VideoStreamAdapter::RestrictionsOrStateVisitor {
Adaptation operator()(const RestrictionsWithCounters& r) const {
return Adaptation(adaptation_validation_id, r.restrictions, r.counters,
input_state, min_pixel_limit_reached());
input_state);
}
Adaptation operator()(const Adaptation::Status& status) const {
RTC_DCHECK_NE(status, Adaptation::Status::kValid);
return Adaptation(adaptation_validation_id, status, input_state,
min_pixel_limit_reached());
}
bool min_pixel_limit_reached() const {
return input_state.frame_size_pixels().has_value() &&
GetLowerResolutionThan(input_state.frame_size_pixels().value()) <
input_state.min_pixels_per_frame();
return Adaptation(adaptation_validation_id, status);
}
const int adaptation_validation_id;
@ -399,7 +389,9 @@ Adaptation VideoStreamAdapter::GetAdaptationDown() {
++adaptation_validation_id_;
RestrictionsOrState restrictions_or_state =
GetAdaptationDownStep(input_state, current_restrictions_);
if (MinPixelLimitReached(input_state)) {
encoder_stats_observer_->OnMinPixelLimitReached();
}
// Check for min_fps
if (degradation_preference_ == DegradationPreference::BALANCED &&
absl::holds_alternative<RestrictionsWithCounters>(
@ -664,7 +656,7 @@ Adaptation VideoStreamAdapter::GetAdaptationTo(
RTC_DCHECK_RUN_ON(&sequence_checker_);
VideoStreamInputState input_state = input_state_provider_->InputState();
return Adaptation(adaptation_validation_id_, restrictions, counters,
input_state, false);
input_state);
}
void VideoStreamAdapter::BroadcastVideoRestrictionsUpdate(

View File

@ -20,6 +20,7 @@
#include "api/adaptation/resource.h"
#include "api/rtp_parameters.h"
#include "api/video/video_adaptation_counters.h"
#include "api/video/video_stream_encoder_observer.h"
#include "call/adaptation/adaptation_constraint.h"
#include "call/adaptation/degradation_preference_provider.h"
#include "call/adaptation/video_source_restrictions.h"
@ -87,8 +88,6 @@ class Adaptation final {
const VideoStreamInputState& input_state() const;
const VideoSourceRestrictions& restrictions() const;
const VideoAdaptationCounters& counters() const;
// Used for stats reporting.
bool min_pixel_limit_reached() const;
private:
friend class VideoStreamAdapter;
@ -97,13 +96,9 @@ class Adaptation final {
Adaptation(int validation_id,
VideoSourceRestrictions restrictions,
VideoAdaptationCounters counters,
VideoStreamInputState input_state,
bool min_pixel_limit_reached);
VideoStreamInputState input_state);
// Constructor when adaptation is not valid. Status MUST NOT be kValid.
Adaptation(int validation_id,
Status invalid_status,
VideoStreamInputState input_state,
bool min_pixel_limit_reached);
Adaptation(int validation_id, Status invalid_status);
// An Adaptation can become invalidated if the state of VideoStreamAdapter is
// modified before the Adaptation is applied. To guard against this, this ID
@ -111,7 +106,6 @@ class Adaptation final {
// TODO(https://crbug.com/webrtc/11700): Remove the validation_id_.
const int validation_id_;
const Status status_;
const bool min_pixel_limit_reached_;
// Input state when adaptation was made.
const VideoStreamInputState input_state_;
const VideoSourceRestrictions restrictions_;
@ -126,8 +120,8 @@ class Adaptation final {
// 3. Modify the stream's restrictions in one of the valid ways.
class VideoStreamAdapter {
public:
explicit VideoStreamAdapter(
VideoStreamInputStateProvider* input_state_provider);
VideoStreamAdapter(VideoStreamInputStateProvider* input_state_provider,
VideoStreamEncoderObserver* encoder_stats_observer);
~VideoStreamAdapter();
VideoSourceRestrictions source_restrictions() const;
@ -224,6 +218,8 @@ class VideoStreamAdapter {
// Gets the input state which is the basis of all adaptations.
// Thread safe.
VideoStreamInputStateProvider* input_state_provider_;
// Used to signal when min pixel limit has been reached.
VideoStreamEncoderObserver* const encoder_stats_observer_;
// Decides the next adaptation target in DegradationPreference::BALANCED.
const BalancedDegradationSettings balanced_settings_;
// To guard against applying adaptations that have become invalidated, an

View File

@ -21,6 +21,7 @@
#include "api/video_codecs/video_encoder_config.h"
#include "call/adaptation/adaptation_constraint.h"
#include "call/adaptation/encoder_settings.h"
#include "call/adaptation/test/fake_frame_rate_provider.h"
#include "call/adaptation/test/fake_resource.h"
#include "call/adaptation/video_source_restrictions.h"
#include "call/adaptation/video_stream_input_state.h"
@ -137,7 +138,7 @@ class FakeVideoStreamAdapterListner : public VideoSourceRestrictionsListener {
VideoSourceRestrictions restrictions,
const VideoAdaptationCounters& adaptation_counters,
rtc::scoped_refptr<Resource> reason,
const VideoSourceRestrictions& unfiltered_restrictions) {
const VideoSourceRestrictions& unfiltered_restrictions) override {
calls_++;
last_restrictions_ = unfiltered_restrictions;
}
@ -172,14 +173,14 @@ class VideoStreamAdapterTest : public ::testing::Test {
public:
VideoStreamAdapterTest()
: field_trials_(BalancedFieldTrialConfig()),
input_state_provider_(),
resource_(FakeResource::Create("FakeResource")),
adapter_(&input_state_provider_) {}
adapter_(&input_state_provider_, &encoder_stats_observer_) {}
protected:
webrtc::test::ScopedFieldTrials field_trials_;
FakeVideoStreamInputStateProvider input_state_provider_;
rtc::scoped_refptr<Resource> resource_;
testing::StrictMock<MockVideoStreamEncoderObserver> encoder_stats_observer_;
VideoStreamAdapter adapter_;
};
@ -195,7 +196,6 @@ TEST_F(VideoStreamAdapterTest, MaintainFramerate_DecreasesPixelsToThreeFifths) {
kDefaultMinPixelsPerFrame);
Adaptation adaptation = adapter_.GetAdaptationDown();
EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
EXPECT_FALSE(adaptation.min_pixel_limit_reached());
adapter_.ApplyAdaptation(adaptation, nullptr);
EXPECT_EQ(static_cast<size_t>((kInputPixels * 3) / 5),
adapter_.source_restrictions().max_pixels_per_frame());
@ -212,6 +212,7 @@ TEST_F(VideoStreamAdapterTest,
adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
input_state_provider_.SetInputState(kMinPixelsPerFrame + 1, 30,
kMinPixelsPerFrame);
EXPECT_CALL(encoder_stats_observer_, OnMinPixelLimitReached());
// Even though we are above kMinPixelsPerFrame, because adapting down would
// have exceeded the limit, we are said to have reached the limit already.
// This differs from the frame rate adaptation logic, which would have clamped
@ -219,7 +220,6 @@ TEST_F(VideoStreamAdapterTest,
// step.
Adaptation adaptation = adapter_.GetAdaptationDown();
EXPECT_EQ(Adaptation::Status::kLimitReached, adaptation.status());
EXPECT_TRUE(adaptation.min_pixel_limit_reached());
}
TEST_F(VideoStreamAdapterTest, MaintainFramerate_IncreasePixelsToFiveThirds) {
@ -537,6 +537,7 @@ TEST_F(VideoStreamAdapterTest, Balanced_LimitReached) {
adapter_.GetAdaptationUp().status());
// Adapting down once result in restricted frame rate, in this case we reach
// the lowest possible frame rate immediately: kBalancedLowFrameRateFps.
EXPECT_CALL(encoder_stats_observer_, OnMinPixelLimitReached()).Times(2);
fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
EXPECT_EQ(static_cast<double>(kBalancedLowFrameRateFps),
adapter_.source_restrictions().max_frame_rate());
@ -940,7 +941,8 @@ TEST_F(VideoStreamAdapterTest, AdaptationConstraintDisallowsAdaptationsUp) {
TEST(VideoStreamAdapterDeathTest,
SetDegradationPreferenceInvalidatesAdaptations) {
FakeVideoStreamInputStateProvider input_state_provider;
VideoStreamAdapter adapter(&input_state_provider);
testing::StrictMock<MockVideoStreamEncoderObserver> encoder_stats_observer_;
VideoStreamAdapter adapter(&input_state_provider, &encoder_stats_observer_);
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
input_state_provider.SetInputState(1280 * 720, 30, kDefaultMinPixelsPerFrame);
Adaptation adaptation = adapter.GetAdaptationDown();
@ -950,7 +952,8 @@ TEST(VideoStreamAdapterDeathTest,
TEST(VideoStreamAdapterDeathTest, AdaptDownInvalidatesAdaptations) {
FakeVideoStreamInputStateProvider input_state_provider;
VideoStreamAdapter adapter(&input_state_provider);
testing::StrictMock<MockVideoStreamEncoderObserver> encoder_stats_observer_;
VideoStreamAdapter adapter(&input_state_provider, &encoder_stats_observer_);
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
input_state_provider.SetInputState(1280 * 720, 30, kDefaultMinPixelsPerFrame);
Adaptation adaptation = adapter.GetAdaptationDown();

View File

@ -341,10 +341,10 @@ VideoStreamEncoder::VideoStreamEncoder(
encoder_switch_requested_(false),
input_state_provider_(encoder_stats_observer),
video_stream_adapter_(
std::make_unique<VideoStreamAdapter>(&input_state_provider_)),
std::make_unique<VideoStreamAdapter>(&input_state_provider_,
encoder_stats_observer)),
resource_adaptation_processor_(
std::make_unique<ResourceAdaptationProcessor>(
encoder_stats_observer,
video_stream_adapter_.get())),
degradation_preference_manager_(
std::make_unique<DegradationPreferenceManager>()),