[Adaptation] Move TriggerAdaptationDueToFrameDroppedDueToSize

It has no relevance in ResourceAdaptationProcessorInterface.
The logic moves to an interaction directly on the VideoStreamAdapter.

Bug: webrtc:11700
Change-Id: I4c7b3e1e1361722a69b71e8f9bde33f5909c011a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/178380
Commit-Queue: Evan Shrubsole <eshr@google.com>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31634}
This commit is contained in:
Evan Shrubsole
2020-07-06 11:16:51 +02:00
committed by Commit Bot
parent c3efe1abfa
commit afd1dcbde0
7 changed files with 132 additions and 37 deletions

View File

@ -390,26 +390,6 @@ ResourceAdaptationProcessor::OnResourceOveruse(
message.Release());
}
void ResourceAdaptationProcessor::TriggerAdaptationDueToFrameDroppedDueToSize(
rtc::scoped_refptr<Resource> reason_resource) {
RTC_DCHECK_RUN_ON(resource_adaptation_queue_);
RTC_LOG(INFO) << "TriggerAdaptationDueToFrameDroppedDueToSize called";
VideoAdaptationCounters counters_before =
stream_adapter_->adaptation_counters();
OnResourceOveruse(reason_resource);
if (effective_degradation_preference_ == DegradationPreference::BALANCED &&
stream_adapter_->adaptation_counters().fps_adaptations >
counters_before.fps_adaptations) {
// Oops, we adapted frame rate. Adapt again, maybe it will adapt resolution!
// Though this is not guaranteed...
OnResourceOveruse(reason_resource);
}
if (stream_adapter_->adaptation_counters().resolution_adaptations >
counters_before.resolution_adaptations) {
encoder_stats_observer_->OnInitialQualityResolutionAdaptDown();
}
}
std::pair<std::vector<rtc::scoped_refptr<Resource>>,
VideoStreamAdapter::RestrictionsWithCounters>
ResourceAdaptationProcessor::FindMostLimitedResources() const {

View File

@ -96,12 +96,6 @@ class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
void OnDegradationPreferenceUpdated(
DegradationPreference degradation_preference) override;
// May trigger 1-2 adaptations. It is meant to reduce resolution but this is
// not guaranteed. It may adapt frame rate, which does not address the issue.
// TODO(hbos): Can we get rid of this?
void TriggerAdaptationDueToFrameDroppedDueToSize(
rtc::scoped_refptr<Resource> reason_resource) override;
private:
// If resource usage measurements happens off the adaptation task queue, this
// class takes care of posting the measurement for the processor to handle it

View File

@ -72,15 +72,6 @@ class ResourceAdaptationProcessorInterface {
AdaptationListener* adaptation_listener) = 0;
virtual void RemoveAdaptationListener(
AdaptationListener* adaptation_listener) = 0;
// May trigger one or more adaptations. It is meant to reduce resolution -
// useful if a frame was dropped due to its size - however, the implementation
// may not guarantee this (see resource_adaptation_processor.h).
// TODO(hbos): This is only part of the interface for backwards-compatiblity
// reasons. Can we replace this by something which actually satisfies the
// resolution constraints or get rid of it altogether?
virtual void TriggerAdaptationDueToFrameDroppedDueToSize(
rtc::scoped_refptr<Resource> reason_resource) = 0;
};
} // namespace webrtc

View File

