Move quality rampup experiment to overuse module
Bug: webrtc:11222 Change-Id: I8d0860bfe8bdfe0a051f5a6165cdcfa0cc25cfb5 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/168181 Reviewed-by: Erik Språng <sprang@webrtc.org> Reviewed-by: Henrik Boström <hbos@webrtc.org> Commit-Queue: Evan Shrubsole <eshr@google.com> Cr-Commit-Position: refs/heads/master@{#30465}
This commit is contained in:

committed by
Commit Bot

parent
78c7c5247c
commit
e331a122aa
@ -91,10 +91,13 @@ class ResourceAdaptationModuleInterface {
|
|||||||
// VideoStreamEncoderInterface::SetStartBitrate.
|
// VideoStreamEncoderInterface::SetStartBitrate.
|
||||||
virtual void SetStartBitrate(DataRate start_bitrate) = 0;
|
virtual void SetStartBitrate(DataRate start_bitrate) = 0;
|
||||||
virtual void SetTargetBitrate(DataRate target_bitrate) = 0;
|
virtual void SetTargetBitrate(DataRate target_bitrate) = 0;
|
||||||
// Removes all restrictions; the module will need to adapt all over again.
|
// The encoder rates are the target encoder bitrate distributed across spatial
|
||||||
// TODO(hbos): It's not clear why anybody should be able to tell the module to
|
// and temporal layers. This may be different than target bitrate depending on
|
||||||
// reset like this; can we get rid of this method?
|
// encoder configuration, e.g. if we can encode at desired quality in less
|
||||||
virtual void ResetVideoSourceRestrictions() = 0;
|
// than the allowed target bitrate or if the encoder has not been initialized
|
||||||
|
// yet.
|
||||||
|
virtual void SetEncoderRates(
|
||||||
|
const VideoEncoder::RateControlParameters& encoder_rates) = 0;
|
||||||
|
|
||||||
// The following methods correspond to the pipeline that a frame goes through.
|
// The following methods correspond to the pipeline that a frame goes through.
|
||||||
// Note that if the encoder is parallelized, multiple frames may be processed
|
// Note that if the encoder is parallelized, multiple frames may be processed
|
||||||
|
@ -221,128 +221,103 @@ class OveruseFrameDetectorResourceAdaptationModule::VideoSourceRestrictor {
|
|||||||
RTC_DISALLOW_COPY_AND_ASSIGN(VideoSourceRestrictor);
|
RTC_DISALLOW_COPY_AND_ASSIGN(VideoSourceRestrictor);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Class holding adaptation information.
|
class OveruseFrameDetectorResourceAdaptationModule::AdaptCounter final {
|
||||||
OveruseFrameDetectorResourceAdaptationModule::AdaptCounter::AdaptCounter() {
|
public:
|
||||||
fps_counters_.resize(kScaleReasonSize);
|
AdaptCounter() {
|
||||||
resolution_counters_.resize(kScaleReasonSize);
|
fps_counters_.resize(kScaleReasonSize);
|
||||||
static_assert(kScaleReasonSize == 2, "Update MoveCount.");
|
resolution_counters_.resize(kScaleReasonSize);
|
||||||
}
|
static_assert(kScaleReasonSize == 2, "Update MoveCount.");
|
||||||
|
|
||||||
OveruseFrameDetectorResourceAdaptationModule::AdaptCounter::~AdaptCounter() {}
|
|
||||||
|
|
||||||
std::string
|
|
||||||
OveruseFrameDetectorResourceAdaptationModule::AdaptCounter::ToString() const {
|
|
||||||
rtc::StringBuilder ss;
|
|
||||||
ss << "Downgrade counts: fps: {" << ToString(fps_counters_);
|
|
||||||
ss << "}, resolution: {" << ToString(resolution_counters_) << "}";
|
|
||||||
return ss.Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
VideoStreamEncoderObserver::AdaptationSteps
|
|
||||||
OveruseFrameDetectorResourceAdaptationModule::AdaptCounter::Counts(
|
|
||||||
int reason) const {
|
|
||||||
VideoStreamEncoderObserver::AdaptationSteps counts;
|
|
||||||
counts.num_framerate_reductions = fps_counters_[reason];
|
|
||||||
counts.num_resolution_reductions = resolution_counters_[reason];
|
|
||||||
return counts;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OveruseFrameDetectorResourceAdaptationModule::AdaptCounter::
|
|
||||||
IncrementFramerate(int reason) {
|
|
||||||
++(fps_counters_[reason]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OveruseFrameDetectorResourceAdaptationModule::AdaptCounter::
|
|
||||||
IncrementResolution(int reason) {
|
|
||||||
++(resolution_counters_[reason]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OveruseFrameDetectorResourceAdaptationModule::AdaptCounter::
|
|
||||||
DecrementFramerate(int reason) {
|
|
||||||
if (fps_counters_[reason] == 0) {
|
|
||||||
// Balanced mode: Adapt up is in a different order, switch reason.
|
|
||||||
// E.g. framerate adapt down: quality (2), framerate adapt up: cpu (3).
|
|
||||||
// 1. Down resolution (cpu): res={quality:0,cpu:1}, fps={quality:0,cpu:0}
|
|
||||||
// 2. Down fps (quality): res={quality:0,cpu:1}, fps={quality:1,cpu:0}
|
|
||||||
// 3. Up fps (cpu): res={quality:1,cpu:0}, fps={quality:0,cpu:0}
|
|
||||||
// 4. Up resolution (quality): res={quality:0,cpu:0}, fps={quality:0,cpu:0}
|
|
||||||
RTC_DCHECK_GT(TotalCount(reason), 0) << "No downgrade for reason.";
|
|
||||||
RTC_DCHECK_GT(FramerateCount(), 0) << "Framerate not downgraded.";
|
|
||||||
MoveCount(&resolution_counters_, reason);
|
|
||||||
MoveCount(&fps_counters_, (reason + 1) % kScaleReasonSize);
|
|
||||||
}
|
}
|
||||||
--(fps_counters_[reason]);
|
~AdaptCounter() = default;
|
||||||
RTC_DCHECK_GE(fps_counters_[reason], 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OveruseFrameDetectorResourceAdaptationModule::AdaptCounter::
|
// Get number of adaptation downscales for |reason|.
|
||||||
DecrementResolution(int reason) {
|
VideoStreamEncoderObserver::AdaptationSteps Counts(int reason) const {
|
||||||
if (resolution_counters_[reason] == 0) {
|
VideoStreamEncoderObserver::AdaptationSteps counts;
|
||||||
// Balanced mode: Adapt up is in a different order, switch reason.
|
counts.num_framerate_reductions = fps_counters_[reason];
|
||||||
RTC_DCHECK_GT(TotalCount(reason), 0) << "No downgrade for reason.";
|
counts.num_resolution_reductions = resolution_counters_[reason];
|
||||||
RTC_DCHECK_GT(ResolutionCount(), 0) << "Resolution not downgraded.";
|
return counts;
|
||||||
MoveCount(&fps_counters_, reason);
|
|
||||||
MoveCount(&resolution_counters_, (reason + 1) % kScaleReasonSize);
|
|
||||||
}
|
}
|
||||||
--(resolution_counters_[reason]);
|
|
||||||
RTC_DCHECK_GE(resolution_counters_[reason], 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OveruseFrameDetectorResourceAdaptationModule::AdaptCounter::
|
std::string ToString() const {
|
||||||
DecrementFramerate(int reason, int cur_fps) {
|
rtc::StringBuilder ss;
|
||||||
DecrementFramerate(reason);
|
ss << "Downgrade counts: fps: {" << ToString(fps_counters_);
|
||||||
// Reset if at max fps (i.e. in case of fewer steps up than down).
|
ss << "}, resolution: {" << ToString(resolution_counters_) << "}";
|
||||||
if (cur_fps == std::numeric_limits<int>::max())
|
return ss.Release();
|
||||||
absl::c_fill(fps_counters_, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int OveruseFrameDetectorResourceAdaptationModule::AdaptCounter::FramerateCount()
|
|
||||||
const {
|
|
||||||
return Count(fps_counters_);
|
|
||||||
}
|
|
||||||
|
|
||||||
int OveruseFrameDetectorResourceAdaptationModule::AdaptCounter::
|
|
||||||
ResolutionCount() const {
|
|
||||||
return Count(resolution_counters_);
|
|
||||||
}
|
|
||||||
|
|
||||||
int OveruseFrameDetectorResourceAdaptationModule::AdaptCounter::FramerateCount(
|
|
||||||
int reason) const {
|
|
||||||
return fps_counters_[reason];
|
|
||||||
}
|
|
||||||
|
|
||||||
int OveruseFrameDetectorResourceAdaptationModule::AdaptCounter::ResolutionCount(
|
|
||||||
int reason) const {
|
|
||||||
return resolution_counters_[reason];
|
|
||||||
}
|
|
||||||
|
|
||||||
int OveruseFrameDetectorResourceAdaptationModule::AdaptCounter::TotalCount(
|
|
||||||
int reason) const {
|
|
||||||
return FramerateCount(reason) + ResolutionCount(reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
int OveruseFrameDetectorResourceAdaptationModule::AdaptCounter::Count(
|
|
||||||
const std::vector<int>& counters) const {
|
|
||||||
return absl::c_accumulate(counters, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OveruseFrameDetectorResourceAdaptationModule::AdaptCounter::MoveCount(
|
|
||||||
std::vector<int>* counters,
|
|
||||||
int from_reason) {
|
|
||||||
int to_reason = (from_reason + 1) % kScaleReasonSize;
|
|
||||||
++((*counters)[to_reason]);
|
|
||||||
--((*counters)[from_reason]);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
|
||||||
OveruseFrameDetectorResourceAdaptationModule::AdaptCounter::ToString(
|
|
||||||
const std::vector<int>& counters) const {
|
|
||||||
rtc::StringBuilder ss;
|
|
||||||
for (size_t reason = 0; reason < kScaleReasonSize; ++reason) {
|
|
||||||
ss << (reason ? " cpu" : "quality") << ":" << counters[reason];
|
|
||||||
}
|
}
|
||||||
return ss.Release();
|
|
||||||
}
|
void IncrementFramerate(int reason) { ++(fps_counters_[reason]); }
|
||||||
|
void IncrementResolution(int reason) { ++(resolution_counters_[reason]); }
|
||||||
|
void DecrementFramerate(int reason) {
|
||||||
|
if (fps_counters_[reason] == 0) {
|
||||||
|
// Balanced mode: Adapt up is in a different order, switch reason.
|
||||||
|
// E.g. framerate adapt down: quality (2), framerate adapt up: cpu (3).
|
||||||
|
// 1. Down resolution (cpu): res={quality:0,cpu:1}, fps={quality:0,cpu:0}
|
||||||
|
// 2. Down fps (quality): res={quality:0,cpu:1}, fps={quality:1,cpu:0}
|
||||||
|
// 3. Up fps (cpu): res={quality:1,cpu:0}, fps={quality:0,cpu:0}
|
||||||
|
// 4. Up resolution (quality):res={quality:0,cpu:0}, fps={quality:0,cpu:0}
|
||||||
|
RTC_DCHECK_GT(TotalCount(reason), 0) << "No downgrade for reason.";
|
||||||
|
RTC_DCHECK_GT(FramerateCount(), 0) << "Framerate not downgraded.";
|
||||||
|
MoveCount(&resolution_counters_, reason);
|
||||||
|
MoveCount(&fps_counters_, (reason + 1) % kScaleReasonSize);
|
||||||
|
}
|
||||||
|
--(fps_counters_[reason]);
|
||||||
|
RTC_DCHECK_GE(fps_counters_[reason], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DecrementResolution(int reason) {
|
||||||
|
if (resolution_counters_[reason] == 0) {
|
||||||
|
// Balanced mode: Adapt up is in a different order, switch reason.
|
||||||
|
RTC_DCHECK_GT(TotalCount(reason), 0) << "No downgrade for reason.";
|
||||||
|
RTC_DCHECK_GT(ResolutionCount(), 0) << "Resolution not downgraded.";
|
||||||
|
MoveCount(&fps_counters_, reason);
|
||||||
|
MoveCount(&resolution_counters_, (reason + 1) % kScaleReasonSize);
|
||||||
|
}
|
||||||
|
--(resolution_counters_[reason]);
|
||||||
|
RTC_DCHECK_GE(resolution_counters_[reason], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DecrementFramerate(int reason, int cur_fps) {
|
||||||
|
DecrementFramerate(reason);
|
||||||
|
// Reset if at max fps (i.e. in case of fewer steps up than down).
|
||||||
|
if (cur_fps == std::numeric_limits<int>::max())
|
||||||
|
absl::c_fill(fps_counters_, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the total number of downgrades (for all adapt reasons).
|
||||||
|
int FramerateCount() const { return Count(fps_counters_); }
|
||||||
|
int ResolutionCount() const { return Count(resolution_counters_); }
|
||||||
|
|
||||||
|
// Gets the total number of downgrades for |reason|.
|
||||||
|
int FramerateCount(int reason) const { return fps_counters_[reason]; }
|
||||||
|
int ResolutionCount(int reason) const { return resolution_counters_[reason]; }
|
||||||
|
int TotalCount(int reason) const {
|
||||||
|
return FramerateCount(reason) + ResolutionCount(reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string ToString(const std::vector<int>& counters) const {
|
||||||
|
rtc::StringBuilder ss;
|
||||||
|
for (size_t reason = 0; reason < kScaleReasonSize; ++reason) {
|
||||||
|
ss << (reason ? " cpu" : "quality") << ":" << counters[reason];
|
||||||
|
}
|
||||||
|
return ss.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Count(const std::vector<int>& counters) const {
|
||||||
|
return absl::c_accumulate(counters, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveCount(std::vector<int>* counters, int from_reason) {
|
||||||
|
int to_reason = (from_reason + 1) % kScaleReasonSize;
|
||||||
|
++((*counters)[to_reason]);
|
||||||
|
--((*counters)[from_reason]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Degradation counters holding number of framerate/resolution reductions
|
||||||
|
// per adapt reason.
|
||||||
|
std::vector<int> fps_counters_;
|
||||||
|
std::vector<int> resolution_counters_;
|
||||||
|
};
|
||||||
|
|
||||||
OveruseFrameDetectorResourceAdaptationModule::
|
OveruseFrameDetectorResourceAdaptationModule::
|
||||||
OveruseFrameDetectorResourceAdaptationModule(
|
OveruseFrameDetectorResourceAdaptationModule(
|
||||||
@ -368,6 +343,8 @@ OveruseFrameDetectorResourceAdaptationModule::
|
|||||||
quality_scaler_(nullptr),
|
quality_scaler_(nullptr),
|
||||||
quality_scaling_experiment_enabled_(QualityScalingExperiment::Enabled()),
|
quality_scaling_experiment_enabled_(QualityScalingExperiment::Enabled()),
|
||||||
quality_scaler_settings_(QualityScalerSettings::ParseFromFieldTrials()),
|
quality_scaler_settings_(QualityScalerSettings::ParseFromFieldTrials()),
|
||||||
|
quality_rampup_done_(false),
|
||||||
|
quality_rampup_experiment_(QualityRampupExperiment::ParseSettings()),
|
||||||
encoder_settings_(absl::nullopt),
|
encoder_settings_(absl::nullopt),
|
||||||
encoder_stats_observer_(encoder_stats_observer),
|
encoder_stats_observer_(encoder_stats_observer),
|
||||||
initial_framedrop_(0) {
|
initial_framedrop_(0) {
|
||||||
@ -432,6 +409,10 @@ void OveruseFrameDetectorResourceAdaptationModule::SetDegradationPreference(
|
|||||||
void OveruseFrameDetectorResourceAdaptationModule::SetEncoderSettings(
|
void OveruseFrameDetectorResourceAdaptationModule::SetEncoderSettings(
|
||||||
EncoderSettings encoder_settings) {
|
EncoderSettings encoder_settings) {
|
||||||
encoder_settings_ = std::move(encoder_settings);
|
encoder_settings_ = std::move(encoder_settings);
|
||||||
|
|
||||||
|
quality_rampup_experiment_.SetMaxBitrate(
|
||||||
|
LastInputFrameSizeOrDefault(),
|
||||||
|
encoder_settings_->video_codec().maxBitrate);
|
||||||
MaybeUpdateTargetFrameRate();
|
MaybeUpdateTargetFrameRate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,6 +449,11 @@ void OveruseFrameDetectorResourceAdaptationModule::SetTargetBitrate(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OveruseFrameDetectorResourceAdaptationModule::SetEncoderRates(
|
||||||
|
const VideoEncoder::RateControlParameters& encoder_rates) {
|
||||||
|
encoder_rates_ = encoder_rates;
|
||||||
|
}
|
||||||
|
|
||||||
void OveruseFrameDetectorResourceAdaptationModule::
|
void OveruseFrameDetectorResourceAdaptationModule::
|
||||||
ResetVideoSourceRestrictions() {
|
ResetVideoSourceRestrictions() {
|
||||||
last_adaptation_request_.reset();
|
last_adaptation_request_.reset();
|
||||||
@ -540,6 +526,7 @@ void OveruseFrameDetectorResourceAdaptationModule::OnFrameDropped(
|
|||||||
|
|
||||||
void OveruseFrameDetectorResourceAdaptationModule::OnMaybeEncodeFrame() {
|
void OveruseFrameDetectorResourceAdaptationModule::OnMaybeEncodeFrame() {
|
||||||
initial_framedrop_ = kMaxInitialFramedrop;
|
initial_framedrop_ = kMaxInitialFramedrop;
|
||||||
|
MaybePerformQualityRampupExperiment();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OveruseFrameDetectorResourceAdaptationModule::DropInitialFrames() const {
|
bool OveruseFrameDetectorResourceAdaptationModule::DropInitialFrames() const {
|
||||||
@ -994,4 +981,38 @@ bool OveruseFrameDetectorResourceAdaptationModule::CanAdaptUpResolution(
|
|||||||
static_cast<uint32_t>(bitrate_limits->min_start_bitrate_bps);
|
static_cast<uint32_t>(bitrate_limits->min_start_bitrate_bps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OveruseFrameDetectorResourceAdaptationModule::
|
||||||
|
MaybePerformQualityRampupExperiment() {
|
||||||
|
if (!quality_scaler_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (quality_rampup_done_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int64_t now_ms = clock_->TimeInMilliseconds();
|
||||||
|
uint32_t bw_kbps = encoder_rates_.has_value()
|
||||||
|
? encoder_rates_.value().bandwidth_allocation.kbps()
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
bool try_quality_rampup = false;
|
||||||
|
if (quality_rampup_experiment_.BwHigh(now_ms, bw_kbps)) {
|
||||||
|
// Verify that encoder is at max bitrate and the QP is low.
|
||||||
|
if (encoder_settings_ &&
|
||||||
|
encoder_target_bitrate_bps_.value_or(0) ==
|
||||||
|
encoder_settings_->video_codec().maxBitrate * 1000 &&
|
||||||
|
quality_scaler_->QpFastFilterLow()) {
|
||||||
|
try_quality_rampup = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (try_quality_rampup &&
|
||||||
|
GetConstAdaptCounter().ResolutionCount(
|
||||||
|
AdaptationObserverInterface::AdaptReason::kQuality) > 0 &&
|
||||||
|
GetConstAdaptCounter().TotalCount(
|
||||||
|
AdaptationObserverInterface::AdaptReason::kCpu) == 0) {
|
||||||
|
RTC_LOG(LS_INFO) << "Reset quality limitations.";
|
||||||
|
ResetVideoSourceRestrictions();
|
||||||
|
quality_rampup_done_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "api/video_codecs/video_encoder_config.h"
|
#include "api/video_codecs/video_encoder_config.h"
|
||||||
#include "call/adaptation/resource_adaptation_module_interface.h"
|
#include "call/adaptation/resource_adaptation_module_interface.h"
|
||||||
#include "rtc_base/experiments/balanced_degradation_settings.h"
|
#include "rtc_base/experiments/balanced_degradation_settings.h"
|
||||||
|
#include "rtc_base/experiments/quality_rampup_experiment.h"
|
||||||
#include "rtc_base/experiments/quality_scaler_settings.h"
|
#include "rtc_base/experiments/quality_scaler_settings.h"
|
||||||
#include "system_wrappers/include/clock.h"
|
#include "system_wrappers/include/clock.h"
|
||||||
#include "video/overuse_frame_detector.h"
|
#include "video/overuse_frame_detector.h"
|
||||||
@ -66,7 +67,6 @@ class OveruseFrameDetectorResourceAdaptationModule
|
|||||||
DegradationPreference degradation_preference() const {
|
DegradationPreference degradation_preference() const {
|
||||||
return degradation_preference_;
|
return degradation_preference_;
|
||||||
}
|
}
|
||||||
QualityScaler* quality_scaler() const { return quality_scaler_.get(); }
|
|
||||||
|
|
||||||
// ResourceAdaptationModuleInterface implementation.
|
// ResourceAdaptationModuleInterface implementation.
|
||||||
void StartResourceAdaptation(
|
void StartResourceAdaptation(
|
||||||
@ -78,7 +78,8 @@ class OveruseFrameDetectorResourceAdaptationModule
|
|||||||
void SetEncoderSettings(EncoderSettings encoder_settings) override;
|
void SetEncoderSettings(EncoderSettings encoder_settings) override;
|
||||||
void SetStartBitrate(DataRate start_bitrate) override;
|
void SetStartBitrate(DataRate start_bitrate) override;
|
||||||
void SetTargetBitrate(DataRate target_bitrate) override;
|
void SetTargetBitrate(DataRate target_bitrate) override;
|
||||||
void ResetVideoSourceRestrictions() override;
|
void SetEncoderRates(
|
||||||
|
const VideoEncoder::RateControlParameters& encoder_rates) override;
|
||||||
|
|
||||||
void OnFrame(const VideoFrame& frame) override;
|
void OnFrame(const VideoFrame& frame) override;
|
||||||
void OnFrameDroppedDueToSize() override;
|
void OnFrameDroppedDueToSize() override;
|
||||||
@ -89,6 +90,7 @@ class OveruseFrameDetectorResourceAdaptationModule
|
|||||||
int64_t time_sent_in_us,
|
int64_t time_sent_in_us,
|
||||||
absl::optional<int> encode_duration_us) override;
|
absl::optional<int> encode_duration_us) override;
|
||||||
void OnFrameDropped(EncodedImageCallback::DropReason reason) override;
|
void OnFrameDropped(EncodedImageCallback::DropReason reason) override;
|
||||||
|
|
||||||
bool DropInitialFrames() const;
|
bool DropInitialFrames() const;
|
||||||
|
|
||||||
// TODO(eshr): This can be made private if we configure on
|
// TODO(eshr): This can be made private if we configure on
|
||||||
@ -96,42 +98,6 @@ class OveruseFrameDetectorResourceAdaptationModule
|
|||||||
// (https://crbug.com/webrtc/11338)
|
// (https://crbug.com/webrtc/11338)
|
||||||
void ConfigureQualityScaler(const VideoEncoder::EncoderInfo& encoder_info);
|
void ConfigureQualityScaler(const VideoEncoder::EncoderInfo& encoder_info);
|
||||||
|
|
||||||
class AdaptCounter final {
|
|
||||||
public:
|
|
||||||
AdaptCounter();
|
|
||||||
~AdaptCounter();
|
|
||||||
|
|
||||||
// Get number of adaptation downscales for |reason|.
|
|
||||||
VideoStreamEncoderObserver::AdaptationSteps Counts(int reason) const;
|
|
||||||
|
|
||||||
std::string ToString() const;
|
|
||||||
|
|
||||||
void IncrementFramerate(int reason);
|
|
||||||
void IncrementResolution(int reason);
|
|
||||||
void DecrementFramerate(int reason);
|
|
||||||
void DecrementResolution(int reason);
|
|
||||||
void DecrementFramerate(int reason, int cur_fps);
|
|
||||||
|
|
||||||
// Gets the total number of downgrades (for all adapt reasons).
|
|
||||||
int FramerateCount() const;
|
|
||||||
int ResolutionCount() const;
|
|
||||||
|
|
||||||
// Gets the total number of downgrades for |reason|.
|
|
||||||
int FramerateCount(int reason) const;
|
|
||||||
int ResolutionCount(int reason) const;
|
|
||||||
int TotalCount(int reason) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string ToString(const std::vector<int>& counters) const;
|
|
||||||
int Count(const std::vector<int>& counters) const;
|
|
||||||
void MoveCount(std::vector<int>* counters, int from_reason);
|
|
||||||
|
|
||||||
// Degradation counters holding number of framerate/resolution reductions
|
|
||||||
// per adapt reason.
|
|
||||||
std::vector<int> fps_counters_;
|
|
||||||
std::vector<int> resolution_counters_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// AdaptationObserverInterface implementation. Used both "internally" as
|
// AdaptationObserverInterface implementation. Used both "internally" as
|
||||||
// feedback from |overuse_detector_|, and externally from VideoStreamEncoder:
|
// feedback from |overuse_detector_|, and externally from VideoStreamEncoder:
|
||||||
// - It is wired to the VideoStreamEncoder::quality_scaler_.
|
// - It is wired to the VideoStreamEncoder::quality_scaler_.
|
||||||
@ -143,12 +109,8 @@ class OveruseFrameDetectorResourceAdaptationModule
|
|||||||
void AdaptUp(AdaptReason reason) override;
|
void AdaptUp(AdaptReason reason) override;
|
||||||
bool AdaptDown(AdaptReason reason) override;
|
bool AdaptDown(AdaptReason reason) override;
|
||||||
|
|
||||||
// Used by VideoStreamEncoder::MaybeEncodeVideoFrame().
|
|
||||||
// TODO(hbos): VideoStreamEncoder should not be responsible for any part of
|
|
||||||
// the adaptation. Move this logic to this module?
|
|
||||||
const AdaptCounter& GetConstAdaptCounter();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class AdaptCounter;
|
||||||
class VideoSourceRestrictor;
|
class VideoSourceRestrictor;
|
||||||
|
|
||||||
struct AdaptationRequest {
|
struct AdaptationRequest {
|
||||||
@ -171,6 +133,7 @@ class OveruseFrameDetectorResourceAdaptationModule
|
|||||||
int LastInputFrameSizeOrDefault() const;
|
int LastInputFrameSizeOrDefault() const;
|
||||||
VideoStreamEncoderObserver::AdaptationSteps GetActiveCounts(
|
VideoStreamEncoderObserver::AdaptationSteps GetActiveCounts(
|
||||||
AdaptReason reason);
|
AdaptReason reason);
|
||||||
|
const AdaptCounter& GetConstAdaptCounter();
|
||||||
|
|
||||||
// Makes |video_source_restrictions_| up-to-date and informs the
|
// Makes |video_source_restrictions_| up-to-date and informs the
|
||||||
// |adaptation_listener_| if restrictions are changed, allowing the listener
|
// |adaptation_listener_| if restrictions are changed, allowing the listener
|
||||||
@ -190,6 +153,14 @@ class OveruseFrameDetectorResourceAdaptationModule
|
|||||||
AdaptCounter& GetAdaptCounter();
|
AdaptCounter& GetAdaptCounter();
|
||||||
bool CanAdaptUpResolution(int pixels, uint32_t bitrate_bps) const;
|
bool CanAdaptUpResolution(int pixels, uint32_t bitrate_bps) const;
|
||||||
|
|
||||||
|
// Checks to see if we should execute the quality rampup experiment. The
|
||||||
|
// experiment resets all video restrictions at the start of the call in the
|
||||||
|
// case the bandwidth estimate is high enough.
|
||||||
|
// TODO(https://crbug.com/webrtc/11222) Move experiment details into an inner
|
||||||
|
// class.
|
||||||
|
void MaybePerformQualityRampupExperiment();
|
||||||
|
void ResetVideoSourceRestrictions();
|
||||||
|
|
||||||
ResourceAdaptationModuleListener* const adaptation_listener_;
|
ResourceAdaptationModuleListener* const adaptation_listener_;
|
||||||
Clock* clock_;
|
Clock* clock_;
|
||||||
const bool experiment_cpu_load_estimator_;
|
const bool experiment_cpu_load_estimator_;
|
||||||
@ -215,9 +186,12 @@ class OveruseFrameDetectorResourceAdaptationModule
|
|||||||
absl::optional<double> target_frame_rate_;
|
absl::optional<double> target_frame_rate_;
|
||||||
// This is the last non-zero target bitrate for the encoder.
|
// This is the last non-zero target bitrate for the encoder.
|
||||||
absl::optional<uint32_t> encoder_target_bitrate_bps_;
|
absl::optional<uint32_t> encoder_target_bitrate_bps_;
|
||||||
|
absl::optional<VideoEncoder::RateControlParameters> encoder_rates_;
|
||||||
std::unique_ptr<QualityScaler> quality_scaler_;
|
std::unique_ptr<QualityScaler> quality_scaler_;
|
||||||
const bool quality_scaling_experiment_enabled_;
|
const bool quality_scaling_experiment_enabled_;
|
||||||
const QualityScalerSettings quality_scaler_settings_;
|
const QualityScalerSettings quality_scaler_settings_;
|
||||||
|
bool quality_rampup_done_;
|
||||||
|
QualityRampupExperiment quality_rampup_experiment_;
|
||||||
StartBitrate start_bitrate_;
|
StartBitrate start_bitrate_;
|
||||||
absl::optional<EncoderSettings> encoder_settings_;
|
absl::optional<EncoderSettings> encoder_settings_;
|
||||||
VideoStreamEncoderObserver* const encoder_stats_observer_;
|
VideoStreamEncoderObserver* const encoder_stats_observer_;
|
||||||
|
@ -249,8 +249,6 @@ VideoStreamEncoder::VideoStreamEncoder(
|
|||||||
TaskQueueFactory* task_queue_factory)
|
TaskQueueFactory* task_queue_factory)
|
||||||
: shutdown_event_(true /* manual_reset */, false),
|
: shutdown_event_(true /* manual_reset */, false),
|
||||||
number_of_cores_(number_of_cores),
|
number_of_cores_(number_of_cores),
|
||||||
quality_rampup_done_(false),
|
|
||||||
quality_rampup_experiment_(QualityRampupExperiment::ParseSettings()),
|
|
||||||
quality_scaling_experiment_enabled_(QualityScalingExperiment::Enabled()),
|
quality_scaling_experiment_enabled_(QualityScalingExperiment::Enabled()),
|
||||||
sink_(nullptr),
|
sink_(nullptr),
|
||||||
settings_(settings),
|
settings_(settings),
|
||||||
@ -650,8 +648,6 @@ void VideoStreamEncoder::ReconfigureEncoder() {
|
|||||||
send_codec_ = codec;
|
send_codec_ = codec;
|
||||||
|
|
||||||
encoder_switch_experiment_.SetCodec(send_codec_.codecType);
|
encoder_switch_experiment_.SetCodec(send_codec_.codecType);
|
||||||
quality_rampup_experiment_.SetMaxBitrate(
|
|
||||||
last_frame_info_->width * last_frame_info_->height, codec.maxBitrate);
|
|
||||||
|
|
||||||
// Keep the same encoder, as long as the video_format is unchanged.
|
// Keep the same encoder, as long as the video_format is unchanged.
|
||||||
// Encoder creation block is split in two since EncoderInfo needed to start
|
// Encoder creation block is split in two since EncoderInfo needed to start
|
||||||
@ -981,6 +977,7 @@ void VideoStreamEncoder::SetEncoderRates(
|
|||||||
frame_encode_metadata_writer_.OnSetRates(
|
frame_encode_metadata_writer_.OnSetRates(
|
||||||
rate_settings.rate_control.bitrate,
|
rate_settings.rate_control.bitrate,
|
||||||
static_cast<uint32_t>(rate_settings.rate_control.framerate_fps + 0.5));
|
static_cast<uint32_t>(rate_settings.rate_control.framerate_fps + 0.5));
|
||||||
|
resource_adaptation_module_->SetEncoderRates(rate_settings.rate_control);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1065,16 +1062,6 @@ void VideoStreamEncoder::MaybeEncodeVideoFrame(const VideoFrame& video_frame,
|
|||||||
}
|
}
|
||||||
resource_adaptation_module_->OnMaybeEncodeFrame();
|
resource_adaptation_module_->OnMaybeEncodeFrame();
|
||||||
|
|
||||||
if (!quality_rampup_done_ && TryQualityRampup(now_ms) &&
|
|
||||||
resource_adaptation_module_->GetConstAdaptCounter().ResolutionCount(
|
|
||||||
AdaptationObserverInterface::AdaptReason::kQuality) > 0 &&
|
|
||||||
resource_adaptation_module_->GetConstAdaptCounter().TotalCount(
|
|
||||||
AdaptationObserverInterface::AdaptReason::kCpu) == 0) {
|
|
||||||
RTC_LOG(LS_INFO) << "Reset quality limitations.";
|
|
||||||
resource_adaptation_module_->ResetVideoSourceRestrictions();
|
|
||||||
quality_rampup_done_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (EncoderPaused()) {
|
if (EncoderPaused()) {
|
||||||
// Storing references to a native buffer risks blocking frame capture.
|
// Storing references to a native buffer risks blocking frame capture.
|
||||||
if (video_frame.video_frame_buffer()->type() !=
|
if (video_frame.video_frame_buffer()->type() !=
|
||||||
@ -1590,27 +1577,6 @@ bool VideoStreamEncoder::DropDueToSize(uint32_t pixel_count) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VideoStreamEncoder::TryQualityRampup(int64_t now_ms) {
|
|
||||||
QualityScaler* quality_scaler = resource_adaptation_module_->quality_scaler();
|
|
||||||
if (!quality_scaler)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
uint32_t bw_kbps = last_encoder_rate_settings_
|
|
||||||
? last_encoder_rate_settings_->rate_control
|
|
||||||
.bandwidth_allocation.kbps()
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
if (quality_rampup_experiment_.BwHigh(now_ms, bw_kbps)) {
|
|
||||||
// Verify that encoder is at max bitrate and the QP is low.
|
|
||||||
if (encoder_target_bitrate_bps_.value_or(0) ==
|
|
||||||
send_codec_.maxBitrate * 1000 &&
|
|
||||||
quality_scaler->QpFastFilterLow()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VideoStreamEncoder::TriggerAdaptDown(
|
bool VideoStreamEncoder::TriggerAdaptDown(
|
||||||
AdaptationObserverInterface::AdaptReason reason) {
|
AdaptationObserverInterface::AdaptReason reason) {
|
||||||
RTC_DCHECK_RUN_ON(&encoder_queue_);
|
RTC_DCHECK_RUN_ON(&encoder_queue_);
|
||||||
|
@ -173,7 +173,6 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
|
|||||||
// Indicates wether frame should be dropped because the pixel count is too
|
// Indicates wether frame should be dropped because the pixel count is too
|
||||||
// large for the current bitrate configuration.
|
// large for the current bitrate configuration.
|
||||||
bool DropDueToSize(uint32_t pixel_count) const RTC_RUN_ON(&encoder_queue_);
|
bool DropDueToSize(uint32_t pixel_count) const RTC_RUN_ON(&encoder_queue_);
|
||||||
bool TryQualityRampup(int64_t now_ms) RTC_RUN_ON(&encoder_queue_);
|
|
||||||
|
|
||||||
// Implements EncodedImageCallback.
|
// Implements EncodedImageCallback.
|
||||||
EncodedImageCallback::Result OnEncodedImage(
|
EncodedImageCallback::Result OnEncodedImage(
|
||||||
@ -211,9 +210,6 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
|
|||||||
rtc::Event shutdown_event_;
|
rtc::Event shutdown_event_;
|
||||||
|
|
||||||
const uint32_t number_of_cores_;
|
const uint32_t number_of_cores_;
|
||||||
bool quality_rampup_done_ RTC_GUARDED_BY(&encoder_queue_);
|
|
||||||
QualityRampupExperiment quality_rampup_experiment_
|
|
||||||
RTC_GUARDED_BY(&encoder_queue_);
|
|
||||||
|
|
||||||
const bool quality_scaling_experiment_enabled_;
|
const bool quality_scaling_experiment_enabled_;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user