OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "remoting/protocol/webrtc_capture_scheduler_simple.h" |
| 6 |
| 7 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" |
| 8 |
| 9 namespace remoting { |
| 10 namespace protocol { |
| 11 |
| 12 namespace { |
| 13 |
| 14 const int kTargetFrameRate = 30; |
| 15 constexpr base::TimeDelta kTargetFrameInterval = |
| 16 base::TimeDelta::FromMilliseconds(1000 / kTargetFrameRate); |
| 17 |
| 18 // Target quantizer at which stop the encoding top-off. |
| 19 const int kTargetQuantizerForVp8TopOff = 30; |
| 20 |
| 21 } // namespace |
| 22 |
| 23 WebrtcCaptureSchedulerSimple::WebrtcCaptureSchedulerSimple() {} |
| 24 WebrtcCaptureSchedulerSimple::~WebrtcCaptureSchedulerSimple() {} |
| 25 |
| 26 void WebrtcCaptureSchedulerSimple::Start( |
| 27 const base::Closure& capture_callback) { |
| 28 capture_callback_ = capture_callback; |
| 29 ScheduleNextFrame(); |
| 30 } |
| 31 |
| 32 void WebrtcCaptureSchedulerSimple::Pause(bool pause) { |
| 33 paused_ = pause; |
| 34 if (paused_) { |
| 35 capture_timer_.Stop(); |
| 36 } else if (!capture_callback_.is_null()) { |
| 37 ScheduleNextFrame(); |
| 38 } |
| 39 } |
| 40 |
| 41 void WebrtcCaptureSchedulerSimple::SetKeyFrameRequest() { |
| 42 key_frame_request_ = true; |
| 43 } |
| 44 |
| 45 void WebrtcCaptureSchedulerSimple::SetTargetBitrate(int bitrate_kbps) { |
| 46 target_bitrate_kbps_ = bitrate_kbps; |
| 47 } |
| 48 |
| 49 bool WebrtcCaptureSchedulerSimple::GetEncoderFrameParams( |
| 50 const webrtc::DesktopFrame& frame, |
| 51 WebrtcVideoEncoder::FrameParams* params_out) { |
| 52 if (frame.updated_region().is_empty() && !top_off_is_active_ && |
| 53 !key_frame_request_) { |
| 54 ScheduleNextFrame(); |
| 55 return false; |
| 56 } |
| 57 |
| 58 params_out->bitrate_kbps = target_bitrate_kbps_; |
| 59 |
| 60 // TODO(sergeyu): Currently duration is always set to 1/15 of a second. |
| 61 // Experiment with different values, and try changing it dynamically. |
| 62 params_out->duration = base::TimeDelta::FromSeconds(1) / 15; |
| 63 |
| 64 params_out->key_frame = key_frame_request_; |
| 65 key_frame_request_ = false; |
| 66 |
| 67 params_out->vpx_min_quantizer = 10; |
| 68 params_out->vpx_max_quantizer = 63; |
| 69 |
| 70 params_out->clear_active_map = !top_off_is_active_; |
| 71 |
| 72 return true; |
| 73 } |
| 74 |
| 75 void WebrtcCaptureSchedulerSimple::OnFrameEncoded( |
| 76 const WebrtcVideoEncoder::EncodedFrame& encoded_frame, |
| 77 const webrtc::EncodedImageCallback::Result& send_result) { |
| 78 if (encoded_frame.data.empty()) { |
| 79 top_off_is_active_ = false; |
| 80 ScheduleNextFrame(); |
| 81 return; |
| 82 } |
| 83 |
| 84 // Top-off until the target quantizer value is reached. |
| 85 top_off_is_active_ = encoded_frame.quantizer > kTargetQuantizerForVp8TopOff; |
| 86 |
| 87 // Capture next frame after we finish sending the current one. |
| 88 const double kKiloBitsPerByte = 8.0 / 1000.0; |
| 89 base::TimeDelta expected_send_delay = base::TimeDelta::FromSecondsD( |
| 90 encoded_frame.data.size() * kKiloBitsPerByte / target_bitrate_kbps_); |
| 91 last_frame_send_finish_time_ = base::TimeTicks::Now() + expected_send_delay; |
| 92 |
| 93 ScheduleNextFrame(); |
| 94 } |
| 95 |
| 96 void WebrtcCaptureSchedulerSimple::ScheduleNextFrame() { |
| 97 if (paused_) |
| 98 return; |
| 99 |
| 100 base::TimeTicks now = base::TimeTicks::Now(); |
| 101 base::TimeDelta delay; |
| 102 |
| 103 // If this is not the first frame then capture next frame after the previous |
| 104 // one has finished sending. |
| 105 if (!last_frame_send_finish_time_.is_null()) { |
| 106 delay = std::max(base::TimeDelta(), last_frame_send_finish_time_ - now); |
| 107 } |
| 108 |
| 109 // Cap interval between frames to kTargetFrameInterval. |
| 110 if (!last_capture_started_time_.is_null()) { |
| 111 delay = std::max(delay, |
| 112 last_capture_started_time_ + kTargetFrameInterval - now); |
| 113 } |
| 114 |
| 115 capture_timer_.Start( |
| 116 FROM_HERE, delay, |
| 117 base::Bind(&WebrtcCaptureSchedulerSimple::CaptureNextFrame, |
| 118 base::Unretained(this))); |
| 119 } |
| 120 |
| 121 void WebrtcCaptureSchedulerSimple::CaptureNextFrame() { |
| 122 last_capture_started_time_ = base::TimeTicks::Now(); |
| 123 capture_callback_.Run(); |
| 124 } |
| 125 |
| 126 } // namespace protocol |
| 127 } // namespace remoting |
OLD | NEW |