Home | History | Annotate | Download | only in video
      1 /*
      2  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
      3  *
      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
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #ifndef WEBRTC_VIDEO_OVERUSE_FRAME_DETECTOR_H_
     12 #define WEBRTC_VIDEO_OVERUSE_FRAME_DETECTOR_H_
     13 
     14 #include "webrtc/base/constructormagic.h"
     15 #include "webrtc/base/criticalsection.h"
     16 #include "webrtc/base/scoped_ptr.h"
     17 #include "webrtc/base/exp_filter.h"
     18 #include "webrtc/base/thread_annotations.h"
     19 #include "webrtc/base/thread_checker.h"
     20 #include "webrtc/modules/include/module.h"
     21 
     22 namespace webrtc {
     23 
     24 class Clock;
     25 
     26 // CpuOveruseObserver is called when a system overuse is detected and
     27 // VideoEngine cannot keep up the encoding frequency.
     28 class CpuOveruseObserver {
     29  public:
     30   // Called as soon as an overuse is detected.
     31   virtual void OveruseDetected() = 0;
     32   // Called periodically when the system is not overused any longer.
     33   virtual void NormalUsage() = 0;
     34 
     35  protected:
     36   virtual ~CpuOveruseObserver() {}
     37 };
     38 
     39 struct CpuOveruseOptions {
     40   CpuOveruseOptions()
     41       : low_encode_usage_threshold_percent(55),
     42         high_encode_usage_threshold_percent(85),
     43         frame_timeout_interval_ms(1500),
     44         min_frame_samples(120),
     45         min_process_count(3),
     46         high_threshold_consecutive_count(2) {}
     47 
     48   int low_encode_usage_threshold_percent;  // Threshold for triggering underuse.
     49   int high_encode_usage_threshold_percent;  // Threshold for triggering overuse.
     50   // General settings.
     51   int frame_timeout_interval_ms;  // The maximum allowed interval between two
     52                                   // frames before resetting estimations.
     53   int min_frame_samples;  // The minimum number of frames required.
     54   int min_process_count;  // The number of initial process times required before
     55                           // triggering an overuse/underuse.
     56   int high_threshold_consecutive_count;  // The number of consecutive checks
     57                                          // above the high threshold before
     58                                          // triggering an overuse.
     59 };
     60 
     61 struct CpuOveruseMetrics {
     62   CpuOveruseMetrics() : encode_usage_percent(-1) {}
     63 
     64   int encode_usage_percent;  // Average encode time divided by the average time
     65                              // difference between incoming captured frames.
     66 };
     67 
     68 class CpuOveruseMetricsObserver {
     69  public:
     70   virtual ~CpuOveruseMetricsObserver() {}
     71   virtual void CpuOveruseMetricsUpdated(const CpuOveruseMetrics& metrics) = 0;
     72 };
     73 
     74 
     75 // Use to detect system overuse based on the send-side processing time of
     76 // incoming frames.
     77 class OveruseFrameDetector : public Module {
     78  public:
     79   OveruseFrameDetector(Clock* clock,
     80                        const CpuOveruseOptions& options,
     81                        CpuOveruseObserver* overuse_observer,
     82                        CpuOveruseMetricsObserver* metrics_observer);
     83   ~OveruseFrameDetector();
     84 
     85   // Called for each captured frame.
     86   void FrameCaptured(int width, int height, int64_t capture_time_ms);
     87 
     88   // Called for each sent frame.
     89   void FrameSent(int64_t capture_time_ms);
     90 
     91   // Only public for testing.
     92   int LastProcessingTimeMs() const;
     93   int FramesInQueue() const;
     94 
     95   // Implements Module.
     96   int64_t TimeUntilNextProcess() override;
     97   int32_t Process() override;
     98 
     99  private:
    100   class SendProcessingUsage;
    101   class FrameQueue;
    102 
    103   void UpdateCpuOveruseMetrics() EXCLUSIVE_LOCKS_REQUIRED(crit_);
    104 
    105   // TODO(asapersson): This method is only used on one thread, so it shouldn't
    106   // need a guard.
    107   void AddProcessingTime(int elapsed_ms) EXCLUSIVE_LOCKS_REQUIRED(crit_);
    108 
    109   // Only called on the processing thread.
    110   bool IsOverusing(const CpuOveruseMetrics& metrics);
    111   bool IsUnderusing(const CpuOveruseMetrics& metrics, int64_t time_now);
    112 
    113   bool FrameTimeoutDetected(int64_t now) const EXCLUSIVE_LOCKS_REQUIRED(crit_);
    114   bool FrameSizeChanged(int num_pixels) const EXCLUSIVE_LOCKS_REQUIRED(crit_);
    115 
    116   void ResetAll(int num_pixels) EXCLUSIVE_LOCKS_REQUIRED(crit_);
    117 
    118   // Protecting all members except const and those that are only accessed on the
    119   // processing thread.
    120   // TODO(asapersson): See if we can reduce locking.  As is, video frame
    121   // processing contends with reading stats and the processing thread.
    122   mutable rtc::CriticalSection crit_;
    123 
    124   const CpuOveruseOptions options_;
    125 
    126   // Observer getting overuse reports.
    127   CpuOveruseObserver* const observer_;
    128 
    129   // Stats metrics.
    130   CpuOveruseMetricsObserver* const metrics_observer_;
    131   CpuOveruseMetrics metrics_ GUARDED_BY(crit_);
    132 
    133   Clock* const clock_;
    134   int64_t num_process_times_ GUARDED_BY(crit_);
    135 
    136   int64_t last_capture_time_ GUARDED_BY(crit_);
    137 
    138   // Number of pixels of last captured frame.
    139   int num_pixels_ GUARDED_BY(crit_);
    140 
    141   // These seven members are only accessed on the processing thread.
    142   int64_t next_process_time_;
    143   int64_t last_overuse_time_;
    144   int checks_above_threshold_;
    145   int num_overuse_detections_;
    146   int64_t last_rampup_time_;
    147   bool in_quick_rampup_;
    148   int current_rampup_delay_ms_;
    149 
    150   int64_t last_sample_time_ms_;    // Only accessed by one thread.
    151 
    152   // TODO(asapersson): Can these be regular members (avoid separate heap
    153   // allocs)?
    154   const rtc::scoped_ptr<SendProcessingUsage> usage_ GUARDED_BY(crit_);
    155   const rtc::scoped_ptr<FrameQueue> frame_queue_ GUARDED_BY(crit_);
    156 
    157   rtc::ThreadChecker processing_thread_;
    158 
    159   RTC_DISALLOW_COPY_AND_ASSIGN(OveruseFrameDetector);
    160 };
    161 
    162 }  // namespace webrtc
    163 
    164 #endif  // WEBRTC_VIDEO_OVERUSE_FRAME_DETECTOR_H_
    165