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

Side by Side Diff: remoting/host/capturer_gdi.cc

Issue 6780014: Clean up remoting project (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: got rid of ref counting on user authenticator Created 9 years, 8 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « remoting/host/capturer_gdi.h ('k') | remoting/host/capturer_gdi_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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/host/capturer_gdi.h"
6 #include "remoting/host/differ.h"
7
8 #include "ui/gfx/rect.h"
9
10 namespace remoting {
11
12 // 3780 pixels per meter is equivalent to 96 DPI, typical on desktop monitors.
13 static const int kPixelsPerMeter = 3780;
14 // 32 bit RGBA is 4 bytes per pixel.
15 static const int kBytesPerPixel = 4;
16
17 CapturerGdi::CapturerGdi()
18 : desktop_dc_(NULL),
19 memory_dc_(NULL),
20 dc_size_(0, 0),
21 current_buffer_(0),
22 pixel_format_(media::VideoFrame::RGB32),
23 capture_fullscreen_(true) {
24 memset(target_bitmap_, 0, sizeof(target_bitmap_));
25 memset(buffers_, 0, sizeof(buffers_));
26 ScreenConfigurationChanged();
27 }
28
29 CapturerGdi::~CapturerGdi() {
30 ReleaseBuffers();
31 }
32
33 media::VideoFrame::Format CapturerGdi::pixel_format() const {
34 return pixel_format_;
35 }
36
37 void CapturerGdi::ClearInvalidRects() {
38 helper.ClearInvalidRects();
39 }
40
41 void CapturerGdi::InvalidateRects(const InvalidRects& inval_rects) {
42 helper.InvalidateRects(inval_rects);
43 }
44
45 void CapturerGdi::InvalidateScreen(const gfx::Size& size) {
46 helper.InvalidateScreen(size);
47 }
48
49 void CapturerGdi::InvalidateFullScreen() {
50 helper.InvalidateFullScreen();
51 }
52
53 void CapturerGdi::CaptureInvalidRects(CaptureCompletedCallback* callback) {
54 CalculateInvalidRects();
55 InvalidRects inval_rects;
56 helper.SwapInvalidRects(inval_rects);
57 CaptureRects(inval_rects, callback);
58 }
59
60 const gfx::Size& CapturerGdi::size_most_recent() const {
61 return helper.size_most_recent();
62 }
63
64 void CapturerGdi::ReleaseBuffers() {
65 for (int i = kNumBuffers - 1; i >= 0; i--) {
66 if (target_bitmap_[i]) {
67 DeleteObject(target_bitmap_[i]);
68 target_bitmap_[i] = NULL;
69 }
70 if (buffers_[i].data) {
71 DeleteObject(buffers_[i].data);
72 buffers_[i].data = NULL;
73 }
74 }
75
76 desktop_dc_ = NULL;
77 if (memory_dc_) {
78 DeleteDC(memory_dc_);
79 memory_dc_ = NULL;
80 }
81 }
82
83 void CapturerGdi::ScreenConfigurationChanged() {
84 // We poll for screen configuration changes, so ignore notifications.
85 }
86
87 void CapturerGdi::UpdateBufferCapture(const gfx::Size& size) {
88 // Make sure the DCs have the correct dimensions.
89 if (size != dc_size_) {
90 // TODO(simonmorris): screen dimensions changing isn't equivalent to needing
91 // a new DC, but it's good enough for now.
92 desktop_dc_ = GetDC(GetDesktopWindow());
93 if (memory_dc_)
94 DeleteDC(memory_dc_);
95 memory_dc_ = CreateCompatibleDC(desktop_dc_);
96 dc_size_ = size;
97 }
98
99 // Make sure the current bitmap has the correct dimensions.
100 if (size != buffers_[current_buffer_].size) {
101 ReallocateBuffer(current_buffer_, size);
102 capture_fullscreen_ = true;
103 }
104 }
105
106 void CapturerGdi::ReallocateBuffer(int buffer_index, const gfx::Size& size) {
107 // Delete any previously constructed bitmap.
108 if (target_bitmap_[buffer_index]) {
109 DeleteObject(target_bitmap_[buffer_index]);
110 target_bitmap_[buffer_index] = NULL;
111 }
112 if (buffers_[buffer_index].data) {
113 DeleteObject(buffers_[buffer_index].data);
114 buffers_[buffer_index].data = NULL;
115 }
116
117 // Create a bitmap to keep the desktop image.
118 int rounded_width = (size.width() + 3) & (~3);
119
120 // Dimensions of screen.
121 pixel_format_ = media::VideoFrame::RGB32;
122 int bytes_per_row = rounded_width * kBytesPerPixel;
123
124 // Create a device independent bitmap (DIB) that is the same size.
125 BITMAPINFO bmi;
126 memset(&bmi, 0, sizeof(bmi));
127 bmi.bmiHeader.biHeight = -size.height();
128 bmi.bmiHeader.biWidth = size.width();
129 bmi.bmiHeader.biPlanes = 1;
130 bmi.bmiHeader.biBitCount = kBytesPerPixel * 8;
131 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
132 bmi.bmiHeader.biSizeImage = bytes_per_row * size.height();
133 bmi.bmiHeader.biXPelsPerMeter = kPixelsPerMeter;
134 bmi.bmiHeader.biYPelsPerMeter = kPixelsPerMeter;
135
136 // Create memory for the buffers.
137 target_bitmap_[buffer_index] =
138 CreateDIBSection(desktop_dc_, &bmi, DIB_RGB_COLORS,
139 static_cast<void**>(&buffers_[buffer_index].data),
140 NULL, 0);
141 buffers_[buffer_index].size = gfx::Size(bmi.bmiHeader.biWidth,
142 std::abs(bmi.bmiHeader.biHeight));
143 buffers_[buffer_index].bytes_per_pixel = bmi.bmiHeader.biBitCount / 8;
144 buffers_[buffer_index].bytes_per_row =
145 bmi.bmiHeader.biSizeImage / std::abs(bmi.bmiHeader.biHeight);
146 }
147
148 void CapturerGdi::CalculateInvalidRects() {
149 CaptureImage();
150
151 const VideoFrameBuffer& current = buffers_[current_buffer_];
152 if (helper.IsCaptureFullScreen(current.size))
153 capture_fullscreen_ = true;
154
155 if (capture_fullscreen_) {
156 InvalidateScreen(current.size);
157 capture_fullscreen_ = false;
158 return;
159 }
160
161 // Find the previous and current screens.
162 int prev_buffer_id = current_buffer_ - 1;
163 if (prev_buffer_id < 0) {
164 prev_buffer_id = kNumBuffers - 1;
165 }
166 const VideoFrameBuffer& prev = buffers_[prev_buffer_id];
167
168 // Maybe the previous and current screens can't be differenced.
169 if ((current.size != prev.size) ||
170 (current.bytes_per_pixel != prev.bytes_per_pixel) ||
171 (current.bytes_per_row != prev.bytes_per_row)) {
172 InvalidateScreen(current.size);
173 return;
174 }
175
176 // Make sure the differencer is set up correctly for these previous and
177 // current screens.
178 if (!differ_.get() ||
179 (differ_->width() != current.size.width()) ||
180 (differ_->height() != current.size.height()) ||
181 (differ_->bytes_per_pixel() != current.bytes_per_pixel) ||
182 (differ_->bytes_per_row() != current.bytes_per_row)) {
183 differ_.reset(new Differ(current.size.width(), current.size.height(),
184 current.bytes_per_pixel, current.bytes_per_row));
185 }
186
187 InvalidRects rects;
188 differ_->CalcDirtyRects(prev.data, current.data, &rects);
189
190 InvalidateRects(rects);
191 }
192
193 void CapturerGdi::CaptureRects(const InvalidRects& rects,
194 CaptureCompletedCallback* callback) {
195 scoped_ptr<CaptureCompletedCallback> callback_deleter(callback);
196
197 const VideoFrameBuffer& buffer = buffers_[current_buffer_];
198 current_buffer_ = (current_buffer_ + 1) % kNumBuffers;
199
200 DataPlanes planes;
201 planes.data[0] = static_cast<uint8*>(buffer.data);
202 planes.strides[0] = buffer.bytes_per_row;
203
204 scoped_refptr<CaptureData> data(new CaptureData(planes,
205 buffer.size,
206 pixel_format_));
207 data->mutable_dirty_rects() = rects;
208
209 helper.set_size_most_recent(data->size());
210
211 callback->Run(data);
212 }
213
214 void CapturerGdi::CaptureImage() {
215 // Make sure the structures we use to capture the image have the correct size.
216 UpdateBufferCapture(GetScreenSize());
217
218 // Select the target bitmap into the memory dc.
219 SelectObject(memory_dc_, target_bitmap_[current_buffer_]);
220
221 // And then copy the rect from desktop to memory.
222 BitBlt(memory_dc_, 0, 0, buffers_[current_buffer_].size.width(),
223 buffers_[current_buffer_].size.height(), desktop_dc_, 0, 0,
224 SRCCOPY | CAPTUREBLT);
225 }
226
227 gfx::Size CapturerGdi::GetScreenSize() {
228 return gfx::Size(GetSystemMetrics(SM_CXSCREEN),
229 GetSystemMetrics(SM_CYSCREEN));
230 }
231
232 // static
233 Capturer* Capturer::Create() {
234 return new CapturerGdi();
235 }
236
237 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/capturer_gdi.h ('k') | remoting/host/capturer_gdi_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698