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

Side by Side Diff: remoting/protocol/webrtc_frame_scheduler_simple.cc

Issue 2431843002: Update WebrtcFrameScheduler to avoid concurrent captures. (Closed)
Patch Set: Created 4 years, 2 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 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/protocol/webrtc_frame_scheduler_simple.h" 5 #include "remoting/protocol/webrtc_frame_scheduler_simple.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "remoting/protocol/webrtc_dummy_video_encoder.h" 9 #include "remoting/protocol/webrtc_dummy_video_encoder.h"
10 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" 10 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 WebrtcFrameSchedulerSimple::WebrtcFrameSchedulerSimple() 57 WebrtcFrameSchedulerSimple::WebrtcFrameSchedulerSimple()
58 : pacing_bucket_(LeakyBucket::kUnlimitedDepth, 0), 58 : pacing_bucket_(LeakyBucket::kUnlimitedDepth, 0),
59 frame_processing_delay_us_(kStatsWindow), 59 frame_processing_delay_us_(kStatsWindow),
60 updated_region_area_(kStatsWindow), 60 updated_region_area_(kStatsWindow),
61 weak_factory_(this) {} 61 weak_factory_(this) {}
62 WebrtcFrameSchedulerSimple::~WebrtcFrameSchedulerSimple() {} 62 WebrtcFrameSchedulerSimple::~WebrtcFrameSchedulerSimple() {}
63 63
64 void WebrtcFrameSchedulerSimple::OnKeyFrameRequested() { 64 void WebrtcFrameSchedulerSimple::OnKeyFrameRequested() {
65 DCHECK(thread_checker_.CalledOnValidThread()); 65 DCHECK(thread_checker_.CalledOnValidThread());
66 key_frame_request_ = true; 66 key_frame_request_ = true;
67 if (!capture_timer_.IsRunning()) 67 ScheduleNextFrame(base::TimeTicks::Now());
68 ScheduleNextFrame(base::TimeTicks::Now());
69 } 68 }
70 69
71 void WebrtcFrameSchedulerSimple::OnChannelParameters(int packet_loss, 70 void WebrtcFrameSchedulerSimple::OnChannelParameters(int packet_loss,
72 base::TimeDelta rtt) { 71 base::TimeDelta rtt) {
73 DCHECK(thread_checker_.CalledOnValidThread()); 72 DCHECK(thread_checker_.CalledOnValidThread());
74 } 73 }
75 74
76 void WebrtcFrameSchedulerSimple::OnTargetBitrateChanged(int bitrate_kbps) { 75 void WebrtcFrameSchedulerSimple::OnTargetBitrateChanged(int bitrate_kbps) {
77 DCHECK(thread_checker_.CalledOnValidThread()); 76 DCHECK(thread_checker_.CalledOnValidThread());
78 base::TimeTicks now = base::TimeTicks::Now(); 77 base::TimeTicks now = base::TimeTicks::Now();
(...skipping 23 matching lines...) Expand all
102 101
103 bool WebrtcFrameSchedulerSimple::GetEncoderFrameParams( 102 bool WebrtcFrameSchedulerSimple::GetEncoderFrameParams(
104 const webrtc::DesktopFrame& frame, 103 const webrtc::DesktopFrame& frame,
105 WebrtcVideoEncoder::FrameParams* params_out) { 104 WebrtcVideoEncoder::FrameParams* params_out) {
106 DCHECK(thread_checker_.CalledOnValidThread()); 105 DCHECK(thread_checker_.CalledOnValidThread());
107 106
108 base::TimeTicks now = base::TimeTicks::Now(); 107 base::TimeTicks now = base::TimeTicks::Now();
109 108
110 if (frame.updated_region().is_empty() && !top_off_is_active_ && 109 if (frame.updated_region().is_empty() && !top_off_is_active_ &&
111 !key_frame_request_) { 110 !key_frame_request_) {
111 frame_pending_ = false;
112 ScheduleNextFrame(now); 112 ScheduleNextFrame(now);
113 return false; 113 return false;
114 } 114 }
115 115
116 // TODO(sergeyu): This logic is applicable only to VP8. Reconsider it for VP9. 116 // TODO(sergeyu): This logic is applicable only to VP8. Reconsider it for VP9.
117 int minimum_bitrate = 117 int minimum_bitrate =
118 static_cast<int64_t>(kVp8MinimumTargetBitrateKbpsPerMegapixel) * 118 static_cast<int64_t>(kVp8MinimumTargetBitrateKbpsPerMegapixel) *
119 frame.size().width() * frame.size().height() / 1000000LL; 119 frame.size().width() * frame.size().height() / 1000000LL;
120 params_out->bitrate_kbps = 120 params_out->bitrate_kbps =
121 std::max(minimum_bitrate, pacing_bucket_.rate() * 8 / 1000); 121 std::max(minimum_bitrate, pacing_bucket_.rate() * 8 / 1000);
(...skipping 28 matching lines...) Expand all
150 150
151 params_out->clear_active_map = !top_off_is_active_; 151 params_out->clear_active_map = !top_off_is_active_;
152 152
153 return true; 153 return true;
154 } 154 }
155 155
156 void WebrtcFrameSchedulerSimple::OnFrameEncoded( 156 void WebrtcFrameSchedulerSimple::OnFrameEncoded(
157 const WebrtcVideoEncoder::EncodedFrame& encoded_frame, 157 const WebrtcVideoEncoder::EncodedFrame& encoded_frame,
158 const webrtc::EncodedImageCallback::Result& send_result) { 158 const webrtc::EncodedImageCallback::Result& send_result) {
159 DCHECK(thread_checker_.CalledOnValidThread()); 159 DCHECK(thread_checker_.CalledOnValidThread());
160 DCHECK(frame_pending_);
161 frame_pending_ = false;
160 162
161 base::TimeTicks now = base::TimeTicks::Now(); 163 base::TimeTicks now = base::TimeTicks::Now();
162 pacing_bucket_.RefillOrSpill(encoded_frame.data.size(), now); 164 pacing_bucket_.RefillOrSpill(encoded_frame.data.size(), now);
163 165
164 if (encoded_frame.data.empty()) { 166 if (encoded_frame.data.empty()) {
165 top_off_is_active_ = false; 167 top_off_is_active_ = false;
166 } else { 168 } else {
167 frame_processing_delay_us_.Record( 169 frame_processing_delay_us_.Record(
168 (now - last_capture_started_time_).InMicroseconds()); 170 (now - last_capture_started_time_).InMicroseconds());
169 171
170 // Top-off until the target quantizer value is reached. 172 // Top-off until the target quantizer value is reached.
171 top_off_is_active_ = encoded_frame.quantizer > kTargetQuantizerForVp8TopOff; 173 top_off_is_active_ = encoded_frame.quantizer > kTargetQuantizerForVp8TopOff;
172 } 174 }
173 175
174 ScheduleNextFrame(now); 176 ScheduleNextFrame(now);
175 } 177 }
176 178
177 void WebrtcFrameSchedulerSimple::ScheduleNextFrame(base::TimeTicks now) { 179 void WebrtcFrameSchedulerSimple::ScheduleNextFrame(base::TimeTicks now) {
178 DCHECK(thread_checker_.CalledOnValidThread()); 180 DCHECK(thread_checker_.CalledOnValidThread());
179 181
180 // Don't capture frames when paused or target bitrate is 0 or there is 182 // Don't capture frames when paused or target bitrate is 0 or there is
181 // no capture callback set. 183 // no capture callback set.
Jamie 2016/10/18 22:40:26 Update this comment. As written now, it's just an
Sergey Ulanov 2016/10/18 23:11:02 Removed it.
182 if (paused_ || pacing_bucket_.rate() == 0 || capture_callback_.is_null()) 184 if (paused_ || pacing_bucket_.rate() == 0 || capture_callback_.is_null() ||
185 frame_pending_) {
183 return; 186 return;
187 }
184 188
185 // If this is not the first frame then capture next frame after the previous 189 // If this is not the first frame then capture next frame after the previous
186 // one has finished sending. 190 // one has finished sending.
187 base::TimeDelta expected_processing_time = 191 base::TimeDelta expected_processing_time =
188 base::TimeDelta::FromMicroseconds(frame_processing_delay_us_.Max()); 192 base::TimeDelta::FromMicroseconds(frame_processing_delay_us_.Max());
189 base::TimeTicks target_capture_time = 193 base::TimeTicks target_capture_time =
190 pacing_bucket_.GetEmptyTime() - expected_processing_time; 194 pacing_bucket_.GetEmptyTime() - expected_processing_time;
191 195
192 // Cap interval between frames to kTargetFrameInterval. 196 // Cap interval between frames to kTargetFrameInterval.
193 if (!last_capture_started_time_.is_null()) { 197 if (!last_capture_started_time_.is_null()) {
194 target_capture_time = std::max( 198 target_capture_time = std::max(
195 target_capture_time, last_capture_started_time_ + kTargetFrameInterval); 199 target_capture_time, last_capture_started_time_ + kTargetFrameInterval);
196 } 200 }
197 201
198 if (target_capture_time < now) 202 if (target_capture_time < now)
199 target_capture_time = now; 203 target_capture_time = now;
200 204
201 capture_timer_.Start(FROM_HERE, target_capture_time - now, 205 capture_timer_.Start(FROM_HERE, target_capture_time - now,
202 base::Bind(&WebrtcFrameSchedulerSimple::CaptureNextFrame, 206 base::Bind(&WebrtcFrameSchedulerSimple::CaptureNextFrame,
203 base::Unretained(this))); 207 base::Unretained(this)));
204 } 208 }
205 209
206 void WebrtcFrameSchedulerSimple::CaptureNextFrame() { 210 void WebrtcFrameSchedulerSimple::CaptureNextFrame() {
207 DCHECK(thread_checker_.CalledOnValidThread()); 211 DCHECK(thread_checker_.CalledOnValidThread());
208 212 DCHECK(!frame_pending_);
209 last_capture_started_time_ = base::TimeTicks::Now(); 213 last_capture_started_time_ = base::TimeTicks::Now();
214 frame_pending_ = true;
210 capture_callback_.Run(); 215 capture_callback_.Run();
211 } 216 }
212 217
213 } // namespace protocol 218 } // namespace protocol
214 } // namespace remoting 219 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698