blob: 9f78c6c0ff1d0a5daee5655948f95dcf8e4ed8d1 [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
Peter Boström7623ce42015-12-09 12:13:30 +010011#ifndef WEBRTC_VIDEO_OVERUSE_FRAME_DETECTOR_H_
12#define WEBRTC_VIDEO_OVERUSE_FRAME_DETECTOR_H_
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000013
Peter Boströme4499152016-02-05 11:13:28 +010014#include <list>
kwiberg27f982b2016-03-01 11:52:33 -080015#include <memory>
Peter Boströme4499152016-02-05 11:13:28 +010016
henrike@webrtc.org88fbb2d2014-05-21 21:18:46 +000017#include "webrtc/base/constructormagic.h"
tommi@webrtc.org7a57f8f2015-02-08 18:27:46 +000018#include "webrtc/base/criticalsection.h"
Peter Boströme4499152016-02-05 11:13:28 +010019#include "webrtc/base/optional.h"
minyue@webrtc.org74aaf292014-07-16 21:28:26 +000020#include "webrtc/base/exp_filter.h"
asapersson@webrtc.orgcd621a82014-11-11 09:40:19 +000021#include "webrtc/base/thread_annotations.h"
tommi@webrtc.org7a57f8f2015-02-08 18:27:46 +000022#include "webrtc/base/thread_checker.h"
Henrik Kjellanderff761fb2015-11-04 08:31:52 +010023#include "webrtc/modules/include/module.h"
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000024
25namespace webrtc {
26
27class Clock;
Peter Boströme4499152016-02-05 11:13:28 +010028class EncodedFrameObserver;
29class VideoFrame;
Peter Boström300eeb62015-05-12 16:51:11 +020030
31// CpuOveruseObserver is called when a system overuse is detected and
32// VideoEngine cannot keep up the encoding frequency.
33class CpuOveruseObserver {
34 public:
35 // Called as soon as an overuse is detected.
36 virtual void OveruseDetected() = 0;
37 // Called periodically when the system is not overused any longer.
38 virtual void NormalUsage() = 0;
39
40 protected:
41 virtual ~CpuOveruseObserver() {}
42};
43
44struct CpuOveruseOptions {
torbjorng448468d2016-02-10 08:11:57 -080045 CpuOveruseOptions();
Peter Boström300eeb62015-05-12 16:51:11 +020046
Peter Boström300eeb62015-05-12 16:51:11 +020047 int low_encode_usage_threshold_percent; // Threshold for triggering underuse.
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +010048 int high_encode_usage_threshold_percent; // Threshold for triggering overuse.
Peter Boström300eeb62015-05-12 16:51:11 +020049 // General settings.
50 int frame_timeout_interval_ms; // The maximum allowed interval between two
51 // frames before resetting estimations.
52 int min_frame_samples; // The minimum number of frames required.
53 int min_process_count; // The number of initial process times required before
54 // triggering an overuse/underuse.
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +010055 int high_threshold_consecutive_count; // The number of consecutive checks
56 // above the high threshold before
57 // triggering an overuse.
Peter Boström300eeb62015-05-12 16:51:11 +020058};
59
60struct CpuOveruseMetrics {
asapersson1aa420b2015-12-07 03:12:22 -080061 CpuOveruseMetrics() : encode_usage_percent(-1) {}
Peter Boström300eeb62015-05-12 16:51:11 +020062
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +010063 int encode_usage_percent; // Average encode time divided by the average time
64 // difference between incoming captured frames.
Peter Boström300eeb62015-05-12 16:51:11 +020065};
66
67class CpuOveruseMetricsObserver {
68 public:
69 virtual ~CpuOveruseMetricsObserver() {}
Peter Boströme4499152016-02-05 11:13:28 +010070 virtual void OnEncodedFrameTimeMeasured(int encode_duration_ms,
71 const CpuOveruseMetrics& metrics) = 0;
Peter Boström300eeb62015-05-12 16:51:11 +020072};
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000073
Åsa Persson746210f2015-09-08 10:52:42 +020074// Use to detect system overuse based on the send-side processing time of
75// incoming frames.
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000076class OveruseFrameDetector : public Module {
77 public:
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +000078 OveruseFrameDetector(Clock* clock,
Peter Boström4b91bd02015-06-26 06:58:16 +020079 const CpuOveruseOptions& options,
80 CpuOveruseObserver* overuse_observer,
Peter Boströme4499152016-02-05 11:13:28 +010081 EncodedFrameObserver* encoder_timing_,
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +000082 CpuOveruseMetricsObserver* metrics_observer);
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000083 ~OveruseFrameDetector();
84
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +000085 // Called for each captured frame.
Peter Boströme4499152016-02-05 11:13:28 +010086 void FrameCaptured(const VideoFrame& frame);
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000087
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +000088 // Called for each sent frame.
Peter Boströme4499152016-02-05 11:13:28 +010089 void FrameSent(uint32_t timestamp);
asapersson@webrtc.orgb24d3352013-11-20 13:51:40 +000090
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000091 // Implements Module.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000092 int64_t TimeUntilNextProcess() override;
pbosa26ac922016-02-25 04:50:01 -080093 void Process() override;
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000094
95 private:
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +000096 class SendProcessingUsage;
Peter Boströme4499152016-02-05 11:13:28 +010097 struct FrameTiming {
98 FrameTiming(int64_t capture_ntp_ms, uint32_t timestamp, int64_t now)
99 : capture_ntp_ms(capture_ntp_ms),
100 timestamp(timestamp),
101 capture_ms(now),
102 last_send_ms(-1) {}
103 int64_t capture_ntp_ms;
104 uint32_t timestamp;
105 int64_t capture_ms;
106 int64_t last_send_ms;
107 };
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000108
Peter Boströme4499152016-02-05 11:13:28 +0100109 void EncodedFrameTimeMeasured(int encode_duration_ms)
110 EXCLUSIVE_LOCKS_REQUIRED(crit_);
asapersson@webrtc.org9e5b0342013-12-04 13:47:44 +0000111
asapersson74d85e12015-09-24 00:53:32 -0700112 // Only called on the processing thread.
113 bool IsOverusing(const CpuOveruseMetrics& metrics);
114 bool IsUnderusing(const CpuOveruseMetrics& metrics, int64_t time_now);
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000115
asapersson@webrtc.orgcd621a82014-11-11 09:40:19 +0000116 bool FrameTimeoutDetected(int64_t now) const EXCLUSIVE_LOCKS_REQUIRED(crit_);
117 bool FrameSizeChanged(int num_pixels) const EXCLUSIVE_LOCKS_REQUIRED(crit_);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000118
asapersson@webrtc.orgcd621a82014-11-11 09:40:19 +0000119 void ResetAll(int num_pixels) EXCLUSIVE_LOCKS_REQUIRED(crit_);
asapersson@webrtc.orgb60346e2014-02-17 19:02:15 +0000120
tommi@webrtc.org7a57f8f2015-02-08 18:27:46 +0000121 // Protecting all members except const and those that are only accessed on the
122 // processing thread.
123 // TODO(asapersson): See if we can reduce locking. As is, video frame
124 // processing contends with reading stats and the processing thread.
pbos5ad935c2016-01-25 03:52:44 -0800125 rtc::CriticalSection crit_;
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000126
Peter Boström4b91bd02015-06-26 06:58:16 +0200127 const CpuOveruseOptions options_;
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000128
Peter Boström4b91bd02015-06-26 06:58:16 +0200129 // Observer getting overuse reports.
130 CpuOveruseObserver* const observer_;
Peter Boströme4499152016-02-05 11:13:28 +0100131 EncodedFrameObserver* const encoder_timing_;
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000132
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +0000133 // Stats metrics.
134 CpuOveruseMetricsObserver* const metrics_observer_;
Peter Boströme4499152016-02-05 11:13:28 +0100135 rtc::Optional<CpuOveruseMetrics> metrics_ GUARDED_BY(crit_);
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +0000136
tommi@webrtc.orga907e012015-01-28 17:33:12 +0000137 Clock* const clock_;
asapersson@webrtc.orgcd621a82014-11-11 09:40:19 +0000138 int64_t num_process_times_ GUARDED_BY(crit_);
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000139
Peter Boströme4499152016-02-05 11:13:28 +0100140 int64_t last_capture_time_ms_ GUARDED_BY(crit_);
141 int64_t last_processed_capture_time_ms_ GUARDED_BY(crit_);
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000142
asapersson74d85e12015-09-24 00:53:32 -0700143 // Number of pixels of last captured frame.
144 int num_pixels_ GUARDED_BY(crit_);
145
146 // These seven members are only accessed on the processing thread.
Peter Boströme4499152016-02-05 11:13:28 +0100147 int64_t next_process_time_ms_;
148 int64_t last_overuse_time_ms_;
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000149 int checks_above_threshold_;
asapersson@webrtc.orgd9803072014-06-16 14:27:19 +0000150 int num_overuse_detections_;
Peter Boströme4499152016-02-05 11:13:28 +0100151 int64_t last_rampup_time_ms_;
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000152 bool in_quick_rampup_;
153 int current_rampup_delay_ms_;
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000154
tommi@webrtc.org7a57f8f2015-02-08 18:27:46 +0000155 // TODO(asapersson): Can these be regular members (avoid separate heap
156 // allocs)?
kwiberg27f982b2016-03-01 11:52:33 -0800157 const std::unique_ptr<SendProcessingUsage> usage_ GUARDED_BY(crit_);
Peter Boströme4499152016-02-05 11:13:28 +0100158 std::list<FrameTiming> frame_timing_ GUARDED_BY(crit_);
asapersson@webrtc.org44149392015-02-04 08:34:47 +0000159
tommi@webrtc.org7a57f8f2015-02-08 18:27:46 +0000160 rtc::ThreadChecker processing_thread_;
asapersson@webrtc.orgb24d3352013-11-20 13:51:40 +0000161
henrikg3c089d72015-09-16 05:37:44 -0700162 RTC_DISALLOW_COPY_AND_ASSIGN(OveruseFrameDetector);
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000163};
164
165} // namespace webrtc
166
Peter Boström7623ce42015-12-09 12:13:30 +0100167#endif // WEBRTC_VIDEO_OVERUSE_FRAME_DETECTOR_H_