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

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

Issue 2035803002: Fix WebRtcFrameScheduler to wait for first key frame request. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 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.h" 5 #include "remoting/protocol/webrtc_frame_scheduler.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <memory> 8 #include <memory>
9 9
10 #include "base/location.h"
Irfan 2016/06/02 19:06:00 what is this used for ?
Sergey Ulanov 2016/06/03 06:01:23 it defines FROM_HERE macro used for PostTask()
10 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/threading/thread_task_runner_handle.h"
11 #include "remoting/base/constants.h" 14 #include "remoting/base/constants.h"
12 #include "remoting/proto/video.pb.h" 15 #include "remoting/proto/video.pb.h"
13 16
14 namespace remoting { 17 namespace remoting {
15 namespace protocol { 18 namespace protocol {
16 19
17 namespace { 20 namespace {
18 21
19 // Target quantizer at which stop the encoding top-off. 22 // Target quantizer at which stop the encoding top-off.
20 const int kTargetQuantizerForTopOff = 30; 23 const int kTargetQuantizerForTopOff = 30;
(...skipping 10 matching lines...) Expand all
31 // at 30 FPS to capture, encode and send frames over webrtc transport. 34 // at 30 FPS to capture, encode and send frames over webrtc transport.
32 // An improved solution will use target bitrate feedback to pace out 35 // An improved solution will use target bitrate feedback to pace out
33 // the capture rate. 36 // the capture rate.
34 WebRtcFrameScheduler::WebRtcFrameScheduler( 37 WebRtcFrameScheduler::WebRtcFrameScheduler(
35 scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner, 38 scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner,
36 std::unique_ptr<webrtc::DesktopCapturer> capturer, 39 std::unique_ptr<webrtc::DesktopCapturer> capturer,
37 WebrtcTransport* webrtc_transport, 40 WebrtcTransport* webrtc_transport,
38 std::unique_ptr<VideoEncoder> encoder) 41 std::unique_ptr<VideoEncoder> encoder)
39 : target_bitrate_kbps_(kDefaultTargetBitrateKbps), 42 : target_bitrate_kbps_(kDefaultTargetBitrateKbps),
40 last_quantizer_(kMaxQuantizer), 43 last_quantizer_(kMaxQuantizer),
44 main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
41 encode_task_runner_(encode_task_runner), 45 encode_task_runner_(encode_task_runner),
42 capturer_(std::move(capturer)), 46 capturer_(std::move(capturer)),
43 webrtc_transport_(webrtc_transport), 47 webrtc_transport_(webrtc_transport),
44 encoder_(std::move(encoder)), 48 encoder_(std::move(encoder)),
45 weak_factory_(this) { 49 weak_factory_(this) {
46 DCHECK(encode_task_runner_); 50 DCHECK(encode_task_runner_);
47 DCHECK(capturer_); 51 DCHECK(capturer_);
48 DCHECK(webrtc_transport_); 52 DCHECK(webrtc_transport_);
49 DCHECK(encoder_); 53 DCHECK(encoder_);
50 // Does not really start anything. Registers callback on this class. 54 // Does not really start anything. Registers callback on this class.
51 capturer_->Start(this); 55 capturer_->Start(this);
52 capture_timer_.reset(new base::RepeatingTimer()); 56 capture_timer_.reset(new base::RepeatingTimer());
53 } 57 }
54 58
55 WebRtcFrameScheduler::~WebRtcFrameScheduler() { 59 WebRtcFrameScheduler::~WebRtcFrameScheduler() {
56 encode_task_runner_->DeleteSoon(FROM_HERE, encoder_.release()); 60 encode_task_runner_->DeleteSoon(FROM_HERE, encoder_.release());
57 } 61 }
58 62
59 void WebRtcFrameScheduler::Start() { 63 void WebRtcFrameScheduler::Start() {
60 // Register for PLI requests. 64 // Register for PLI requests.
61 webrtc_transport_->video_encoder_factory()->SetKeyFrameRequestCallback( 65 webrtc_transport_->video_encoder_factory()->SetKeyFrameRequestCallback(
62 base::Bind(&WebRtcFrameScheduler::SetKeyFrameRequest, 66 base::Bind(&WebRtcFrameScheduler::SetKeyFrameRequest,
63 base::Unretained(this))); 67 base::Unretained(this)));
64 // Register for target bitrate notifications. 68 // Register for target bitrate notifications.
65 webrtc_transport_->video_encoder_factory()->SetTargetBitrateCallback( 69 webrtc_transport_->video_encoder_factory()->SetTargetBitrateCallback(
66 base::Bind(&WebRtcFrameScheduler::SetTargetBitrate, 70 base::Bind(&WebRtcFrameScheduler::SetTargetBitrate,
67 base::Unretained(this))); 71 base::Unretained(this)));
68 capture_timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(1) / 30, this,
69 &WebRtcFrameScheduler::CaptureNextFrame);
70 } 72 }
71 73
72 void WebRtcFrameScheduler::Stop() { 74 void WebRtcFrameScheduler::Stop() {
73 // Clear PLI request callback. 75 // Clear PLI request callback.
74 webrtc_transport_->video_encoder_factory()->SetKeyFrameRequestCallback( 76 webrtc_transport_->video_encoder_factory()->SetKeyFrameRequestCallback(
75 base::Closure()); 77 base::Closure());
76 webrtc_transport_->video_encoder_factory()->SetTargetBitrateCallback( 78 webrtc_transport_->video_encoder_factory()->SetTargetBitrateCallback(
77 TargetBitrateCallback()); 79 TargetBitrateCallback());
78 // Cancel any pending encode. 80 // Cancel any pending encode.
79 task_tracker_.TryCancelAll(); 81 task_tracker_.TryCancelAll();
(...skipping 10 matching lines...) Expand all
90 92
91 void WebRtcFrameScheduler::SetSizeCallback( 93 void WebRtcFrameScheduler::SetSizeCallback(
92 const VideoStream::SizeCallback& callback) { 94 const VideoStream::SizeCallback& callback) {
93 size_callback_ = callback; 95 size_callback_ = callback;
94 } 96 }
95 97
96 void WebRtcFrameScheduler::SetKeyFrameRequest() { 98 void WebRtcFrameScheduler::SetKeyFrameRequest() {
97 VLOG(1) << "Request key frame"; 99 VLOG(1) << "Request key frame";
98 base::AutoLock lock(lock_); 100 base::AutoLock lock(lock_);
99 key_frame_request_ = true; 101 key_frame_request_ = true;
102 if (!received_first_frame_request_) {
103 received_first_frame_request_ = true;
104 main_task_runner_->PostTask(
105 FROM_HERE, base::Bind(&WebRtcFrameScheduler::StartCaptureTimer,
106 weak_factory_.GetWeakPtr()));
107 }
108 }
109
110 void WebRtcFrameScheduler::StartCaptureTimer() {
111 capture_timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(1) / 30, this,
112 &WebRtcFrameScheduler::CaptureNextFrame);
100 } 113 }
101 114
102 void WebRtcFrameScheduler::SetTargetBitrate(int target_bitrate_kbps) { 115 void WebRtcFrameScheduler::SetTargetBitrate(int target_bitrate_kbps) {
103 VLOG(1) << "Set Target bitrate " << target_bitrate_kbps; 116 VLOG(1) << "Set Target bitrate " << target_bitrate_kbps;
104 base::AutoLock lock(lock_); 117 base::AutoLock lock(lock_);
105 target_bitrate_kbps_ = target_bitrate_kbps; 118 target_bitrate_kbps_ = target_bitrate_kbps;
106 } 119 }
107 120
108 bool WebRtcFrameScheduler::ClearAndGetKeyFrameRequest() { 121 bool WebRtcFrameScheduler::ClearAndGetKeyFrameRequest() {
109 base::AutoLock lock(lock_); 122 base::AutoLock lock(lock_);
(...skipping 13 matching lines...) Expand all
123 std::unique_ptr<webrtc::DesktopFrame> owned_frame(frame); 136 std::unique_ptr<webrtc::DesktopFrame> owned_frame(frame);
124 137
125 if (encode_pending_) { 138 if (encode_pending_) {
126 // TODO(isheriff): consider queuing here 139 // TODO(isheriff): consider queuing here
127 VLOG(1) << "Dropping captured frame since encoder is still busy"; 140 VLOG(1) << "Dropping captured frame since encoder is still busy";
128 return; 141 return;
129 } 142 }
130 143
131 // If unchanged and does not need top-off, return. 144 // If unchanged and does not need top-off, return.
132 if (!frame || (frame->updated_region().is_empty() && 145 if (!frame || (frame->updated_region().is_empty() &&
133 last_quantizer_ <= kTargetQuantizerForTopOff)) 146 last_quantizer_ <= kTargetQuantizerForTopOff)) {
134 return; 147 return;
148 }
135 149
136 last_capture_completed_ticks_ = captured_ticks; 150 last_capture_completed_ticks_ = captured_ticks;
137 151
138 webrtc::DesktopVector dpi = 152 webrtc::DesktopVector dpi =
139 frame->dpi().is_zero() ? webrtc::DesktopVector(kDefaultDpi, kDefaultDpi) 153 frame->dpi().is_zero() ? webrtc::DesktopVector(kDefaultDpi, kDefaultDpi)
140 : frame->dpi(); 154 : frame->dpi();
141 155
142 if (!frame_size_.equals(frame->size()) || !frame_dpi_.equals(dpi)) { 156 if (!frame_size_.equals(frame->size()) || !frame_dpi_.equals(dpi)) {
143 frame_size_ = frame->size(); 157 frame_size_ = frame->size();
144 frame_dpi_ = dpi; 158 frame_dpi_ = dpi;
(...skipping 10 matching lines...) Expand all
155 weak_factory_.GetWeakPtr())); 169 weak_factory_.GetWeakPtr()));
156 } 170 }
157 171
158 void WebRtcFrameScheduler::CaptureNextFrame() { 172 void WebRtcFrameScheduler::CaptureNextFrame() {
159 DCHECK(thread_checker_.CalledOnValidThread()); 173 DCHECK(thread_checker_.CalledOnValidThread());
160 174
161 if (capture_pending_ || encode_pending_) { 175 if (capture_pending_ || encode_pending_) {
162 VLOG(1) << "Capture/encode still pending.."; 176 VLOG(1) << "Capture/encode still pending..";
163 return; 177 return;
164 } 178 }
179
165 capture_pending_ = true; 180 capture_pending_ = true;
166 VLOG(1) << "Capture next frame after " 181 VLOG(1) << "Capture next frame after "
167 << (base::TimeTicks::Now() - last_capture_started_ticks_) 182 << (base::TimeTicks::Now() - last_capture_started_ticks_)
168 .InMilliseconds(); 183 .InMilliseconds();
169 last_capture_started_ticks_ = base::TimeTicks::Now(); 184 last_capture_started_ticks_ = base::TimeTicks::Now();
170 capturer_->Capture(webrtc::DesktopRegion()); 185 capturer_->Capture(webrtc::DesktopRegion());
171 } 186 }
172 187
173 // static 188 // static
174 std::unique_ptr<VideoPacket> WebRtcFrameScheduler::EncodeFrame( 189 std::unique_ptr<VideoPacket> WebRtcFrameScheduler::EncodeFrame(
(...skipping 28 matching lines...) Expand all
203 encode_pending_ = false; 218 encode_pending_ = false;
204 if (!packet) 219 if (!packet)
205 return; 220 return;
206 last_quantizer_ = packet->quantizer(); 221 last_quantizer_ = packet->quantizer();
207 base::TimeTicks current = base::TimeTicks::Now(); 222 base::TimeTicks current = base::TimeTicks::Now();
208 uint32_t encoded_bits = packet->data().size() * 8.0; 223 uint32_t encoded_bits = packet->data().size() * 8.0;
209 224
210 // Simplistic adaptation of frame polling in the range 5 FPS to 30 FPS. 225 // Simplistic adaptation of frame polling in the range 5 FPS to 30 FPS.
211 uint32_t next_sched_ms = std::max( 226 uint32_t next_sched_ms = std::max(
212 33, std::min(static_cast<int>(encoded_bits / target_bitrate_kbps_), 200)); 227 33, std::min(static_cast<int>(encoded_bits / target_bitrate_kbps_), 200));
213 // TODO(isheriff): Investigate why first frame fails to send at times.
214 // This gets resolved through a PLI request.
215 if (webrtc_transport_->video_encoder_factory()->SendEncodedFrame( 228 if (webrtc_transport_->video_encoder_factory()->SendEncodedFrame(
216 std::move(packet)) >= 0) { 229 std::move(packet)) >= 0) {
217 VLOG(1) << " Send duration " 230 VLOG(1) << " Send duration "
218 << (base::TimeTicks::Now() - current).InMilliseconds() 231 << (base::TimeTicks::Now() - current).InMilliseconds()
219 << "next sched " << next_sched_ms; 232 << "next sched " << next_sched_ms;
220 } else { 233 } else {
221 LOG(ERROR) << "SendEncodedFrame() failed"; 234 LOG(ERROR) << "SendEncodedFrame() failed";
222 } 235 }
223 capture_timer_->Start(FROM_HERE, 236 capture_timer_->Start(FROM_HERE,
224 base::TimeDelta::FromMilliseconds(next_sched_ms), this, 237 base::TimeDelta::FromMilliseconds(next_sched_ms), this,
225 &WebRtcFrameScheduler::CaptureNextFrame); 238 &WebRtcFrameScheduler::CaptureNextFrame);
226 } 239 }
227 240
228 } // namespace protocol 241 } // namespace protocol
229 } // namespace remoting 242 } // namespace remoting
OLDNEW
« remoting/protocol/connection_unittest.cc ('K') | « remoting/protocol/webrtc_frame_scheduler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698