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 |