| OLD | NEW | 
|    1 /* |    1 /* | 
|    2  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |    2  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 
|    3  * |    3  * | 
|    4  *  Use of this source code is governed by a BSD-style license |    4  *  Use of this source code is governed by a BSD-style license | 
|    5  *  that can be found in the LICENSE file in the root of the source |    5  *  that can be found in the LICENSE file in the root of the source | 
|    6  *  tree. An additional intellectual property rights grant can be found |    6  *  tree. An additional intellectual property rights grant can be found | 
|    7  *  in the file PATENTS.  All contributing project authors may |    7  *  in the file PATENTS.  All contributing project authors may | 
|    8  *  be found in the AUTHORS file in the root of the source tree. |    8  *  be found in the AUTHORS file in the root of the source tree. | 
|    9  */ |    9  */ | 
|   10  |   10  | 
|   11 #include <memory> |   11 #include <memory> | 
|   12  |   12  | 
|   13 #include "webrtc/base/event.h" |   13 #include "webrtc/base/event.h" | 
|   14 #include "webrtc/system_wrappers/include/clock.h" |   14 #include "webrtc/system_wrappers/include/clock.h" | 
|   15 #include "webrtc/test/gmock.h" |   15 #include "webrtc/test/gmock.h" | 
|   16 #include "webrtc/test/gtest.h" |   16 #include "webrtc/test/gtest.h" | 
|   17 #include "webrtc/video/overuse_frame_detector.h" |   17 #include "webrtc/video/overuse_frame_detector.h" | 
|   18 #include "webrtc/video_frame.h" |   18 #include "webrtc/video_frame.h" | 
 |   19 #include "webrtc/modules/video_coding/utility/quality_scaler.h" | 
