Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: remoting/host/capture_scheduler.cc

Issue 850983002: Implement video frame acknowledgements in the chromoting protocol. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/host/capture_scheduler.h" 5 #include "remoting/host/capture_scheduler.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/sys_info.h" 10 #include "base/sys_info.h"
11 #include "base/time/default_tick_clock.h" 11 #include "base/time/default_tick_clock.h"
12 #include "base/time/time.h" 12 #include "base/time/time.h"
13 13
14 namespace { 14 namespace {
15 15
16 // Number of samples to average the most recent capture and encode time 16 // Number of samples to average the most recent capture and encode time
17 // over. 17 // over.
18 const int kStatisticsWindow = 3; 18 const int kStatisticsWindow = 3;
19 19
20 // The hard limit is 30fps or 33ms per recording cycle. 20 // The hard limit is 30fps or 33ms per recording cycle.
21 const int64 kDefaultMinimumIntervalMs = 33; 21 const int64 kDefaultMinimumIntervalMs = 33;
22 22
23 // Controls how much CPU time we can use for encode and capture. 23 // Controls how much CPU time we can use for encode and capture.
24 // Range of this value is between 0 to 1. 0 means using 0% of of all CPUs 24 // Range of this value is between 0 to 1. 0 means using 0% of of all CPUs
25 // available while 1 means using 100% of all CPUs available. 25 // available while 1 means using 100% of all CPUs available.
26 const double kRecordingCpuConsumption = 0.5; 26 const double kRecordingCpuConsumption = 0.5;
27 27
28 // Maximum number of captured frames in the encoding queue. Currently capturer
29 // implementations do not allow to keep more than 2 DesktopFrame objects.
30 static const int kMaxFramesInEncodingQueue = 2;
31
28 // Maximum number of frames that can be processed simultaneously. 32 // Maximum number of frames that can be processed simultaneously.
29 static const int kMaxPendingFrames = 2; 33 static const int kMaxPendingFrames = 4;
34 static const int kMaxPendingFramesWithoutAcks = 2;
30 35
31 } // namespace 36 } // namespace
32 37
33 namespace remoting { 38 namespace remoting {
34 39
35 // We assume that the number of available cores is constant. 40 // We assume that the number of available cores is constant.
36 CaptureScheduler::CaptureScheduler(const base::Closure& capture_closure) 41 CaptureScheduler::CaptureScheduler(const base::Closure& capture_closure,
42 bool acks_supported)
37 : capture_closure_(capture_closure), 43 : capture_closure_(capture_closure),
44 acks_supported_(acks_supported),
45 max_pending_frames_(acks_supported ? kMaxPendingFrames
46 : kMaxPendingFramesWithoutAcks),
38 tick_clock_(new base::DefaultTickClock()), 47 tick_clock_(new base::DefaultTickClock()),
39 capture_timer_(new base::Timer(false, false)), 48 capture_timer_(new base::Timer(false, false)),
40 minimum_interval_( 49 minimum_interval_(
41 base::TimeDelta::FromMilliseconds(kDefaultMinimumIntervalMs)), 50 base::TimeDelta::FromMilliseconds(kDefaultMinimumIntervalMs)),
42 num_of_processors_(base::SysInfo::NumberOfProcessors()), 51 num_of_processors_(base::SysInfo::NumberOfProcessors()),
43 capture_time_(kStatisticsWindow), 52 capture_time_(kStatisticsWindow),
44 encode_time_(kStatisticsWindow), 53 encode_time_(kStatisticsWindow),
45 pending_frames_(0), 54 num_encoding_frames_(0),
55 num_sending_frames_(0),
46 capture_pending_(false), 56 capture_pending_(false),
47 is_paused_(false) { 57 is_paused_(false) {
48 DCHECK(num_of_processors_); 58 DCHECK(num_of_processors_);
49 } 59 }
50 60
51 CaptureScheduler::~CaptureScheduler() { 61 CaptureScheduler::~CaptureScheduler() {
52 } 62 }
53 63
54 void CaptureScheduler::Start() { 64 void CaptureScheduler::Start() {
55 DCHECK(CalledOnValidThread()); 65 DCHECK(CalledOnValidThread());
(...skipping 15 matching lines...) Expand all
71 } 81 }
72 } 82 }
73 83
74 void CaptureScheduler::OnCaptureCompleted() { 84 void CaptureScheduler::OnCaptureCompleted() {
75 DCHECK(CalledOnValidThread()); 85 DCHECK(CalledOnValidThread());
76 86
77 capture_pending_ = false; 87 capture_pending_ = false;
78 capture_time_.Record( 88 capture_time_.Record(
79 (tick_clock_->NowTicks() - last_capture_started_time_).InMilliseconds()); 89 (tick_clock_->NowTicks() - last_capture_started_time_).InMilliseconds());
80 90
81 ScheduleNextCapture(); 91 ++num_encoding_frames_;
82 }
83
84 void CaptureScheduler::OnFrameSent() {
85 DCHECK(CalledOnValidThread());
86
87 // Decrement the pending capture count.
88 pending_frames_--;
89 DCHECK_GE(pending_frames_, 0);
90 92
91 ScheduleNextCapture(); 93 ScheduleNextCapture();
92 } 94 }
93 95
94 void CaptureScheduler::OnFrameEncoded(base::TimeDelta encode_time) { 96 void CaptureScheduler::OnFrameEncoded(base::TimeDelta encode_time) {
95 DCHECK(CalledOnValidThread()); 97 DCHECK(CalledOnValidThread());
96 98
97 encode_time_.Record(encode_time.InMilliseconds()); 99 encode_time_.Record(encode_time.InMilliseconds());
100
101 --num_encoding_frames_;
102 ++num_sending_frames_;
103
104 ScheduleNextCapture();
105 }
106
107 void CaptureScheduler::OnFrameSent() {
108 DCHECK(CalledOnValidThread());
109
110 // If ACKs are supported then wait for the ACK before decrementing
111 // |num_sending_frames_|.
112 if (!acks_supported_) {
113 --num_sending_frames_;
114 DCHECK_GE(num_sending_frames_, 0);
115
116 ScheduleNextCapture();
117 }
118 }
119
120 void CaptureScheduler::OnFrameAck() {
121 DCHECK(CalledOnValidThread());
122 DCHECK(acks_supported_);
123
124 --num_sending_frames_;
125 DCHECK_GE(num_sending_frames_, 0);
126
98 ScheduleNextCapture(); 127 ScheduleNextCapture();
99 } 128 }
100 129
101 void CaptureScheduler::ScheduleNextCapture() { 130 void CaptureScheduler::ScheduleNextCapture() {
102 DCHECK(CalledOnValidThread()); 131 DCHECK(CalledOnValidThread());
103 132
104 if (is_paused_ || pending_frames_ >= kMaxPendingFrames || capture_pending_) 133 if (is_paused_ || capture_pending_ ||
134 num_encoding_frames_ >= kMaxFramesInEncodingQueue) {
135 return;
136 }
137
138 if (num_encoding_frames_ + num_sending_frames_ >= max_pending_frames_)
105 return; 139 return;
106 140
107 // Delay by an amount chosen such that if capture and encode times 141 // Delay by an amount chosen such that if capture and encode times
108 // continue to follow the averages, then we'll consume the target 142 // continue to follow the averages, then we'll consume the target
109 // fraction of CPU across all cores. 143 // fraction of CPU across all cores.
110 base::TimeDelta delay = 144 base::TimeDelta delay =
111 std::max(minimum_interval_, 145 std::max(minimum_interval_,
112 base::TimeDelta::FromMilliseconds( 146 base::TimeDelta::FromMilliseconds(
113 (capture_time_.Average() + encode_time_.Average()) / 147 (capture_time_.Average() + encode_time_.Average()) /
114 (kRecordingCpuConsumption * num_of_processors_))); 148 (kRecordingCpuConsumption * num_of_processors_)));
115 149
116 // Account for the time that has passed since the last capture. 150 // Account for the time that has passed since the last capture.
117 delay = std::max(base::TimeDelta(), delay - (tick_clock_->NowTicks() - 151 delay = std::max(base::TimeDelta(), delay - (tick_clock_->NowTicks() -
118 last_capture_started_time_)); 152 last_capture_started_time_));
119 153
120 capture_timer_->Start( 154 capture_timer_->Start(
121 FROM_HERE, delay, 155 FROM_HERE, delay,
122 base::Bind(&CaptureScheduler::CaptureNextFrame, base::Unretained(this))); 156 base::Bind(&CaptureScheduler::CaptureNextFrame, base::Unretained(this)));
123 } 157 }
124 158
125 void CaptureScheduler::CaptureNextFrame() { 159 void CaptureScheduler::CaptureNextFrame() {
126 DCHECK(CalledOnValidThread()); 160 DCHECK(CalledOnValidThread());
127 DCHECK(!is_paused_); 161 DCHECK(!is_paused_);
128 DCHECK(!capture_pending_); 162 DCHECK(!capture_pending_);
129 163
130 pending_frames_++;
131 DCHECK_LE(pending_frames_, kMaxPendingFrames);
132
133 capture_pending_ = true; 164 capture_pending_ = true;
134 last_capture_started_time_ = tick_clock_->NowTicks(); 165 last_capture_started_time_ = tick_clock_->NowTicks();
135 capture_closure_.Run(); 166 capture_closure_.Run();
136 } 167 }
137 168
138 } // namespace remoting 169 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698