Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Unified Diff: remoting/protocol/webrtc_capture_scheduler_simple.cc

Issue 2335923002: Add WebrtcCaptureScheduler interface. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: remoting/protocol/webrtc_capture_scheduler_simple.cc
diff --git a/remoting/protocol/webrtc_capture_scheduler_simple.cc b/remoting/protocol/webrtc_capture_scheduler_simple.cc
new file mode 100644
index 0000000000000000000000000000000000000000..5b7138ca4216c1b280b4cbcbf848d5cf224f5fe3
--- /dev/null
+++ b/remoting/protocol/webrtc_capture_scheduler_simple.cc
@@ -0,0 +1,127 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/protocol/webrtc_capture_scheduler_simple.h"
+
+#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
+
+namespace remoting {
+namespace protocol {
+
+namespace {
+
+const int kTargetFrameRate = 30;
+constexpr base::TimeDelta kTargetFrameInterval =
+ base::TimeDelta::FromMilliseconds(1000 / kTargetFrameRate);
+
+// Target quantizer at which stop the encoding top-off.
+const int kTargetQuantizerForVp8TopOff = 30;
+
+} // namespace
+
+WebrtcCaptureSchedulerSimple::WebrtcCaptureSchedulerSimple() {}
+WebrtcCaptureSchedulerSimple::~WebrtcCaptureSchedulerSimple() {}
+
+void WebrtcCaptureSchedulerSimple::Start(
+ const base::Closure& capture_callback) {
+ capture_callback_ = capture_callback;
+ ScheduleNextFrame();
+}
+
+void WebrtcCaptureSchedulerSimple::Pause(bool pause) {
+ paused_ = pause;
+ if (paused_) {
+ capture_timer_.Stop();
+ } else if (!capture_callback_.is_null()) {
+ ScheduleNextFrame();
+ }
+}
+
+void WebrtcCaptureSchedulerSimple::SetKeyFrameRequest() {
+ key_frame_request_ = true;
+}
+
+void WebrtcCaptureSchedulerSimple::SetTargetBitrate(int bitrate_kbps) {
+ target_bitrate_kbps_ = bitrate_kbps;
+}
+
+bool WebrtcCaptureSchedulerSimple::GetEncoderFrameParams(
+ const webrtc::DesktopFrame& frame,
+ WebrtcVideoEncoder::FrameParams* params_out) {
+ if (frame.updated_region().is_empty() && !top_off_is_active_ &&
+ !key_frame_request_) {
+ ScheduleNextFrame();
+ return false;
+ }
+
+ params_out->bitrate_kbps = target_bitrate_kbps_;
+
+ // TODO(sergeyu): Currently duration is always set to 1/15 of a second.
+ // Experiment with different values, and try changing it dynamically.
+ params_out->duration = base::TimeDelta::FromSeconds(1) / 15;
+
+ params_out->key_frame = key_frame_request_;
+ key_frame_request_ = false;
+
+ params_out->vpx_min_quantizer = 10;
+ params_out->vpx_max_quantizer = 63;
+
+ params_out->clear_active_map = !top_off_is_active_;
+
+ return true;
+}
+
+void WebrtcCaptureSchedulerSimple::OnFrameEncoded(
+ const WebrtcVideoEncoder::EncodedFrame& encoded_frame,
+ const webrtc::EncodedImageCallback::Result& send_result) {
+ if (encoded_frame.data.empty()) {
+ top_off_is_active_ = false;
+ ScheduleNextFrame();
+ return;
+ }
+
+ // Top-off until the target quantizer value is reached.
+ top_off_is_active_ = encoded_frame.quantizer > kTargetQuantizerForVp8TopOff;
+
+ // Capture next frame after we finish sending the current one.
+ const double kKiloBitsPerByte = 8.0 / 1000.0;
+ base::TimeDelta expected_send_delay = base::TimeDelta::FromSecondsD(
+ encoded_frame.data.size() * kKiloBitsPerByte / target_bitrate_kbps_);
+ last_frame_send_finish_time_ = base::TimeTicks::Now() + expected_send_delay;
+
+ ScheduleNextFrame();
+}
+
+void WebrtcCaptureSchedulerSimple::ScheduleNextFrame() {
+ if (paused_)
+ return;
+
+ base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeDelta delay;
+
+ // If this is not the first frame then capture next frame after the previous
+ // one has finished sending.
+ if (!last_frame_send_finish_time_.is_null()) {
+ delay = std::max(base::TimeDelta(), last_frame_send_finish_time_ - now);
+ }
+
+ // Cap interval between frames to kTargetFrameInterval.
+ if (!last_capture_started_time_.is_null()) {
+ delay = std::max(delay,
+ last_capture_started_time_ + kTargetFrameInterval - now);
+ }
+
+ capture_timer_.Start(
+ FROM_HERE, delay,
+ base::Bind(&WebrtcCaptureSchedulerSimple::CaptureNextFrame,
+ base::Unretained(this)));
+}
+
+void WebrtcCaptureSchedulerSimple::CaptureNextFrame() {
+ last_capture_started_time_ = base::TimeTicks::Now();
+ capture_callback_.Run();
+}
+
+} // namespace protocol
+} // namespace remoting

Powered by Google App Engine
This is Rietveld 408576698