Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |