Chromium Code Reviews| 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..97ac9502cdf452b32280984cdc561c529b88bb74 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,108 @@ 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(); |
| + rtc::Optional<int> overried_usage_value; |
| + if (last_toggling_ms_ == -1) { |
| + last_toggling_ms_ = now_ms; |
| + } else { |
| + switch (state_) { |
|
ilnik
2017/03/31 09:20:19
If i understood correctly, this may be called ever
sprang_webrtc
2017/03/31 09:46:42
Done.
|
| + 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."; |
| + } |
| + overried_usage_value.emplace(250); |
| + 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."; |
| + } |
| + 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 +327,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 +425,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 +502,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_; |