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