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

Unified Diff: remoting/client/dual_buffer_frame_consumer.cc

Issue 2156713002: [Chromoting] Implement DualBufferFrameConsumer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove deprecated SoftwareVideoRenderer ctor Created 4 years, 5 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/client/dual_buffer_frame_consumer.cc
diff --git a/remoting/client/dual_buffer_frame_consumer.cc b/remoting/client/dual_buffer_frame_consumer.cc
new file mode 100644
index 0000000000000000000000000000000000000000..3d2115806fb2aab3ba4a0fc8a4cc59bb70c37d33
--- /dev/null
+++ b/remoting/client/dual_buffer_frame_consumer.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/client/dual_buffer_frame_consumer.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/location.h"
+#include "base/memory/ptr_util.h"
+#include "remoting/base/util.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
+#include "third_party/webrtc/modules/desktop_capture/shared_desktop_frame.h"
+
+namespace remoting {
+
+DualBufferFrameConsumer::DualBufferFrameConsumer(
+ base::Callback<void(std::unique_ptr<webrtc::DesktopFrame>)> callback,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ protocol::FrameConsumer::PixelFormat format)
+ : callback_(callback),
+ task_runner_(task_runner),
+ pixel_format_(format),
+ weak_factory_(this) {
+ weak_ptr_ = weak_factory_.GetWeakPtr();
+ thread_checker_.DetachFromThread();
+}
+
+DualBufferFrameConsumer::~DualBufferFrameConsumer() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+}
+
+void DualBufferFrameConsumer::RequestFullDesktopFrame() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!buffers_[0]) {
+ return;
+ }
+ DCHECK(buffers_[0]->size().equals(buffers_[1]->size()));
+ std::unique_ptr<webrtc::DesktopFrame> full_frame(
Sergey Ulanov 2016/07/21 19:14:25 Add some comments to explain what happens here.
Yuwei 2016/07/22 03:38:22 Done.
+ webrtc::BasicDesktopFrame::CopyOf(*buffers_[0]));
+ webrtc::DesktopRect desktop_rect =
+ webrtc::DesktopRect::MakeSize(buffers_[0]->size());
+ for (webrtc::DesktopRegion::Iterator i(buffer_1_mask_); !i.IsAtEnd();
+ i.Advance()) {
+ CopyRGB32Rect(buffers_[0]->data(), buffers_[1]->stride(), desktop_rect,
Sergey Ulanov 2016/07/21 19:14:26 Please use DesktopFrame::CopyPixelsFrom().
Yuwei 2016/07/22 03:38:22 Done.
+ full_frame->data(), full_frame->stride(), desktop_rect,
+ i.rect());
+ }
+ full_frame->mutable_updated_region()->SetRect(desktop_rect);
+
+ RunRenderCallback(std::move(full_frame), base::Closure());
+}
+
+std::unique_ptr<webrtc::DesktopFrame> DualBufferFrameConsumer::AllocateFrame(
+ const webrtc::DesktopSize& size) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Both buffers are reallocated whenever screen size changes.
+ if (!buffers_[0] || !buffers_[0]->size().equals(size)) {
+ buffers_[0] = webrtc::SharedDesktopFrame::Wrap(
+ base::WrapUnique(new webrtc::BasicDesktopFrame(size)));
+ buffers_[1] = webrtc::SharedDesktopFrame::Wrap(
+ base::WrapUnique(new webrtc::BasicDesktopFrame(size)));
+ buffer_1_mask_.Clear();
+ current_buffer_ = 0;
+ } else {
+ current_buffer_ = (current_buffer_ + 1) % 2;
+ }
+ return buffers_[current_buffer_]->Share();
+}
+
+void DualBufferFrameConsumer::DrawFrame(
+ std::unique_ptr<webrtc::DesktopFrame> frame,
+ const base::Closure& done) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ webrtc::SharedDesktopFrame* shared_frame =
+ reinterpret_cast<webrtc::SharedDesktopFrame*> (frame.get());
+ if (shared_frame->GetUnderlyingFrame() == buffers_[1]->GetUnderlyingFrame()) {
+ buffer_1_mask_.AddRegion(frame->updated_region());
+ } else if (shared_frame->GetUnderlyingFrame() ==
+ buffers_[0]->GetUnderlyingFrame()) {
+ buffer_1_mask_.Subtract(frame->updated_region());
+ } else {
+ // This may happen if the resolution is changed but a previous shared frame
Sergey Ulanov 2016/07/21 19:14:25 Currently SoftwareVideoRenderer never processes mo
Yuwei 2016/07/22 03:38:22 Removed the else branch. The problem is that Soft
Sergey Ulanov 2016/07/22 18:04:19 Ugh. I was wrong when I wrote that SoftwareVideoRe
Yuwei 2016/07/22 18:35:15 I think the fact is that multiple frames can be pr
+ // with different resolution is received. In this case it is save to ignore
+ // the frame since a new full desktop frame will be received soon.
+ if (done) {
+ done.Run();
+ }
+ return;
+ }
+ RunRenderCallback(std::move(frame), done);
+}
+
+protocol::FrameConsumer::PixelFormat
+DualBufferFrameConsumer::GetPixelFormat() {
+ return pixel_format_;
+}
+
+base::WeakPtr<DualBufferFrameConsumer> DualBufferFrameConsumer::GetWeakPtr() {
+ return weak_ptr_;
+}
+
+void DualBufferFrameConsumer::RunRenderCallback(
+ std::unique_ptr<webrtc::DesktopFrame> frame,
+ const base::Closure& done) {
+ if (!task_runner_) {
+ callback_.Run(std::move(frame));
+ if (done) {
Sergey Ulanov 2016/07/21 19:14:26 I don't think you need this check. DrawFrame() sho
Yuwei 2016/07/22 03:38:22 Done. Removed.
+ done.Run();
Sergey Ulanov 2016/07/21 19:14:26 We cannot assume that the frame have been rendered
Yuwei 2016/07/21 20:00:41 I guess the measurement will be messed up if anoth
Sergey Ulanov 2016/07/21 20:22:48 To make it work correctly the renderer will need t
Yuwei 2016/07/22 03:38:22 Done.
+ }
+ return;
+ }
+ task_runner_->PostTaskAndReply(
+ FROM_HERE, base::Bind(callback_, base::Passed(&frame)),
+ base::Bind(&DualBufferFrameConsumer::OnFrameRendered, GetWeakPtr(),
+ done));
+}
+
+void DualBufferFrameConsumer::OnFrameRendered(const base::Closure& done) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (done) {
+ done.Run();
+ }
+}
+
+} // namespace remoting

Powered by Google App Engine
This is Rietveld 408576698