[Adaptation] Report AdaptationCounters OnVideoSourceRestrictionsUpdated.

This CL is part of the Call-Level Adaptation Processing design doc:
https://docs.google.com/document/d/1ZyC26yOCknrrcYa839ZWLxD6o6Gig5A3lVTh4E41074/edit?usp=sharing

By pushing VideoAdaptationCounters updates on VideoSourceRestrictions
changes, alongside the Resource* that triggered the adaptation, we are
able to update |active_counts_| without an explicit dependency on the
VideoStreamAdapter. This allows a future CL to split up "processor"
logic from "video stream encoder resource and active counts" logic,
which will ultimately be necessary in order to do processing on a
"processing queue" and encoder and stats logic on the "encoder queue".

If the restrictions got cleared by an API call
(ResetVideoSourceRestrictions() or SetDegradationPreference()) we pass
null as the "reason_resource". This allows is to clear the
active_counts_, and the code that invokes
OnVideoSourceRestrictionsUpdated() does not have to be aware of
active_counts_ (needed to split the processor module in two).

Bug: webrtc:11172
Change-Id: Icab6d5121c0ebd27d2a00f1bffc8191f8f05f562
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/173000
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Evan Shrubsole <eshr@google.com>
Cr-Commit-Position: refs/heads/master@{#31103}
This commit is contained in:
Henrik Boström
2020-04-17 15:31:48 +02:00
committed by Commit Bot
parent 00032698ac
commit d2930c6c2b
8 changed files with 78 additions and 56 deletions

View File

@ -13,6 +13,7 @@
#include "absl/types/optional.h"
#include "api/rtp_parameters.h"
#include "api/video/video_adaptation_counters.h"
#include "api/video/video_frame.h"
#include "call/adaptation/encoder_settings.h"
#include "call/adaptation/resource.h"
@ -26,8 +27,13 @@ class ResourceAdaptationProcessorListener {
public:
virtual ~ResourceAdaptationProcessorListener();
// The |restrictions| are filtered by degradation preference but not the
// |adaptation_counters|, which are currently only reported for legacy stats
// calculation purposes.
virtual void OnVideoSourceRestrictionsUpdated(
VideoSourceRestrictions restrictions) = 0;
VideoSourceRestrictions restrictions,
const VideoAdaptationCounters& adaptation_counters,
const Resource* reason) = 0;
};
// Responsible for reconfiguring encoded streams based on resource consumption,

View File