@ -521,6 +521,49 @@ VideoStreamAdapter::RestrictionsOrState VideoStreamAdapter::IncreaseFramerate(
return new_restrictions;
}
Adaptation VideoStreamAdapter::GetAdaptDownResolution() {
RTC_DCHECK_RUN_ON(&sequence_checker_);
VideoStreamInputState input_state = input_state_provider_->InputState();
switch (degradation_preference_) {
case DegradationPreference::DISABLED:
case DegradationPreference::MAINTAIN_RESOLUTION: {
return Adaptation(adaptation_validation_id_,
Adaptation::Status::kLimitReached, input_state, false);
}
case DegradationPreference::MAINTAIN_FRAMERATE:
return GetAdaptationDown();
case DegradationPreference::BALANCED: {
return RestrictionsOrStateToAdaptation(
GetAdaptDownResolutionStepForBalanced(input_state), input_state);
}
default:
RTC_NOTREACHED();
}
}
VideoStreamAdapter::RestrictionsOrState
VideoStreamAdapter::GetAdaptDownResolutionStepForBalanced(
const VideoStreamInputState& input_state) const {
// Adapt twice if the first adaptation did not decrease resolution.
auto first_step = GetAdaptationDownStep(input_state);
if (!absl::holds_alternative<RestrictionsWithCounters>(first_step)) {
return first_step;
}
auto first_restrictions = absl::get<RestrictionsWithCounters>(first_step);
if (first_restrictions.counters.resolution_adaptations >
current_restrictions_.counters.resolution_adaptations) {
return first_step;
}
// We didn't decrease resolution so force it; amend a resolution resuction
// to the existing framerate reduction in |first_restrictions|.
auto second_step = DecreaseResolution(input_state, first_restrictions);
if (absl::holds_alternative<RestrictionsWithCounters>(second_step)) {
return second_step;
}
// If the second step was not successful then settle for the first one.
return first_step;
}
void VideoStreamAdapter::ApplyAdaptation(
const Adaptation& adaptation,
rtc::scoped_refptr<Resource> resource) {

View File

@ -145,6 +145,11 @@ class VideoStreamAdapter {
Adaptation GetAdaptationDown();
Adaptation GetAdaptationTo(const VideoAdaptationCounters& counters,
const VideoSourceRestrictions& restrictions);
// Tries to adapt the resolution one step. This is used for initial frame
// dropping. Does nothing if the degradation preference is not BALANCED or
// MAINTAIN_FRAMERATE. In the case of BALANCED, it will try twice to reduce
// the resolution. If it fails twice it gives up.
Adaptation GetAdaptDownResolution();
// Updates source_restrictions() the Adaptation.
void ApplyAdaptation(const Adaptation& adaptation,
@ -170,6 +175,9 @@ class VideoStreamAdapter {
RestrictionsOrState GetAdaptationDownStep(
const VideoStreamInputState& input_state) const
RTC_RUN_ON(&sequence_checker_);
RestrictionsOrState GetAdaptDownResolutionStepForBalanced(
const VideoStreamInputState& input_state) const
RTC_RUN_ON(&sequence_checker_);
Adaptation GetAdaptationUp(const VideoStreamInputState& input_state) const
RTC_RUN_ON(&sequence_checker_);

View File

@ -782,6 +782,82 @@ TEST_F(VideoStreamAdapterTest,
EXPECT_EQ(0, adapter_.adaptation_counters().Total());
}
TEST_F(VideoStreamAdapterTest,
GetAdaptDownResolutionAdaptsResolutionInMaintainFramerate) {
adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
input_state_provider_.SetInputState(1280 * 720, 30,
kDefaultMinPixelsPerFrame);
auto adaptation = adapter_.GetAdaptDownResolution();
EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
EXPECT_EQ(1, adaptation.counters().resolution_adaptations);
EXPECT_EQ(0, adaptation.counters().fps_adaptations);
}
TEST_F(
VideoStreamAdapterTest,
GetAdaptDownResolutionReturnsLimitReachedInDisabledAndMaintainResolution) {
adapter_.SetDegradationPreference(DegradationPreference::DISABLED);
input_state_provider_.SetInputState(1280 * 720, 30,
kDefaultMinPixelsPerFrame);
EXPECT_EQ(Adaptation::Status::kLimitReached,
adapter_.GetAdaptDownResolution().status());
adapter_.SetDegradationPreference(DegradationPreference::DISABLED);
EXPECT_EQ(Adaptation::Status::kLimitReached,
adapter_.GetAdaptDownResolution().status());
}
TEST_F(VideoStreamAdapterTest,
GetAdaptDownResolutionAdaptsFpsAndResolutionInBalanced) {
// Note: This test depends on BALANCED implementation, but with current
// implementation and input state settings, BALANCED will adapt resolution and
// frame rate once.
adapter_.SetDegradationPreference(DegradationPreference::BALANCED);
input_state_provider_.SetInputState(1280 * 720, 30,
kDefaultMinPixelsPerFrame);
auto adaptation = adapter_.GetAdaptDownResolution();
EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
EXPECT_EQ(1, adaptation.counters().resolution_adaptations);
EXPECT_EQ(1, adaptation.counters().fps_adaptations);
}
TEST_F(
VideoStreamAdapterTest,
GetAdaptDownResolutionAdaptsOnlyResolutionIfFpsAlreadyAdapterInBalanced) {
// Note: This test depends on BALANCED implementation, but with current
// implementation and input state settings, BALANCED will adapt resolution
// only.
adapter_.SetDegradationPreference(DegradationPreference::BALANCED);
input_state_provider_.SetInputState(1280 * 720, 5, kDefaultMinPixelsPerFrame);
FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30,
kDefaultMinPixelsPerFrame);
auto first_adaptation = adapter_.GetAdaptationDown();
fake_stream.ApplyAdaptation(first_adaptation);
auto adaptation = adapter_.GetAdaptDownResolution();
EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
EXPECT_EQ(1, adaptation.counters().resolution_adaptations);
EXPECT_EQ(first_adaptation.counters().fps_adaptations,
adaptation.counters().fps_adaptations);
}
TEST_F(VideoStreamAdapterTest,
GetAdaptDownResolutionAdaptsOnlyFpsIfResolutionLowInBalanced) {
// Note: This test depends on BALANCED implementation, but with current
// implementation and input state settings, BALANCED will adapt resolution
// only.
adapter_.SetDegradationPreference(DegradationPreference::BALANCED);
input_state_provider_.SetInputState(kDefaultMinPixelsPerFrame, 30,
kDefaultMinPixelsPerFrame);
auto adaptation = adapter_.GetAdaptDownResolution();
EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
EXPECT_EQ(0, adaptation.counters().resolution_adaptations);
EXPECT_EQ(1, adaptation.counters().fps_adaptations);
}
// Death tests.
// Disabled on Android because death tests misbehave on Android, see
// base/test/gtest_util.h.

View File

@ -445,8 +445,11 @@ void VideoStreamEncoderResourceManager::OnFrameDroppedDueToSize() {
// happens if the processor is destroyed. No action needed.
return;
}
adaptation_processor_->TriggerAdaptationDueToFrameDroppedDueToSize(
quality_scaler_resource_);
Adaptation reduce_resolution = stream_adapter_->GetAdaptDownResolution();
if (reduce_resolution.status() == Adaptation::Status::kValid) {
stream_adapter_->ApplyAdaptation(reduce_resolution,
quality_scaler_resource_);
}
});
initial_frame_dropper_->OnFrameDroppedDueToSize();
}