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

Unified Diff: remoting/protocol/webrtc_frame_scheduler_simple.cc

Issue 2335923002: Add WebrtcCaptureScheduler interface. (Closed)
Patch Set: include <algorithm> 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
« no previous file with comments | « remoting/protocol/webrtc_frame_scheduler_simple.h ('k') | remoting/protocol/webrtc_video_stream.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/protocol/webrtc_frame_scheduler_simple.cc
diff --git a/remoting/protocol/webrtc_frame_scheduler_simple.cc b/remoting/protocol/webrtc_frame_scheduler_simple.cc
new file mode 100644
index 0000000000000000000000000000000000000000..daedb6f3aa3d2afdc6fe737756347b3d29708790
--- /dev/null
+++ b/remoting/protocol/webrtc_frame_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_frame_scheduler_simple.h"
+
+#include <algorithm>
+
+#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
+
+WebrtcFrameSchedulerSimple::WebrtcFrameSchedulerSimple() {}
+WebrtcFrameSchedulerSimple::~WebrtcFrameSchedulerSimple() {}
+
+void WebrtcFrameSchedulerSimple::Start(const base::Closure& capture_callback) {
+ capture_callback_ = capture_callback;
+ ScheduleNextFrame();
+}
+
+void WebrtcFrameSchedulerSimple::Pause(bool pause) {
+ paused_ = pause;
+ if (paused_) {
+ capture_timer_.Stop();
+ } else if (!capture_callback_.is_null()) {
+ ScheduleNextFrame();
+ }
+}
+
+void WebrtcFrameSchedulerSimple::SetKeyFrameRequest() {
+ key_frame_request_ = true;
+}
+
+void WebrtcFrameSchedulerSimple::SetTargetBitrate(int bitrate_kbps) {
+ target_bitrate_kbps_ = bitrate_kbps;
+}
+
+bool WebrtcFrameSchedulerSimple::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 WebrtcFrameSchedulerSimple::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 WebrtcFrameSchedulerSimple::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(&WebrtcFrameSchedulerSimple::CaptureNextFrame,
+ base::Unretained(this)));
+}
+
+void WebrtcFrameSchedulerSimple::CaptureNextFrame() {
+ last_capture_started_time_ = base::TimeTicks::Now();
+ capture_callback_.Run();
+}
+
+} // namespace protocol
+} // namespace remoting
« no previous file with comments | « remoting/protocol/webrtc_frame_scheduler_simple.h ('k') | remoting/protocol/webrtc_video_stream.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698