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/memory/ptr_util.h" | |
11 #include "remoting/base/util.h" | |
12 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" | |
13 #include "third_party/webrtc/modules/desktop_capture/shared_desktop_frame.h" | |
14 | |
15 namespace remoting { | |
16 | |
17 DualBufferFrameConsumer::DualBufferFrameConsumer( | |
18 base::Callback<void(std::unique_ptr<webrtc::DesktopFrame>)> callback, | |
19 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | |
20 protocol::FrameConsumer::PixelFormat format) | |
21 : callback_(callback), | |
22 task_runner_(task_runner), | |
23 pixel_format_(format), | |
24 weak_factory_(this) { | |
25 weak_ptr_ = weak_factory_.GetWeakPtr(); | |
26 thread_checker_.DetachFromThread(); | |
27 } | |
28 | |
29 DualBufferFrameConsumer::~DualBufferFrameConsumer() { | |
30 DCHECK(thread_checker_.CalledOnValidThread()); | |
31 } | |
32 | |
33 void DualBufferFrameConsumer::RequestFullDesktopFrame() { | |
34 DCHECK(thread_checker_.CalledOnValidThread()); | |
35 if (!buffer_0_) { | |
36 return; | |
37 } | |
38 DCHECK(buffer_0_->size().equals(buffer_1_->size())); | |
39 std::unique_ptr<webrtc::DesktopFrame> full_frame( | |
40 webrtc::BasicDesktopFrame::CopyOf(*buffer_0_)); | |
41 webrtc::DesktopRect desktop_rect = | |
42 webrtc::DesktopRect::MakeSize(buffer_0_->size()); | |
43 for (webrtc::DesktopRegion::Iterator i(buffer_1_mask_); !i.IsAtEnd(); | |
44 i.Advance()) { | |
45 CopyRGB32Rect(buffer_1_->data(), buffer_1_->stride(), desktop_rect, | |
46 full_frame->data(), full_frame->stride(), desktop_rect, | |
47 i.rect()); | |
48 } | |
49 full_frame->mutable_updated_region()->SetRect(desktop_rect); | |
50 | |
51 RunRenderCallback(std::move(full_frame), base::Closure()); | |
52 } | |
53 | |
54 std::unique_ptr<webrtc::DesktopFrame> DualBufferFrameConsumer::AllocateFrame( | |
55 const webrtc::DesktopSize& size) { | |
56 DCHECK(thread_checker_.CalledOnValidThread()); | |
57 if (!buffer_0_ || !buffer_0_->size().equals(size)) { | |
58 buffer_0_ = webrtc::SharedDesktopFrame::Wrap( | |
Sergey Ulanov
2016/07/20 18:39:26
add comment that both buffers are reallocated when
Yuwei
2016/07/21 00:07:32
Done.
| |
59 base::WrapUnique(new webrtc::BasicDesktopFrame(size))); | |
60 buffer_1_ = webrtc::SharedDesktopFrame::Wrap( | |
61 base::WrapUnique(new webrtc::BasicDesktopFrame(size))); | |
62 buffer_1_mask_.Clear(); | |
63 next_buffer_ = 0; | |
64 } | |
65 next_buffer_ = (next_buffer_ + 1) % 2; | |
Sergey Ulanov
2016/07/20 18:39:26
I think you want to synchronize buffers here (or m
Yuwei
2016/07/20 19:12:43
Do you mean that when rendering is slower than dec
| |
66 if (next_buffer_ == 0) { | |
Sergey Ulanov
2016/07/20 18:39:26
If you replace buffer_?_ with buffers_[] then this
Yuwei
2016/07/21 00:07:32
Done.
| |
67 return buffer_1_->Share(); | |
68 } else { | |
69 return buffer_0_->Share(); | |
70 } | |
71 } | |
72 | |
73 void DualBufferFrameConsumer::DrawFrame( | |
74 std::unique_ptr<webrtc::DesktopFrame> frame, | |
75 const base::Closure& done) { | |
76 DCHECK(thread_checker_.CalledOnValidThread()); | |
77 if ((reinterpret_cast<webrtc::SharedDesktopFrame*> (frame.get())) | |
Yuwei
2016/07/18 22:38:35
This assumes |frame| must come from AllocateFrame.
Sergey Ulanov
2016/07/20 18:39:26
Yes, this is a valid assumption. Caller must use A
Yuwei
2016/07/21 00:07:32
Acknowledged.
| |
78 ->GetUnderlyingFrame() == buffer_1_->GetUnderlyingFrame()) { | |
79 buffer_1_mask_.AddRegion(frame->updated_region()); | |
80 } else { | |
81 buffer_1_mask_.Subtract(frame->updated_region()); | |
82 } | |
83 RunRenderCallback(std::move(frame), done); | |
84 } | |
85 | |
86 protocol::FrameConsumer::PixelFormat | |
87 DualBufferFrameConsumer::GetPixelFormat() { | |
88 return pixel_format_; | |
89 } | |
90 | |
91 base::WeakPtr<DualBufferFrameConsumer> DualBufferFrameConsumer::GetWeakPtr() { | |
92 return weak_ptr_; | |
93 } | |
94 | |
95 void DualBufferFrameConsumer::RunRenderCallback( | |
96 std::unique_ptr<webrtc::DesktopFrame> frame, | |
97 const base::Closure& done) { | |
98 if (!task_runner_) { | |
99 callback_.Run(std::move(frame)); | |
100 done.Run(); | |
101 return; | |
102 } | |
103 task_runner_->PostTaskAndReply( | |
104 FROM_HERE, base::Bind(callback_, base::Passed(&frame)), | |
105 base::Bind(&DualBufferFrameConsumer::OnFrameRendered, GetWeakPtr(), | |
106 done)); | |
107 } | |
108 | |
109 void DualBufferFrameConsumer::OnFrameRendered(const base::Closure& done) { | |
110 DCHECK(thread_checker_.CalledOnValidThread()); | |
111 if (done) { | |
112 done.Run(); | |
113 } | |
114 } | |
115 | |
116 } // namespace remoting | |
OLD | NEW |