diff --git a/call/adaptation/resource_adaptation_processor.cc b/call/adaptation/resource_adaptation_processor.cc index 3c93781e14..01322b913c 100644 --- a/call/adaptation/resource_adaptation_processor.cc +++ b/call/adaptation/resource_adaptation_processor.cc @@ -68,13 +68,11 @@ ResourceAdaptationProcessor::MitigationResultAndLogMessage:: : result(result), message(std::move(message)) {} ResourceAdaptationProcessor::ResourceAdaptationProcessor( - VideoStreamInputStateProvider* input_state_provider, VideoStreamEncoderObserver* encoder_stats_observer, VideoStreamAdapter* stream_adapter) : resource_adaptation_queue_(nullptr), resource_listener_delegate_( new rtc::RefCountedObject(this)), - input_state_provider_(input_state_provider), encoder_stats_observer_(encoder_stats_observer), resources_(), degradation_preference_(DegradationPreference::DISABLED), @@ -279,15 +277,6 @@ void ResourceAdaptationProcessor::OnResourceUsageStateMeasured( } } -bool ResourceAdaptationProcessor::HasSufficientInputForAdaptation( - const VideoStreamInputState& input_state) const { - RTC_DCHECK_RUN_ON(resource_adaptation_queue_); - return input_state.HasInputFrameSizeAndFramesPerSecond() && - (effective_degradation_preference_ != - DegradationPreference::MAINTAIN_RESOLUTION || - input_state.frames_per_second() >= kMinFrameRateFps); -} - ResourceAdaptationProcessor::MitigationResultAndLogMessage ResourceAdaptationProcessor::OnResourceUnderuse( rtc::scoped_refptr reason_resource) { @@ -300,15 +289,6 @@ ResourceAdaptationProcessor::OnResourceUnderuse( MitigationResult::kDisabled, "Not adapting up because DegradationPreference is disabled"); } - VideoStreamInputState input_state = input_state_provider_->InputState(); - if (!HasSufficientInputForAdaptation(input_state)) { - processing_in_progress_ = false; - return MitigationResultAndLogMessage( - MitigationResult::kInsufficientInput, - "Not adapting up because input is insufficient"); - } - // Update video input states and encoder settings for accurate adaptation. - stream_adapter_->SetInput(input_state); // How can this stream be adapted up? Adaptation adaptation = stream_adapter_->GetAdaptationUp(); if (adaptation.status() != Adaptation::Status::kValid) { @@ -331,9 +311,9 @@ ResourceAdaptationProcessor::OnResourceUnderuse( FindMostLimitedResources(); for (const auto* constraint : adaptation_constraints_) { - if (!constraint->IsAdaptationUpAllowed(input_state, restrictions_before, - restrictions_after, - reason_resource)) { + if (!constraint->IsAdaptationUpAllowed( + adaptation.input_state(), restrictions_before, restrictions_after, + reason_resource)) { processing_in_progress_ = false; rtc::StringBuilder message; message << "Not adapting up because constraint \"" << constraint->Name() @@ -375,7 +355,8 @@ ResourceAdaptationProcessor::OnResourceUnderuse( stream_adapter_->ApplyAdaptation(adaptation, reason_resource); for (auto* adaptation_listener : adaptation_listeners_) { adaptation_listener->OnAdaptationApplied( - input_state, restrictions_before, restrictions_after, reason_resource); + adaptation.input_state(), restrictions_before, restrictions_after, + reason_resource); } processing_in_progress_ = false; rtc::StringBuilder message; @@ -397,15 +378,6 @@ ResourceAdaptationProcessor::OnResourceOveruse( MitigationResult::kDisabled, "Not adapting down because DegradationPreference is disabled"); } - VideoStreamInputState input_state = input_state_provider_->InputState(); - if (!HasSufficientInputForAdaptation(input_state)) { - processing_in_progress_ = false; - return MitigationResultAndLogMessage( - MitigationResult::kInsufficientInput, - "Not adapting down because input is insufficient"); - } - // Update video input states and encoder settings for accurate adaptation. - stream_adapter_->SetInput(input_state); // How can this stream be adapted up? Adaptation adaptation = stream_adapter_->GetAdaptationDown(); if (adaptation.min_pixel_limit_reached()) { @@ -429,7 +401,8 @@ ResourceAdaptationProcessor::OnResourceOveruse( stream_adapter_->ApplyAdaptation(adaptation, reason_resource); for (auto* adaptation_listener : adaptation_listeners_) { adaptation_listener->OnAdaptationApplied( - input_state, restrictions_before, restrictions_after, reason_resource); + adaptation.input_state(), restrictions_before, restrictions_after, + reason_resource); } processing_in_progress_ = false; rtc::StringBuilder message; @@ -527,10 +500,9 @@ void ResourceAdaptationProcessor:: most_limited.adaptation_counters, most_limited.restrictions); RTC_DCHECK_EQ(adapt_to.status(), Adaptation::Status::kValid); stream_adapter_->ApplyAdaptation(adapt_to, nullptr); - auto input_state = input_state_provider_->InputState(); for (auto* adaptation_listener : adaptation_listeners_) { adaptation_listener->OnAdaptationApplied( - input_state, removed_limitations.restrictions, + adapt_to.input_state(), removed_limitations.restrictions, most_limited.restrictions, nullptr); } diff --git a/call/adaptation/resource_adaptation_processor.h b/call/adaptation/resource_adaptation_processor.h index f9dec8946e..66f1300d3a 100644 --- a/call/adaptation/resource_adaptation_processor.h +++ b/call/adaptation/resource_adaptation_processor.h @@ -55,7 +55,6 @@ class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface, public ResourceListener { public: ResourceAdaptationProcessor( - VideoStreamInputStateProvider* input_state_provider, VideoStreamEncoderObserver* encoder_stats_observer, VideoStreamAdapter* video_stream_adapter); ~ResourceAdaptationProcessor() override; @@ -105,9 +104,6 @@ class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface, rtc::scoped_refptr reason_resource) override; private: - bool HasSufficientInputForAdaptation( - const VideoStreamInputState& input_state) const; - // If resource usage measurements happens off the adaptation task queue, this // class takes care of posting the measurement for the processor to handle it // on the adaptation task queue. @@ -131,7 +127,6 @@ class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface, enum class MitigationResult { kDisabled, - kInsufficientInput, kNotMostLimitedResource, kSharedMostLimitedResource, kRejectedByAdapter, @@ -179,8 +174,6 @@ class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface, TaskQueueBase* resource_adaptation_queue_; rtc::scoped_refptr resource_listener_delegate_; // Input and output. - VideoStreamInputStateProvider* const input_state_provider_ - RTC_GUARDED_BY(resource_adaptation_queue_); VideoStreamEncoderObserver* const encoder_stats_observer_ RTC_GUARDED_BY(resource_adaptation_queue_); std::vector resource_limitations_listeners_ diff --git a/call/adaptation/resource_adaptation_processor_unittest.cc b/call/adaptation/resource_adaptation_processor_unittest.cc index b661333337..e466c471f0 100644 --- a/call/adaptation/resource_adaptation_processor_unittest.cc +++ b/call/adaptation/resource_adaptation_processor_unittest.cc @@ -92,9 +92,9 @@ class ResourceAdaptationProcessorTest : public ::testing::Test { other_resource_(FakeResource::Create("OtherFakeResource")), adaptation_constraint_("FakeAdaptationConstraint"), adaptation_listener_(), - video_stream_adapter_(std::make_unique()), + video_stream_adapter_( + std::make_unique(&input_state_provider_)), processor_(std::make_unique( - &input_state_provider_, /*encoder_stats_observer=*/&frame_rate_provider_, video_stream_adapter_.get())) { processor_->SetResourceAdaptationQueue(TaskQueueBase::Current()); diff --git a/call/adaptation/video_stream_adapter.cc b/call/adaptation/video_stream_adapter.cc index bce27820d4..94ef25d98f 100644 --- a/call/adaptation/video_stream_adapter.cc +++ b/call/adaptation/video_stream_adapter.cc @@ -100,6 +100,8 @@ const char* Adaptation::StatusToString(Adaptation::Status status) { return "kLimitReached"; case Adaptation::Status::kAwaitingPreviousAdaptation: return "kAwaitingPreviousAdaptation"; + case Status::kInsufficientInput: + return "kInsufficientInput"; } } @@ -113,35 +115,45 @@ Adaptation::Step::Step(VideoSourceRestrictions restrictions, restrictions(restrictions), counters(counters) {} -Adaptation::Adaptation(int validation_id, Step step) +Adaptation::Adaptation(int validation_id, + Step step, + VideoStreamInputState input_state) : validation_id_(validation_id), status_(Status::kValid), step_(std::move(step)), - min_pixel_limit_reached_(false) {} + min_pixel_limit_reached_(false), + input_state_(input_state) {} Adaptation::Adaptation(int validation_id, Step step, + VideoStreamInputState input_state, bool min_pixel_limit_reached) : validation_id_(validation_id), status_(Status::kValid), step_(std::move(step)), - min_pixel_limit_reached_(min_pixel_limit_reached) {} + min_pixel_limit_reached_(min_pixel_limit_reached), + input_state_(input_state) {} -Adaptation::Adaptation(int validation_id, Status invalid_status) +Adaptation::Adaptation(int validation_id, + Status invalid_status, + VideoStreamInputState input_state) : validation_id_(validation_id), status_(invalid_status), step_(absl::nullopt), - min_pixel_limit_reached_(false) { + min_pixel_limit_reached_(false), + input_state_(input_state) { RTC_DCHECK_NE(status_, Status::kValid); } Adaptation::Adaptation(int validation_id, Status invalid_status, + VideoStreamInputState input_state, bool min_pixel_limit_reached) : validation_id_(validation_id), status_(invalid_status), step_(absl::nullopt), - min_pixel_limit_reached_(min_pixel_limit_reached) { + min_pixel_limit_reached_(min_pixel_limit_reached), + input_state_(input_state) { RTC_DCHECK_NE(status_, Status::kValid); } @@ -157,6 +169,9 @@ const Adaptation::Step& Adaptation::step() const { RTC_DCHECK_EQ(status_, Status::kValid); return step_.value(); } +const VideoStreamInputState& Adaptation::input_state() const { + return input_state_; +} // VideoSourceRestrictor is responsible for keeping track of current // VideoSourceRestrictions. @@ -329,12 +344,13 @@ class VideoStreamAdapter::VideoSourceRestrictor { VideoAdaptationCounters adaptations_; }; -VideoStreamAdapter::VideoStreamAdapter() +VideoStreamAdapter::VideoStreamAdapter( + VideoStreamInputStateProvider* input_state_provider) : source_restrictor_(std::make_unique()), + input_state_provider_(input_state_provider), balanced_settings_(), adaptation_validation_id_(0), degradation_preference_(DegradationPreference::DISABLED), - input_state_(), last_adaptation_request_(absl::nullopt), last_video_source_restrictions_() { sequence_checker_.Detach(); @@ -399,29 +415,28 @@ void VideoStreamAdapter::SetDegradationPreference( } } -void VideoStreamAdapter::SetInput(VideoStreamInputState input_state) { - // Invalidate any previously returned Adaptation. - RTC_DCHECK_RUN_ON(&sequence_checker_); - ++adaptation_validation_id_; - input_state_ = input_state; - source_restrictor_->set_min_pixels_per_frame( - input_state_.min_pixels_per_frame()); -} - -Adaptation VideoStreamAdapter::GetAdaptationUp() const { +Adaptation VideoStreamAdapter::GetAdaptationUp() { RTC_DCHECK_RUN_ON(&sequence_checker_); RTC_DCHECK_NE(degradation_preference_, DegradationPreference::DISABLED); - RTC_DCHECK(input_state_.HasInputFrameSizeAndFramesPerSecond()); + VideoStreamInputState input_state = input_state_provider_->InputState(); + ++adaptation_validation_id_; + if (!HasSufficientInputForAdaptation(input_state)) { + return Adaptation(adaptation_validation_id_, + Adaptation::Status::kInsufficientInput, input_state); + } + source_restrictor_->set_min_pixels_per_frame( + input_state.min_pixels_per_frame()); // Don't adapt if we're awaiting a previous adaptation to have an effect. bool last_request_increased_resolution = last_adaptation_request_ && last_adaptation_request_->step_type_ == Adaptation::StepType::kIncreaseResolution; if (last_request_increased_resolution && degradation_preference_ == DegradationPreference::MAINTAIN_FRAMERATE && - input_state_.frame_size_pixels().value() <= + input_state.frame_size_pixels().value() <= last_adaptation_request_->input_pixel_count_) { return Adaptation(adaptation_validation_id_, - Adaptation::Status::kAwaitingPreviousAdaptation); + Adaptation::Status::kAwaitingPreviousAdaptation, + input_state); } // Maybe propose targets based on degradation preference. @@ -429,20 +444,21 @@ Adaptation VideoStreamAdapter::GetAdaptationUp() const { case DegradationPreference::BALANCED: { // Attempt to increase target frame rate. int target_fps = - balanced_settings_.MaxFps(input_state_.video_codec_type(), - input_state_.frame_size_pixels().value()); + balanced_settings_.MaxFps(input_state.video_codec_type(), + input_state.frame_size_pixels().value()); if (source_restrictor_->CanIncreaseFrameRateTo(target_fps)) { return Adaptation( adaptation_validation_id_, Adaptation::Step(Adaptation::StepType::kIncreaseFrameRate, - target_fps)); + target_fps), + input_state); } // Scale up resolution. ABSL_FALLTHROUGH_INTENDED; } case DegradationPreference::MAINTAIN_FRAMERATE: { // Attempt to increase pixel count. - int target_pixels = input_state_.frame_size_pixels().value(); + int target_pixels = input_state.frame_size_pixels().value(); if (source_restrictor_->adaptation_counters().resolution_adaptations == 1) { RTC_LOG(LS_INFO) << "Removing resolution down-scaling setting."; @@ -451,16 +467,17 @@ Adaptation VideoStreamAdapter::GetAdaptationUp() const { target_pixels = GetHigherResolutionThan(target_pixels); if (!source_restrictor_->CanIncreaseResolutionTo(target_pixels)) { return Adaptation(adaptation_validation_id_, - Adaptation::Status::kLimitReached); + Adaptation::Status::kLimitReached, input_state); } return Adaptation( adaptation_validation_id_, Adaptation::Step(Adaptation::StepType::kIncreaseResolution, - target_pixels)); + target_pixels), + input_state); } case DegradationPreference::MAINTAIN_RESOLUTION: { // Scale up framerate. - int target_fps = input_state_.frames_per_second(); + int target_fps = input_state.frames_per_second(); if (source_restrictor_->adaptation_counters().fps_adaptations == 1) { RTC_LOG(LS_INFO) << "Removing framerate down-scaling setting."; target_fps = std::numeric_limits::max(); @@ -468,24 +485,32 @@ Adaptation VideoStreamAdapter::GetAdaptationUp() const { target_fps = GetHigherFrameRateThan(target_fps); if (!source_restrictor_->CanIncreaseFrameRateTo(target_fps)) { return Adaptation(adaptation_validation_id_, - Adaptation::Status::kLimitReached); + Adaptation::Status::kLimitReached, input_state); } return Adaptation( adaptation_validation_id_, Adaptation::Step(Adaptation::StepType::kIncreaseFrameRate, - target_fps)); + target_fps), + input_state); } case DegradationPreference::DISABLED: RTC_NOTREACHED(); return Adaptation(adaptation_validation_id_, - Adaptation::Status::kLimitReached); + Adaptation::Status::kLimitReached, input_state); } } -Adaptation VideoStreamAdapter::GetAdaptationDown() const { +Adaptation VideoStreamAdapter::GetAdaptationDown() { RTC_DCHECK_RUN_ON(&sequence_checker_); RTC_DCHECK_NE(degradation_preference_, DegradationPreference::DISABLED); - RTC_DCHECK(input_state_.HasInputFrameSizeAndFramesPerSecond()); + VideoStreamInputState input_state = input_state_provider_->InputState(); + ++adaptation_validation_id_; + if (!HasSufficientInputForAdaptation(input_state)) { + return Adaptation(adaptation_validation_id_, + Adaptation::Status::kInsufficientInput, input_state); + } + source_restrictor_->set_min_pixels_per_frame( + input_state.min_pixels_per_frame()); // Don't adapt if we're awaiting a previous adaptation to have an effect or // if we switched degradation preference. bool last_request_decreased_resolution = @@ -493,10 +518,11 @@ Adaptation VideoStreamAdapter::GetAdaptationDown() const { Adaptation::StepType::kDecreaseResolution; if (last_request_decreased_resolution && degradation_preference_ == DegradationPreference::MAINTAIN_FRAMERATE && - input_state_.frame_size_pixels().value() >= + input_state.frame_size_pixels().value() >= last_adaptation_request_->input_pixel_count_) { return Adaptation(adaptation_validation_id_, - Adaptation::Status::kAwaitingPreviousAdaptation); + Adaptation::Status::kAwaitingPreviousAdaptation, + input_state); } // Maybe propose targets based on degradation preference. @@ -504,13 +530,14 @@ Adaptation VideoStreamAdapter::GetAdaptationDown() const { case DegradationPreference::BALANCED: { // Try scale down framerate, if lower. int target_fps = - balanced_settings_.MinFps(input_state_.video_codec_type(), - input_state_.frame_size_pixels().value()); + balanced_settings_.MinFps(input_state.video_codec_type(), + input_state.frame_size_pixels().value()); if (source_restrictor_->CanDecreaseFrameRateTo(target_fps)) { return Adaptation( adaptation_validation_id_, Adaptation::Step(Adaptation::StepType::kDecreaseFrameRate, - target_fps)); + target_fps), + input_state); } // Scale down resolution. ABSL_FALLTHROUGH_INTENDED; @@ -518,35 +545,36 @@ Adaptation VideoStreamAdapter::GetAdaptationDown() const { case DegradationPreference::MAINTAIN_FRAMERATE: { // Scale down resolution. int target_pixels = - GetLowerResolutionThan(input_state_.frame_size_pixels().value()); + GetLowerResolutionThan(input_state.frame_size_pixels().value()); bool min_pixel_limit_reached = target_pixels < source_restrictor_->min_pixels_per_frame(); if (!source_restrictor_->CanDecreaseResolutionTo(target_pixels)) { return Adaptation(adaptation_validation_id_, - Adaptation::Status::kLimitReached, + Adaptation::Status::kLimitReached, input_state, min_pixel_limit_reached); } return Adaptation( adaptation_validation_id_, Adaptation::Step(Adaptation::StepType::kDecreaseResolution, target_pixels), - min_pixel_limit_reached); + input_state, min_pixel_limit_reached); } case DegradationPreference::MAINTAIN_RESOLUTION: { - int target_fps = GetLowerFrameRateThan(input_state_.frames_per_second()); + int target_fps = GetLowerFrameRateThan(input_state.frames_per_second()); if (!source_restrictor_->CanDecreaseFrameRateTo(target_fps)) { return Adaptation(adaptation_validation_id_, - Adaptation::Status::kLimitReached); + Adaptation::Status::kLimitReached, input_state); } return Adaptation( adaptation_validation_id_, Adaptation::Step(Adaptation::StepType::kDecreaseFrameRate, - target_fps)); + target_fps), + input_state); } case DegradationPreference::DISABLED: RTC_NOTREACHED(); return Adaptation(adaptation_validation_id_, - Adaptation::Status::kLimitReached); + Adaptation::Status::kLimitReached, input_state); } } @@ -577,8 +605,8 @@ void VideoStreamAdapter::ApplyAdaptation( // Remember the input pixels and fps of this adaptation. Used to avoid // adapting again before this adaptation has had an effect. last_adaptation_request_.emplace(AdaptationRequest{ - input_state_.frame_size_pixels().value(), - input_state_.frames_per_second(), adaptation.step().type}); + adaptation.input_state_.frame_size_pixels().value(), + adaptation.input_state_.frames_per_second(), adaptation.step().type}); // Adapt! source_restrictor_->ApplyAdaptationStep(adaptation.step(), degradation_preference_); @@ -587,11 +615,12 @@ void VideoStreamAdapter::ApplyAdaptation( Adaptation VideoStreamAdapter::GetAdaptationTo( const VideoAdaptationCounters& counters, - const VideoSourceRestrictions& restrictions) const { + const VideoSourceRestrictions& restrictions) { // Adapts up/down from the current levels so counters are equal. RTC_DCHECK_RUN_ON(&sequence_checker_); + VideoStreamInputState input_state = input_state_provider_->InputState(); return Adaptation(adaptation_validation_id_, - Adaptation::Step(restrictions, counters)); + Adaptation::Step(restrictions, counters), input_state); } void VideoStreamAdapter::BroadcastVideoRestrictionsUpdate( @@ -611,4 +640,12 @@ void VideoStreamAdapter::BroadcastVideoRestrictionsUpdate( last_filtered_restrictions_ = filtered; } +bool VideoStreamAdapter::HasSufficientInputForAdaptation( + const VideoStreamInputState& input_state) const { + return input_state.HasInputFrameSizeAndFramesPerSecond() && + (degradation_preference_ != + DegradationPreference::MAINTAIN_RESOLUTION || + input_state.frames_per_second() >= kMinFrameRateFps); +} + } // namespace webrtc diff --git a/call/adaptation/video_stream_adapter.h b/call/adaptation/video_stream_adapter.h index c82569d985..216c36c2bd 100644 --- a/call/adaptation/video_stream_adapter.h +++ b/call/adaptation/video_stream_adapter.h @@ -20,6 +20,7 @@ #include "api/video/video_adaptation_counters.h" #include "call/adaptation/video_source_restrictions.h" #include "call/adaptation/video_stream_input_state.h" +#include "call/adaptation/video_stream_input_state_provider.h" #include "modules/video_coding/utility/quality_scaler.h" #include "rtc_base/experiments/balanced_degradation_settings.h" @@ -67,6 +68,8 @@ class Adaptation final { // adaptation has not yet been reflected in the input resolution or frame // rate; adaptation is refused to avoid "double-adapting". kAwaitingPreviousAdaptation, + // Not enough input. + kInsufficientInput, }; static const char* StatusToString(Status status); @@ -77,6 +80,8 @@ class Adaptation final { // Used for stats reporting. bool min_pixel_limit_reached() const; + const VideoStreamInputState& input_state() const; + private: // The adapter needs to know about step type and step target in order to // construct and perform an Adaptation, which is a detail we do not want to @@ -107,12 +112,18 @@ class Adaptation final { }; // Constructs with a valid adaptation Step. Status is kValid. - Adaptation(int validation_id, Step step); - Adaptation(int validation_id, Step step, bool min_pixel_limit_reached); + Adaptation(int validation_id, Step step, VideoStreamInputState input_state); + Adaptation(int validation_id, + Step step, + VideoStreamInputState input_state, + bool min_pixel_limit_reached); // Constructor when adaptation is not valid. Status MUST NOT be kValid. - Adaptation(int validation_id, Status invalid_status); Adaptation(int validation_id, Status invalid_status, + VideoStreamInputState input_state); + Adaptation(int validation_id, + Status invalid_status, + VideoStreamInputState input_state, bool min_pixel_limit_reached); const Step& step() const; // Only callable if |status_| is kValid. @@ -124,6 +135,8 @@ class Adaptation final { const Status status_; const absl::optional step_; // Only present if |status_| is kValid. const bool min_pixel_limit_reached_; + // Input state when adaptation was made. + const VideoStreamInputState input_state_; }; // Owns the VideoSourceRestriction for a single stream and is responsible for @@ -134,7 +147,8 @@ class Adaptation final { // 3. Modify the stream's restrictions in one of the valid ways. class VideoStreamAdapter { public: - VideoStreamAdapter(); + explicit VideoStreamAdapter( + VideoStreamInputStateProvider* input_state_provider); ~VideoStreamAdapter(); VideoSourceRestrictions source_restrictions() const; @@ -150,15 +164,13 @@ class VideoStreamAdapter { // 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. void SetDegradationPreference(DegradationPreference degradation_preference); - // The adaptaiton logic depends on these inputs. - void SetInput(VideoStreamInputState input_state); // Returns an adaptation that we are guaranteed to be able to apply, or a // status code indicating the reason why we cannot adapt. - Adaptation GetAdaptationUp() const; - Adaptation GetAdaptationDown() const; + Adaptation GetAdaptationUp(); + Adaptation GetAdaptationDown(); Adaptation GetAdaptationTo(const VideoAdaptationCounters& counters, - const VideoSourceRestrictions& restrictions) const; + const VideoSourceRestrictions& restrictions); struct RestrictionsWithCounters { VideoSourceRestrictions restrictions; @@ -192,6 +204,9 @@ class VideoStreamAdapter { void BroadcastVideoRestrictionsUpdate( const rtc::scoped_refptr& resource); + bool HasSufficientInputForAdaptation(const VideoStreamInputState& input_state) + const RTC_RUN_ON(&sequence_checker_); + // The input frame rate and resolution at the time of an adaptation in the // direction described by |mode_| (up or down). // TODO(https://crbug.com/webrtc/11393): Can this be renamed? Can this be @@ -209,6 +224,9 @@ class VideoStreamAdapter { // Owner and modifier of the VideoSourceRestriction of this stream adaptor. const std::unique_ptr source_restrictor_ RTC_GUARDED_BY(&sequence_checker_); + // Gets the input state which is the basis of all adaptations. + // Thread safe. + VideoStreamInputStateProvider* input_state_provider_; // Decides the next adaptation target in DegradationPreference::BALANCED. const BalancedDegradationSettings balanced_settings_; // To guard against applying adaptations that have become invalidated, an @@ -219,7 +237,6 @@ class VideoStreamAdapter { // https://w3c.github.io/mst-content-hint/#dom-rtcdegradationpreference DegradationPreference degradation_preference_ RTC_GUARDED_BY(&sequence_checker_); - VideoStreamInputState input_state_ RTC_GUARDED_BY(&sequence_checker_); // The input frame rate, resolution and adaptation direction of the last // ApplyAdaptationTarget(). Used to avoid adapting twice if a recent // adaptation has not had an effect on the input frame rate or resolution yet. diff --git a/call/adaptation/video_stream_adapter_unittest.cc b/call/adaptation/video_stream_adapter_unittest.cc index ebb0a0f10a..87e1f67501 100644 --- a/call/adaptation/video_stream_adapter_unittest.cc +++ b/call/adaptation/video_stream_adapter_unittest.cc @@ -20,6 +20,7 @@ #include "api/video_codecs/video_encoder_config.h" #include "call/adaptation/encoder_settings.h" #include "call/adaptation/video_source_restrictions.h" +#include "call/adaptation/video_stream_input_state.h" #include "rtc_base/string_encode.h" #include "test/field_trial.h" #include "test/gmock.h" @@ -49,16 +50,27 @@ std::string BalancedFieldTrialConfig() { rtc::ToString(kBalancedHighFrameRateFps) + "/"; } -VideoStreamInputState InputState(int input_pixels, - int input_fps, - int min_pixels_per_frame) { - VideoStreamInputState input_state; - input_state.set_has_input(true); - input_state.set_frame_size_pixels(input_pixels); - input_state.set_frames_per_second(input_fps); - input_state.set_min_pixels_per_frame(min_pixels_per_frame); - return input_state; -} +class FakeVideoStreamInputStateProvider : public VideoStreamInputStateProvider { + public: + FakeVideoStreamInputStateProvider() + : VideoStreamInputStateProvider(nullptr) {} + virtual ~FakeVideoStreamInputStateProvider() = default; + + void SetInputState(int input_pixels, + int input_fps, + int min_pixels_per_frame) { + VideoStreamInputState input_state; + input_state.set_has_input(true); + input_state.set_frame_size_pixels(input_pixels); + input_state.set_frames_per_second(input_fps); + input_state.set_min_pixels_per_frame(min_pixels_per_frame); + fake_input_state_ = input_state; + } + VideoStreamInputState InputState() override { return fake_input_state_; } + + private: + VideoStreamInputState fake_input_state_; +}; // Responsible for adjusting the inputs to VideoStreamAdapter (SetInput), such // as pixels and frame rate, according to the most recent source restrictions. @@ -68,15 +80,16 @@ VideoStreamInputState InputState(int input_pixels, class FakeVideoStream { public: FakeVideoStream(VideoStreamAdapter* adapter, + FakeVideoStreamInputStateProvider* provider, int input_pixels, int input_fps, int min_pixels_per_frame) : adapter_(adapter), + provider_(provider), input_pixels_(input_pixels), input_fps_(input_fps), min_pixels_per_frame_(min_pixels_per_frame) { - adapter_->SetInput( - InputState(input_pixels_, input_fps_, min_pixels_per_frame_)); + provider_->SetInputState(input_pixels_, input_fps_, min_pixels_per_frame_); } int input_pixels() const { return input_pixels_; } @@ -99,12 +112,12 @@ class FakeVideoStream { if (restrictions.max_frame_rate().has_value()) { input_fps_ = restrictions.max_frame_rate().value(); } - adapter_->SetInput( - InputState(input_pixels_, input_fps_, min_pixels_per_frame_)); + provider_->SetInputState(input_pixels_, input_fps_, min_pixels_per_frame_); } private: VideoStreamAdapter* adapter_; + FakeVideoStreamInputStateProvider* provider_; int input_pixels_; int input_fps_; int min_pixels_per_frame_; @@ -134,188 +147,191 @@ class FakeVideoStreamAdapterListner : public VideoSourceRestrictionsListener { } // namespace -TEST(VideoStreamAdapterTest, NoRestrictionsByDefault) { - VideoStreamAdapter adapter; - EXPECT_EQ(VideoSourceRestrictions(), adapter.source_restrictions()); - EXPECT_EQ(0, adapter.adaptation_counters().Total()); +class VideoStreamAdapterTest : public ::testing::Test { + public: + VideoStreamAdapterTest() + : field_trials_(BalancedFieldTrialConfig()), + input_state_provider_(), + adapter_(&input_state_provider_) {} + + protected: + webrtc::test::ScopedFieldTrials field_trials_; + FakeVideoStreamInputStateProvider input_state_provider_; + VideoStreamAdapter adapter_; +}; + +TEST_F(VideoStreamAdapterTest, NoRestrictionsByDefault) { + EXPECT_EQ(VideoSourceRestrictions(), adapter_.source_restrictions()); + EXPECT_EQ(0, adapter_.adaptation_counters().Total()); } -TEST(VideoStreamAdapterTest, MaintainFramerate_DecreasesPixelsToThreeFifths) { +TEST_F(VideoStreamAdapterTest, MaintainFramerate_DecreasesPixelsToThreeFifths) { const int kInputPixels = 1280 * 720; - VideoStreamAdapter adapter; - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); - adapter.SetInput(InputState(kInputPixels, 30, kDefaultMinPixelsPerFrame)); - Adaptation adaptation = adapter.GetAdaptationDown(); + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); + input_state_provider_.SetInputState(kInputPixels, 30, + kDefaultMinPixelsPerFrame); + Adaptation adaptation = adapter_.GetAdaptationDown(); EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); EXPECT_FALSE(adaptation.min_pixel_limit_reached()); - adapter.ApplyAdaptation(adaptation, nullptr); + adapter_.ApplyAdaptation(adaptation, nullptr); EXPECT_EQ(static_cast((kInputPixels * 3) / 5), - adapter.source_restrictions().max_pixels_per_frame()); + adapter_.source_restrictions().max_pixels_per_frame()); EXPECT_EQ(absl::nullopt, - adapter.source_restrictions().target_pixels_per_frame()); - EXPECT_EQ(absl::nullopt, adapter.source_restrictions().max_frame_rate()); - EXPECT_EQ(1, adapter.adaptation_counters().resolution_adaptations); + adapter_.source_restrictions().target_pixels_per_frame()); + EXPECT_EQ(absl::nullopt, adapter_.source_restrictions().max_frame_rate()); + EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); } -TEST(VideoStreamAdapterTest, MaintainFramerate_DecreasesPixelsToLimitReached) { +TEST_F(VideoStreamAdapterTest, + MaintainFramerate_DecreasesPixelsToLimitReached) { const int kMinPixelsPerFrame = 640 * 480; - VideoStreamAdapter adapter; - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); - adapter.SetInput(InputState(kMinPixelsPerFrame + 1, 30, kMinPixelsPerFrame)); + + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); + input_state_provider_.SetInputState(kMinPixelsPerFrame + 1, 30, + kMinPixelsPerFrame); // 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 // to the limit in the first step and reported kLimitReached in the second // step. - Adaptation adaptation = adapter.GetAdaptationDown(); + Adaptation adaptation = adapter_.GetAdaptationDown(); EXPECT_EQ(Adaptation::Status::kLimitReached, adaptation.status()); EXPECT_TRUE(adaptation.min_pixel_limit_reached()); } -TEST(VideoStreamAdapterTest, MaintainFramerate_IncreasePixelsToFiveThirds) { - VideoStreamAdapter adapter; - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); - FakeVideoStream fake_stream(&adapter, 1280 * 720, 30, +TEST_F(VideoStreamAdapterTest, MaintainFramerate_IncreasePixelsToFiveThirds) { + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); + FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, kDefaultMinPixelsPerFrame); // Go down twice, ensuring going back up is still a restricted resolution. - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); - EXPECT_EQ(2, adapter.adaptation_counters().resolution_adaptations); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); + EXPECT_EQ(2, adapter_.adaptation_counters().resolution_adaptations); int input_pixels = fake_stream.input_pixels(); // Go up once. The target is 5/3 and the max is 12/5 of the target. const int target = (input_pixels * 5) / 3; - fake_stream.ApplyAdaptation(adapter.GetAdaptationUp()); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationUp()); EXPECT_EQ(static_cast((target * 12) / 5), - adapter.source_restrictions().max_pixels_per_frame()); + adapter_.source_restrictions().max_pixels_per_frame()); EXPECT_EQ(static_cast(target), - adapter.source_restrictions().target_pixels_per_frame()); - EXPECT_EQ(absl::nullopt, adapter.source_restrictions().max_frame_rate()); - EXPECT_EQ(1, adapter.adaptation_counters().resolution_adaptations); + adapter_.source_restrictions().target_pixels_per_frame()); + EXPECT_EQ(absl::nullopt, adapter_.source_restrictions().max_frame_rate()); + EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); } -TEST(VideoStreamAdapterTest, MaintainFramerate_IncreasePixelsToUnrestricted) { - VideoStreamAdapter adapter; - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); - FakeVideoStream fake_stream(&adapter, 1280 * 720, 30, +TEST_F(VideoStreamAdapterTest, MaintainFramerate_IncreasePixelsToUnrestricted) { + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); + FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, kDefaultMinPixelsPerFrame); // We are unrestricted by default and should not be able to adapt up. EXPECT_EQ(Adaptation::Status::kLimitReached, - adapter.GetAdaptationUp().status()); + adapter_.GetAdaptationUp().status()); // If we go down once and then back up we should not have any restrictions. - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); - EXPECT_EQ(1, adapter.adaptation_counters().resolution_adaptations); - fake_stream.ApplyAdaptation(adapter.GetAdaptationUp()); - EXPECT_EQ(VideoSourceRestrictions(), adapter.source_restrictions()); - EXPECT_EQ(0, adapter.adaptation_counters().Total()); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); + EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationUp()); + EXPECT_EQ(VideoSourceRestrictions(), adapter_.source_restrictions()); + EXPECT_EQ(0, adapter_.adaptation_counters().Total()); } -TEST(VideoStreamAdapterTest, MaintainResolution_DecreasesFpsToTwoThirds) { +TEST_F(VideoStreamAdapterTest, MaintainResolution_DecreasesFpsToTwoThirds) { const int kInputFps = 30; - VideoStreamAdapter adapter; - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); - adapter.SetInput( - InputState(1280 * 720, kInputFps, kDefaultMinPixelsPerFrame)); - Adaptation adaptation = adapter.GetAdaptationDown(); + + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); + input_state_provider_.SetInputState(1280 * 720, kInputFps, + kDefaultMinPixelsPerFrame); + Adaptation adaptation = adapter_.GetAdaptationDown(); EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); - adapter.ApplyAdaptation(adaptation, nullptr); + adapter_.ApplyAdaptation(adaptation, nullptr); EXPECT_EQ(absl::nullopt, - adapter.source_restrictions().max_pixels_per_frame()); + adapter_.source_restrictions().max_pixels_per_frame()); EXPECT_EQ(absl::nullopt, - adapter.source_restrictions().target_pixels_per_frame()); + adapter_.source_restrictions().target_pixels_per_frame()); EXPECT_EQ(static_cast((kInputFps * 2) / 3), - adapter.source_restrictions().max_frame_rate()); - EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations); + adapter_.source_restrictions().max_frame_rate()); + EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); } -TEST(VideoStreamAdapterTest, MaintainResolution_DecreasesFpsToLimitReached) { - VideoStreamAdapter adapter; - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); - FakeVideoStream fake_stream(&adapter, 1280 * 720, kMinFrameRateFps + 1, - kDefaultMinPixelsPerFrame); +TEST_F(VideoStreamAdapterTest, MaintainResolution_DecreasesFpsToLimitReached) { + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); + FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, + kMinFrameRateFps + 1, kDefaultMinPixelsPerFrame); // If we are not yet at the limit and the next step would exceed it, the step // is clamped such that we end up exactly on the limit. - Adaptation adaptation = adapter.GetAdaptationDown(); + Adaptation adaptation = adapter_.GetAdaptationDown(); EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); fake_stream.ApplyAdaptation(adaptation); EXPECT_EQ(static_cast(kMinFrameRateFps), - adapter.source_restrictions().max_frame_rate()); - EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations); + adapter_.source_restrictions().max_frame_rate()); + EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); // Having reached the limit, the next adaptation down is not valid. EXPECT_EQ(Adaptation::Status::kLimitReached, - adapter.GetAdaptationDown().status()); + adapter_.GetAdaptationDown().status()); } -TEST(VideoStreamAdapterTest, MaintainResolution_IncreaseFpsToThreeHalves) { - VideoStreamAdapter adapter; - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); - FakeVideoStream fake_stream(&adapter, 1280 * 720, 30, +TEST_F(VideoStreamAdapterTest, MaintainResolution_IncreaseFpsToThreeHalves) { + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); + FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, kDefaultMinPixelsPerFrame); // Go down twice, ensuring going back up is still a restricted frame rate. - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); - EXPECT_EQ(2, adapter.adaptation_counters().fps_adaptations); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); + EXPECT_EQ(2, adapter_.adaptation_counters().fps_adaptations); int input_fps = fake_stream.input_fps(); // Go up once. The target is 3/2 of the input. - Adaptation adaptation = adapter.GetAdaptationUp(); + Adaptation adaptation = adapter_.GetAdaptationUp(); EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); fake_stream.ApplyAdaptation(adaptation); EXPECT_EQ(absl::nullopt, - adapter.source_restrictions().max_pixels_per_frame()); + adapter_.source_restrictions().max_pixels_per_frame()); EXPECT_EQ(absl::nullopt, - adapter.source_restrictions().target_pixels_per_frame()); + adapter_.source_restrictions().target_pixels_per_frame()); EXPECT_EQ(static_cast((input_fps * 3) / 2), - adapter.source_restrictions().max_frame_rate()); - EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations); + adapter_.source_restrictions().max_frame_rate()); + EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); } -TEST(VideoStreamAdapterTest, MaintainResolution_IncreaseFpsToUnrestricted) { - VideoStreamAdapter adapter; - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); - FakeVideoStream fake_stream(&adapter, 1280 * 720, 30, +TEST_F(VideoStreamAdapterTest, MaintainResolution_IncreaseFpsToUnrestricted) { + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); + FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, kDefaultMinPixelsPerFrame); // We are unrestricted by default and should not be able to adapt up. EXPECT_EQ(Adaptation::Status::kLimitReached, - adapter.GetAdaptationUp().status()); + adapter_.GetAdaptationUp().status()); // If we go down once and then back up we should not have any restrictions. - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); - EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations); - fake_stream.ApplyAdaptation(adapter.GetAdaptationUp()); - EXPECT_EQ(VideoSourceRestrictions(), adapter.source_restrictions()); - EXPECT_EQ(0, adapter.adaptation_counters().Total()); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); + EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationUp()); + EXPECT_EQ(VideoSourceRestrictions(), adapter_.source_restrictions()); + EXPECT_EQ(0, adapter_.adaptation_counters().Total()); } -TEST(VideoStreamAdapterTest, Balanced_DecreaseFrameRate) { - webrtc::test::ScopedFieldTrials balanced_field_trials( - BalancedFieldTrialConfig()); - VideoStreamAdapter adapter; - adapter.SetDegradationPreference(DegradationPreference::BALANCED); - adapter.SetInput(InputState(kBalancedMediumResolutionPixels, - kBalancedHighFrameRateFps, - kDefaultMinPixelsPerFrame)); +TEST_F(VideoStreamAdapterTest, Balanced_DecreaseFrameRate) { + adapter_.SetDegradationPreference(DegradationPreference::BALANCED); + input_state_provider_.SetInputState(kBalancedMediumResolutionPixels, + kBalancedHighFrameRateFps, + kDefaultMinPixelsPerFrame); // If our frame rate is higher than the frame rate associated with our // resolution we should try to adapt to the frame rate associated with our // resolution: kBalancedMediumFrameRateFps. - Adaptation adaptation = adapter.GetAdaptationDown(); + Adaptation adaptation = adapter_.GetAdaptationDown(); EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); - adapter.ApplyAdaptation(adaptation, nullptr); + adapter_.ApplyAdaptation(adaptation, nullptr); EXPECT_EQ(absl::nullopt, - adapter.source_restrictions().max_pixels_per_frame()); + adapter_.source_restrictions().max_pixels_per_frame()); EXPECT_EQ(absl::nullopt, - adapter.source_restrictions().target_pixels_per_frame()); + adapter_.source_restrictions().target_pixels_per_frame()); EXPECT_EQ(static_cast(kBalancedMediumFrameRateFps), - adapter.source_restrictions().max_frame_rate()); - EXPECT_EQ(0, adapter.adaptation_counters().resolution_adaptations); - EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations); + adapter_.source_restrictions().max_frame_rate()); + EXPECT_EQ(0, adapter_.adaptation_counters().resolution_adaptations); + EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); } -TEST(VideoStreamAdapterTest, Balanced_DecreaseResolution) { - webrtc::test::ScopedFieldTrials balanced_field_trials( - BalancedFieldTrialConfig()); - VideoStreamAdapter adapter; - adapter.SetDegradationPreference(DegradationPreference::BALANCED); - FakeVideoStream fake_stream(&adapter, kBalancedHighResolutionPixels, - kBalancedHighFrameRateFps, - kDefaultMinPixelsPerFrame); +TEST_F(VideoStreamAdapterTest, Balanced_DecreaseResolution) { + adapter_.SetDegradationPreference(DegradationPreference::BALANCED); + FakeVideoStream fake_stream( + &adapter_, &input_state_provider_, kBalancedHighResolutionPixels, + kBalancedHighFrameRateFps, kDefaultMinPixelsPerFrame); // If we are not below the current resolution's frame rate limit, we should // adapt resolution according to "maintain-framerate" logic (three fifths). // @@ -325,35 +341,35 @@ TEST(VideoStreamAdapterTest, Balanced_DecreaseResolution) { // does prevent the source from going higher, though, so it's technically not // a NO-OP. { - Adaptation adaptation = adapter.GetAdaptationDown(); + Adaptation adaptation = adapter_.GetAdaptationDown(); EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); fake_stream.ApplyAdaptation(adaptation); } EXPECT_EQ(absl::nullopt, - adapter.source_restrictions().max_pixels_per_frame()); + adapter_.source_restrictions().max_pixels_per_frame()); EXPECT_EQ(absl::nullopt, - adapter.source_restrictions().target_pixels_per_frame()); + adapter_.source_restrictions().target_pixels_per_frame()); EXPECT_EQ(static_cast(kBalancedHighFrameRateFps), - adapter.source_restrictions().max_frame_rate()); - EXPECT_EQ(0, adapter.adaptation_counters().resolution_adaptations); - EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations); + adapter_.source_restrictions().max_frame_rate()); + EXPECT_EQ(0, adapter_.adaptation_counters().resolution_adaptations); + EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); // Verify "maintain-framerate" logic the second time we adapt: Frame rate // restrictions remains the same and resolution goes down. { - Adaptation adaptation = adapter.GetAdaptationDown(); + Adaptation adaptation = adapter_.GetAdaptationDown(); EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); fake_stream.ApplyAdaptation(adaptation); } constexpr size_t kReducedPixelsFirstStep = static_cast((kBalancedHighResolutionPixels * 3) / 5); EXPECT_EQ(kReducedPixelsFirstStep, - adapter.source_restrictions().max_pixels_per_frame()); + adapter_.source_restrictions().max_pixels_per_frame()); EXPECT_EQ(absl::nullopt, - adapter.source_restrictions().target_pixels_per_frame()); + adapter_.source_restrictions().target_pixels_per_frame()); EXPECT_EQ(static_cast(kBalancedHighFrameRateFps), - adapter.source_restrictions().max_frame_rate()); - EXPECT_EQ(1, adapter.adaptation_counters().resolution_adaptations); - EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations); + adapter_.source_restrictions().max_frame_rate()); + EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); + EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); // If we adapt again, because the balanced settings' proposed frame rate is // still kBalancedHighFrameRateFps, "maintain-framerate" will trigger again. static_assert(kReducedPixelsFirstStep > kBalancedMediumResolutionPixels, @@ -361,18 +377,18 @@ TEST(VideoStreamAdapterTest, Balanced_DecreaseResolution) { "balanced setting resolution"); constexpr size_t kReducedPixelsSecondStep = (kReducedPixelsFirstStep * 3) / 5; { - Adaptation adaptation = adapter.GetAdaptationDown(); + Adaptation adaptation = adapter_.GetAdaptationDown(); EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); fake_stream.ApplyAdaptation(adaptation); } EXPECT_EQ(kReducedPixelsSecondStep, - adapter.source_restrictions().max_pixels_per_frame()); + adapter_.source_restrictions().max_pixels_per_frame()); EXPECT_EQ(absl::nullopt, - adapter.source_restrictions().target_pixels_per_frame()); + adapter_.source_restrictions().target_pixels_per_frame()); EXPECT_EQ(static_cast(kBalancedHighFrameRateFps), - adapter.source_restrictions().max_frame_rate()); - EXPECT_EQ(2, adapter.adaptation_counters().resolution_adaptations); - EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations); + adapter_.source_restrictions().max_frame_rate()); + EXPECT_EQ(2, adapter_.adaptation_counters().resolution_adaptations); + EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); } // Testing when to adapt frame rate and when to adapt resolution is quite @@ -382,14 +398,11 @@ TEST(VideoStreamAdapterTest, Balanced_DecreaseResolution) { // adapt up we don't do it in the reverse order. Instead we always try to adapt // frame rate first according to balanced settings' configs and only when the // frame rate is already achieved do we adjust the resolution. -TEST(VideoStreamAdapterTest, Balanced_IncreaseFrameRateAndResolution) { - webrtc::test::ScopedFieldTrials balanced_field_trials( - BalancedFieldTrialConfig()); - VideoStreamAdapter adapter; - adapter.SetDegradationPreference(DegradationPreference::BALANCED); - FakeVideoStream fake_stream(&adapter, kBalancedHighResolutionPixels, - kBalancedHighFrameRateFps, - kDefaultMinPixelsPerFrame); +TEST_F(VideoStreamAdapterTest, Balanced_IncreaseFrameRateAndResolution) { + adapter_.SetDegradationPreference(DegradationPreference::BALANCED); + FakeVideoStream fake_stream( + &adapter_, &input_state_provider_, kBalancedHighResolutionPixels, + kBalancedHighFrameRateFps, kDefaultMinPixelsPerFrame); // The desired starting point of this test is having adapted frame rate twice. // This requires performing a number of adaptations. constexpr size_t kReducedPixelsFirstStep = @@ -407,41 +420,41 @@ TEST(VideoStreamAdapterTest, Balanced_IncreaseFrameRateAndResolution) { "settings' medium pixel configuration"); // The first adaptation should affect the frame rate: See // Balanced_DecreaseResolution for explanation why. - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); EXPECT_EQ(static_cast(kBalancedHighFrameRateFps), - adapter.source_restrictions().max_frame_rate()); + adapter_.source_restrictions().max_frame_rate()); // The next three adaptations affects the resolution, because we have to reach // kBalancedMediumResolutionPixels before a lower frame rate is considered by // BalancedDegradationSettings. The number three is derived from the // static_asserts above. - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); EXPECT_EQ(kReducedPixelsFirstStep, - adapter.source_restrictions().max_pixels_per_frame()); - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); + adapter_.source_restrictions().max_pixels_per_frame()); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); EXPECT_EQ(kReducedPixelsSecondStep, - adapter.source_restrictions().max_pixels_per_frame()); - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); + adapter_.source_restrictions().max_pixels_per_frame()); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); EXPECT_EQ(kReducedPixelsThirdStep, - adapter.source_restrictions().max_pixels_per_frame()); + adapter_.source_restrictions().max_pixels_per_frame()); // Thus, the next adaptation will reduce frame rate to // kBalancedMediumFrameRateFps. - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); EXPECT_EQ(static_cast(kBalancedMediumFrameRateFps), - adapter.source_restrictions().max_frame_rate()); - EXPECT_EQ(3, adapter.adaptation_counters().resolution_adaptations); - EXPECT_EQ(2, adapter.adaptation_counters().fps_adaptations); + adapter_.source_restrictions().max_frame_rate()); + EXPECT_EQ(3, adapter_.adaptation_counters().resolution_adaptations); + EXPECT_EQ(2, adapter_.adaptation_counters().fps_adaptations); // Adapt up! // While our resolution is in the medium-range, the frame rate associated with // the next resolution configuration up ("high") is kBalancedHighFrameRateFps // and "balanced" prefers adapting frame rate if not already applied. { - Adaptation adaptation = adapter.GetAdaptationUp(); + Adaptation adaptation = adapter_.GetAdaptationUp(); EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); fake_stream.ApplyAdaptation(adaptation); EXPECT_EQ(static_cast(kBalancedHighFrameRateFps), - adapter.source_restrictions().max_frame_rate()); - EXPECT_EQ(3, adapter.adaptation_counters().resolution_adaptations); - EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations); + adapter_.source_restrictions().max_frame_rate()); + EXPECT_EQ(3, adapter_.adaptation_counters().resolution_adaptations); + EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); } // Now that we have already achieved the next frame rate up, we act according // to "maintain-framerate". We go back up in resolution. Due to rounding @@ -451,63 +464,60 @@ TEST(VideoStreamAdapterTest, Balanced_IncreaseFrameRateAndResolution) { constexpr size_t kReducedPixelsSecondStepUp = (kReducedPixelsThirdStep * 5) / 3; { - Adaptation adaptation = adapter.GetAdaptationUp(); + Adaptation adaptation = adapter_.GetAdaptationUp(); EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); fake_stream.ApplyAdaptation(adaptation); EXPECT_EQ(kReducedPixelsSecondStepUp, - adapter.source_restrictions().target_pixels_per_frame()); - EXPECT_EQ(2, adapter.adaptation_counters().resolution_adaptations); - EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations); + adapter_.source_restrictions().target_pixels_per_frame()); + EXPECT_EQ(2, adapter_.adaptation_counters().resolution_adaptations); + EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); } // Now that our resolution is back in the high-range, the next frame rate to // try out is "unlimited". { - Adaptation adaptation = adapter.GetAdaptationUp(); + Adaptation adaptation = adapter_.GetAdaptationUp(); EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); fake_stream.ApplyAdaptation(adaptation); - EXPECT_EQ(absl::nullopt, adapter.source_restrictions().max_frame_rate()); - EXPECT_EQ(2, adapter.adaptation_counters().resolution_adaptations); - EXPECT_EQ(0, adapter.adaptation_counters().fps_adaptations); + EXPECT_EQ(absl::nullopt, adapter_.source_restrictions().max_frame_rate()); + EXPECT_EQ(2, adapter_.adaptation_counters().resolution_adaptations); + EXPECT_EQ(0, adapter_.adaptation_counters().fps_adaptations); } // Now only adapting resolution remains. constexpr size_t kReducedPixelsFirstStepUp = (kReducedPixelsSecondStepUp * 5) / 3; { - Adaptation adaptation = adapter.GetAdaptationUp(); + Adaptation adaptation = adapter_.GetAdaptationUp(); EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); fake_stream.ApplyAdaptation(adaptation); EXPECT_EQ(kReducedPixelsFirstStepUp, - adapter.source_restrictions().target_pixels_per_frame()); - EXPECT_EQ(1, adapter.adaptation_counters().resolution_adaptations); - EXPECT_EQ(0, adapter.adaptation_counters().fps_adaptations); + adapter_.source_restrictions().target_pixels_per_frame()); + EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); + EXPECT_EQ(0, adapter_.adaptation_counters().fps_adaptations); } // The last step up should make us entirely unrestricted. { - Adaptation adaptation = adapter.GetAdaptationUp(); + Adaptation adaptation = adapter_.GetAdaptationUp(); EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); fake_stream.ApplyAdaptation(adaptation); - EXPECT_EQ(VideoSourceRestrictions(), adapter.source_restrictions()); - EXPECT_EQ(0, adapter.adaptation_counters().Total()); + EXPECT_EQ(VideoSourceRestrictions(), adapter_.source_restrictions()); + EXPECT_EQ(0, adapter_.adaptation_counters().Total()); } } -TEST(VideoStreamAdapterTest, Balanced_LimitReached) { - webrtc::test::ScopedFieldTrials balanced_field_trials( - BalancedFieldTrialConfig()); - VideoStreamAdapter adapter; - adapter.SetDegradationPreference(DegradationPreference::BALANCED); - FakeVideoStream fake_stream(&adapter, kBalancedLowResolutionPixels, - kBalancedLowFrameRateFps, - kDefaultMinPixelsPerFrame); +TEST_F(VideoStreamAdapterTest, Balanced_LimitReached) { + adapter_.SetDegradationPreference(DegradationPreference::BALANCED); + FakeVideoStream fake_stream( + &adapter_, &input_state_provider_, kBalancedLowResolutionPixels, + kBalancedLowFrameRateFps, kDefaultMinPixelsPerFrame); // Attempting to adapt up while unrestricted should result in kLimitReached. EXPECT_EQ(Adaptation::Status::kLimitReached, - adapter.GetAdaptationUp().status()); + adapter_.GetAdaptationUp().status()); // Adapting down once result in restricted frame rate, in this case we reach // the lowest possible frame rate immediately: kBalancedLowFrameRateFps. - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); EXPECT_EQ(static_cast(kBalancedLowFrameRateFps), - adapter.source_restrictions().max_frame_rate()); - EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations); + adapter_.source_restrictions().max_frame_rate()); + EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); // Any further adaptation must follow "maintain-framerate" rules (these are // covered in more depth by the MaintainFramerate tests). This test does not // assert exactly how resolution is adjusted, only that resolution always @@ -516,292 +526,284 @@ TEST(VideoStreamAdapterTest, Balanced_LimitReached) { bool did_reach_limit = false; // If we have not reached the limit within 5 adaptations something is wrong... for (int i = 0; i < 5; i++) { - Adaptation adaptation = adapter.GetAdaptationDown(); + Adaptation adaptation = adapter_.GetAdaptationDown(); if (adaptation.status() == Adaptation::Status::kLimitReached) { did_reach_limit = true; break; } EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); fake_stream.ApplyAdaptation(adaptation); - EXPECT_LT(adapter.source_restrictions().max_pixels_per_frame().value(), + EXPECT_LT(adapter_.source_restrictions().max_pixels_per_frame().value(), previous_resolution); previous_resolution = - adapter.source_restrictions().max_pixels_per_frame().value(); + adapter_.source_restrictions().max_pixels_per_frame().value(); } EXPECT_TRUE(did_reach_limit); // Frame rate restrictions are the same as before. EXPECT_EQ(static_cast(kBalancedLowFrameRateFps), - adapter.source_restrictions().max_frame_rate()); - EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations); + adapter_.source_restrictions().max_frame_rate()); + EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); } // kAwaitingPreviousAdaptation is only supported in "maintain-framerate". -TEST(VideoStreamAdapterTest, MaintainFramerate_AwaitingPreviousAdaptationDown) { - VideoStreamAdapter adapter; - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); - adapter.SetInput(InputState(1280 * 720, 30, kDefaultMinPixelsPerFrame)); +TEST_F(VideoStreamAdapterTest, + MaintainFramerate_AwaitingPreviousAdaptationDown) { + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); + input_state_provider_.SetInputState(1280 * 720, 30, + kDefaultMinPixelsPerFrame); // Adapt down once, but don't update the input. - adapter.ApplyAdaptation(adapter.GetAdaptationDown(), nullptr); - EXPECT_EQ(1, adapter.adaptation_counters().resolution_adaptations); + adapter_.ApplyAdaptation(adapter_.GetAdaptationDown(), nullptr); + EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); { // Having performed the adaptation, but not updated the input based on the // new restrictions, adapting again in the same direction will not work. - Adaptation adaptation = adapter.GetAdaptationDown(); + Adaptation adaptation = adapter_.GetAdaptationDown(); EXPECT_EQ(Adaptation::Status::kAwaitingPreviousAdaptation, adaptation.status()); } } // kAwaitingPreviousAdaptation is only supported in "maintain-framerate". -TEST(VideoStreamAdapterTest, MaintainFramerate_AwaitingPreviousAdaptationUp) { - VideoStreamAdapter adapter; - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); - FakeVideoStream fake_stream(&adapter, 1280 * 720, 30, +TEST_F(VideoStreamAdapterTest, MaintainFramerate_AwaitingPreviousAdaptationUp) { + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); + FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, kDefaultMinPixelsPerFrame); // Perform two adaptation down so that adapting up twice is possible. - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); - EXPECT_EQ(2, adapter.adaptation_counters().resolution_adaptations); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); + EXPECT_EQ(2, adapter_.adaptation_counters().resolution_adaptations); // Adapt up once, but don't update the input. - adapter.ApplyAdaptation(adapter.GetAdaptationUp(), nullptr); - EXPECT_EQ(1, adapter.adaptation_counters().resolution_adaptations); + adapter_.ApplyAdaptation(adapter_.GetAdaptationUp(), nullptr); + EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); { // Having performed the adaptation, but not updated the input based on the // new restrictions, adapting again in the same direction will not work. - Adaptation adaptation = adapter.GetAdaptationUp(); + Adaptation adaptation = adapter_.GetAdaptationUp(); EXPECT_EQ(Adaptation::Status::kAwaitingPreviousAdaptation, adaptation.status()); } } -TEST(VideoStreamAdapterTest, - MaintainResolution_AdaptsUpAfterSwitchingDegradationPreference) { - VideoStreamAdapter adapter; - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); - FakeVideoStream fake_stream(&adapter, 1280 * 720, 30, +TEST_F(VideoStreamAdapterTest, + MaintainResolution_AdaptsUpAfterSwitchingDegradationPreference) { + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); + FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, kDefaultMinPixelsPerFrame); // Adapt down in fps for later. - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); - EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); + EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); - fake_stream.ApplyAdaptation(adapter.GetAdaptationUp()); - EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations); - EXPECT_EQ(0, adapter.adaptation_counters().resolution_adaptations); + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationUp()); + EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); + EXPECT_EQ(0, adapter_.adaptation_counters().resolution_adaptations); // We should be able to adapt in framerate one last time after the change of // degradation preference. - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); - Adaptation adaptation = adapter.GetAdaptationUp(); + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); + Adaptation adaptation = adapter_.GetAdaptationUp(); EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); - fake_stream.ApplyAdaptation(adapter.GetAdaptationUp()); - EXPECT_EQ(0, adapter.adaptation_counters().fps_adaptations); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationUp()); + EXPECT_EQ(0, adapter_.adaptation_counters().fps_adaptations); } -TEST(VideoStreamAdapterTest, - MaintainFramerate_AdaptsUpAfterSwitchingDegradationPreference) { - VideoStreamAdapter adapter; - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); - FakeVideoStream fake_stream(&adapter, 1280 * 720, 30, +TEST_F(VideoStreamAdapterTest, + MaintainFramerate_AdaptsUpAfterSwitchingDegradationPreference) { + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); + FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, kDefaultMinPixelsPerFrame); // Adapt down in resolution for later. - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); - EXPECT_EQ(1, adapter.adaptation_counters().resolution_adaptations); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); + EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); - fake_stream.ApplyAdaptation(adapter.GetAdaptationUp()); - EXPECT_EQ(1, adapter.adaptation_counters().resolution_adaptations); - EXPECT_EQ(0, adapter.adaptation_counters().fps_adaptations); + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationUp()); + EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); + EXPECT_EQ(0, adapter_.adaptation_counters().fps_adaptations); // We should be able to adapt in framerate one last time after the change of // degradation preference. - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); - Adaptation adaptation = adapter.GetAdaptationUp(); + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); + Adaptation adaptation = adapter_.GetAdaptationUp(); EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); - fake_stream.ApplyAdaptation(adapter.GetAdaptationUp()); - EXPECT_EQ(0, adapter.adaptation_counters().resolution_adaptations); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationUp()); + EXPECT_EQ(0, adapter_.adaptation_counters().resolution_adaptations); } -TEST(VideoStreamAdapterTest, - PendingResolutionIncreaseAllowsAdaptUpAfterSwitchToMaintainResolution) { - VideoStreamAdapter adapter; - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); - FakeVideoStream fake_stream(&adapter, 1280 * 720, 30, +TEST_F(VideoStreamAdapterTest, + PendingResolutionIncreaseAllowsAdaptUpAfterSwitchToMaintainResolution) { + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); + FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, kDefaultMinPixelsPerFrame); // Adapt fps down so we can adapt up later in the test. - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); // Apply adaptation up but don't update input. - adapter.ApplyAdaptation(adapter.GetAdaptationUp(), nullptr); + adapter_.ApplyAdaptation(adapter_.GetAdaptationUp(), nullptr); EXPECT_EQ(Adaptation::Status::kAwaitingPreviousAdaptation, - adapter.GetAdaptationUp().status()); + adapter_.GetAdaptationUp().status()); - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); - Adaptation adaptation = adapter.GetAdaptationUp(); + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); + Adaptation adaptation = adapter_.GetAdaptationUp(); EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); } -TEST(VideoStreamAdapterTest, - MaintainFramerate_AdaptsDownAfterSwitchingDegradationPreference) { - VideoStreamAdapter adapter; - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); - FakeVideoStream fake_stream(&adapter, 1280 * 720, 30, +TEST_F(VideoStreamAdapterTest, + MaintainFramerate_AdaptsDownAfterSwitchingDegradationPreference) { + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); + FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, kDefaultMinPixelsPerFrame); // Adapt down once, should change FPS. - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); - EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); + EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); // Adaptation down should apply after the degradation prefs change. - Adaptation adaptation = adapter.GetAdaptationDown(); + Adaptation adaptation = adapter_.GetAdaptationDown(); EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); fake_stream.ApplyAdaptation(adaptation); - EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations); - EXPECT_EQ(1, adapter.adaptation_counters().resolution_adaptations); + EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); + EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); } -TEST(VideoStreamAdapterTest, - MaintainResolution_AdaptsDownAfterSwitchingDegradationPreference) { - VideoStreamAdapter adapter; - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); - FakeVideoStream fake_stream(&adapter, 1280 * 720, 30, +TEST_F(VideoStreamAdapterTest, + MaintainResolution_AdaptsDownAfterSwitchingDegradationPreference) { + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); + FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, kDefaultMinPixelsPerFrame); // Adapt down once, should change FPS. - fake_stream.ApplyAdaptation(adapter.GetAdaptationDown()); - EXPECT_EQ(1, adapter.adaptation_counters().resolution_adaptations); + fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); + EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); - Adaptation adaptation = adapter.GetAdaptationDown(); + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); + Adaptation adaptation = adapter_.GetAdaptationDown(); EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); fake_stream.ApplyAdaptation(adaptation); - EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations); - EXPECT_EQ(1, adapter.adaptation_counters().resolution_adaptations); + EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); + EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); } -TEST(VideoStreamAdapterTest, - PendingResolutionDecreaseAllowsAdaptDownAfterSwitchToMaintainResolution) { - VideoStreamAdapter adapter; - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); - FakeVideoStream fake_stream(&adapter, 1280 * 720, 30, +TEST_F( + VideoStreamAdapterTest, + PendingResolutionDecreaseAllowsAdaptDownAfterSwitchToMaintainResolution) { + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); + FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, kDefaultMinPixelsPerFrame); // Apply adaptation but don't update the input. - adapter.ApplyAdaptation(adapter.GetAdaptationDown(), nullptr); + adapter_.ApplyAdaptation(adapter_.GetAdaptationDown(), nullptr); EXPECT_EQ(Adaptation::Status::kAwaitingPreviousAdaptation, - adapter.GetAdaptationDown().status()); - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); - Adaptation adaptation = adapter.GetAdaptationDown(); + adapter_.GetAdaptationDown().status()); + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); + Adaptation adaptation = adapter_.GetAdaptationDown(); EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); } -TEST(VideoStreamAdapterTest, RestrictionsBroadcasted) { - VideoStreamAdapter adapter; +TEST_F(VideoStreamAdapterTest, RestrictionBroadcasted) { FakeVideoStreamAdapterListner listener; - adapter.AddRestrictionsListener(&listener); - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); - FakeVideoStream fake_stream(&adapter, 1280 * 720, 30, + adapter_.AddRestrictionsListener(&listener); + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); + FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, kDefaultMinPixelsPerFrame); // Not broadcast on invalid ApplyAdaptation. { - Adaptation adaptation = adapter.GetAdaptationUp(); - adapter.ApplyAdaptation(adaptation, nullptr); + Adaptation adaptation = adapter_.GetAdaptationUp(); + adapter_.ApplyAdaptation(adaptation, nullptr); EXPECT_EQ(0, listener.calls()); } // Broadcast on ApplyAdaptation. { - Adaptation adaptation = adapter.GetAdaptationDown(); + Adaptation adaptation = adapter_.GetAdaptationDown(); VideoStreamAdapter::RestrictionsWithCounters peek = - adapter.PeekNextRestrictions(adaptation); + adapter_.PeekNextRestrictions(adaptation); fake_stream.ApplyAdaptation(adaptation); EXPECT_EQ(1, listener.calls()); EXPECT_EQ(peek.restrictions, listener.last_restrictions()); } // Broadcast on ClearRestrictions(). - adapter.ClearRestrictions(); + adapter_.ClearRestrictions(); EXPECT_EQ(2, listener.calls()); EXPECT_EQ(VideoSourceRestrictions(), listener.last_restrictions()); } -TEST(VideoStreamAdapterTest, PeekNextRestrictions) { - VideoStreamAdapter adapter; +TEST_F(VideoStreamAdapterTest, PeekNextRestrictions) { // Any non-disabled DegradationPreference will do. - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); - FakeVideoStream fake_stream(&adapter, 1280 * 720, 30, + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); + FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, kDefaultMinPixelsPerFrame); // When adaptation is not possible. { - Adaptation adaptation = adapter.GetAdaptationUp(); + Adaptation adaptation = adapter_.GetAdaptationUp(); EXPECT_EQ(Adaptation::Status::kLimitReached, adaptation.status()); VideoStreamAdapter::RestrictionsWithCounters restrictions_with_counters = - adapter.PeekNextRestrictions(adaptation); + adapter_.PeekNextRestrictions(adaptation); EXPECT_EQ(restrictions_with_counters.restrictions, - adapter.source_restrictions()); + adapter_.source_restrictions()); EXPECT_EQ(0, restrictions_with_counters.adaptation_counters.Total()); } // When we adapt down. { - Adaptation adaptation = adapter.GetAdaptationDown(); + Adaptation adaptation = adapter_.GetAdaptationDown(); EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); VideoStreamAdapter::RestrictionsWithCounters restrictions_with_counters = - adapter.PeekNextRestrictions(adaptation); + adapter_.PeekNextRestrictions(adaptation); fake_stream.ApplyAdaptation(adaptation); EXPECT_EQ(restrictions_with_counters.restrictions, - adapter.source_restrictions()); + adapter_.source_restrictions()); EXPECT_EQ(restrictions_with_counters.adaptation_counters, - adapter.adaptation_counters()); + adapter_.adaptation_counters()); } // When we adapt up. { - Adaptation adaptation = adapter.GetAdaptationUp(); + Adaptation adaptation = adapter_.GetAdaptationUp(); EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); VideoStreamAdapter::RestrictionsWithCounters restrictions_with_counters = - adapter.PeekNextRestrictions(adaptation); + adapter_.PeekNextRestrictions(adaptation); fake_stream.ApplyAdaptation(adaptation); EXPECT_EQ(restrictions_with_counters.restrictions, - adapter.source_restrictions()); + adapter_.source_restrictions()); EXPECT_EQ(restrictions_with_counters.adaptation_counters, - adapter.adaptation_counters()); + adapter_.adaptation_counters()); } } -TEST(VideoStreamAdapterTest, PeekRestrictionsDoesNotBroadcast) { - VideoStreamAdapter adapter; +TEST_F(VideoStreamAdapterTest, PeekRestrictionsDoesNotBroadcast) { FakeVideoStreamAdapterListner listener; - adapter.AddRestrictionsListener(&listener); - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); - FakeVideoStream fake_stream(&adapter, 1280 * 720, 30, + adapter_.AddRestrictionsListener(&listener); + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); + FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, kDefaultMinPixelsPerFrame); - Adaptation adaptation = adapter.GetAdaptationDown(); - adapter.PeekNextRestrictions(adaptation); + Adaptation adaptation = adapter_.GetAdaptationDown(); + adapter_.PeekNextRestrictions(adaptation); EXPECT_EQ(0, listener.calls()); } -TEST(VideoStreamAdapterTest, - SetDegradationPreferenceToOrFromBalancedClearsRestrictions) { - VideoStreamAdapter adapter; - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); - adapter.SetInput(InputState(1280 * 720, 30, kDefaultMinPixelsPerFrame)); - adapter.ApplyAdaptation(adapter.GetAdaptationDown(), nullptr); - EXPECT_NE(VideoSourceRestrictions(), adapter.source_restrictions()); - EXPECT_NE(0, adapter.adaptation_counters().Total()); +TEST_F(VideoStreamAdapterTest, + SetDegradationPreferenceToOrFromBalancedClearsRestrictions) { + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); + input_state_provider_.SetInputState(1280 * 720, 30, + kDefaultMinPixelsPerFrame); + adapter_.ApplyAdaptation(adapter_.GetAdaptationDown(), nullptr); + EXPECT_NE(VideoSourceRestrictions(), adapter_.source_restrictions()); + EXPECT_NE(0, adapter_.adaptation_counters().Total()); // Changing from non-balanced to balanced clears the restrictions. - adapter.SetDegradationPreference(DegradationPreference::BALANCED); - EXPECT_EQ(VideoSourceRestrictions(), adapter.source_restrictions()); - EXPECT_EQ(0, adapter.adaptation_counters().Total()); + adapter_.SetDegradationPreference(DegradationPreference::BALANCED); + EXPECT_EQ(VideoSourceRestrictions(), adapter_.source_restrictions()); + EXPECT_EQ(0, adapter_.adaptation_counters().Total()); // Apply adaptation again. - adapter.ApplyAdaptation(adapter.GetAdaptationDown(), nullptr); - EXPECT_NE(VideoSourceRestrictions(), adapter.source_restrictions()); - EXPECT_NE(0, adapter.adaptation_counters().Total()); + adapter_.ApplyAdaptation(adapter_.GetAdaptationDown(), nullptr); + EXPECT_NE(VideoSourceRestrictions(), adapter_.source_restrictions()); + EXPECT_NE(0, adapter_.adaptation_counters().Total()); // Changing from balanced to non-balanced clears the restrictions. - adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); - EXPECT_EQ(VideoSourceRestrictions(), adapter.source_restrictions()); - EXPECT_EQ(0, adapter.adaptation_counters().Total()); + adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); + EXPECT_EQ(VideoSourceRestrictions(), adapter_.source_restrictions()); + EXPECT_EQ(0, adapter_.adaptation_counters().Total()); } // Death tests. @@ -811,20 +813,22 @@ TEST(VideoStreamAdapterTest, TEST(VideoStreamAdapterDeathTest, SetDegradationPreferenceInvalidatesAdaptations) { - VideoStreamAdapter adapter; + FakeVideoStreamInputStateProvider input_state_provider; + VideoStreamAdapter adapter(&input_state_provider); adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); - adapter.SetInput(InputState(1280 * 720, 30, kDefaultMinPixelsPerFrame)); + input_state_provider.SetInputState(1280 * 720, 30, kDefaultMinPixelsPerFrame); Adaptation adaptation = adapter.GetAdaptationDown(); adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); EXPECT_DEATH(adapter.ApplyAdaptation(adaptation, nullptr), ""); } -TEST(VideoStreamAdapterDeathTest, SetInputInvalidatesAdaptations) { - VideoStreamAdapter adapter; +TEST(VideoStreamAdapterDeathTest, AdaptDownInvalidatesAdaptations) { + FakeVideoStreamInputStateProvider input_state_provider; + VideoStreamAdapter adapter(&input_state_provider); adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); - adapter.SetInput(InputState(1280 * 720, 30, kDefaultMinPixelsPerFrame)); + input_state_provider.SetInputState(1280 * 720, 30, kDefaultMinPixelsPerFrame); Adaptation adaptation = adapter.GetAdaptationDown(); - adapter.SetInput(InputState(1280 * 720, 31, kDefaultMinPixelsPerFrame)); + adapter.GetAdaptationDown(); EXPECT_DEATH(adapter.PeekNextRestrictions(adaptation), ""); } diff --git a/call/adaptation/video_stream_input_state_provider.cc b/call/adaptation/video_stream_input_state_provider.cc index eac30bbfac..4ecf858a11 100644 --- a/call/adaptation/video_stream_input_state_provider.cc +++ b/call/adaptation/video_stream_input_state_provider.cc @@ -16,6 +16,8 @@ VideoStreamInputStateProvider::VideoStreamInputStateProvider( VideoStreamEncoderObserver* frame_rate_provider) : frame_rate_provider_(frame_rate_provider) {} +VideoStreamInputStateProvider::~VideoStreamInputStateProvider() {} + void VideoStreamInputStateProvider::OnHasInputChanged(bool has_input) { rtc::CritScope lock(&crit_); input_state_.set_has_input(has_input); diff --git a/call/adaptation/video_stream_input_state_provider.h b/call/adaptation/video_stream_input_state_provider.h index 7093e97fdd..a20ac1788a 100644 --- a/call/adaptation/video_stream_input_state_provider.h +++ b/call/adaptation/video_stream_input_state_provider.h @@ -22,12 +22,13 @@ class VideoStreamInputStateProvider { public: VideoStreamInputStateProvider( VideoStreamEncoderObserver* frame_rate_provider); + virtual ~VideoStreamInputStateProvider(); void OnHasInputChanged(bool has_input); void OnFrameSizeObserved(int frame_size_pixels); void OnEncoderSettingsChanged(EncoderSettings encoder_settings); - VideoStreamInputState InputState(); + virtual VideoStreamInputState InputState(); private: mutable rtc::CriticalSection crit_; diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc index 53e189123a..abcec29fca 100644 --- a/video/video_stream_encoder.cc +++ b/video/video_stream_encoder.cc @@ -256,10 +256,10 @@ VideoStreamEncoder::VideoStreamEncoder( ParseAutomatincAnimationDetectionFieldTrial()), encoder_switch_requested_(false), input_state_provider_(encoder_stats_observer), - video_stream_adapter_(std::make_unique()), + video_stream_adapter_( + std::make_unique(&input_state_provider_)), resource_adaptation_processor_( std::make_unique( - &input_state_provider_, encoder_stats_observer, video_stream_adapter_.get())), adaptation_constraints_(),