| Index: webrtc/video/overuse_frame_detector.cc
|
| diff --git a/webrtc/video/overuse_frame_detector.cc b/webrtc/video/overuse_frame_detector.cc
|
| index 68b98a444cac2df6b71711c728266a8eb0ea4d1c..42ee350257f03225ac39aee2062d0ba47f704f05 100644
|
| --- a/webrtc/video/overuse_frame_detector.cc
|
| +++ b/webrtc/video/overuse_frame_detector.cc
|
| @@ -16,12 +16,15 @@
|
| #include <algorithm>
|
| #include <list>
|
| #include <map>
|
| +#include <string>
|
| +#include <utility>
|
|
|
| #include "webrtc/api/video/video_frame.h"
|
| #include "webrtc/base/checks.h"
|
| #include "webrtc/base/logging.h"
|
| #include "webrtc/base/numerics/exp_filter.h"
|
| #include "webrtc/common_video/include/frame_callback.h"
|
| +#include "webrtc/system_wrappers/include/field_trial.h"
|
|
|
| #if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
| #include <mach/mach.h>
|
| @@ -116,7 +119,7 @@ class OveruseFrameDetector::SendProcessingUsage {
|
| filtered_frame_diff_ms_(new rtc::ExpFilter(kWeightFactorFrameDiff)) {
|
| Reset();
|
| }
|
| - ~SendProcessingUsage() {}
|
| + virtual ~SendProcessingUsage() {}
|
|
|
| void Reset() {
|
| count_ = 0;
|
| @@ -139,7 +142,7 @@ class OveruseFrameDetector::SendProcessingUsage {
|
| filtered_processing_ms_->Apply(exp, processing_ms);
|
| }
|
|
|
| - int Value() const {
|
| + virtual int Value() {
|
| if (count_ < static_cast<uint32_t>(options_.min_frame_samples)) {
|
| return static_cast<int>(InitialUsageInPercent() + 0.5f);
|
| }
|
| @@ -171,6 +174,117 @@ class OveruseFrameDetector::SendProcessingUsage {
|
| std::unique_ptr<rtc::ExpFilter> filtered_frame_diff_ms_;
|
| };
|
|
|
| +// Class used for manual testing of overuse, enabled via field trial flag.
|
| +class OveruseFrameDetector::OverdoseInjector
|
| + : public OveruseFrameDetector::SendProcessingUsage {
|
| + public:
|
| + OverdoseInjector(const CpuOveruseOptions& options,
|
| + int64_t normal_period_ms,
|
| + int64_t overuse_period_ms,
|
| + int64_t underuse_period_ms)
|
| + : OveruseFrameDetector::SendProcessingUsage(options),
|
| + normal_period_ms_(normal_period_ms),
|
| + overuse_period_ms_(overuse_period_ms),
|
| + underuse_period_ms_(underuse_period_ms),
|
| + state_(State::kNormal),
|
| + last_toggling_ms_(-1) {
|
| + RTC_DCHECK_GT(overuse_period_ms, 0);
|
| + RTC_DCHECK_GT(normal_period_ms, 0);
|
| + LOG(LS_INFO) << "Simulating overuse with intervals " << normal_period_ms
|
| + << "ms normal mode, " << overuse_period_ms
|
| + << "ms overuse mode.";
|
| + }
|
| +
|
| + ~OverdoseInjector() override {}
|
| +
|
| + int Value() override {
|
| + int64_t now_ms = rtc::TimeMillis();
|
| + if (last_toggling_ms_ == -1) {
|
| + last_toggling_ms_ = now_ms;
|
| + } else {
|
| + switch (state_) {
|
| + case State::kNormal:
|
| + if (now_ms > last_toggling_ms_ + normal_period_ms_) {
|
| + state_ = State::kOveruse;
|
| + last_toggling_ms_ = now_ms;
|
| + LOG(LS_INFO) << "Simulating CPU overuse.";
|
| + }
|
| + break;
|
| + case State::kOveruse:
|
| + if (now_ms > last_toggling_ms_ + overuse_period_ms_) {
|
| + state_ = State::kUnderuse;
|
| + last_toggling_ms_ = now_ms;
|
| + LOG(LS_INFO) << "Simulating CPU underuse.";
|
| + }
|
| + break;
|
| + case State::kUnderuse:
|
| + if (now_ms > last_toggling_ms_ + underuse_period_ms_) {
|
| + state_ = State::kNormal;
|
| + last_toggling_ms_ = now_ms;
|
| + LOG(LS_INFO) << "Actual CPU overuse measurements in effect.";
|
| + }
|
| + break;
|
| + }
|
| + }
|
| +
|
| + rtc::Optional<int> overried_usage_value;
|
| + switch (state_) {
|
| + case State::kNormal:
|
| + break;
|
| + case State::kOveruse:
|
| + overried_usage_value.emplace(250);
|
| + break;
|
| + case State::kUnderuse:
|
| + overried_usage_value.emplace(5);
|
| + break;
|
| + }
|
| +
|
| + return overried_usage_value.value_or(SendProcessingUsage::Value());
|
| + }
|
| +
|
| + private:
|
| + const int64_t normal_period_ms_;
|
| + const int64_t overuse_period_ms_;
|
| + const int64_t underuse_period_ms_;
|
| + enum class State { kNormal, kOveruse, kUnderuse } state_;
|
| + int64_t last_toggling_ms_;
|
| +};
|
| +
|
| +std::unique_ptr<OveruseFrameDetector::SendProcessingUsage>
|
| +OveruseFrameDetector::CreateSendProcessingUsage(
|
| + const CpuOveruseOptions& options) {
|
| + std::unique_ptr<SendProcessingUsage> instance;
|
| + std::string toggling_interval =
|
| + field_trial::FindFullName("WebRTC-ForceSimulatedOveruseIntervalMs");
|
| + if (!toggling_interval.empty()) {
|
| + int normal_period_ms = 0;
|
| + int overuse_period_ms = 0;
|
| + int underuse_period_ms = 0;
|
| + if (sscanf(toggling_interval.c_str(), "%d-%d-%d", &normal_period_ms,
|
| + &overuse_period_ms, &underuse_period_ms) == 3) {
|
| + if (normal_period_ms > 0 && overuse_period_ms > 0 &&
|
| + underuse_period_ms > 0) {
|
| + instance.reset(new OverdoseInjector(
|
| + options, normal_period_ms, overuse_period_ms, underuse_period_ms));
|
| + } else {
|
| + LOG(LS_WARNING)
|
| + << "Invalid (non-positive) normal/overuse/underuse periods: "
|
| + << normal_period_ms << " / " << overuse_period_ms << " / "
|
| + << underuse_period_ms;
|
| + }
|
| + } else {
|
| + LOG(LS_WARNING) << "Malformed toggling interval: " << toggling_interval;
|
| + }
|
| + }
|
| +
|
| + if (!instance) {
|
| + // No valid overuse simulation parameters set, use normal usage class.
|
| + instance.reset(new SendProcessingUsage(options));
|
| + }
|
| +
|
| + return instance;
|
| +}
|
| +
|
| class OveruseFrameDetector::CheckOveruseTask : public rtc::QueuedTask {
|
| public:
|
| explicit CheckOveruseTask(OveruseFrameDetector* overuse_detector)
|
| @@ -222,7 +336,7 @@ OveruseFrameDetector::OveruseFrameDetector(
|
| last_rampup_time_ms_(-1),
|
| in_quick_rampup_(false),
|
| current_rampup_delay_ms_(kStandardRampUpDelayMs),
|
| - usage_(new SendProcessingUsage(options)) {
|
| + usage_(CreateSendProcessingUsage(options)) {
|
| task_checker_.Detach();
|
| }
|
|
|
| @@ -320,8 +434,9 @@ void OveruseFrameDetector::FrameSent(uint32_t timestamp,
|
| while (!frame_timing_.empty()) {
|
| FrameTiming timing = frame_timing_.front();
|
| if (time_sent_in_us - timing.capture_us <
|
| - kEncodingTimeMeasureWindowMs * rtc::kNumMicrosecsPerMillisec)
|
| + kEncodingTimeMeasureWindowMs * rtc::kNumMicrosecsPerMillisec) {
|
| break;
|
| + }
|
| if (timing.last_send_us != -1) {
|
| int encode_duration_us =
|
| static_cast<int>(timing.last_send_us - timing.capture_us);
|
| @@ -396,6 +511,7 @@ void OveruseFrameDetector::CheckForOveruse() {
|
|
|
| bool OveruseFrameDetector::IsOverusing(const CpuOveruseMetrics& metrics) {
|
| RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
|
| +
|
| if (metrics.encode_usage_percent >=
|
| options_.high_encode_usage_threshold_percent) {
|
| ++checks_above_threshold_;
|
|
|