|   19  |   20  | 
|   20 namespace webrtc { |   21 namespace webrtc { | 
|   21  |   22  | 
|   22 using ::testing::Invoke; |   23 using ::testing::InvokeWithoutArgs; | 
|   23  |   24  | 
|   24 namespace { |   25 namespace { | 
|   25   const int kWidth = 640; |   26   const int kWidth = 640; | 
|   26   const int kHeight = 480; |   27   const int kHeight = 480; | 
|   27   const int kFrameInterval33ms = 33; |   28   const int kFrameInterval33ms = 33; | 
|   28   const int kProcessIntervalMs = 5000; |   29   const int kProcessIntervalMs = 5000; | 
|   29   const int kProcessTime5ms = 5; |   30   const int kProcessTime5ms = 5; | 
|   30 }  // namespace |   31 }  // namespace | 
|   31  |   32  | 
|   32 class MockCpuOveruseObserver : public CpuOveruseObserver { |   33 class MockCpuOveruseObserver : public ScalingObserverInterface { | 
|   33  public: |   34  public: | 
|   34   MockCpuOveruseObserver() {} |   35   MockCpuOveruseObserver() {} | 
|   35   virtual ~MockCpuOveruseObserver() {} |   36   virtual ~MockCpuOveruseObserver() {} | 
|   36  |   37  | 
|   37   MOCK_METHOD0(OveruseDetected, void()); |   38   MOCK_METHOD1(ScaleUp, void(ScaleReason)); | 
|   38   MOCK_METHOD0(NormalUsage, void()); |   39   MOCK_METHOD1(ScaleDown, void(ScaleReason)); | 
|   39 }; |   40 }; | 
|   40  |   41  | 
|   41 class CpuOveruseObserverImpl : public CpuOveruseObserver { |   42 class CpuOveruseObserverImpl : public ScalingObserverInterface { | 
|   42  public: |   43  public: | 
|   43   CpuOveruseObserverImpl() : |   44   CpuOveruseObserverImpl() : | 
|   44     overuse_(0), |   45     overuse_(0), | 
|   45     normaluse_(0) {} |   46     normaluse_(0) {} | 
|   46   virtual ~CpuOveruseObserverImpl() {} |   47   virtual ~CpuOveruseObserverImpl() {} | 
|   47  |   48  | 
|   48   void OveruseDetected() { ++overuse_; } |   49   void ScaleDown(ScaleReason) { ++overuse_; } | 
|   49   void NormalUsage() { ++normaluse_; } |   50   void ScaleUp(ScaleReason) { ++normaluse_; } | 
|   50  |   51  | 
|   51   int overuse_; |   52   int overuse_; | 
|   52   int normaluse_; |   53   int normaluse_; | 
|   53 }; |   54 }; | 
|   54  |   55  | 
|   55 class OveruseFrameDetectorUnderTest : public OveruseFrameDetector { |   56 class OveruseFrameDetectorUnderTest : public OveruseFrameDetector { | 
|   56  public: |   57  public: | 
|   57   OveruseFrameDetectorUnderTest(Clock* clock, |   58   OveruseFrameDetectorUnderTest(Clock* clock, | 
|   58                                 const CpuOveruseOptions& options, |   59                                 const CpuOveruseOptions& options, | 
|   59                                 CpuOveruseObserver* overuse_observer, |   60                                 ScalingObserverInterface* overuse_observer, | 
|   60                                 EncodedFrameObserver* encoder_timing, |   61                                 EncodedFrameObserver* encoder_timing, | 
|   61                                 CpuOveruseMetricsObserver* metrics_observer) |   62                                 CpuOveruseMetricsObserver* metrics_observer) | 
|   62       : OveruseFrameDetector(clock, |   63       : OveruseFrameDetector(clock, | 
|   63                              options, |   64                              options, | 
|   64                              overuse_observer, |   65                              overuse_observer, | 
|   65                              encoder_timing, |   66                              encoder_timing, | 
|   66                              metrics_observer) {} |   67                              metrics_observer) {} | 
|   67   ~OveruseFrameDetectorUnderTest() {} |   68   ~OveruseFrameDetectorUnderTest() {} | 
|   68  |   69  | 
|   69   using OveruseFrameDetector::CheckForOveruse; |   70   using OveruseFrameDetector::CheckForOveruse; | 
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  138     overuse_detector_->CheckForOveruse(); |  139     overuse_detector_->CheckForOveruse(); | 
|  139   } |  140   } | 
|  140  |  141  | 
|  141   int UsagePercent() { return metrics_.encode_usage_percent; } |  142   int UsagePercent() { return metrics_.encode_usage_percent; } | 
|  142  |  143  | 
|  143   CpuOveruseOptions options_; |  144   CpuOveruseOptions options_; | 
|  144   std::unique_ptr<SimulatedClock> clock_; |  145   std::unique_ptr<SimulatedClock> clock_; | 
|  145   std::unique_ptr<MockCpuOveruseObserver> observer_; |  146   std::unique_ptr<MockCpuOveruseObserver> observer_; | 
|  146   std::unique_ptr<OveruseFrameDetectorUnderTest> overuse_detector_; |  147   std::unique_ptr<OveruseFrameDetectorUnderTest> overuse_detector_; | 
|  147   CpuOveruseMetrics metrics_; |  148   CpuOveruseMetrics metrics_; | 
 |  149  | 
 |  150   static const auto reason_ = ScalingObserverInterface::ScaleReason::kCpu; | 
|  148 }; |  151 }; | 
|  149  |  152  | 
|  150  |  153  | 
|  151 // UsagePercent() > high_encode_usage_threshold_percent => overuse. |  154 // UsagePercent() > high_encode_usage_threshold_percent => overuse. | 
|  152 // UsagePercent() < low_encode_usage_threshold_percent => underuse. |  155 // UsagePercent() < low_encode_usage_threshold_percent => underuse. | 
|  153 TEST_F(OveruseFrameDetectorTest, TriggerOveruse) { |  156 TEST_F(OveruseFrameDetectorTest, TriggerOveruse) { | 
|  154   // usage > high => overuse |  157   // usage > high => overuse | 
|  155   EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); |  158   EXPECT_CALL(*(observer_.get()), ScaleDown(reason_)).Times(1); | 
|  156   TriggerOveruse(options_.high_threshold_consecutive_count); |  159   TriggerOveruse(options_.high_threshold_consecutive_count); | 
|  157 } |  160 } | 
|  158  |  161  | 
|  159 TEST_F(OveruseFrameDetectorTest, OveruseAndRecover) { |  162 TEST_F(OveruseFrameDetectorTest, OveruseAndRecover) { | 
|  160   // usage > high => overuse |  163   // usage > high => overuse | 
|  161   EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); |  164   EXPECT_CALL(*(observer_.get()), ScaleDown(reason_)).Times(1); | 
|  162   TriggerOveruse(options_.high_threshold_consecutive_count); |  165   TriggerOveruse(options_.high_threshold_consecutive_count); | 
|  163   // usage < low => underuse |  166   // usage < low => underuse | 
|  164   EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(testing::AtLeast(1)); |  167   EXPECT_CALL(*(observer_.get()), ScaleUp(reason_)).Times(testing::AtLeast(1)); | 
|  165   TriggerUnderuse(); |  168   TriggerUnderuse(); | 
|  166 } |  169 } | 
|  167  |  170  | 
|  168 TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithNoObserver) { |  171 TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithNoObserver) { | 
|  169   overuse_detector_.reset(new OveruseFrameDetectorUnderTest( |  172   overuse_detector_.reset(new OveruseFrameDetectorUnderTest( | 
|  170       clock_.get(), options_, nullptr, nullptr, this)); |  173       clock_.get(), options_, nullptr, nullptr, this)); | 
|  171   EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(0); |  174   EXPECT_CALL(*(observer_.get()), ScaleDown(reason_)).Times(0); | 
|  172   TriggerOveruse(options_.high_threshold_consecutive_count); |  175   TriggerOveruse(options_.high_threshold_consecutive_count); | 
|  173   EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(0); |  176   EXPECT_CALL(*(observer_.get()), ScaleUp(reason_)).Times(0); | 
|  174   TriggerUnderuse(); |  177   TriggerUnderuse(); | 
|  175 } |  178 } | 
|  176  |  179  | 
|  177 TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) { |  180 TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) { | 
|  178   EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(2); |  181   EXPECT_CALL(*(observer_.get()), ScaleDown(reason_)).Times(2); | 
|  179   TriggerOveruse(options_.high_threshold_consecutive_count); |  182   TriggerOveruse(options_.high_threshold_consecutive_count); | 
|  180   TriggerOveruse(options_.high_threshold_consecutive_count); |  183   TriggerOveruse(options_.high_threshold_consecutive_count); | 
|  181   EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(testing::AtLeast(1)); |  184   EXPECT_CALL(*(observer_.get()), ScaleUp(reason_)).Times(testing::AtLeast(1)); | 
|  182   TriggerUnderuse(); |  185   TriggerUnderuse(); | 
|  183 } |  186 } | 
|  184  |  187  | 
|  185 TEST_F(OveruseFrameDetectorTest, TriggerUnderuseWithMinProcessCount) { |  188 TEST_F(OveruseFrameDetectorTest, TriggerUnderuseWithMinProcessCount) { | 
|  186   options_.min_process_count = 1; |  189   options_.min_process_count = 1; | 
|  187   CpuOveruseObserverImpl overuse_observer; |  190   CpuOveruseObserverImpl overuse_observer; | 
|  188   overuse_detector_.reset(new OveruseFrameDetectorUnderTest( |  191   overuse_detector_.reset(new OveruseFrameDetectorUnderTest( | 
|  189       clock_.get(), options_, &overuse_observer, nullptr, this)); |  192       clock_.get(), options_, &overuse_observer, nullptr, this)); | 
|  190   InsertAndSendFramesWithInterval( |  193   InsertAndSendFramesWithInterval( | 
|  191       1200, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); |  194       1200, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); | 
|  192   overuse_detector_->CheckForOveruse(); |  195   overuse_detector_->CheckForOveruse(); | 
|  193   EXPECT_EQ(0, overuse_observer.normaluse_); |  196   EXPECT_EQ(0, overuse_observer.normaluse_); | 
|  194   clock_->AdvanceTimeMilliseconds(kProcessIntervalMs); |  197   clock_->AdvanceTimeMilliseconds(kProcessIntervalMs); | 
|  195   overuse_detector_->CheckForOveruse(); |  198   overuse_detector_->CheckForOveruse(); | 
|  196   EXPECT_EQ(1, overuse_observer.normaluse_); |  199   EXPECT_EQ(1, overuse_observer.normaluse_); | 
|  197 } |  200 } | 
|  198  |  201  | 
|  199 TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) { |  202 TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) { | 
|  200   EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(0); |  203   EXPECT_CALL(*(observer_.get()), ScaleUp(reason_)).Times(0); | 
|  201   EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(64); |  204   EXPECT_CALL(*(observer_.get()), ScaleDown(reason_)).Times(64); | 
|  202   for (size_t i = 0; i < 64; ++i) { |  205   for (size_t i = 0; i < 64; ++i) { | 
|  203     TriggerOveruse(options_.high_threshold_consecutive_count); |  206     TriggerOveruse(options_.high_threshold_consecutive_count); | 
|  204   } |  207   } | 
|  205 } |  208 } | 
|  206  |  209  | 
|  207 TEST_F(OveruseFrameDetectorTest, ConsecutiveCountTriggersOveruse) { |  210 TEST_F(OveruseFrameDetectorTest, ConsecutiveCountTriggersOveruse) { | 
|  208   EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); |  211   EXPECT_CALL(*(observer_.get()), ScaleDown(reason_)).Times(1); | 
|  209   options_.high_threshold_consecutive_count = 2; |  212   options_.high_threshold_consecutive_count = 2; | 
|  210   ReinitializeOveruseDetector(); |  213   ReinitializeOveruseDetector(); | 
|  211   TriggerOveruse(2); |  214   TriggerOveruse(2); | 
|  212 } |  215 } | 
|  213  |  216  | 
|  214 TEST_F(OveruseFrameDetectorTest, IncorrectConsecutiveCountTriggersNoOveruse) { |  217 TEST_F(OveruseFrameDetectorTest, IncorrectConsecutiveCountTriggersNoOveruse) { | 
|  215   EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(0); |  218   EXPECT_CALL(*(observer_.get()), ScaleDown(reason_)).Times(0); | 
|  216   options_.high_threshold_consecutive_count = 2; |  219   options_.high_threshold_consecutive_count = 2; | 
|  217   ReinitializeOveruseDetector(); |  220   ReinitializeOveruseDetector(); | 
|  218   TriggerOveruse(1); |  221   TriggerOveruse(1); | 
|  219 } |  222 } | 
|  220  |  223  | 
|  221 TEST_F(OveruseFrameDetectorTest, ProcessingUsage) { |  224 TEST_F(OveruseFrameDetectorTest, ProcessingUsage) { | 
|  222   InsertAndSendFramesWithInterval( |  225   InsertAndSendFramesWithInterval( | 
|  223       1000, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); |  226       1000, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); | 
|  224   EXPECT_EQ(kProcessTime5ms * 100 / kFrameInterval33ms, UsagePercent()); |  227   EXPECT_EQ(kProcessTime5ms * 100 / kFrameInterval33ms, UsagePercent()); | 
|  225 } |  228 } | 
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  271       1, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); |  274       1, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); | 
|  272   EXPECT_NE(InitialUsage(), UsagePercent()); |  275   EXPECT_NE(InitialUsage(), UsagePercent()); | 
|  273 } |  276 } | 
|  274  |  277  | 
|  275 TEST_F(OveruseFrameDetectorTest, InitialProcessingUsage) { |  278 TEST_F(OveruseFrameDetectorTest, InitialProcessingUsage) { | 
|  276   ForceUpdate(kWidth, kHeight); |  279   ForceUpdate(kWidth, kHeight); | 
|  277   EXPECT_EQ(InitialUsage(), UsagePercent()); |  280   EXPECT_EQ(InitialUsage(), UsagePercent()); | 
|  278 } |  281 } | 
|  279  |  282  | 
|  280 TEST_F(OveruseFrameDetectorTest, MeasuresMultipleConcurrentSamples) { |  283 TEST_F(OveruseFrameDetectorTest, MeasuresMultipleConcurrentSamples) { | 
|  281   EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(testing::AtLeast(1)); |  284   EXPECT_CALL(*(observer_.get()), ScaleDown(reason_)) | 
 |  285       .Times(testing::AtLeast(1)); | 
|  282   static const int kIntervalMs = 33; |  286   static const int kIntervalMs = 33; | 
|  283   static const size_t kNumFramesEncodingDelay = 3; |  287   static const size_t kNumFramesEncodingDelay = 3; | 
|  284   VideoFrame frame(I420Buffer::Create(kWidth, kHeight), |  288   VideoFrame frame(I420Buffer::Create(kWidth, kHeight), | 
|  285                    webrtc::kVideoRotation_0, 0); |  289                    webrtc::kVideoRotation_0, 0); | 
|  286   for (size_t i = 0; i < 1000; ++i) { |  290   for (size_t i = 0; i < 1000; ++i) { | 
|  287     // Unique timestamps. |  291     // Unique timestamps. | 
|  288     frame.set_timestamp(static_cast<uint32_t>(i)); |  292     frame.set_timestamp(static_cast<uint32_t>(i)); | 
|  289     overuse_detector_->FrameCaptured(frame, clock_->TimeInMilliseconds()); |  293     overuse_detector_->FrameCaptured(frame, clock_->TimeInMilliseconds()); | 
|  290     clock_->AdvanceTimeMilliseconds(kIntervalMs); |  294     clock_->AdvanceTimeMilliseconds(kIntervalMs); | 
|  291     if (i > kNumFramesEncodingDelay) { |  295     if (i > kNumFramesEncodingDelay) { | 
|  292       overuse_detector_->FrameSent( |  296       overuse_detector_->FrameSent( | 
|  293           static_cast<uint32_t>(i - kNumFramesEncodingDelay), |  297           static_cast<uint32_t>(i - kNumFramesEncodingDelay), | 
|  294           clock_->TimeInMilliseconds()); |  298           clock_->TimeInMilliseconds()); | 
|  295     } |  299     } | 
|  296     overuse_detector_->CheckForOveruse(); |  300     overuse_detector_->CheckForOveruse(); | 
|  297   } |  301   } | 
|  298 } |  302 } | 
|  299  |  303  | 
|  300 TEST_F(OveruseFrameDetectorTest, UpdatesExistingSamples) { |  304 TEST_F(OveruseFrameDetectorTest, UpdatesExistingSamples) { | 
|  301   // >85% encoding time should trigger overuse. |  305   // >85% encoding time should trigger overuse. | 
|  302   EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(testing::AtLeast(1)); |  306   EXPECT_CALL(*(observer_.get()), ScaleDown(reason_)) | 
 |  307       .Times(testing::AtLeast(1)); | 
|  303   static const int kIntervalMs = 33; |  308   static const int kIntervalMs = 33; | 
|  304   static const int kDelayMs = 30; |  309   static const int kDelayMs = 30; | 
|  305   VideoFrame frame(I420Buffer::Create(kWidth, kHeight), |  310   VideoFrame frame(I420Buffer::Create(kWidth, kHeight), | 
|  306                    webrtc::kVideoRotation_0, 0); |  311                    webrtc::kVideoRotation_0, 0); | 
|  307   uint32_t timestamp = 0; |  312   uint32_t timestamp = 0; | 
|  308   for (size_t i = 0; i < 1000; ++i) { |  313   for (size_t i = 0; i < 1000; ++i) { | 
|  309     frame.set_timestamp(timestamp); |  314     frame.set_timestamp(timestamp); | 
|  310     overuse_detector_->FrameCaptured(frame, clock_->TimeInMilliseconds()); |  315     overuse_detector_->FrameCaptured(frame, clock_->TimeInMilliseconds()); | 
|  311     // Encode and send first parts almost instantly. |  316     // Encode and send first parts almost instantly. | 
|  312     clock_->AdvanceTimeMilliseconds(1); |  317     clock_->AdvanceTimeMilliseconds(1); | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
|  325  |  330  | 
|  326   rtc::Event event(false, false); |  331   rtc::Event event(false, false); | 
|  327   queue.PostTask([this, &event] { |  332   queue.PostTask([this, &event] { | 
|  328     overuse_detector_->StartCheckForOveruse(); |  333     overuse_detector_->StartCheckForOveruse(); | 
|  329     event.Set(); |  334     event.Set(); | 
|  330   }); |  335   }); | 
|  331   event.Wait(rtc::Event::kForever); |  336   event.Wait(rtc::Event::kForever); | 
|  332  |  337  | 
|  333   // Expect NormalUsage(). When called, stop the |overuse_detector_| and then |  338   // Expect NormalUsage(). When called, stop the |overuse_detector_| and then | 
|  334   // set |event| to end the test. |  339   // set |event| to end the test. | 
|  335   EXPECT_CALL(*(observer_.get()), NormalUsage()) |  340   EXPECT_CALL(*(observer_.get()), ScaleUp(reason_)) | 
|  336       .WillOnce(Invoke([this, &event] { |  341       .WillOnce(InvokeWithoutArgs([this, &event] { | 
|  337         overuse_detector_->StopCheckForOveruse(); |  342         overuse_detector_->StopCheckForOveruse(); | 
|  338         event.Set(); |  343         event.Set(); | 
|  339       })); |  344       })); | 
|  340  |  345  | 
|  341   queue.PostTask([this, &event] { |  346   queue.PostTask([this, &event] { | 
|  342     const int kDelayMs1 = 5; |  347     const int kDelayMs1 = 5; | 
|  343     const int kDelayMs2 = 6; |  348     const int kDelayMs2 = 6; | 
|  344     InsertAndSendFramesWithInterval(1300, kFrameInterval33ms, kWidth, kHeight, |  349     InsertAndSendFramesWithInterval(1300, kFrameInterval33ms, kWidth, kHeight, | 
|  345                                     kDelayMs1); |  350                                     kDelayMs1); | 
|  346     InsertAndSendFramesWithInterval(1, kFrameInterval33ms, kWidth, kHeight, |  351     InsertAndSendFramesWithInterval(1, kFrameInterval33ms, kWidth, kHeight, | 
|  347                                     kDelayMs2); |  352                                     kDelayMs2); | 
|  348   }); |  353   }); | 
|  349  |  354  | 
|  350   EXPECT_TRUE(event.Wait(10000)); |  355   EXPECT_TRUE(event.Wait(10000)); | 
|  351 } |  356 } | 
|  352  |  357  | 
|  353 }  // namespace webrtc |  358 }  // namespace webrtc | 
| OLD | NEW |