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

Unified Diff: remoting/protocol/webrtc_frame_scheduler.cc

Issue 1846893002: Interface with webrtc through encoded frames (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 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_frame_scheduler.cc
diff --git a/remoting/protocol/webrtc_frame_scheduler.cc b/remoting/protocol/webrtc_frame_scheduler.cc
new file mode 100644
index 0000000000000000000000000000000000000000..fbbc7d537b2811745c7ec562d92f6d21575a2731
--- /dev/null
+++ b/remoting/protocol/webrtc_frame_scheduler.cc
@@ -0,0 +1,159 @@
+// 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.h"
+
+#include "base/logging.h"
+#include "remoting/proto/video.pb.h"
+
+namespace remoting {
+namespace protocol {
+
+// The frame scheduler currently uses a simple polling technique
+// at 30 FPS to capture, encode and send frames over webrtc transport.
+// An improved solution will use target bitrate feedback to pace out
+// the capture rate.
+WebRtcFrameScheduler::WebRtcFrameScheduler(
+ scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner,
+ scoped_ptr<webrtc::DesktopCapturer> capturer,
+ WebrtcTransport* webrtc_transport,
+ scoped_ptr<VideoEncoder> encoder)
+ : key_frame_request_(false),
Sergey Ulanov 2016/03/31 22:06:19 initialize boolean values in the header please.
Irfan 2016/04/05 21:23:27 Done.
+ capture_pending_(false),
+ encode_pending_(false),
+ encode_task_runner_(encode_task_runner),
+ capturer_(std::move(capturer)),
+ webrtc_transport_(webrtc_transport),
+ encoder_(std::move(encoder)),
+ weak_factory_(this) {
+ DCHECK(encode_task_runner_);
+ DCHECK(capturer_);
+ DCHECK(webrtc_transport_);
+ DCHECK(encoder_);
+ // Does not really start anything. Registers callback on this class.
+ capturer_->Start(this);
+ capture_timer_.reset(new base::RepeatingTimer());
+
+ // Register for PLI requests.
+ webrtc_transport_->video_encoder_factory()->SetKeyFrameRequestCallback(
+ base::Bind(&WebRtcFrameScheduler::SetKeyFrameRequest,
+ base::Unretained(this)));
+}
+
+WebRtcFrameScheduler::~WebRtcFrameScheduler() {
+ encode_task_runner_->DeleteSoon(FROM_HERE, encoder_.release());
+}
+
+void WebRtcFrameScheduler::Start() {
+ capture_timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(1) / 30, this,
+ &WebRtcFrameScheduler::CaptureNextFrame);
+}
+
+void WebRtcFrameScheduler::Stop() {
+ // Cancel any pending encode.
+ task_tracker_.TryCancelAll();
+ capture_timer_->Stop();
+}
+
+void WebRtcFrameScheduler::SetSizeCallback(const SizeCallback& callback) {
+ size_callback_ = callback;
+}
+
+void WebRtcFrameScheduler::SetKeyFrameRequest() {
+ VLOG(1) << "Request key frame";
+ base::AutoLock lock(lock_);
+ key_frame_request_ = true;
+}
+
+bool WebRtcFrameScheduler::ClearAndGetKeyFrameRequest() {
+ base::AutoLock lock(lock_);
+ bool key_frame_request = key_frame_request_;
+ key_frame_request_ = false;
+ return key_frame_request;
+}
+
+webrtc::SharedMemory* WebRtcFrameScheduler::CreateSharedMemory(size_t size) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return nullptr;
+}
+
+void WebRtcFrameScheduler::OnCaptureCompleted(webrtc::DesktopFrame* frame) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ VLOG(1) << "Capture overhead "
+ << (base::TimeTicks::Now() - last_capture_ticks_).InMilliseconds();
+ capture_pending_ = false;
+
+ scoped_ptr<webrtc::DesktopFrame> owned_frame(frame);
+
+ if (encode_pending_) {
+ // TODO(isheriff): consider queuing here
+ VLOG(1) << "Dropping captured frame since encoder is still busy";
+ return;
+ }
+ if (!frame || frame->updated_region().is_empty())
+ return;
+
+ if (!frame_size_.equals(frame->size())) {
+ frame_size_ = frame->size();
+ size_callback_.Run(frame_size_);
+ }
+ encode_pending_ = true;
+ task_tracker_.PostTaskAndReply(
+ encode_task_runner_.get(), FROM_HERE,
+ base::Bind(&WebRtcFrameScheduler::EncodeFrame, base::Unretained(this),
Sergey Ulanov 2016/03/31 22:06:19 I don't think base::Unretained() is safe here. The
Irfan 2016/04/05 21:23:27 Done.
+ base::Passed(std::move(owned_frame))),
+ base::Bind(&WebRtcFrameScheduler::OnFrameEncoded,
+ weak_factory_.GetWeakPtr()));
+}
+
+void WebRtcFrameScheduler::CaptureNextFrame() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (capture_pending_ || encode_pending_) {
+ VLOG(1) << "Capture/encode still pending..";
+ return;
+ }
+ capture_pending_ = true;
+ VLOG(1) << "Capture next frame after "
+ << (base::TimeTicks::Now() - last_capture_ticks_).InMilliseconds();
+ last_capture_ticks_ = base::TimeTicks::Now();
+ capturer_->Capture(webrtc::DesktopRegion());
+}
+
+void WebRtcFrameScheduler::EncodeFrame(scoped_ptr<webrtc::DesktopFrame> frame) {
+ base::TimeTicks current = base::TimeTicks::Now();
+ uint32_t flags = 0;
+ if (ClearAndGetKeyFrameRequest())
+ flags |= VideoEncoder::kRequestKeyFrame;
+
+ scoped_ptr<VideoPacket> packet = encoder_->Encode(*frame, flags);
+ if (!packet) {
Sergey Ulanov 2016/03/31 22:06:19 nit: remove brackets for consistency with other si
Irfan 2016/04/05 21:23:27 Done.
+ return;
+ }
+ VLOG(1) << "Encode duration "
+ << (base::TimeTicks::Now() - current).InMilliseconds()
+ << " payload size " << packet->data().size();
+ int64_t capture_timestamp_ms =
+ (base::TimeTicks::Now() - base::TimeTicks()).InMilliseconds();
+ current = base::TimeTicks::Now();
+
+ // TODO(isheriff): Investigate why first frame fails to send at times.
+ // This gets resolved through a PLI request.
+ webrtc_transport_->video_encoder_factory()->SendEncodedFrame(
+ capture_timestamp_ms,
+ reinterpret_cast<uint8_t*>(const_cast<char*>(packet->data().data())),
+ packet->data().size(), packet->format().screen_width(),
+ packet->format().screen_height(), packet->key_frame());
+ VLOG(1) << "Send duration "
+ << (base::TimeTicks::Now() - current).InMilliseconds();
+}
+
+void WebRtcFrameScheduler::OnFrameEncoded() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ encode_pending_ = false;
+}
+
+} // namespace protocol
+} // namespace remoting

Powered by Google App Engine
This is Rietveld 408576698