OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/host/video_frame_capturer.h" | 5 #include "remoting/host/video_frame_capturer.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 | 8 |
9 #include "base/file_path.h" | 9 #include "base/file_path.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 virtual void Start(const CursorShapeChangedCallback& callback) OVERRIDE; | 50 virtual void Start(const CursorShapeChangedCallback& callback) OVERRIDE; |
51 virtual void Stop() OVERRIDE; | 51 virtual void Stop() OVERRIDE; |
52 virtual media::VideoFrame::Format pixel_format() const OVERRIDE; | 52 virtual media::VideoFrame::Format pixel_format() const OVERRIDE; |
53 virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE; | 53 virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE; |
54 virtual void CaptureInvalidRegion( | 54 virtual void CaptureInvalidRegion( |
55 const CaptureCompletedCallback& callback) OVERRIDE; | 55 const CaptureCompletedCallback& callback) OVERRIDE; |
56 virtual const SkISize& size_most_recent() const OVERRIDE; | 56 virtual const SkISize& size_most_recent() const OVERRIDE; |
57 | 57 |
58 private: | 58 private: |
59 struct VideoFrameBuffer { | 59 struct VideoFrameBuffer { |
60 VideoFrameBuffer(void* data, const SkISize& size, int bytes_per_pixel, | 60 VideoFrameBuffer(); |
61 int bytes_per_row) | 61 |
62 : data(data), size(size), bytes_per_pixel(bytes_per_pixel), | |
63 bytes_per_row(bytes_per_row) { | |
64 } | |
65 VideoFrameBuffer() { | |
66 data = 0; | |
67 size = SkISize::Make(0, 0); | |
68 bytes_per_pixel = 0; | |
69 bytes_per_row = 0; | |
70 } | |
71 void* data; | 62 void* data; |
72 SkISize size; | 63 SkISize size; |
73 int bytes_per_pixel; | 64 int bytes_per_pixel; |
74 int bytes_per_row; | 65 int bytes_per_row; |
75 int resource_generation; | 66 int resource_generation; |
76 }; | 67 }; |
77 | 68 |
78 // Make sure that the device contexts and the current bufffer match the screen | 69 // Make sure that the device contexts and the current bufffer match the screen |
79 // configuration. | 70 // configuration. |
80 void PrepareCaptureResources(); | 71 void PrepareCaptureResources(); |
81 | 72 |
82 // Allocates the specified capture buffer using the current device contexts | 73 // Allocates the specified capture buffer using the current device contexts |
83 // and desktop dimensions, releasing any pre-existing buffer. | 74 // and desktop dimensions, releasing any pre-existing buffer. |
84 void AllocateBuffer(int buffer_index); | 75 void AllocateBuffer(int buffer_index, int resource_generation); |
85 | 76 |
86 void CalculateInvalidRegion(); | 77 void CalculateInvalidRegion(); |
87 void CaptureRegion(const SkRegion& region, | 78 void CaptureRegion(const SkRegion& region, |
88 const CaptureCompletedCallback& callback); | 79 const CaptureCompletedCallback& callback); |
89 | 80 |
90 // Generates an image in the current buffer. | 81 // Generates an image in the current buffer. |
91 void CaptureImage(); | 82 void CaptureImage(); |
92 | 83 |
93 // Expand the cursor shape to add a white outline for visibility against | 84 // Expand the cursor shape to add a white outline for visibility against |
94 // dark backgrounds. | 85 // dark backgrounds. |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 DwmEnableCompositionFunc composition_func_; | 129 DwmEnableCompositionFunc composition_func_; |
139 | 130 |
140 DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerWin); | 131 DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerWin); |
141 }; | 132 }; |
142 | 133 |
143 // 3780 pixels per meter is equivalent to 96 DPI, typical on desktop monitors. | 134 // 3780 pixels per meter is equivalent to 96 DPI, typical on desktop monitors. |
144 static const int kPixelsPerMeter = 3780; | 135 static const int kPixelsPerMeter = 3780; |
145 // 32 bit RGBA is 4 bytes per pixel. | 136 // 32 bit RGBA is 4 bytes per pixel. |
146 static const int kBytesPerPixel = 4; | 137 static const int kBytesPerPixel = 4; |
147 | 138 |
| 139 VideoFrameCapturerWin::VideoFrameBuffer::VideoFrameBuffer() |
| 140 : data(NULL), |
| 141 size(SkISize::Make(0, 0)), |
| 142 bytes_per_pixel(0), |
| 143 bytes_per_row(0), |
| 144 resource_generation(0) { |
| 145 } |
| 146 |
148 VideoFrameCapturerWin::VideoFrameCapturerWin() | 147 VideoFrameCapturerWin::VideoFrameCapturerWin() |
149 : last_cursor_size_(SkISize::Make(0, 0)), | 148 : last_cursor_size_(SkISize::Make(0, 0)), |
150 desktop_dc_rect_(SkIRect::MakeEmpty()), | 149 desktop_dc_rect_(SkIRect::MakeEmpty()), |
151 resource_generation_(0), | 150 resource_generation_(0), |
152 current_buffer_(0), | 151 current_buffer_(0), |
153 pixel_format_(media::VideoFrame::RGB32), | 152 pixel_format_(media::VideoFrame::RGB32), |
154 composition_func_(NULL) { | 153 composition_func_(NULL) { |
155 } | 154 } |
156 | 155 |
157 VideoFrameCapturerWin::~VideoFrameCapturerWin() { | 156 VideoFrameCapturerWin::~VideoFrameCapturerWin() { |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 memory_dc_.Set(CreateCompatibleDC(*desktop_dc_)); | 249 memory_dc_.Set(CreateCompatibleDC(*desktop_dc_)); |
251 desktop_dc_rect_ = screen_rect; | 250 desktop_dc_rect_ = screen_rect; |
252 | 251 |
253 ++resource_generation_; | 252 ++resource_generation_; |
254 } | 253 } |
255 | 254 |
256 // If the current buffer is from an older generation then allocate a new one. | 255 // If the current buffer is from an older generation then allocate a new one. |
257 // Note that we can't reallocate other buffers at this point, since the caller | 256 // Note that we can't reallocate other buffers at this point, since the caller |
258 // may still be reading from them. | 257 // may still be reading from them. |
259 if (resource_generation_ != buffers_[current_buffer_].resource_generation) { | 258 if (resource_generation_ != buffers_[current_buffer_].resource_generation) { |
260 AllocateBuffer(current_buffer_); | 259 AllocateBuffer(current_buffer_, resource_generation_); |
261 | 260 |
262 SkRegion region; | 261 SkRegion region; |
263 region.op(SkIRect::MakeSize(helper_.size_most_recent()), | 262 region.op(SkIRect::MakeSize(helper_.size_most_recent()), |
264 SkRegion::kUnion_Op); | 263 SkRegion::kUnion_Op); |
265 InvalidateRegion(region); | 264 InvalidateRegion(region); |
266 } | 265 } |
267 } | 266 } |
268 | 267 |
269 void VideoFrameCapturerWin::AllocateBuffer(int buffer_index) { | 268 void VideoFrameCapturerWin::AllocateBuffer(int buffer_index, |
| 269 int resource_generation) { |
270 DCHECK(desktop_dc_.get() != NULL); | 270 DCHECK(desktop_dc_.get() != NULL); |
271 DCHECK(memory_dc_.Get() != NULL); | 271 DCHECK(memory_dc_.Get() != NULL); |
272 // Windows requires DIB sections' rows to start DWORD-aligned, which is | 272 // Windows requires DIB sections' rows to start DWORD-aligned, which is |
273 // implicit when working with RGB32 pixels. | 273 // implicit when working with RGB32 pixels. |
274 DCHECK_EQ(pixel_format_, media::VideoFrame::RGB32); | 274 DCHECK_EQ(pixel_format_, media::VideoFrame::RGB32); |
275 | 275 |
276 // Describe a device independent bitmap (DIB) that is the size of the desktop. | 276 // Describe a device independent bitmap (DIB) that is the size of the desktop. |
277 BITMAPINFO bmi; | 277 BITMAPINFO bmi; |
278 memset(&bmi, 0, sizeof(bmi)); | 278 memset(&bmi, 0, sizeof(bmi)); |
279 bmi.bmiHeader.biHeight = -desktop_dc_rect_.height(); | 279 bmi.bmiHeader.biHeight = -desktop_dc_rect_.height(); |
280 bmi.bmiHeader.biWidth = desktop_dc_rect_.width(); | 280 bmi.bmiHeader.biWidth = desktop_dc_rect_.width(); |
281 bmi.bmiHeader.biPlanes = 1; | 281 bmi.bmiHeader.biPlanes = 1; |
282 bmi.bmiHeader.biBitCount = kBytesPerPixel * 8; | 282 bmi.bmiHeader.biBitCount = kBytesPerPixel * 8; |
283 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader); | 283 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader); |
284 int bytes_per_row = desktop_dc_rect_.width() * kBytesPerPixel; | 284 int bytes_per_row = desktop_dc_rect_.width() * kBytesPerPixel; |
285 bmi.bmiHeader.biSizeImage = bytes_per_row * desktop_dc_rect_.height(); | 285 bmi.bmiHeader.biSizeImage = bytes_per_row * desktop_dc_rect_.height(); |
286 bmi.bmiHeader.biXPelsPerMeter = kPixelsPerMeter; | 286 bmi.bmiHeader.biXPelsPerMeter = kPixelsPerMeter; |
287 bmi.bmiHeader.biYPelsPerMeter = kPixelsPerMeter; | 287 bmi.bmiHeader.biYPelsPerMeter = kPixelsPerMeter; |
288 | 288 |
289 // Create the DIB, and store a pointer to its pixel buffer. | 289 // Create the DIB, and store a pointer to its pixel buffer. |
290 target_bitmap_[buffer_index] = | 290 target_bitmap_[buffer_index] = |
291 CreateDIBSection(*desktop_dc_, &bmi, DIB_RGB_COLORS, | 291 CreateDIBSection(*desktop_dc_, &bmi, DIB_RGB_COLORS, |
292 static_cast<void**>(&buffers_[buffer_index].data), | 292 static_cast<void**>(&buffers_[buffer_index].data), |
293 NULL, 0); | 293 NULL, 0); |
294 buffers_[buffer_index].size = SkISize::Make(bmi.bmiHeader.biWidth, | 294 buffers_[buffer_index].size = SkISize::Make(bmi.bmiHeader.biWidth, |
295 std::abs(bmi.bmiHeader.biHeight)); | 295 std::abs(bmi.bmiHeader.biHeight)); |
296 buffers_[buffer_index].bytes_per_pixel = bmi.bmiHeader.biBitCount / 8; | 296 buffers_[buffer_index].bytes_per_pixel = bmi.bmiHeader.biBitCount / 8; |
297 buffers_[buffer_index].bytes_per_row = | 297 buffers_[buffer_index].bytes_per_row = |
298 bmi.bmiHeader.biSizeImage / std::abs(bmi.bmiHeader.biHeight); | 298 bmi.bmiHeader.biSizeImage / std::abs(bmi.bmiHeader.biHeight); |
| 299 buffers_[buffer_index].resource_generation = resource_generation; |
299 } | 300 } |
300 | 301 |
301 void VideoFrameCapturerWin::CalculateInvalidRegion() { | 302 void VideoFrameCapturerWin::CalculateInvalidRegion() { |
302 CaptureImage(); | 303 CaptureImage(); |
303 | 304 |
304 const VideoFrameBuffer& current = buffers_[current_buffer_]; | 305 const VideoFrameBuffer& current = buffers_[current_buffer_]; |
305 | 306 |
306 // Find the previous and current screens. | 307 // Find the previous and current screens. |
307 int prev_buffer_id = current_buffer_ - 1; | 308 int prev_buffer_id = current_buffer_ - 1; |
308 if (prev_buffer_id < 0) { | 309 if (prev_buffer_id < 0) { |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 } | 546 } |
546 | 547 |
547 } // namespace | 548 } // namespace |
548 | 549 |
549 // static | 550 // static |
550 VideoFrameCapturer* VideoFrameCapturer::Create() { | 551 VideoFrameCapturer* VideoFrameCapturer::Create() { |
551 return new VideoFrameCapturerWin(); | 552 return new VideoFrameCapturerWin(); |
552 } | 553 } |
553 | 554 |
554 } // namespace remoting | 555 } // namespace remoting |
OLD | NEW |