diff --git a/webrtc/video_engine/overuse_frame_detector.cc b/webrtc/video_engine/overuse_frame_detector.cc index a5e2d6f5de..21aa7690b1 100644 --- a/webrtc/video_engine/overuse_frame_detector.cc +++ b/webrtc/video_engine/overuse_frame_detector.cc @@ -29,11 +29,16 @@ namespace webrtc { namespace { const int64_t kProcessIntervalMs = 5000; +// Number of initial process times before reporting. +const int64_t kMinProcessCountBeforeReporting = 3; + +const int64_t kFrameTimeoutIntervalMs = 1500; + // Consecutive checks above threshold to trigger overuse. const int kConsecutiveChecksAboveThreshold = 2; // Minimum samples required to perform a check. -const size_t kMinFrameSampleCount = 15; +const size_t kMinFrameSampleCount = 120; // Weight factor to apply to the standard deviation. const float kWeightFactor = 0.997f; @@ -238,9 +243,11 @@ OveruseFrameDetector::OveruseFrameDetector(Clock* clock, : crit_(CriticalSectionWrapper::CreateCriticalSection()), normaluse_stddev_ms_(normaluse_stddev_ms), overuse_stddev_ms_(overuse_stddev_ms), + min_process_count_before_reporting_(kMinProcessCountBeforeReporting), observer_(NULL), clock_(clock), next_process_time_(clock_->TimeInMilliseconds()), + num_process_times_(0), last_capture_time_(0), last_overuse_time_(0), checks_above_threshold_(0), @@ -288,26 +295,34 @@ int32_t OveruseFrameDetector::TimeUntilNextProcess() { return next_process_time_ - clock_->TimeInMilliseconds(); } +bool OveruseFrameDetector::DetectFrameTimeout(int64_t now) const { + if (last_capture_time_ == 0) { + return false; + } + return (now - last_capture_time_) > kFrameTimeoutIntervalMs; +} + void OveruseFrameDetector::FrameCaptured(int width, int height) { CriticalSectionScoped cs(crit_.get()); + int64_t now = clock_->TimeInMilliseconds(); int num_pixels = width * height; - if (num_pixels != num_pixels_) { + if (num_pixels != num_pixels_ || DetectFrameTimeout(now)) { // Frame size changed, reset statistics. num_pixels_ = num_pixels; capture_deltas_.Reset(); last_capture_time_ = 0; capture_queue_delay_->ClearFrames(); + num_process_times_ = 0; } - int64_t time = clock_->TimeInMilliseconds(); if (last_capture_time_ != 0) { - capture_deltas_.AddSample(time - last_capture_time_); - encode_usage_->AddSample(time - last_capture_time_); + capture_deltas_.AddSample(now - last_capture_time_); + encode_usage_->AddSample(now - last_capture_time_); } - last_capture_time_ = time; + last_capture_time_ = now; - capture_queue_delay_->FrameCaptured(time); + capture_queue_delay_->FrameCaptured(now); } void OveruseFrameDetector::FrameProcessingStarted() { @@ -342,6 +357,7 @@ int32_t OveruseFrameDetector::Process() { int64_t diff_ms = now - next_process_time_ + kProcessIntervalMs; next_process_time_ = now + kProcessIntervalMs; + ++num_process_times_; // Don't trigger overuse unless we've seen a certain number of frames. if (capture_deltas_.Count() < kMinFrameSampleCount) @@ -349,6 +365,10 @@ int32_t OveruseFrameDetector::Process() { capture_queue_delay_->CalculateDelayChange(diff_ms); + if (num_process_times_ <= min_process_count_before_reporting_) { + return 0; + } + if (IsOverusing()) { // If the last thing we did was going up, and now have to back down, we need // to check if this peak was short. If so we should back off to avoid going diff --git a/webrtc/video_engine/overuse_frame_detector.h b/webrtc/video_engine/overuse_frame_detector.h index 5dbb48a223..c9f691cc07 100644 --- a/webrtc/video_engine/overuse_frame_detector.h +++ b/webrtc/video_engine/overuse_frame_detector.h @@ -14,6 +14,7 @@ #include "webrtc/modules/interface/module.h" #include "webrtc/system_wrappers/interface/constructor_magic.h" #include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/test/testsupport/gtest_prod_util.h" namespace webrtc { @@ -104,6 +105,19 @@ class OveruseFrameDetector : public Module { virtual int32_t Process() OVERRIDE; private: + FRIEND_TEST_ALL_PREFIXES(OveruseFrameDetectorTest, TriggerOveruse); + FRIEND_TEST_ALL_PREFIXES(OveruseFrameDetectorTest, OveruseAndRecover); + FRIEND_TEST_ALL_PREFIXES(OveruseFrameDetectorTest, DoubleOveruseAndRecover); + FRIEND_TEST_ALL_PREFIXES( + OveruseFrameDetectorTest, TriggerNormalUsageWithMinProcessCount); + FRIEND_TEST_ALL_PREFIXES( + OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage); + FRIEND_TEST_ALL_PREFIXES(OveruseFrameDetectorTest, LastCaptureJitter); + + void set_min_process_count_before_reporting(int64_t count) { + min_process_count_before_reporting_ = count; + } + class EncodeTimeAvg; class EncodeUsage; class CaptureQueueDelay; @@ -111,6 +125,8 @@ class OveruseFrameDetector : public Module { bool IsOverusing(); bool IsUnderusing(int64_t time_now); + bool DetectFrameTimeout(int64_t now) const; + // Protecting all members. scoped_ptr crit_; @@ -118,11 +134,14 @@ class OveruseFrameDetector : public Module { const float normaluse_stddev_ms_; const float overuse_stddev_ms_; + int64_t min_process_count_before_reporting_; + // Observer getting overuse reports. CpuOveruseObserver* observer_; Clock* clock_; int64_t next_process_time_; + int64_t num_process_times_; Statistics capture_deltas_; int64_t last_capture_time_; diff --git a/webrtc/video_engine/overuse_frame_detector_unittest.cc b/webrtc/video_engine/overuse_frame_detector_unittest.cc index f974f28898..8d45fdb23c 100644 --- a/webrtc/video_engine/overuse_frame_detector_unittest.cc +++ b/webrtc/video_engine/overuse_frame_detector_unittest.cc @@ -50,11 +50,11 @@ class OveruseFrameDetectorTest : public ::testing::Test { EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); - InsertFramesWithInterval(50, regular_frame_interval_ms); + InsertFramesWithInterval(200, regular_frame_interval_ms); InsertFramesWithInterval(50, 110); overuse_detector_->Process(); - InsertFramesWithInterval(50, regular_frame_interval_ms); + InsertFramesWithInterval(200, regular_frame_interval_ms); InsertFramesWithInterval(50, 110); overuse_detector_->Process(); } @@ -74,21 +74,35 @@ class OveruseFrameDetectorTest : public ::testing::Test { }; TEST_F(OveruseFrameDetectorTest, TriggerOveruse) { + overuse_detector_->set_min_process_count_before_reporting(0); TriggerOveruse(); } TEST_F(OveruseFrameDetectorTest, OveruseAndRecover) { + overuse_detector_->set_min_process_count_before_reporting(0); TriggerOveruse(); TriggerNormalUsage(); } TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) { + overuse_detector_->set_min_process_count_before_reporting(0); TriggerOveruse(); TriggerOveruse(); TriggerNormalUsage(); } +TEST_F(OveruseFrameDetectorTest, TriggerNormalUsageWithMinProcessCount) { + overuse_detector_->set_min_process_count_before_reporting(1); + InsertFramesWithInterval(900, 33); + overuse_detector_->Process(); + EXPECT_EQ(-1, overuse_detector_->last_capture_jitter_ms()); + clock_->AdvanceTimeMilliseconds(5000); + overuse_detector_->Process(); + EXPECT_GT(overuse_detector_->last_capture_jitter_ms(), 0); +} + TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) { + overuse_detector_->set_min_process_count_before_reporting(0); EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(0); for(size_t i = 0; i < 64; ++i) @@ -96,6 +110,7 @@ TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) { } TEST_F(OveruseFrameDetectorTest, LastCaptureJitter) { + overuse_detector_->set_min_process_count_before_reporting(0); EXPECT_EQ(-1, overuse_detector_->last_capture_jitter_ms()); TriggerOveruse(); EXPECT_GT(overuse_detector_->last_capture_jitter_ms(), 0);