@ -361,22 +361,17 @@ void VideoStreamAdapter::ClearRestrictions() {
last_adaptation_request_.reset();
}
VideoStreamAdapter::SetDegradationPreferenceResult
VideoStreamAdapter::SetDegradationPreference(
void VideoStreamAdapter::SetDegradationPreference(
DegradationPreference degradation_preference) {
if (degradation_preference_ == degradation_preference)
return SetDegradationPreferenceResult::kRestrictionsNotCleared;
return;
// Invalidate any previously returned Adaptation.
++adaptation_validation_id_;
bool did_clear = false;
if (degradation_preference == DegradationPreference::BALANCED ||
degradation_preference_ == DegradationPreference::BALANCED) {
ClearRestrictions();
did_clear = true;
}
degradation_preference_ = degradation_preference;
return did_clear ? SetDegradationPreferenceResult::kRestrictionsCleared
: SetDegradationPreferenceResult::kRestrictionsNotCleared;
}
void VideoStreamAdapter::SetInput(VideoStreamInputState input_state) {

View File

@ -109,11 +109,6 @@ class Adaptation final {
// 3. Modify the stream's restrictions in one of the valid ways.
class VideoStreamAdapter {
public:
enum class SetDegradationPreferenceResult {
kRestrictionsNotCleared,
kRestrictionsCleared,
};
VideoStreamAdapter();
~VideoStreamAdapter();
@ -129,8 +124,7 @@ class VideoStreamAdapter {
// TODO(hbos): Setting the degradation preference should not clear
// 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.
SetDegradationPreferenceResult SetDegradationPreference(
DegradationPreference degradation_preference);
void SetDegradationPreference(DegradationPreference degradation_preference);
// The adaptaiton logic depends on these inputs.
void SetInput(VideoStreamInputState input_state);

View File

@ -588,18 +588,13 @@ TEST(VideoStreamAdapterTest, PeekNextRestrictions) {
TEST(VideoStreamAdapterTest,
SetDegradationPreferenceToOrFromBalancedClearsRestrictions) {
VideoStreamAdapter adapter;
EXPECT_EQ(VideoStreamAdapter::SetDegradationPreferenceResult::
kRestrictionsNotCleared,
adapter.SetDegradationPreference(
DegradationPreference::MAINTAIN_FRAMERATE));
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
adapter.SetInput(InputState(1280 * 720, 30, kDefaultMinPixelsPerFrame));
adapter.ApplyAdaptation(adapter.GetAdaptationDown());
EXPECT_NE(VideoSourceRestrictions(), adapter.source_restrictions());
EXPECT_NE(0, adapter.adaptation_counters().Total());
// Changing from non-balanced to balanced clears the restrictions.
EXPECT_EQ(
VideoStreamAdapter::SetDegradationPreferenceResult::kRestrictionsCleared,
adapter.SetDegradationPreference(DegradationPreference::BALANCED));
adapter.SetDegradationPreference(DegradationPreference::BALANCED);
EXPECT_EQ(VideoSourceRestrictions(), adapter.source_restrictions());
EXPECT_EQ(0, adapter.adaptation_counters().Total());
// Apply adaptation again.
@ -607,10 +602,7 @@ TEST(VideoStreamAdapterTest,
EXPECT_NE(VideoSourceRestrictions(), adapter.source_restrictions());
EXPECT_NE(0, adapter.adaptation_counters().Total());
// Changing from balanced to non-balanced clears the restrictions.
EXPECT_EQ(
VideoStreamAdapter::SetDegradationPreferenceResult::kRestrictionsCleared,
adapter.SetDegradationPreference(
DegradationPreference::MAINTAIN_RESOLUTION));
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
EXPECT_EQ(VideoSourceRestrictions(), adapter.source_restrictions());
EXPECT_EQ(0, adapter.adaptation_counters().Total());
}

View File

@ -11,6 +11,7 @@
#include "video/adaptation/resource_adaptation_processor.h"
#include <algorithm>
#include <cmath>
#include <limits>
#include <memory>
#include <string>
@ -323,6 +324,7 @@ void ResourceAdaptationProcessor::AddResource(Resource* resource,
void ResourceAdaptationProcessor::SetDegradationPreference(
DegradationPreference degradation_preference) {
degradation_preference_ = degradation_preference;
UpdateStatsAdaptationSettings();
MaybeUpdateEffectiveDegradationPreference();
}
@ -358,9 +360,7 @@ void ResourceAdaptationProcessor::SetEncoderRates(
void ResourceAdaptationProcessor::ResetVideoSourceRestrictions() {
stream_adapter_->ClearRestrictions();
ResetActiveCounts();
encoder_stats_observer_->ClearAdaptationStats();
MaybeUpdateVideoSourceRestrictions();
MaybeUpdateVideoSourceRestrictions(nullptr);
}
void ResourceAdaptationProcessor::OnFrameDroppedDueToSize() {
@ -533,10 +533,7 @@ void ResourceAdaptationProcessor::OnResourceUnderuse(
stream_adapter_->ApplyAdaptation(adaptation);
// Update VideoSourceRestrictions based on adaptation. This also informs the
// |adaptation_listener_|.
MaybeUpdateVideoSourceRestrictions();
// Stats and logging.
UpdateAdaptationStats(GetReasonFromResource(reason_resource));
RTC_LOG(LS_INFO) << ActiveCountsToString();
MaybeUpdateVideoSourceRestrictions(&reason_resource);
}
ResourceListenerResponse ResourceAdaptationProcessor::OnResourceOveruse(
@ -562,10 +559,7 @@ ResourceListenerResponse ResourceAdaptationProcessor::OnResourceOveruse(
stream_adapter_->ApplyAdaptation(adaptation);
// Update VideoSourceRestrictions based on adaptation. This also informs the
// |adaptation_listener_|.
MaybeUpdateVideoSourceRestrictions();
// Stats and logging.
UpdateAdaptationStats(GetReasonFromResource(reason_resource));
RTC_LOG(INFO) << ActiveCountsToString();
MaybeUpdateVideoSourceRestrictions(&reason_resource);
return response;
}
@ -604,28 +598,59 @@ void ResourceAdaptationProcessor::MaybeUpdateEffectiveDegradationPreference() {
degradation_preference_ == DegradationPreference::BALANCED)
? DegradationPreference::MAINTAIN_RESOLUTION
: degradation_preference_;
if (stream_adapter_->SetDegradationPreference(
effective_degradation_preference_) ==
VideoStreamAdapter::SetDegradationPreferenceResult::
kRestrictionsCleared) {
ResetActiveCounts();
encoder_stats_observer_->ClearAdaptationStats();
}
MaybeUpdateVideoSourceRestrictions();
stream_adapter_->SetDegradationPreference(effective_degradation_preference_);
MaybeUpdateVideoSourceRestrictions(nullptr);
}
void ResourceAdaptationProcessor::MaybeUpdateVideoSourceRestrictions() {
void ResourceAdaptationProcessor::MaybeUpdateVideoSourceRestrictions(
const Resource* reason_resource) {
VideoSourceRestrictions new_restrictions =
FilterRestrictionsByDegradationPreference(
stream_adapter_->source_restrictions(), degradation_preference_);
if (video_source_restrictions_ != new_restrictions) {
video_source_restrictions_ = std::move(new_restrictions);
// TODO(https://crbug.com/webrtc/11172): Support multiple listeners and
// loop through them here instead of calling two hardcoded listeners (|this|
// and |adaptation_listener_|).
OnVideoSourceRestrictionsUpdated(video_source_restrictions_,
stream_adapter_->adaptation_counters(),
reason_resource);
adaptation_listener_->OnVideoSourceRestrictionsUpdated(
video_source_restrictions_);
MaybeUpdateTargetFrameRate();
video_source_restrictions_, stream_adapter_->adaptation_counters(),
reason_resource);
}
}
void ResourceAdaptationProcessor::OnVideoSourceRestrictionsUpdated(
VideoSourceRestrictions restrictions,
const VideoAdaptationCounters& adaptation_counters,
const Resource* reason) {
VideoAdaptationCounters previous_adaptation_counters =
active_counts_[VideoAdaptationReason::kQuality] +
active_counts_[VideoAdaptationReason::kCpu];
int adaptation_counters_total_abs_diff = std::abs(
adaptation_counters.Total() - previous_adaptation_counters.Total());
if (reason) {
// A resource signal triggered this adaptation. The adaptation counters have
// to be updated every time the adaptation counter is incremented or
// decremented due to a resource.
RTC_DCHECK_EQ(adaptation_counters_total_abs_diff, 1);
VideoAdaptationReason reason_type = GetReasonFromResource(*reason);
UpdateAdaptationStats(adaptation_counters, reason_type);
} else if (adaptation_counters.Total() == 0) {
// Adaptation was manually reset - clear the per-reason counters too.
ResetActiveCounts();
encoder_stats_observer_->ClearAdaptationStats();
} else {
// If a reason did not increase or decrease the Total() by 1 and the
// restrictions were not just reset, the adaptation counters MUST not have
// been modified and there is nothing to do stats-wise.
RTC_DCHECK_EQ(adaptation_counters_total_abs_diff, 0);
}
RTC_LOG(LS_INFO) << ActiveCountsToString();
MaybeUpdateTargetFrameRate();
}
void ResourceAdaptationProcessor::MaybeUpdateTargetFrameRate() {
absl::optional<double> codec_max_frame_rate =
encoder_settings_.has_value()
@ -710,12 +735,11 @@ void ResourceAdaptationProcessor::OnAdaptationCountChanged(
}
void ResourceAdaptationProcessor::UpdateAdaptationStats(
const VideoAdaptationCounters& total_counts,
VideoAdaptationReason reason) {
// Update active counts
VideoAdaptationCounters& active_count = active_counts_[reason];
VideoAdaptationCounters& other_active = active_counts_[OtherReason(reason)];
const VideoAdaptationCounters total_counts =
stream_adapter_->adaptation_counters();
OnAdaptationCountChanged(total_counts, &active_count, &other_active);

View File

@ -59,7 +59,8 @@ extern const int kDefaultInputPixelsHeight;
// indirectly in video_stream_encoder_unittest.cc and other tests exercising
// VideoStreamEncoder.
class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
public ResourceListener {
public ResourceListener,
public ResourceAdaptationProcessorListener {
public:
// The processor can be constructed on any sequence, but must be initialized
// and used on a single sequence, e.g. the encoder queue.
@ -83,7 +84,7 @@ class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
void StartResourceAdaptation(
ResourceAdaptationProcessorListener* adaptation_listener) override;
void StopResourceAdaptation() override;
// Uses a default AdaptReason of kCpu.
// Uses a default VideoAdaptationReason of kCpu.
void AddResource(Resource* resource) override;
void AddResource(Resource* resource, VideoAdaptationReason reason);
void SetDegradationPreference(
@ -116,6 +117,11 @@ class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
ResourceListenerResponse OnResourceUsageStateMeasured(
const Resource& resource) override;
void OnVideoSourceRestrictionsUpdated(
VideoSourceRestrictions restrictions,
const VideoAdaptationCounters& adaptation_counters,
const Resource* reason) override;
// For reasons of adaptation and statistics, we not only count the total
// number of adaptations, but we also count the number of adaptations per
// reason.
@ -157,7 +163,7 @@ class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
// Makes |video_source_restrictions_| up-to-date and informs the
// |adaptation_listener_| if restrictions are changed, allowing the listener
// to reconfigure the source accordingly.
void MaybeUpdateVideoSourceRestrictions();
void MaybeUpdateVideoSourceRestrictions(const Resource* reason_resource);
// Calculates an up-to-date value of the target frame rate and informs the
// |encode_usage_resource_| of the new value.
void MaybeUpdateTargetFrameRate();
@ -166,7 +172,8 @@ class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
void UpdateQualityScalerSettings(
absl::optional<VideoEncoder::QpThresholds> qp_thresholds);
void UpdateAdaptationStats(VideoAdaptationReason reason);
void UpdateAdaptationStats(const VideoAdaptationCounters& total_counts,
VideoAdaptationReason reason);
void UpdateStatsAdaptationSettings() const;
// Checks to see if we should execute the quality rampup experiment. The

View File

@ -1657,7 +1657,9 @@ bool VideoStreamEncoder::DropDueToSize(uint32_t pixel_count) const {
}
void VideoStreamEncoder::OnVideoSourceRestrictionsUpdated(
VideoSourceRestrictions restrictions) {
VideoSourceRestrictions restrictions,
const VideoAdaptationCounters& adaptation_counters,
const Resource* reason) {
RTC_DCHECK_RUN_ON(&encoder_queue_);
video_source_sink_controller_->SetRestrictions(std::move(restrictions));
video_source_sink_controller_->PushSourceSinkSettings();

View File

@ -108,7 +108,9 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
rtc::TaskQueue* encoder_queue() { return &encoder_queue_; }
void OnVideoSourceRestrictionsUpdated(
VideoSourceRestrictions restrictions) override;
VideoSourceRestrictions restrictions,
const VideoAdaptationCounters& adaptation_counters,
const Resource* reason) override;
// Used for injected test resources.
// TODO(eshr): Move all adaptation tests out of VideoStreamEncoder tests.