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 (!buffers_[0]) { | |
36 return; | |
37 } | |
38 DCHECK(buffers_[0]->size().equals(buffers_[1]->size())); | |
39 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.
| |
40 webrtc::BasicDesktopFrame::CopyOf(*buffers_[0])); | |
41 webrtc::DesktopRect desktop_rect = | |
42 webrtc::DesktopRect::MakeSize(buffers_[0]->size()); | |
43 for (webrtc::DesktopRegion::Iterator i(buffer_1_mask_); !i.IsAtEnd(); | |
44 i.Advance()) { | |
45 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.
| |
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 | |
58 // Both buffers are reallocated whenever screen size changes. | |
59 if (!buffers_[0] || !buffers_[0]->size().equals(size)) { | |
60 buffers_[0] = webrtc::SharedDesktopFrame::Wrap( | |
61 base::WrapUnique(new webrtc::BasicDesktopFrame(size))); | |
62 buffers_[1] = webrtc::SharedDesktopFrame::Wrap( | |
63 base::WrapUnique(new webrtc::BasicDesktopFrame(size))); | |
64 buffer_1_mask_.Clear(); | |
65 current_buffer_ = 0; | |
66 } else { | |
67 current_buffer_ = (current_buffer_ + 1) % 2; | |
68 } | |
69 return buffers_[current_buffer_]->Share(); | |
70 } | |
71 | |
72 void DualBufferFrameConsumer::DrawFrame( | |
73 std::unique_ptr<webrtc::DesktopFrame> frame, | |
74 const base::Closure& done) { | |
75 DCHECK(thread_checker_.CalledOnValidThread()); | |
76 webrtc::SharedDesktopFrame* shared_frame = | |
77 reinterpret_cast<webrtc::SharedDesktopFrame*> (frame.get()); | |
78 if (shared_frame->GetUnderlyingFrame() == buffers_[1]->GetUnderlyingFrame()) { | |
79 buffer_1_mask_.AddRegion(frame->updated_region()); | |
80 } else if (shared_frame->GetUnderlyingFrame() == | |
81 buffers_[0]->GetUnderlyingFrame()) { | |
82 buffer_1_mask_.Subtract(frame->updated_region()); | |
83 } else { | |
84 // 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
| |
85 // with different resolution is received. In this case it is save to ignore | |
86 // the frame since a new full desktop frame will be received soon. | |
87 if (done) { | |
88 done.Run(); | |
89 } | |
90 return; | |
91 } | |
92 RunRenderCallback(std::move(frame), done); | |
93 } | |
94 | |
95 protocol::FrameConsumer::PixelFormat | |
96 DualBufferFrameConsumer::GetPixelFormat() { | |
97 return pixel_format_; | |
98 } | |
99 | |
100 base::WeakPtr<DualBufferFrameConsumer> DualBufferFrameConsumer::GetWeakPtr() { | |
101 return weak_ptr_; | |
102 } | |
103 | |
104 void DualBufferFrameConsumer::RunRenderCallback( | |
105 std::unique_ptr<webrtc::DesktopFrame> frame, | |
106 const base::Closure& done) { | |
107 if (!task_runner_) { | |
108 callback_.Run(std::move(frame)); | |
109 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.
| |
110 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.
| |
111 } | |
112 return; | |
113 } | |
114 task_runner_->PostTaskAndReply( | |
115 FROM_HERE, base::Bind(callback_, base::Passed(&frame)), | |
116 base::Bind(&DualBufferFrameConsumer::OnFrameRendered, GetWeakPtr(), | |
117 done)); | |
118 } | |
119 | |
120 void DualBufferFrameConsumer::OnFrameRendered(const base::Closure& done) { | |
121 DCHECK(thread_checker_.CalledOnValidThread()); | |
122 if (done) { | |
123 done.Run(); | |
124 } | |
125 } | |
126 | |
127 } // namespace remoting | |
OLD | NEW |