1f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org/* 2f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org * 4f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org * Use of this source code is governed by a BSD-style license 5f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org * that can be found in the LICENSE file in the root of the source 6f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org * tree. An additional intellectual property rights grant can be found 7f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org * in the file PATENTS. All contributing project authors may 8f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org */ 10f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org 11f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org#include "webrtc/video_engine/overuse_frame_detector.h" 12f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org 13cb9a72be76527005fc1ad580dd9a31e3d0e779f9mflodman@webrtc.org#include <assert.h> 14ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org#include <math.h> 15cb9a72be76527005fc1ad580dd9a31e3d0e779f9mflodman@webrtc.org 16f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org#include <algorithm> 17f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org#include <list> 189cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org#include <map> 19f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 2031b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org#include "webrtc/base/exp_filter.h" 21f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org#include "webrtc/system_wrappers/interface/clock.h" 22f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 23022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org#include "webrtc/system_wrappers/interface/logging.h" 24f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org 25f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.orgnamespace webrtc { 26f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org 27ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org// TODO(mflodman) Test different values for all of these to trigger correctly, 28ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org// avoid fluctuations etc. 29ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.orgnamespace { 30ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.orgconst int64_t kProcessIntervalMs = 5000; 31ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org 32ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org// Weight factor to apply to the standard deviation. 33ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.orgconst float kWeightFactor = 0.997f; 34ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org// Weight factor to apply to the average. 35ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.orgconst float kWeightFactorMean = 0.98f; 36ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org 37ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org// Delay between consecutive rampups. (Used for quick recovery.) 38ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.orgconst int kQuickRampUpDelayMs = 10 * 1000; 39ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org// Delay between rampup attempts. Initially uses standard, scales up to max. 40c2ef523233552340785557abce1129a0f61537ebasapersson@webrtc.orgconst int kStandardRampUpDelayMs = 40 * 1000; 41f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.orgconst int kMaxRampUpDelayMs = 240 * 1000; 42ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org// Expontential back-off factor, to prevent annoying up-down behaviour. 43ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.orgconst double kRampUpBackoffFactor = 2.0; 44ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org 45eddcc6311725092499404db49f40eda82b552483asapersson@webrtc.org// Max number of overuses detected before always applying the rampup delay. 46c2ef523233552340785557abce1129a0f61537ebasapersson@webrtc.orgconst int kMaxOverusesBeforeApplyRampupDelay = 4; 47f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 48f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org// The maximum exponent to use in VCMExpFilter. 49f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.orgconst float kSampleDiffMs = 33.0f; 50f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.orgconst float kMaxExp = 7.0f; 51f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 52ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org} // namespace 53ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org 54ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.orgStatistics::Statistics() : 55ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org sum_(0.0), 56ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org count_(0), 5731b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org filtered_samples_(new rtc::ExpFilter(kWeightFactorMean)), 5831b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org filtered_variance_(new rtc::ExpFilter(kWeightFactor)) { 599da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org Reset(); 609da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org} 619da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org 629da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.orgvoid Statistics::SetOptions(const CpuOveruseOptions& options) { 639da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org options_ = options; 64ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org} 65ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org 66ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.orgvoid Statistics::Reset() { 67ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org sum_ = 0.0; 68ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org count_ = 0; 699da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org filtered_variance_->Reset(kWeightFactor); 709da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org filtered_variance_->Apply(1.0f, InitialVariance()); 71ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org} 72ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org 73ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.orgvoid Statistics::AddSample(float sample_ms) { 74ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org sum_ += sample_ms; 75ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org ++count_; 76ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org 779da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org if (count_ < static_cast<uint32_t>(options_.min_frame_samples)) { 78ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org // Initialize filtered samples. 79ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org filtered_samples_->Reset(kWeightFactorMean); 80ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org filtered_samples_->Apply(1.0f, InitialMean()); 81ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org return; 82ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org } 83ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org 84f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org float exp = sample_ms / kSampleDiffMs; 85f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org exp = std::min(exp, kMaxExp); 86ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org filtered_samples_->Apply(exp, sample_ms); 8731b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org filtered_variance_->Apply(exp, (sample_ms - filtered_samples_->filtered()) * 8831b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org (sample_ms - filtered_samples_->filtered())); 89ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org} 90ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org 91ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.orgfloat Statistics::InitialMean() const { 92ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org if (count_ == 0) 93ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org return 0.0; 94ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org return sum_ / count_; 95ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org} 96ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org 97ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.orgfloat Statistics::InitialVariance() const { 98ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org // Start in between the underuse and overuse threshold. 999da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org float average_stddev = (options_.low_capture_jitter_threshold_ms + 1009da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org options_.high_capture_jitter_threshold_ms) / 2.0f; 101ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org return average_stddev * average_stddev; 102ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org} 103ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org 10431b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.orgfloat Statistics::Mean() const { return filtered_samples_->filtered(); } 105cb9a72be76527005fc1ad580dd9a31e3d0e779f9mflodman@webrtc.org 106ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.orgfloat Statistics::StdDev() const { 10731b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org return sqrt(std::max(filtered_variance_->filtered(), 0.0f)); 108ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org} 109cb9a72be76527005fc1ad580dd9a31e3d0e779f9mflodman@webrtc.org 110ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.orguint64_t Statistics::Count() const { return count_; } 111cb9a72be76527005fc1ad580dd9a31e3d0e779f9mflodman@webrtc.org 112f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 113f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org// Class for calculating the average encode time. 114f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.orgclass OveruseFrameDetector::EncodeTimeAvg { 115f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org public: 116f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org EncodeTimeAvg() 117f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org : kWeightFactor(0.5f), 118eddcc6311725092499404db49f40eda82b552483asapersson@webrtc.org kInitialAvgEncodeTimeMs(5.0f), 11931b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org filtered_encode_time_ms_(new rtc::ExpFilter(kWeightFactor)) { 120f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org filtered_encode_time_ms_->Apply(1.0f, kInitialAvgEncodeTimeMs); 121f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org } 122f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org ~EncodeTimeAvg() {} 123f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 124f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org void AddEncodeSample(float encode_time_ms, int64_t diff_last_sample_ms) { 125f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org float exp = diff_last_sample_ms / kSampleDiffMs; 126f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org exp = std::min(exp, kMaxExp); 127f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org filtered_encode_time_ms_->Apply(exp, encode_time_ms); 128f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org } 129f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 130f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org int Value() const { 13131b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org return static_cast<int>(filtered_encode_time_ms_->filtered() + 0.5); 132f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org } 133f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 134f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org private: 135f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org const float kWeightFactor; 136eddcc6311725092499404db49f40eda82b552483asapersson@webrtc.org const float kInitialAvgEncodeTimeMs; 13731b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org scoped_ptr<rtc::ExpFilter> filtered_encode_time_ms_; 138f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org}; 139f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 140f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org// Class for calculating the encode usage. 141f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.orgclass OveruseFrameDetector::EncodeUsage { 142f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org public: 143f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org EncodeUsage() 144f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org : kWeightFactorFrameDiff(0.998f), 145f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org kWeightFactorEncodeTime(0.995f), 146c773dedf47e175eaf67d266d95f4b62a96daae90asapersson@webrtc.org kInitialSampleDiffMs(40.0f), 147c773dedf47e175eaf67d266d95f4b62a96daae90asapersson@webrtc.org kMaxSampleDiffMs(45.0f), 148154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org count_(0), 14931b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org filtered_encode_time_ms_(new rtc::ExpFilter(kWeightFactorEncodeTime)), 15031b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org filtered_frame_diff_ms_(new rtc::ExpFilter(kWeightFactorFrameDiff)) { 151154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org Reset(); 152f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org } 153f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org ~EncodeUsage() {} 154f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 155154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org void SetOptions(const CpuOveruseOptions& options) { 156154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org options_ = options; 157154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org } 158154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org 159154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org void Reset() { 160154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org count_ = 0; 161154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org filtered_frame_diff_ms_->Reset(kWeightFactorFrameDiff); 162154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org filtered_frame_diff_ms_->Apply(1.0f, kInitialSampleDiffMs); 163154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org filtered_encode_time_ms_->Reset(kWeightFactorEncodeTime); 164154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org filtered_encode_time_ms_->Apply(1.0f, InitialEncodeTimeMs()); 165154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org } 166154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org 167f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org void AddSample(float sample_ms) { 168f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org float exp = sample_ms / kSampleDiffMs; 169f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org exp = std::min(exp, kMaxExp); 170f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org filtered_frame_diff_ms_->Apply(exp, sample_ms); 171f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org } 172f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 173f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org void AddEncodeSample(float encode_time_ms, int64_t diff_last_sample_ms) { 174154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org ++count_; 175f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org float exp = diff_last_sample_ms / kSampleDiffMs; 176f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org exp = std::min(exp, kMaxExp); 177f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org filtered_encode_time_ms_->Apply(exp, encode_time_ms); 178f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org } 179f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 180f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org int Value() const { 181154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org if (count_ < static_cast<uint32_t>(options_.min_frame_samples)) { 182154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org return static_cast<int>(InitialUsageInPercent() + 0.5f); 183154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org } 18431b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org float frame_diff_ms = std::max(filtered_frame_diff_ms_->filtered(), 1.0f); 185154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org frame_diff_ms = std::min(frame_diff_ms, kMaxSampleDiffMs); 186f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org float encode_usage_percent = 18731b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org 100.0f * filtered_encode_time_ms_->filtered() / frame_diff_ms; 188f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org return static_cast<int>(encode_usage_percent + 0.5); 189f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org } 190f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 191f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org private: 192154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org float InitialUsageInPercent() const { 193154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org // Start in between the underuse and overuse threshold. 194154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org return (options_.low_encode_usage_threshold_percent + 195154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org options_.high_encode_usage_threshold_percent) / 2.0f; 196154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org } 197154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org 198154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org float InitialEncodeTimeMs() const { 199154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org return InitialUsageInPercent() * kInitialSampleDiffMs / 100; 200154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org } 201154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org 202f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org const float kWeightFactorFrameDiff; 203f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org const float kWeightFactorEncodeTime; 204154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org const float kInitialSampleDiffMs; 205154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org const float kMaxSampleDiffMs; 206154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org uint64_t count_; 207154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org CpuOveruseOptions options_; 20831b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org scoped_ptr<rtc::ExpFilter> filtered_encode_time_ms_; 20931b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org scoped_ptr<rtc::ExpFilter> filtered_frame_diff_ms_; 210f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org}; 211f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 2129cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org// Class for calculating the relative standard deviation of encode times. 2139cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.orgclass OveruseFrameDetector::EncodeTimeRsd { 2149cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org public: 2159cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org EncodeTimeRsd(Clock* clock) 2169cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org : kWeightFactor(0.6f), 2179cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org count_(0), 21831b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org filtered_rsd_(new rtc::ExpFilter(kWeightFactor)), 2199cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org hist_samples_(0), 2209cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org hist_sum_(0.0f), 2219cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org last_process_time_ms_(clock->TimeInMilliseconds()) { 2229cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org Reset(); 2239cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org } 2249cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org ~EncodeTimeRsd() {} 2259cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org 2269cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org void SetOptions(const CpuOveruseOptions& options) { 2279cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org options_ = options; 2289cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org } 2299cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org 2309cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org void Reset() { 2319cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org count_ = 0; 2329cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org filtered_rsd_->Reset(kWeightFactor); 2339cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org filtered_rsd_->Apply(1.0f, InitialValue()); 2349cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org hist_.clear(); 2359cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org hist_samples_ = 0; 2369cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org hist_sum_ = 0.0f; 2379cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org } 2389cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org 2399cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org void AddEncodeSample(float encode_time_ms) { 2409cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org int bin = static_cast<int>(encode_time_ms + 0.5f); 2419cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org if (bin <= 0) { 2429cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org // The frame was probably not encoded, skip possible dropped frame. 2439cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org return; 2449cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org } 2459cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org ++count_; 2469cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org ++hist_[bin]; 2479cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org ++hist_samples_; 2489cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org hist_sum_ += bin; 2499cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org } 2509cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org 2519cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org void Process(int64_t now) { 2529cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org if (count_ < static_cast<uint32_t>(options_.min_frame_samples)) { 2539cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org // Have not received min number of frames since last reset. 2549cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org return; 2559cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org } 2569cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org const int kMinHistSamples = 20; 2579cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org if (hist_samples_ < kMinHistSamples) { 2589cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org return; 2599cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org } 2609cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org const int64_t kMinDiffSinceLastProcessMs = 1000; 2619cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org int64_t diff_last_process_ms = now - last_process_time_ms_; 2629cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org if (now - last_process_time_ms_ <= kMinDiffSinceLastProcessMs) { 2639cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org return; 2649cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org } 2659cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org last_process_time_ms_ = now; 2669cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org 2679cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org // Calculate variance (using samples above the mean). 2689cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org // Checks for a larger encode time of some frames while there is a small 2699cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org // increase in the average time. 2709cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org int mean = hist_sum_ / hist_samples_; 2719cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org float variance = 0.0f; 2729cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org int total_count = 0; 2739cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org for (std::map<int,int>::iterator it = hist_.begin(); 2749cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org it != hist_.end(); ++it) { 2759cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org int time = it->first; 2769cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org int count = it->second; 2779cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org if (time > mean) { 2789cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org total_count += count; 2799cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org for (int i = 0; i < count; ++i) { 2809cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org variance += ((time - mean) * (time - mean)); 2819cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org } 2829cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org } 2839cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org } 2849cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org variance /= std::max(total_count, 1); 2859cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org float cov = sqrt(variance) / mean; 2869cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org 2879cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org hist_.clear(); 2889cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org hist_samples_ = 0; 2899cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org hist_sum_ = 0.0f; 2909cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org 2919cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org float exp = static_cast<float>(diff_last_process_ms) / kProcessIntervalMs; 2929cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org exp = std::min(exp, kMaxExp); 2939cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org filtered_rsd_->Apply(exp, 100.0f * cov); 2949cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org } 2959cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org 2969cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org int Value() const { 29731b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org return static_cast<int>(filtered_rsd_->filtered() + 0.5); 2989cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org } 2999cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org 300f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org private: 3019cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org float InitialValue() const { 3029cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org // Start in between the underuse and overuse threshold. 303f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org return std::max(((options_.low_encode_time_rsd_threshold + 304f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org options_.high_encode_time_rsd_threshold) / 2.0f), 0.0f); 3059cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org } 3069cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org 3079cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org const float kWeightFactor; 3089cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org uint32_t count_; // Number of encode samples since last reset. 3099cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org CpuOveruseOptions options_; 31031b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org scoped_ptr<rtc::ExpFilter> filtered_rsd_; 3119cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org int hist_samples_; 3129cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org float hist_sum_; 3139cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org std::map<int,int> hist_; // Histogram of encode time of frames. 3149cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org int64_t last_process_time_ms_; 3159cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org}; 3169cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org 317f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org// Class for calculating the capture queue delay change. 318f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.orgclass OveruseFrameDetector::CaptureQueueDelay { 319f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org public: 320f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org CaptureQueueDelay() 321f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org : kWeightFactor(0.5f), 322f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org delay_ms_(0), 32331b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org filtered_delay_ms_per_s_(new rtc::ExpFilter(kWeightFactor)) { 324f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org filtered_delay_ms_per_s_->Apply(1.0f, 0.0f); 325f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org } 326f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org ~CaptureQueueDelay() {} 327f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 328f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org void FrameCaptured(int64_t now) { 329f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org const size_t kMaxSize = 200; 330f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org if (frames_.size() > kMaxSize) { 331f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org frames_.pop_front(); 332f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org } 333f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org frames_.push_back(now); 334f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org } 335f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 336f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org void FrameProcessingStarted(int64_t now) { 337f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org if (frames_.empty()) { 338f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org return; 339f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org } 340f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org delay_ms_ = now - frames_.front(); 341f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org frames_.pop_front(); 342f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org } 343f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 344f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org void CalculateDelayChange(int64_t diff_last_sample_ms) { 345f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org if (diff_last_sample_ms <= 0) { 346f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org return; 347f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org } 348f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org float exp = static_cast<float>(diff_last_sample_ms) / kProcessIntervalMs; 349f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org exp = std::min(exp, kMaxExp); 350f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org filtered_delay_ms_per_s_->Apply(exp, 351f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org delay_ms_ * 1000.0f / diff_last_sample_ms); 352f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org ClearFrames(); 353f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org } 354f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 355f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org void ClearFrames() { 356f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org frames_.clear(); 357f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org } 358f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 359f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org int delay_ms() const { 360f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org return delay_ms_; 361f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org } 362f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 363f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org int Value() const { 36431b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org return static_cast<int>(filtered_delay_ms_per_s_->filtered() + 0.5); 365f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org } 366f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 367f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org private: 368f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org const float kWeightFactor; 369f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org std::list<int64_t> frames_; 370f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org int delay_ms_; 37131b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org scoped_ptr<rtc::ExpFilter> filtered_delay_ms_per_s_; 372f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org}; 373f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 3749da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.orgOveruseFrameDetector::OveruseFrameDetector(Clock* clock) 375f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org : crit_(CriticalSectionWrapper::CreateCriticalSection()), 376bf76ae2bdfc0b4e8e875f6cce1c85d4d66357bebmflodman@webrtc.org observer_(NULL), 377f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org clock_(clock), 378ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org next_process_time_(clock_->TimeInMilliseconds()), 379995079666dd4be231e6af4b125c481d953d9b735asapersson@webrtc.org num_process_times_(0), 380ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org last_capture_time_(0), 381ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org last_overuse_time_(0), 382ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org checks_above_threshold_(0), 383eddcc6311725092499404db49f40eda82b552483asapersson@webrtc.org num_overuse_detections_(0), 384ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org last_rampup_time_(0), 385ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org in_quick_rampup_(false), 386ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org current_rampup_delay_ms_(kStandardRampUpDelayMs), 3874747585bba09508c7475bf1e5f70a0b981175d9fasapersson@webrtc.org num_pixels_(0), 388f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org last_encode_sample_ms_(0), 389f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org encode_time_(new EncodeTimeAvg()), 3909cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org encode_rsd_(new EncodeTimeRsd(clock)), 391f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org encode_usage_(new EncodeUsage()), 392f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org capture_queue_delay_(new CaptureQueueDelay()) { 393f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org} 394f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org 395f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.orgOveruseFrameDetector::~OveruseFrameDetector() { 396f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org} 397f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org 398bf76ae2bdfc0b4e8e875f6cce1c85d4d66357bebmflodman@webrtc.orgvoid OveruseFrameDetector::SetObserver(CpuOveruseObserver* observer) { 399bf76ae2bdfc0b4e8e875f6cce1c85d4d66357bebmflodman@webrtc.org CriticalSectionScoped cs(crit_.get()); 400bf76ae2bdfc0b4e8e875f6cce1c85d4d66357bebmflodman@webrtc.org observer_ = observer; 401bf76ae2bdfc0b4e8e875f6cce1c85d4d66357bebmflodman@webrtc.org} 402bf76ae2bdfc0b4e8e875f6cce1c85d4d66357bebmflodman@webrtc.org 4039da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.orgvoid OveruseFrameDetector::SetOptions(const CpuOveruseOptions& options) { 4049da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org assert(options.min_frame_samples > 0); 4059da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org CriticalSectionScoped cs(crit_.get()); 4069da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org if (options_.Equals(options)) { 4079da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org return; 4089da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org } 4099da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org options_ = options; 4109da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org capture_deltas_.SetOptions(options); 411154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org encode_usage_->SetOptions(options); 4129cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org encode_rsd_->SetOptions(options); 4139da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org ResetAll(num_pixels_); 4149da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org} 4159da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org 4164e95436d6302be2854cd5b3e7baa3c4f563e4901asapersson@webrtc.orgint OveruseFrameDetector::CaptureQueueDelayMsPerS() const { 417f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org CriticalSectionScoped cs(crit_.get()); 4184e95436d6302be2854cd5b3e7baa3c4f563e4901asapersson@webrtc.org return capture_queue_delay_->delay_ms(); 419f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org} 420f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 4214e95436d6302be2854cd5b3e7baa3c4f563e4901asapersson@webrtc.orgvoid OveruseFrameDetector::GetCpuOveruseMetrics( 4224e95436d6302be2854cd5b3e7baa3c4f563e4901asapersson@webrtc.org CpuOveruseMetrics* metrics) const { 423f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org CriticalSectionScoped cs(crit_.get()); 4244e95436d6302be2854cd5b3e7baa3c4f563e4901asapersson@webrtc.org metrics->capture_jitter_ms = static_cast<int>(capture_deltas_.StdDev() + 0.5); 425f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org metrics->avg_encode_time_ms = encode_time_->Value(); 4269cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org metrics->encode_rsd = encode_rsd_->Value(); 427f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org metrics->encode_usage_percent = encode_usage_->Value(); 428f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org metrics->capture_queue_delay_ms_per_s = capture_queue_delay_->Value(); 429f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org} 430f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 431f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.orgint32_t OveruseFrameDetector::TimeUntilNextProcess() { 432f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org CriticalSectionScoped cs(crit_.get()); 433f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org return next_process_time_ - clock_->TimeInMilliseconds(); 434f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org} 435f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 4369da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.orgbool OveruseFrameDetector::FrameSizeChanged(int num_pixels) const { 4379da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org if (num_pixels != num_pixels_) { 4389da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org return true; 4399da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org } 4409da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org return false; 4419da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org} 4429da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org 4439da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.orgbool OveruseFrameDetector::FrameTimeoutDetected(int64_t now) const { 444995079666dd4be231e6af4b125c481d953d9b735asapersson@webrtc.org if (last_capture_time_ == 0) { 445995079666dd4be231e6af4b125c481d953d9b735asapersson@webrtc.org return false; 446995079666dd4be231e6af4b125c481d953d9b735asapersson@webrtc.org } 4479da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org return (now - last_capture_time_) > options_.frame_timeout_interval_ms; 4489da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org} 4499da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org 4509da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.orgvoid OveruseFrameDetector::ResetAll(int num_pixels) { 4519da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org num_pixels_ = num_pixels; 4529da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org capture_deltas_.Reset(); 453154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org encode_usage_->Reset(); 4549cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org encode_rsd_->Reset(); 4559da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org capture_queue_delay_->ClearFrames(); 4569da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org last_capture_time_ = 0; 4579da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org num_process_times_ = 0; 458995079666dd4be231e6af4b125c481d953d9b735asapersson@webrtc.org} 459995079666dd4be231e6af4b125c481d953d9b735asapersson@webrtc.org 460ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.orgvoid OveruseFrameDetector::FrameCaptured(int width, int height) { 461f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org CriticalSectionScoped cs(crit_.get()); 462ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org 463995079666dd4be231e6af4b125c481d953d9b735asapersson@webrtc.org int64_t now = clock_->TimeInMilliseconds(); 4649da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org if (FrameSizeChanged(width * height) || FrameTimeoutDetected(now)) { 4659da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org ResetAll(width * height); 466ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org } 467ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org 468ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org if (last_capture_time_ != 0) { 469995079666dd4be231e6af4b125c481d953d9b735asapersson@webrtc.org capture_deltas_.AddSample(now - last_capture_time_); 470995079666dd4be231e6af4b125c481d953d9b735asapersson@webrtc.org encode_usage_->AddSample(now - last_capture_time_); 471ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org } 472995079666dd4be231e6af4b125c481d953d9b735asapersson@webrtc.org last_capture_time_ = now; 473f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org 474995079666dd4be231e6af4b125c481d953d9b735asapersson@webrtc.org capture_queue_delay_->FrameCaptured(now); 475dd4f8664a1759e8a3a0329e8aebe6e872d371f20asapersson@webrtc.org} 476dd4f8664a1759e8a3a0329e8aebe6e872d371f20asapersson@webrtc.org 477f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.orgvoid OveruseFrameDetector::FrameProcessingStarted() { 478dd4f8664a1759e8a3a0329e8aebe6e872d371f20asapersson@webrtc.org CriticalSectionScoped cs(crit_.get()); 479f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org capture_queue_delay_->FrameProcessingStarted(clock_->TimeInMilliseconds()); 480dd4f8664a1759e8a3a0329e8aebe6e872d371f20asapersson@webrtc.org} 481dd4f8664a1759e8a3a0329e8aebe6e872d371f20asapersson@webrtc.org 482f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.orgvoid OveruseFrameDetector::FrameEncoded(int encode_time_ms) { 483dd4f8664a1759e8a3a0329e8aebe6e872d371f20asapersson@webrtc.org CriticalSectionScoped cs(crit_.get()); 484f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org int64_t time = clock_->TimeInMilliseconds(); 485f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org if (last_encode_sample_ms_ != 0) { 486f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org int64_t diff_ms = time - last_encode_sample_ms_; 487f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org encode_time_->AddEncodeSample(encode_time_ms, diff_ms); 488f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org encode_usage_->AddEncodeSample(encode_time_ms, diff_ms); 4899cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org encode_rsd_->AddEncodeSample(encode_time_ms); 490f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org } 491f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org last_encode_sample_ms_ = time; 4924747585bba09508c7475bf1e5f70a0b981175d9fasapersson@webrtc.org} 4934747585bba09508c7475bf1e5f70a0b981175d9fasapersson@webrtc.org 494f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.orgint32_t OveruseFrameDetector::Process() { 495f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org CriticalSectionScoped cs(crit_.get()); 496f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org 497ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org int64_t now = clock_->TimeInMilliseconds(); 498cb9a72be76527005fc1ad580dd9a31e3d0e779f9mflodman@webrtc.org 499ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org // Used to protect against Process() being called too often. 500ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org if (now < next_process_time_) 501f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org return 0; 502f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org 503f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org int64_t diff_ms = now - next_process_time_ + kProcessIntervalMs; 504ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org next_process_time_ = now + kProcessIntervalMs; 505995079666dd4be231e6af4b125c481d953d9b735asapersson@webrtc.org ++num_process_times_; 506ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org 5079cd828145084df3ca05280ca93d283ee32b625e9asapersson@webrtc.org encode_rsd_->Process(now); 508f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org capture_queue_delay_->CalculateDelayChange(diff_ms); 509f1630b1f53156a9723ae5431f2fb1e54786593b9asapersson@webrtc.org 5109da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org if (num_process_times_ <= options_.min_process_count) { 511995079666dd4be231e6af4b125c481d953d9b735asapersson@webrtc.org return 0; 512995079666dd4be231e6af4b125c481d953d9b735asapersson@webrtc.org } 513995079666dd4be231e6af4b125c481d953d9b735asapersson@webrtc.org 514cb9a72be76527005fc1ad580dd9a31e3d0e779f9mflodman@webrtc.org if (IsOverusing()) { 515ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org // If the last thing we did was going up, and now have to back down, we need 516ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org // to check if this peak was short. If so we should back off to avoid going 517ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org // back and forth between this load, the system doesn't seem to handle it. 518ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org bool check_for_backoff = last_rampup_time_ > last_overuse_time_; 519ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org if (check_for_backoff) { 520eddcc6311725092499404db49f40eda82b552483asapersson@webrtc.org if (now - last_rampup_time_ < kStandardRampUpDelayMs || 521eddcc6311725092499404db49f40eda82b552483asapersson@webrtc.org num_overuse_detections_ > kMaxOverusesBeforeApplyRampupDelay) { 522ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org // Going up was not ok for very long, back off. 523ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org current_rampup_delay_ms_ *= kRampUpBackoffFactor; 524ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org if (current_rampup_delay_ms_ > kMaxRampUpDelayMs) 525ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org current_rampup_delay_ms_ = kMaxRampUpDelayMs; 526ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org } else { 527ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org // Not currently backing off, reset rampup delay. 528ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org current_rampup_delay_ms_ = kStandardRampUpDelayMs; 529ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org } 530ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org } 531cb9a72be76527005fc1ad580dd9a31e3d0e779f9mflodman@webrtc.org 532ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org last_overuse_time_ = now; 533ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org in_quick_rampup_ = false; 534ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org checks_above_threshold_ = 0; 535eddcc6311725092499404db49f40eda82b552483asapersson@webrtc.org ++num_overuse_detections_; 536cb9a72be76527005fc1ad580dd9a31e3d0e779f9mflodman@webrtc.org 537ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org if (observer_ != NULL) 538ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org observer_->OveruseDetected(); 539ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org } else if (IsUnderusing(now)) { 540ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org last_rampup_time_ = now; 541ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org in_quick_rampup_ = true; 542cb9a72be76527005fc1ad580dd9a31e3d0e779f9mflodman@webrtc.org 543ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org if (observer_ != NULL) 544ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org observer_->NormalUsage(); 545cb9a72be76527005fc1ad580dd9a31e3d0e779f9mflodman@webrtc.org } 546cb9a72be76527005fc1ad580dd9a31e3d0e779f9mflodman@webrtc.org 547022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org int rampup_delay = 548022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org in_quick_rampup_ ? kQuickRampUpDelayMs : current_rampup_delay_ms_; 549eddcc6311725092499404db49f40eda82b552483asapersson@webrtc.org LOG(LS_VERBOSE) << " Frame stats: capture avg: " << capture_deltas_.Mean() 550eddcc6311725092499404db49f40eda82b552483asapersson@webrtc.org << " capture stddev " << capture_deltas_.StdDev() 551eddcc6311725092499404db49f40eda82b552483asapersson@webrtc.org << " encode usage " << encode_usage_->Value() 552eddcc6311725092499404db49f40eda82b552483asapersson@webrtc.org << " encode rsd " << encode_rsd_->Value() 553eddcc6311725092499404db49f40eda82b552483asapersson@webrtc.org << " overuse detections " << num_overuse_detections_ 554eddcc6311725092499404db49f40eda82b552483asapersson@webrtc.org << " rampup delay " << rampup_delay; 555ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org return 0; 556ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org} 557ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.org 558ae14504dd56981e01bad96c86cca729ec31e6596asapersson@webrtc.orgbool OveruseFrameDetector::IsOverusing() { 559154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org bool overusing = false; 560154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org if (options_.enable_capture_jitter_method) { 561154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org overusing = capture_deltas_.StdDev() >= 562154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org options_.high_capture_jitter_threshold_ms; 563154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org } else if (options_.enable_encode_usage_method) { 564f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org bool encode_usage_overuse = 565f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org encode_usage_->Value() >= options_.high_encode_usage_threshold_percent; 566f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org bool encode_rsd_overuse = false; 567f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org if (options_.high_encode_time_rsd_threshold > 0) { 568f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org encode_rsd_overuse = 569f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org (encode_rsd_->Value() >= options_.high_encode_time_rsd_threshold); 570f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org } 571f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org overusing = encode_usage_overuse || encode_rsd_overuse; 572154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org } 573154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org 5749da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org if (overusing) { 575ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org ++checks_above_threshold_; 576ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org } else { 577ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org checks_above_threshold_ = 0; 578ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org } 5799da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org return checks_above_threshold_ >= options_.high_threshold_consecutive_count; 580cb9a72be76527005fc1ad580dd9a31e3d0e779f9mflodman@webrtc.org} 581cb9a72be76527005fc1ad580dd9a31e3d0e779f9mflodman@webrtc.org 582cb9a72be76527005fc1ad580dd9a31e3d0e779f9mflodman@webrtc.orgbool OveruseFrameDetector::IsUnderusing(int64_t time_now) { 583ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org int delay = in_quick_rampup_ ? kQuickRampUpDelayMs : current_rampup_delay_ms_; 584ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org if (time_now < last_rampup_time_ + delay) 585cb9a72be76527005fc1ad580dd9a31e3d0e779f9mflodman@webrtc.org return false; 586ce9de7102a55b923a38147a51f582371b6a45a44pbos@webrtc.org 587154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org bool underusing = false; 588154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org if (options_.enable_capture_jitter_method) { 589154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org underusing = capture_deltas_.StdDev() < 590154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org options_.low_capture_jitter_threshold_ms; 591154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org } else if (options_.enable_encode_usage_method) { 592f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org bool encode_usage_underuse = 593f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org encode_usage_->Value() < options_.low_encode_usage_threshold_percent; 594f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org bool encode_rsd_underuse = true; 595f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org if (options_.low_encode_time_rsd_threshold > 0) { 596f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org encode_rsd_underuse = 597f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org (encode_rsd_->Value() < options_.low_encode_time_rsd_threshold); 598f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org } 599f6eaabf14c12d2fd16152332aadc8a01a98c1a25asapersson@webrtc.org underusing = encode_usage_underuse && encode_rsd_underuse; 600154951d862e0a35cb0158737247e901f78a3068fasapersson@webrtc.org } 6019da327cad743253030f65939c316d009bb48d8e1asapersson@webrtc.org return underusing; 602cb9a72be76527005fc1ad580dd9a31e3d0e779f9mflodman@webrtc.org} 603f8f91d6b9b69eaf2c73a63419a502034cdf371c1mflodman@webrtc.org} // namespace webrtc 604