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_simple.h" | 5 #include "remoting/protocol/webrtc_frame_scheduler_simple.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" | 9 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" |
| 10 | 10 |
| 11 namespace remoting { | 11 namespace remoting { |
| 12 namespace protocol { | 12 namespace protocol { |
| 13 | 13 |
| 14 namespace { | 14 namespace { |
| 15 | 15 |
| 16 // Number of samples used to estimate processing time for the next frame. | |
| 17 const int kStatsWindow = 5; | |
| 18 | |
| 16 const int kTargetFrameRate = 30; | 19 const int kTargetFrameRate = 30; |
| 17 constexpr base::TimeDelta kTargetFrameInterval = | 20 constexpr base::TimeDelta kTargetFrameInterval = |
| 18 base::TimeDelta::FromMilliseconds(1000 / kTargetFrameRate); | 21 base::TimeDelta::FromMilliseconds(1000 / kTargetFrameRate); |
| 19 | 22 |
| 20 // Target quantizer at which stop the encoding top-off. | 23 // Target quantizer at which stop the encoding top-off. |
| 21 const int kTargetQuantizerForVp8TopOff = 30; | 24 const int kTargetQuantizerForVp8TopOff = 30; |
| 22 | 25 |
| 23 } // namespace | 26 } // namespace |
| 24 | 27 |
| 25 WebrtcFrameSchedulerSimple::WebrtcFrameSchedulerSimple() {} | 28 WebrtcFrameSchedulerSimple::WebrtcFrameSchedulerSimple() |
| 29 : frame_processing_delay_us_(kStatsWindow) {} | |
| 26 WebrtcFrameSchedulerSimple::~WebrtcFrameSchedulerSimple() {} | 30 WebrtcFrameSchedulerSimple::~WebrtcFrameSchedulerSimple() {} |
| 27 | 31 |
| 28 void WebrtcFrameSchedulerSimple::Start(const base::Closure& capture_callback) { | 32 void WebrtcFrameSchedulerSimple::Start(const base::Closure& capture_callback) { |
| 29 capture_callback_ = capture_callback; | 33 capture_callback_ = capture_callback; |
| 30 ScheduleNextFrame(); | 34 ScheduleNextFrame(); |
| 31 } | 35 } |
| 32 | 36 |
| 33 void WebrtcFrameSchedulerSimple::Pause(bool pause) { | 37 void WebrtcFrameSchedulerSimple::Pause(bool pause) { |
| 34 paused_ = pause; | 38 paused_ = pause; |
| 35 if (paused_) { | 39 if (paused_) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 75 | 79 |
| 76 void WebrtcFrameSchedulerSimple::OnFrameEncoded( | 80 void WebrtcFrameSchedulerSimple::OnFrameEncoded( |
| 77 const WebrtcVideoEncoder::EncodedFrame& encoded_frame, | 81 const WebrtcVideoEncoder::EncodedFrame& encoded_frame, |
| 78 const webrtc::EncodedImageCallback::Result& send_result) { | 82 const webrtc::EncodedImageCallback::Result& send_result) { |
| 79 if (encoded_frame.data.empty()) { | 83 if (encoded_frame.data.empty()) { |
| 80 top_off_is_active_ = false; | 84 top_off_is_active_ = false; |
| 81 ScheduleNextFrame(); | 85 ScheduleNextFrame(); |
| 82 return; | 86 return; |
| 83 } | 87 } |
| 84 | 88 |
| 89 frame_processing_delay_us_.Record( | |
| 90 (base::TimeTicks::Now() - last_capture_started_time_).InMicroseconds()); | |
| 91 | |
| 85 // Top-off until the target quantizer value is reached. | 92 // Top-off until the target quantizer value is reached. |
| 86 top_off_is_active_ = encoded_frame.quantizer > kTargetQuantizerForVp8TopOff; | 93 top_off_is_active_ = encoded_frame.quantizer > kTargetQuantizerForVp8TopOff; |
| 87 | 94 |
| 88 // Capture next frame after we finish sending the current one. | 95 // Capture next frame after we finish sending the current one. |
| 89 const double kKiloBitsPerByte = 8.0 / 1000.0; | 96 const double kKiloBitsPerByte = 8.0 / 1000.0; |
| 90 base::TimeDelta expected_send_delay = base::TimeDelta::FromSecondsD( | 97 base::TimeDelta expected_send_delay = base::TimeDelta::FromSecondsD( |
| 91 encoded_frame.data.size() * kKiloBitsPerByte / target_bitrate_kbps_); | 98 encoded_frame.data.size() * kKiloBitsPerByte / target_bitrate_kbps_); |
| 92 last_frame_send_finish_time_ = base::TimeTicks::Now() + expected_send_delay; | 99 last_frame_send_finish_time_ = base::TimeTicks::Now() + expected_send_delay; |
| 93 | 100 |
| 94 ScheduleNextFrame(); | 101 ScheduleNextFrame(); |
| 95 } | 102 } |
| 96 | 103 |
| 97 void WebrtcFrameSchedulerSimple::ScheduleNextFrame() { | 104 void WebrtcFrameSchedulerSimple::ScheduleNextFrame() { |
| 98 if (paused_) | 105 if (paused_) |
| 99 return; | 106 return; |
| 100 | 107 |
| 101 base::TimeTicks now = base::TimeTicks::Now(); | 108 base::TimeTicks now = base::TimeTicks::Now(); |
| 102 base::TimeDelta delay; | 109 base::TimeDelta delay; |
| 103 | 110 |
| 104 // If this is not the first frame then capture next frame after the previous | 111 // If this is not the first frame then capture next frame after the previous |
| 105 // one has finished sending. | 112 // one has finished sending. |
| 106 if (!last_frame_send_finish_time_.is_null()) { | 113 if (!last_frame_send_finish_time_.is_null()) { |
| 107 delay = std::max(base::TimeDelta(), last_frame_send_finish_time_ - now); | 114 base::TimeDelta expected_processing_time = |
| 115 base::TimeDelta::FromMicroseconds(frame_processing_delay_us_.Max()); | |
|
Irfan
2016/09/27 18:04:51
assigning expected value to Max() seems confusing.
Sergey Ulanov
2016/09/27 18:49:09
I think we want to approximate the upper bound of
| |
| 116 delay = std::max(base::TimeDelta(), last_frame_send_finish_time_ - | |
| 117 expected_processing_time - now); | |
| 108 } | 118 } |
| 109 | 119 |
| 110 // Cap interval between frames to kTargetFrameInterval. | 120 // Cap interval between frames to kTargetFrameInterval. |
| 111 if (!last_capture_started_time_.is_null()) { | 121 if (!last_capture_started_time_.is_null()) { |
| 112 delay = std::max(delay, | 122 delay = std::max(delay, |
| 113 last_capture_started_time_ + kTargetFrameInterval - now); | 123 last_capture_started_time_ + kTargetFrameInterval - now); |
| 114 } | 124 } |
| 115 | 125 |
| 116 capture_timer_.Start(FROM_HERE, delay, | 126 capture_timer_.Start(FROM_HERE, delay, |
| 117 base::Bind(&WebrtcFrameSchedulerSimple::CaptureNextFrame, | 127 base::Bind(&WebrtcFrameSchedulerSimple::CaptureNextFrame, |
| 118 base::Unretained(this))); | 128 base::Unretained(this))); |
| 119 } | 129 } |
| 120 | 130 |
| 121 void WebrtcFrameSchedulerSimple::CaptureNextFrame() { | 131 void WebrtcFrameSchedulerSimple::CaptureNextFrame() { |
| 122 last_capture_started_time_ = base::TimeTicks::Now(); | 132 last_capture_started_time_ = base::TimeTicks::Now(); |
| 123 capture_callback_.Run(); | 133 capture_callback_.Run(); |
| 124 } | 134 } |
| 125 | 135 |
| 126 } // namespace protocol | 136 } // namespace protocol |
| 127 } // namespace remoting | 137 } // namespace remoting |
| OLD | NEW |