OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "remoting/client/dual_buffer_frame_consumer.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" |
| 9 #include "base/location.h" |
| 10 #include "base/logging.h" |
| 11 #include "base/memory/ptr_util.h" |
| 12 #include "base/threading/thread_task_runner_handle.h" |
| 13 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" |
| 14 #include "third_party/webrtc/modules/desktop_capture/shared_desktop_frame.h" |
| 15 |
| 16 namespace remoting { |
| 17 |
| 18 DualBufferFrameConsumer::DualBufferFrameConsumer( |
| 19 const RenderCallback& callback, |
| 20 scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
| 21 protocol::FrameConsumer::PixelFormat format) |
| 22 : callback_(callback), |
| 23 task_runner_(task_runner), |
| 24 pixel_format_(format), |
| 25 weak_factory_(this) { |
| 26 weak_ptr_ = weak_factory_.GetWeakPtr(); |
| 27 thread_checker_.DetachFromThread(); |
| 28 } |
| 29 |
| 30 DualBufferFrameConsumer::~DualBufferFrameConsumer() { |
| 31 DCHECK(thread_checker_.CalledOnValidThread()); |
| 32 } |
| 33 |
| 34 void DualBufferFrameConsumer::RequestFullDesktopFrame() { |
| 35 DCHECK(thread_checker_.CalledOnValidThread()); |
| 36 if (!buffers_[0]) { |
| 37 return; |
| 38 } |
| 39 DCHECK(buffers_[0]->size().equals(buffers_[1]->size())); |
| 40 // This creates a copy of buffers_[0] and merges area defined in |
| 41 // |buffer_1_mask_| from buffers_[1] into the copy. |
| 42 std::unique_ptr<webrtc::DesktopFrame> full_frame( |
| 43 webrtc::BasicDesktopFrame::CopyOf(*buffers_[0])); |
| 44 webrtc::DesktopRect desktop_rect = |
| 45 webrtc::DesktopRect::MakeSize(buffers_[0]->size()); |
| 46 for (webrtc::DesktopRegion::Iterator i(buffer_1_mask_); !i.IsAtEnd(); |
| 47 i.Advance()) { |
| 48 full_frame->CopyPixelsFrom(*buffers_[1], i.rect().top_left(), |
| 49 i.rect()); |
| 50 } |
| 51 full_frame->mutable_updated_region()->SetRect(desktop_rect); |
| 52 |
| 53 RunRenderCallback(std::move(full_frame), base::Bind(&base::DoNothing)); |
| 54 } |
| 55 |
| 56 std::unique_ptr<webrtc::DesktopFrame> DualBufferFrameConsumer::AllocateFrame( |
| 57 const webrtc::DesktopSize& size) { |
| 58 DCHECK(thread_checker_.CalledOnValidThread()); |
| 59 |
| 60 // Both buffers are reallocated whenever screen size changes. |
| 61 if (!buffers_[0] || !buffers_[0]->size().equals(size)) { |
| 62 buffers_[0] = webrtc::SharedDesktopFrame::Wrap( |
| 63 base::WrapUnique(new webrtc::BasicDesktopFrame(size))); |
| 64 buffers_[1] = webrtc::SharedDesktopFrame::Wrap( |
| 65 base::WrapUnique(new webrtc::BasicDesktopFrame(size))); |
| 66 buffer_1_mask_.Clear(); |
| 67 current_buffer_ = 0; |
| 68 } else { |
| 69 current_buffer_ = (current_buffer_ + 1) % 2; |
| 70 } |
| 71 return buffers_[current_buffer_]->Share(); |
| 72 } |
| 73 |
| 74 void DualBufferFrameConsumer::DrawFrame( |
| 75 std::unique_ptr<webrtc::DesktopFrame> frame, |
| 76 const base::Closure& done) { |
| 77 DCHECK(thread_checker_.CalledOnValidThread()); |
| 78 webrtc::SharedDesktopFrame* shared_frame = |
| 79 reinterpret_cast<webrtc::SharedDesktopFrame*> (frame.get()); |
| 80 if (shared_frame->GetUnderlyingFrame() == buffers_[1]->GetUnderlyingFrame()) { |
| 81 buffer_1_mask_.AddRegion(frame->updated_region()); |
| 82 } else if (shared_frame->GetUnderlyingFrame() == |
| 83 buffers_[0]->GetUnderlyingFrame()) { |
| 84 buffer_1_mask_.Subtract(frame->updated_region()); |
| 85 } |
| 86 RunRenderCallback(std::move(frame), done); |
| 87 } |
| 88 |
| 89 protocol::FrameConsumer::PixelFormat |
| 90 DualBufferFrameConsumer::GetPixelFormat() { |
| 91 return pixel_format_; |
| 92 } |
| 93 |
| 94 base::WeakPtr<DualBufferFrameConsumer> DualBufferFrameConsumer::GetWeakPtr() { |
| 95 return weak_ptr_; |
| 96 } |
| 97 |
| 98 void DualBufferFrameConsumer::RunRenderCallback( |
| 99 std::unique_ptr<webrtc::DesktopFrame> frame, |
| 100 const base::Closure& done) { |
| 101 if (!task_runner_) { |
| 102 callback_.Run(std::move(frame), done); |
| 103 return; |
| 104 } |
| 105 |
| 106 task_runner_->PostTask( |
| 107 FROM_HERE, base::Bind(callback_, base::Passed(&frame), base::Bind( |
| 108 base::IgnoreResult(&base::TaskRunner::PostTask), |
| 109 base::ThreadTaskRunnerHandle::Get(), FROM_HERE, done))); |
| 110 } |
| 111 |
| 112 } // namespace remoting |
OLD | NEW |