blob: 122cce505cab1fb8786cd6598d72f8d3166995f3 [file] [log] [blame]
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +00001/*
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_ENGINE_OVERUSE_FRAME_DETECTOR_H_
12#define WEBRTC_VIDEO_ENGINE_OVERUSE_FRAME_DETECTOR_H_
13
henrike@webrtc.org88fbb2d2014-05-21 21:18:46 +000014#include "webrtc/base/constructormagic.h"
tommi@webrtc.org7a57f8f2015-02-08 18:27:46 +000015#include "webrtc/base/criticalsection.h"
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +000016#include "webrtc/base/scoped_ptr.h"
minyue@webrtc.org74aaf292014-07-16 21:28:26 +000017#include "webrtc/base/exp_filter.h"
asapersson@webrtc.orgcd621a82014-11-11 09:40:19 +000018#include "webrtc/base/thread_annotations.h"
tommi@webrtc.org7a57f8f2015-02-08 18:27:46 +000019#include "webrtc/base/thread_checker.h"
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000020#include "webrtc/modules/interface/module.h"
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000021
22namespace webrtc {
23
24class Clock;
Peter Boström300eeb62015-05-12 16:51:11 +020025
26// CpuOveruseObserver is called when a system overuse is detected and
27// VideoEngine cannot keep up the encoding frequency.
28class 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
39struct CpuOveruseOptions {
40 CpuOveruseOptions()
41 : enable_capture_jitter_method(false),
42 low_capture_jitter_threshold_ms(20.0f),
43 high_capture_jitter_threshold_ms(30.0f),
44 enable_encode_usage_method(true),
45 low_encode_usage_threshold_percent(55),
46 high_encode_usage_threshold_percent(85),
47 low_encode_time_rsd_threshold(-1),
48 high_encode_time_rsd_threshold(-1),
49 enable_extended_processing_usage(true),
50 frame_timeout_interval_ms(1500),
51 min_frame_samples(120),
52 min_process_count(3),
53 high_threshold_consecutive_count(2) {}
54
55 // Method based on inter-arrival jitter of captured frames.
56 bool enable_capture_jitter_method;
57 float low_capture_jitter_threshold_ms; // Threshold for triggering underuse.
58 float high_capture_jitter_threshold_ms; // Threshold for triggering overuse.
59 // Method based on encode time of frames.
60 bool enable_encode_usage_method;
61 int low_encode_usage_threshold_percent; // Threshold for triggering underuse.
62 int high_encode_usage_threshold_percent; // Threshold for triggering overuse.
63 // TODO(asapersson): Remove options, not used.
64 int low_encode_time_rsd_threshold; // Additional threshold for triggering
65 // underuse (used in addition to
66 // threshold above if configured).
67 int high_encode_time_rsd_threshold; // Additional threshold for triggering
68 // overuse (used in addition to
69 // threshold above if configured).
70 bool enable_extended_processing_usage; // Include a larger time span (in
71 // addition to encode time) for
72 // measuring the processing time of a
73 // frame.
74 // General settings.
75 int frame_timeout_interval_ms; // The maximum allowed interval between two
76 // frames before resetting estimations.
77 int min_frame_samples; // The minimum number of frames required.
78 int min_process_count; // The number of initial process times required before
79 // triggering an overuse/underuse.
80 int high_threshold_consecutive_count; // The number of consecutive checks
81 // above the high threshold before
82 // triggering an overuse.
83
84 bool Equals(const CpuOveruseOptions& o) const {
85 return enable_capture_jitter_method == o.enable_capture_jitter_method &&
86 low_capture_jitter_threshold_ms == o.low_capture_jitter_threshold_ms &&
87 high_capture_jitter_threshold_ms ==
88 o.high_capture_jitter_threshold_ms &&
89 enable_encode_usage_method == o.enable_encode_usage_method &&
90 low_encode_usage_threshold_percent ==
91 o.low_encode_usage_threshold_percent &&
92 high_encode_usage_threshold_percent ==
93 o.high_encode_usage_threshold_percent &&
94 low_encode_time_rsd_threshold == o.low_encode_time_rsd_threshold &&
95 high_encode_time_rsd_threshold == o.high_encode_time_rsd_threshold &&
96 enable_extended_processing_usage ==
97 o.enable_extended_processing_usage &&
98 frame_timeout_interval_ms == o.frame_timeout_interval_ms &&
99 min_frame_samples == o.min_frame_samples &&
100 min_process_count == o.min_process_count &&
101 high_threshold_consecutive_count == o.high_threshold_consecutive_count;
102 }
103};
104
105struct CpuOveruseMetrics {
106 CpuOveruseMetrics()
107 : capture_jitter_ms(-1),
108 avg_encode_time_ms(-1),
109 encode_usage_percent(-1),
110 capture_queue_delay_ms_per_s(-1) {}
111
112 int capture_jitter_ms; // The current estimated jitter in ms based on
113 // incoming captured frames.
114 int avg_encode_time_ms; // The average encode time in ms.
115 int encode_usage_percent; // The average encode time divided by the average
116 // time difference between incoming captured frames.
117 int capture_queue_delay_ms_per_s; // The current time delay between an
118 // incoming captured frame until the frame
119 // is being processed. The delay is
120 // expressed in ms delay per second.
121};
122
123class CpuOveruseMetricsObserver {
124 public:
125 virtual ~CpuOveruseMetricsObserver() {}
126 virtual void CpuOveruseMetricsUpdated(const CpuOveruseMetrics& metrics) = 0;
127};
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000128
asapersson@webrtc.orge2af6222013-09-23 20:05:39 +0000129// TODO(pbos): Move this somewhere appropriate.
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000130class Statistics {
131 public:
132 Statistics();
133
asapersson@webrtc.orge2af6222013-09-23 20:05:39 +0000134 void AddSample(float sample_ms);
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000135 void Reset();
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000136 void SetOptions(const CpuOveruseOptions& options);
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000137
asapersson@webrtc.orge2af6222013-09-23 20:05:39 +0000138 float Mean() const;
139 float StdDev() const;
140 uint64_t Count() const;
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000141
142 private:
asapersson@webrtc.orge2af6222013-09-23 20:05:39 +0000143 float InitialMean() const;
144 float InitialVariance() const;
145
146 float sum_;
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000147 uint64_t count_;
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000148 CpuOveruseOptions options_;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000149 rtc::scoped_ptr<rtc::ExpFilter> filtered_samples_;
150 rtc::scoped_ptr<rtc::ExpFilter> filtered_variance_;
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000151};
152
153// Use to detect system overuse based on jitter in incoming frames.
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000154class OveruseFrameDetector : public Module {
155 public:
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +0000156 OveruseFrameDetector(Clock* clock,
157 CpuOveruseMetricsObserver* metrics_observer);
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000158 ~OveruseFrameDetector();
159
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000160 // Registers an observer receiving overuse and underuse callbacks. Set
161 // 'observer' to NULL to disable callbacks.
mflodman@webrtc.org6879c8a2013-07-23 11:35:00 +0000162 void SetObserver(CpuOveruseObserver* observer);
163
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000164 // Sets options for overuse detection.
165 void SetOptions(const CpuOveruseOptions& options);
166
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000167 // Called for each captured frame.
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000168 void FrameCaptured(int width, int height, int64_t capture_time_ms);
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000169
asapersson@webrtc.org9e5b0342013-12-04 13:47:44 +0000170 // Called when the processing of a captured frame is started.
171 void FrameProcessingStarted();
172
173 // Called for each encoded frame.
asapersson@webrtc.orgc7ff8f92013-11-26 11:12:33 +0000174 void FrameEncoded(int encode_time_ms);
175
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000176 // Called for each sent frame.
177 void FrameSent(int64_t capture_time_ms);
178
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000179 // Only public for testing.
asapersson@webrtc.org9e5b0342013-12-04 13:47:44 +0000180 int CaptureQueueDelayMsPerS() const;
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000181 int LastProcessingTimeMs() const;
182 int FramesInQueue() const;
asapersson@webrtc.orgb24d3352013-11-20 13:51:40 +0000183
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000184 // Implements Module.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000185 int64_t TimeUntilNextProcess() override;
186 int32_t Process() override;
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000187
188 private:
asapersson@webrtc.org9e5b0342013-12-04 13:47:44 +0000189 class EncodeTimeAvg;
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000190 class SendProcessingUsage;
asapersson@webrtc.org9e5b0342013-12-04 13:47:44 +0000191 class CaptureQueueDelay;
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000192 class FrameQueue;
193
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +0000194 void UpdateCpuOveruseMetrics() EXCLUSIVE_LOCKS_REQUIRED(crit_);
195
tommi@webrtc.org7a57f8f2015-02-08 18:27:46 +0000196 // TODO(asapersson): This method is only used on one thread, so it shouldn't
197 // need a guard.
asapersson@webrtc.orgcd621a82014-11-11 09:40:19 +0000198 void AddProcessingTime(int elapsed_ms) EXCLUSIVE_LOCKS_REQUIRED(crit_);
asapersson@webrtc.org9e5b0342013-12-04 13:47:44 +0000199
tommi@webrtc.org7a57f8f2015-02-08 18:27:46 +0000200 // TODO(asapersson): This method is always called on the processing thread.
201 // If locking is required, consider doing that locking inside the
202 // implementation and reduce scope as much as possible. We should also
203 // see if we can avoid calling out to other methods while holding the lock.
asapersson@webrtc.orgcd621a82014-11-11 09:40:19 +0000204 bool IsOverusing() EXCLUSIVE_LOCKS_REQUIRED(crit_);
205 bool IsUnderusing(int64_t time_now) EXCLUSIVE_LOCKS_REQUIRED(crit_);
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000206
asapersson@webrtc.orgcd621a82014-11-11 09:40:19 +0000207 bool FrameTimeoutDetected(int64_t now) const EXCLUSIVE_LOCKS_REQUIRED(crit_);
208 bool FrameSizeChanged(int num_pixels) const EXCLUSIVE_LOCKS_REQUIRED(crit_);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000209
asapersson@webrtc.orgcd621a82014-11-11 09:40:19 +0000210 void ResetAll(int num_pixels) EXCLUSIVE_LOCKS_REQUIRED(crit_);
asapersson@webrtc.orgb60346e2014-02-17 19:02:15 +0000211
tommi@webrtc.org7a57f8f2015-02-08 18:27:46 +0000212 // Protecting all members except const and those that are only accessed on the
213 // processing thread.
214 // TODO(asapersson): See if we can reduce locking. As is, video frame
215 // processing contends with reading stats and the processing thread.
216 mutable rtc::CriticalSection crit_;
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000217
218 // Observer getting overuse reports.
asapersson@webrtc.orgcd621a82014-11-11 09:40:19 +0000219 CpuOveruseObserver* observer_ GUARDED_BY(crit_);
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000220
asapersson@webrtc.orgcd621a82014-11-11 09:40:19 +0000221 CpuOveruseOptions options_ GUARDED_BY(crit_);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000222
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +0000223 // Stats metrics.
224 CpuOveruseMetricsObserver* const metrics_observer_;
225 CpuOveruseMetrics metrics_ GUARDED_BY(crit_);
226
tommi@webrtc.orga907e012015-01-28 17:33:12 +0000227 Clock* const clock_;
tommi@webrtc.org7a57f8f2015-02-08 18:27:46 +0000228 int64_t next_process_time_; // Only accessed on the processing thread.
asapersson@webrtc.orgcd621a82014-11-11 09:40:19 +0000229 int64_t num_process_times_ GUARDED_BY(crit_);
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000230
asapersson@webrtc.orgcd621a82014-11-11 09:40:19 +0000231 Statistics capture_deltas_ GUARDED_BY(crit_);
232 int64_t last_capture_time_ GUARDED_BY(crit_);
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000233
tommi@webrtc.org7a57f8f2015-02-08 18:27:46 +0000234 // These six members are only accessed on the processing thread.
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000235 int64_t last_overuse_time_;
236 int checks_above_threshold_;
asapersson@webrtc.orgd9803072014-06-16 14:27:19 +0000237 int num_overuse_detections_;
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000238
239 int64_t last_rampup_time_;
240 bool in_quick_rampup_;
241 int current_rampup_delay_ms_;
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000242
asapersson@webrtc.orge2af6222013-09-23 20:05:39 +0000243 // Number of pixels of last captured frame.
asapersson@webrtc.orgcd621a82014-11-11 09:40:19 +0000244 int num_pixels_ GUARDED_BY(crit_);
asapersson@webrtc.orge2af6222013-09-23 20:05:39 +0000245
asapersson@webrtc.org44149392015-02-04 08:34:47 +0000246 int64_t last_encode_sample_ms_; // Only accessed by one thread.
247
tommi@webrtc.org7a57f8f2015-02-08 18:27:46 +0000248 // TODO(asapersson): Can these be regular members (avoid separate heap
249 // allocs)?
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000250 const rtc::scoped_ptr<EncodeTimeAvg> encode_time_ GUARDED_BY(crit_);
251 const rtc::scoped_ptr<SendProcessingUsage> usage_ GUARDED_BY(crit_);
252 const rtc::scoped_ptr<FrameQueue> frame_queue_ GUARDED_BY(crit_);
asapersson@webrtc.org44149392015-02-04 08:34:47 +0000253
254 int64_t last_sample_time_ms_; // Only accessed by one thread.
asapersson@webrtc.org9e5b0342013-12-04 13:47:44 +0000255
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000256 const rtc::scoped_ptr<CaptureQueueDelay> capture_queue_delay_
257 GUARDED_BY(crit_);
tommi@webrtc.org7a57f8f2015-02-08 18:27:46 +0000258
259 rtc::ThreadChecker processing_thread_;
asapersson@webrtc.orgb24d3352013-11-20 13:51:40 +0000260
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000261 DISALLOW_COPY_AND_ASSIGN(OveruseFrameDetector);
262};
263
264} // namespace webrtc
265
266#endif // WEBRTC_VIDEO_ENGINE_OVERUSE_FRAME_DETECTOR_H_