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

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

Issue 2405333002: Add remoting::protocol::NetworkStateObserver interface. (Closed)
Patch Set: address feedback 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 "third_party/webrtc/modules/desktop_capture/desktop_frame.h" 10 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
10 11
11 namespace remoting { 12 namespace remoting {
12 namespace protocol { 13 namespace protocol {
13 14
14 namespace { 15 namespace {
15 16
16 // Number of samples used to estimate processing time for the next frame. 17 // Number of samples used to estimate processing time for the next frame.
17 const int kStatsWindow = 5; 18 const int kStatsWindow = 5;
18 19
(...skipping 30 matching lines...) Expand all
49 result += r.rect().width() * r.rect().height(); 50 result += r.rect().width() * r.rect().height();
50 } 51 }
51 return result; 52 return result;
52 } 53 }
53 54
54 } // namespace 55 } // namespace
55 56
56 WebrtcFrameSchedulerSimple::WebrtcFrameSchedulerSimple() 57 WebrtcFrameSchedulerSimple::WebrtcFrameSchedulerSimple()
57 : pacing_bucket_(LeakyBucket::kUnlimitedDepth, 0), 58 : pacing_bucket_(LeakyBucket::kUnlimitedDepth, 0),
58 frame_processing_delay_us_(kStatsWindow), 59 frame_processing_delay_us_(kStatsWindow),
59 updated_region_area_(kStatsWindow) {} 60 updated_region_area_(kStatsWindow),
61 weak_factory_(this) {}
60 WebrtcFrameSchedulerSimple::~WebrtcFrameSchedulerSimple() {} 62 WebrtcFrameSchedulerSimple::~WebrtcFrameSchedulerSimple() {}
61 63
62 void WebrtcFrameSchedulerSimple::Start(const base::Closure& capture_callback) { 64 void WebrtcFrameSchedulerSimple::OnKeyFrameRequested() {
65 DCHECK(thread_checker_.CalledOnValidThread());
66 key_frame_request_ = true;
67 if (!capture_timer_.IsRunning())
68 ScheduleNextFrame(base::TimeTicks::Now());
69 }
70
71 void WebrtcFrameSchedulerSimple::OnChannelParameters(int packet_loss,
72 base::TimeDelta rtt) {
73 DCHECK(thread_checker_.CalledOnValidThread());
74 }
75
76 void WebrtcFrameSchedulerSimple::OnTargetBitrateChanged(int bitrate_kbps) {
77 DCHECK(thread_checker_.CalledOnValidThread());
78 base::TimeTicks now = base::TimeTicks::Now();
79 pacing_bucket_.UpdateRate(bitrate_kbps * 1000 / 8, now);
80 ScheduleNextFrame(now);
81 }
82
83 void WebrtcFrameSchedulerSimple::Start(
84 WebrtcDummyVideoEncoderFactory* video_encoder_factory,
85 const base::Closure& capture_callback) {
86 DCHECK(thread_checker_.CalledOnValidThread());
63 capture_callback_ = capture_callback; 87 capture_callback_ = capture_callback;
64 ScheduleNextFrame(base::TimeTicks::Now()); 88 video_encoder_factory->SetVideoChannelStateObserver(
89 weak_factory_.GetWeakPtr());
65 } 90 }
66 91
67 void WebrtcFrameSchedulerSimple::Pause(bool pause) { 92 void WebrtcFrameSchedulerSimple::Pause(bool pause) {
93 DCHECK(thread_checker_.CalledOnValidThread());
94
68 paused_ = pause; 95 paused_ = pause;
69 if (paused_) { 96 if (paused_) {
70 capture_timer_.Stop(); 97 capture_timer_.Stop();
71 } else { 98 } else {
72 ScheduleNextFrame(base::TimeTicks::Now()); 99 ScheduleNextFrame(base::TimeTicks::Now());
73 } 100 }
74 } 101 }
75 102
76 void WebrtcFrameSchedulerSimple::SetKeyFrameRequest() {
77 key_frame_request_ = true;
78 }
79
80 void WebrtcFrameSchedulerSimple::SetTargetBitrate(int bitrate_kbps) {
81 base::TimeTicks now = base::TimeTicks::Now();
82 pacing_bucket_.UpdateRate(bitrate_kbps * 1000 / 8, now);
83 ScheduleNextFrame(now);
84 }
85
86 bool WebrtcFrameSchedulerSimple::GetEncoderFrameParams( 103 bool WebrtcFrameSchedulerSimple::GetEncoderFrameParams(
87 const webrtc::DesktopFrame& frame, 104 const webrtc::DesktopFrame& frame,
88 WebrtcVideoEncoder::FrameParams* params_out) { 105 WebrtcVideoEncoder::FrameParams* params_out) {
106 DCHECK(thread_checker_.CalledOnValidThread());
107
89 base::TimeTicks now = base::TimeTicks::Now(); 108 base::TimeTicks now = base::TimeTicks::Now();
90 109
91 if (frame.updated_region().is_empty() && !top_off_is_active_ && 110 if (frame.updated_region().is_empty() && !top_off_is_active_ &&
92 !key_frame_request_) { 111 !key_frame_request_) {
93 ScheduleNextFrame(now); 112 ScheduleNextFrame(now);
94 return false; 113 return false;
95 } 114 }
96 115
97 // 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.
98 int minimum_bitrate = 117 int minimum_bitrate =
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 params_out->vpx_max_quantizer = 63; 149 params_out->vpx_max_quantizer = 63;
131 150
132 params_out->clear_active_map = !top_off_is_active_; 151 params_out->clear_active_map = !top_off_is_active_;
133 152
134 return true; 153 return true;
135 } 154 }
136 155
137 void WebrtcFrameSchedulerSimple::OnFrameEncoded( 156 void WebrtcFrameSchedulerSimple::OnFrameEncoded(
138 const WebrtcVideoEncoder::EncodedFrame& encoded_frame, 157 const WebrtcVideoEncoder::EncodedFrame& encoded_frame,
139 const webrtc::EncodedImageCallback::Result& send_result) { 158 const webrtc::EncodedImageCallback::Result& send_result) {
159 DCHECK(thread_checker_.CalledOnValidThread());
160
140 base::TimeTicks now = base::TimeTicks::Now(); 161 base::TimeTicks now = base::TimeTicks::Now();
141 pacing_bucket_.RefillOrSpill(encoded_frame.data.size(), now); 162 pacing_bucket_.RefillOrSpill(encoded_frame.data.size(), now);
142 163
143 if (encoded_frame.data.empty()) { 164 if (encoded_frame.data.empty()) {
144 top_off_is_active_ = false; 165 top_off_is_active_ = false;
145 } else { 166 } else {
146 frame_processing_delay_us_.Record( 167 frame_processing_delay_us_.Record(
147 (now - last_capture_started_time_).InMicroseconds()); 168 (now - last_capture_started_time_).InMicroseconds());
148 169
149 // Top-off until the target quantizer value is reached. 170 // Top-off until the target quantizer value is reached.
150 top_off_is_active_ = encoded_frame.quantizer > kTargetQuantizerForVp8TopOff; 171 top_off_is_active_ = encoded_frame.quantizer > kTargetQuantizerForVp8TopOff;
151 } 172 }
152 173
153 ScheduleNextFrame(now); 174 ScheduleNextFrame(now);
154 } 175 }
155 176
156 void WebrtcFrameSchedulerSimple::ScheduleNextFrame(base::TimeTicks now) { 177 void WebrtcFrameSchedulerSimple::ScheduleNextFrame(base::TimeTicks now) {
178 DCHECK(thread_checker_.CalledOnValidThread());
179
157 // Don't capture frames when paused or target bitrate is 0 or there is 180 // Don't capture frames when paused or target bitrate is 0 or there is
158 // no capture callback set. 181 // no capture callback set.
159 if (paused_ || pacing_bucket_.rate() == 0 || capture_callback_.is_null()) 182 if (paused_ || pacing_bucket_.rate() == 0 || capture_callback_.is_null())
160 return; 183 return;
161 184
162 // If this is not the first frame then capture next frame after the previous 185 // If this is not the first frame then capture next frame after the previous
163 // one has finished sending. 186 // one has finished sending.
164 base::TimeDelta expected_processing_time = 187 base::TimeDelta expected_processing_time =
165 base::TimeDelta::FromMicroseconds(frame_processing_delay_us_.Max()); 188 base::TimeDelta::FromMicroseconds(frame_processing_delay_us_.Max());
166 base::TimeTicks target_capture_time = 189 base::TimeTicks target_capture_time =
167 pacing_bucket_.GetEmptyTime() - expected_processing_time; 190 pacing_bucket_.GetEmptyTime() - expected_processing_time;
168 191
169 // Cap interval between frames to kTargetFrameInterval. 192 // Cap interval between frames to kTargetFrameInterval.
170 if (!last_capture_started_time_.is_null()) { 193 if (!last_capture_started_time_.is_null()) {
171 target_capture_time = std::max( 194 target_capture_time = std::max(
172 target_capture_time, last_capture_started_time_ + kTargetFrameInterval); 195 target_capture_time, last_capture_started_time_ + kTargetFrameInterval);
173 } 196 }
174 197
175 if (target_capture_time < now) 198 if (target_capture_time < now)
176 target_capture_time = now; 199 target_capture_time = now;
177 200
178 capture_timer_.Start(FROM_HERE, target_capture_time - now, 201 capture_timer_.Start(FROM_HERE, target_capture_time - now,
179 base::Bind(&WebrtcFrameSchedulerSimple::CaptureNextFrame, 202 base::Bind(&WebrtcFrameSchedulerSimple::CaptureNextFrame,
180 base::Unretained(this))); 203 base::Unretained(this)));
181 } 204 }
182 205
183 void WebrtcFrameSchedulerSimple::CaptureNextFrame() { 206 void WebrtcFrameSchedulerSimple::CaptureNextFrame() {
207 DCHECK(thread_checker_.CalledOnValidThread());
208
184 last_capture_started_time_ = base::TimeTicks::Now(); 209 last_capture_started_time_ = base::TimeTicks::Now();
185 capture_callback_.Run(); 210 capture_callback_.Run();
186 } 211 }
187 212
188 } // namespace protocol 213 } // namespace protocol
189 } // namespace remoting 214 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/protocol/webrtc_frame_scheduler_simple.h ('k') | remoting/protocol/webrtc_video_stream.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698