| Index: webrtc/video/overuse_frame_detector_unittest.cc
 | 
| diff --git a/webrtc/video/overuse_frame_detector_unittest.cc b/webrtc/video/overuse_frame_detector_unittest.cc
 | 
| index bf1c8b4acac1e26648ce65f7e667b3f21318a8cf..ae3b687acccc721931e9854c7e48cc2cf8c86901 100644
 | 
| --- a/webrtc/video/overuse_frame_detector_unittest.cc
 | 
| +++ b/webrtc/video/overuse_frame_detector_unittest.cc
 | 
| @@ -139,6 +139,20 @@ class OveruseFrameDetectorTest : public ::testing::Test,
 | 
|  
 | 
|    int UsagePercent() { return metrics_.encode_usage_percent; }
 | 
|  
 | 
| +  int64_t OveruseProcessingTimeLimitForFramerate(int fps) const {
 | 
| +    int64_t frame_interval = rtc::kNumMicrosecsPerSec / fps;
 | 
| +    int64_t max_processing_time_us =
 | 
| +        (frame_interval * options_.high_encode_usage_threshold_percent) / 100;
 | 
| +    return max_processing_time_us;
 | 
| +  }
 | 
| +
 | 
| +  int64_t UnderuseProcessingTimeLimitForFramerate(int fps) const {
 | 
| +    int64_t frame_interval = rtc::kNumMicrosecsPerSec / fps;
 | 
| +    int64_t max_processing_time_us =
 | 
| +        (frame_interval * options_.low_encode_usage_threshold_percent) / 100;
 | 
| +    return max_processing_time_us;
 | 
| +  }
 | 
| +
 | 
|    CpuOveruseOptions options_;
 | 
|    rtc::ScopedFakeClock clock_;
 | 
|    std::unique_ptr<MockCpuOveruseObserver> observer_;
 | 
| @@ -355,4 +369,115 @@ TEST_F(OveruseFrameDetectorTest, RunOnTqNormalUsage) {
 | 
|    EXPECT_TRUE(event.Wait(10000));
 | 
|  }
 | 
|  
 | 
| +TEST_F(OveruseFrameDetectorTest, MaxIntervalScalesWithFramerate) {
 | 
| +  const int kCapturerMaxFrameRate = 30;
 | 
| +  const int kEncodeMaxFrameRate = 20;  // Maximum fps the encoder can sustain.
 | 
| +
 | 
| +  // Trigger overuse.
 | 
| +  int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kCapturerMaxFrameRate;
 | 
| +  // Processing time just below over use limit given kEncodeMaxFrameRate.
 | 
| +  int64_t processing_time_us =
 | 
| +      (98 * OveruseProcessingTimeLimitForFramerate(kEncodeMaxFrameRate)) / 100;
 | 
| +  EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
 | 
| +  for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
 | 
| +    InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
 | 
| +                                    processing_time_us);
 | 
| +    overuse_detector_->CheckForOveruse();
 | 
| +  }
 | 
| +
 | 
| +  // Simulate frame rate reduction and normal usage.
 | 
| +  frame_interval_us = rtc::kNumMicrosecsPerSec / kEncodeMaxFrameRate;
 | 
| +  overuse_detector_->OnTargetFramerateUpdated(kEncodeMaxFrameRate);
 | 
| +  EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(0);
 | 
| +  for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
 | 
| +    InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
 | 
| +                                    processing_time_us);
 | 
| +    overuse_detector_->CheckForOveruse();
 | 
| +  }
 | 
| +
 | 
| +  // Reduce processing time to trigger underuse.
 | 
| +  processing_time_us =
 | 
| +      (98 * UnderuseProcessingTimeLimitForFramerate(kEncodeMaxFrameRate)) / 100;
 | 
| +  EXPECT_CALL(*(observer_.get()), AdaptUp(reason_)).Times(1);
 | 
| +  InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
 | 
| +                                  processing_time_us);
 | 
| +  overuse_detector_->CheckForOveruse();
 | 
| +}
 | 
| +
 | 
| +TEST_F(OveruseFrameDetectorTest, RespectsMinFramerate) {
 | 
| +  const int kMinFrameRate = 7;  // Minimum fps allowed by current detector impl.
 | 
| +  overuse_detector_->OnTargetFramerateUpdated(kMinFrameRate);
 | 
| +
 | 
| +  // Normal usage just at the limit.
 | 
| +  int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kMinFrameRate;
 | 
| +  // Processing time just below over use limit given kEncodeMaxFrameRate.
 | 
| +  int64_t processing_time_us =
 | 
| +      (98 * OveruseProcessingTimeLimitForFramerate(kMinFrameRate)) / 100;
 | 
| +  EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(0);
 | 
| +  for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
 | 
| +    InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
 | 
| +                                    processing_time_us);
 | 
| +    overuse_detector_->CheckForOveruse();
 | 
| +  }
 | 
| +
 | 
| +  // Over the limit to overuse.
 | 
| +  processing_time_us =
 | 
| +      (102 * OveruseProcessingTimeLimitForFramerate(kMinFrameRate)) / 100;
 | 
| +  EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
 | 
| +  for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
 | 
| +    InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
 | 
| +                                    processing_time_us);
 | 
| +    overuse_detector_->CheckForOveruse();
 | 
| +  }
 | 
| +
 | 
| +  // Reduce input frame rate. Should still trigger overuse.
 | 
| +  overuse_detector_->OnTargetFramerateUpdated(kMinFrameRate - 1);
 | 
| +  EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
 | 
| +  for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
 | 
| +    InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
 | 
| +                                    processing_time_us);
 | 
| +    overuse_detector_->CheckForOveruse();
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +TEST_F(OveruseFrameDetectorTest, LimitsMaxFrameInterval) {
 | 
| +  const int kMaxFrameRate = 20;
 | 
| +  overuse_detector_->OnTargetFramerateUpdated(kMaxFrameRate);
 | 
| +  int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kMaxFrameRate;
 | 
| +  // Maximum frame interval allowed is 35% above ideal.
 | 
| +  int64_t max_frame_interval_us = (135 * frame_interval_us) / 100;
 | 
| +  // Maximum processing time, without triggering overuse, allowed with the above
 | 
| +  // frame interval.
 | 
| +  int64_t max_processing_time_us =
 | 
| +      (max_frame_interval_us * options_.high_encode_usage_threshold_percent) /
 | 
| +      100;
 | 
| +
 | 
| +  // Processing time just below overuse limit given kMaxFrameRate.
 | 
| +  int64_t processing_time_us = (98 * max_processing_time_us) / 100;
 | 
| +  EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(0);
 | 
| +  for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
 | 
| +    InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
 | 
| +                                    kHeight, processing_time_us);
 | 
| +    overuse_detector_->CheckForOveruse();
 | 
| +  }
 | 
| +
 | 
| +  // Go above limit, trigger overuse.
 | 
| +  processing_time_us = (102 * max_processing_time_us) / 100;
 | 
| +  EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
 | 
| +  for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
 | 
| +    InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
 | 
| +                                    kHeight, processing_time_us);
 | 
| +    overuse_detector_->CheckForOveruse();
 | 
| +  }
 | 
| +
 | 
| +  // Increase frame interval, should still trigger overuse.
 | 
| +  max_frame_interval_us *= 2;
 | 
| +  EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
 | 
| +  for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
 | 
| +    InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
 | 
| +                                    kHeight, processing_time_us);
 | 
| +    overuse_detector_->CheckForOveruse();
 | 
| +  }
 | 
| +}
 | 
| +
 | 
|  }  // namespace webrtc
 | 
| 
 |