Chromium Code Reviews| Index: media/video/capture/screen/screen_capturer_win.cc |
| diff --git a/media/video/capture/screen/screen_capturer_win.cc b/media/video/capture/screen/screen_capturer_win.cc |
| index ff148b1384f4d29c1749c85d2cb3f74933b6b2d9..05cd0eefdf9e72a8a2cec1385034c33e5dd5ad97 100644 |
| --- a/media/video/capture/screen/screen_capturer_win.cc |
| +++ b/media/video/capture/screen/screen_capturer_win.cc |
| @@ -19,13 +19,14 @@ |
| #include "base/win/scoped_hdc.h" |
| #include "media/video/capture/screen/differ.h" |
| #include "media/video/capture/screen/mouse_cursor_shape.h" |
| -#include "media/video/capture/screen/screen_capture_data.h" |
| -#include "media/video/capture/screen/screen_capture_frame.h" |
| #include "media/video/capture/screen/screen_capture_frame_queue.h" |
| #include "media/video/capture/screen/screen_capturer_helper.h" |
| #include "media/video/capture/screen/win/desktop.h" |
| #include "media/video/capture/screen/win/scoped_thread_desktop.h" |
| #include "third_party/skia/include/core/SkColorPriv.h" |
| +#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" |
| +#include "third_party/webrtc/modules/desktop_capture/desktop_frame_win.h" |
| +#include "third_party/webrtc/modules/desktop_capture/desktop_region.h" |
| namespace media { |
| @@ -44,32 +45,6 @@ const uint32 kPixelBgraBlack = 0xff000000; |
| const uint32 kPixelBgraWhite = 0xffffffff; |
| const uint32 kPixelBgraTransparent = 0x00000000; |
| -// A class representing a full-frame pixel buffer. |
| -class ScreenCaptureFrameWin : public ScreenCaptureFrame { |
| - public: |
| - ScreenCaptureFrameWin(HDC desktop_dc, const SkISize& size, |
| - ScreenCapturer::Delegate* delegate); |
| - virtual ~ScreenCaptureFrameWin(); |
| - |
| - // Returns handle of the device independent bitmap representing this frame |
| - // buffer to GDI. |
| - HBITMAP GetBitmap(); |
| - |
| - private: |
| - // Allocates a device independent bitmap representing this frame buffer to |
| - // GDI. |
| - void AllocateBitmap(HDC desktop_dc, const SkISize& size); |
| - |
| - // Handle of the device independent bitmap representing this frame buffer to |
| - // GDI. |
| - base::win::ScopedBitmap bitmap_; |
| - |
| - // Used to work with shared memory buffers. |
| - ScreenCapturer::Delegate* delegate_; |
| - |
| - DISALLOW_COPY_AND_ASSIGN(ScreenCaptureFrameWin); |
| -}; |
| - |
| // ScreenCapturerWin captures 32bit RGB using GDI. |
| // |
| // ScreenCapturerWin is double-buffered as required by ScreenCapturer. |
| @@ -79,16 +54,18 @@ class ScreenCapturerWin : public ScreenCapturer { |
| virtual ~ScreenCapturerWin(); |
| // Overridden from ScreenCapturer: |
| - virtual void Start(Delegate* delegate) OVERRIDE; |
| - virtual void CaptureFrame() OVERRIDE; |
| + virtual void Start(Callback* callback) OVERRIDE; |
| + virtual void Capture(const webrtc::DesktopRegion& region) OVERRIDE; |
| + virtual void SetMouseShapeObserver( |
| + MouseShapeObserver* mouse_shape_observer) OVERRIDE; |
| private: |
| // Make sure that the device contexts match the screen configuration. |
| void PrepareCaptureResources(); |
| - // Creates a ScreenCaptureData instance wrapping the current framebuffer and |
| - // notifies |delegate_|. |
| - void CaptureRegion(const SkRegion& region, |
| + // Creates a webrtc::DesktopFrame instance wrapping the current framebuffer |
| + // and notifies |callback_|. |
| + void CaptureRegion(const webrtc::DesktopRegion& region, |
| const base::Time& capture_start_time); |
| // Captures the current screen contents into the current buffer. |
| @@ -101,7 +78,8 @@ class ScreenCapturerWin : public ScreenCapturer { |
| // Capture the current cursor shape. |
| void CaptureCursor(); |
| - Delegate* delegate_; |
| + Callback* callback_; |
| + MouseShapeObserver* mouse_shape_observer_; |
| // A thread-safe list of invalid rectangles, and the size of the most |
| // recently captured screen. |
| @@ -136,73 +114,9 @@ class ScreenCapturerWin : public ScreenCapturer { |
| DISALLOW_COPY_AND_ASSIGN(ScreenCapturerWin); |
| }; |
| -// 3780 pixels per meter is equivalent to 96 DPI, typical on desktop monitors. |
| -static const int kPixelsPerMeter = 3780; |
| - |
| -ScreenCaptureFrameWin::ScreenCaptureFrameWin( |
| - HDC desktop_dc, |
| - const SkISize& size, |
| - ScreenCapturer::Delegate* delegate) |
| - : delegate_(delegate) { |
| - // Try to allocate a shared memory buffer. |
| - uint32 buffer_size = |
| - size.width() * size.height() * ScreenCaptureData::kBytesPerPixel; |
| - scoped_refptr<SharedBuffer> shared_buffer = |
| - delegate_->CreateSharedBuffer(buffer_size); |
| - if (shared_buffer) { |
| - CHECK(shared_buffer->ptr() != NULL); |
| - set_shared_buffer(shared_buffer); |
| - } |
| - |
| - AllocateBitmap(desktop_dc, size); |
| -} |
| - |
| -ScreenCaptureFrameWin::~ScreenCaptureFrameWin() { |
| - if (shared_buffer()) |
| - delegate_->ReleaseSharedBuffer(shared_buffer()); |
| -} |
| - |
| -HBITMAP ScreenCaptureFrameWin::GetBitmap() { |
| - return bitmap_; |
| -} |
| - |
| -void ScreenCaptureFrameWin::AllocateBitmap(HDC desktop_dc, |
| - const SkISize& size) { |
| - int bytes_per_row = size.width() * ScreenCaptureData::kBytesPerPixel; |
| - |
| - // Describe a device independent bitmap (DIB) that is the size of the desktop. |
| - BITMAPINFO bmi; |
| - memset(&bmi, 0, sizeof(bmi)); |
| - bmi.bmiHeader.biHeight = -size.height(); |
| - bmi.bmiHeader.biWidth = size.width(); |
| - bmi.bmiHeader.biPlanes = 1; |
| - bmi.bmiHeader.biBitCount = ScreenCaptureData::kBytesPerPixel * 8; |
| - bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader); |
| - bmi.bmiHeader.biSizeImage = bytes_per_row * size.height(); |
| - bmi.bmiHeader.biXPelsPerMeter = kPixelsPerMeter; |
| - bmi.bmiHeader.biYPelsPerMeter = kPixelsPerMeter; |
| - |
| - // Create the DIB, and store a pointer to its pixel buffer. |
| - HANDLE section_handle = NULL; |
| - if (shared_buffer()) |
| - section_handle = shared_buffer()->handle(); |
| - void* data = NULL; |
| - bitmap_ = CreateDIBSection(desktop_dc, &bmi, DIB_RGB_COLORS, &data, |
| - section_handle, 0); |
| - |
| - // TODO(wez): Cope gracefully with failure (crbug.com/157170). |
| - CHECK(bitmap_ != NULL); |
| - CHECK(data != NULL); |
| - |
| - set_pixels(reinterpret_cast<uint8*>(data)); |
| - set_dimensions(SkISize::Make(bmi.bmiHeader.biWidth, |
| - std::abs(bmi.bmiHeader.biHeight))); |
| - set_bytes_per_row( |
| - bmi.bmiHeader.biSizeImage / std::abs(bmi.bmiHeader.biHeight)); |
| -} |
| - |
| ScreenCapturerWin::ScreenCapturerWin(bool disable_aero) |
| - : delegate_(NULL), |
| + : callback_(NULL), |
| + mouse_shape_observer_(NULL), |
| desktop_dc_rect_(SkIRect::MakeEmpty()), |
| composition_func_(NULL), |
| set_thread_execution_state_failed_(false) { |
| @@ -227,10 +141,10 @@ ScreenCapturerWin::~ScreenCapturerWin() { |
| (*composition_func_)(DWM_EC_ENABLECOMPOSITION); |
| } |
| - delegate_ = NULL; |
| + callback_ = NULL; |
|
alexeypa (please no reviews)
2013/04/26 21:33:58
nit: Remove this line.
Sergey Ulanov
2013/05/07 22:25:50
Done.
|
| } |
| -void ScreenCapturerWin::CaptureFrame() { |
| +void ScreenCapturerWin::Capture(const webrtc::DesktopRegion& region) { |
| base::Time capture_start_time = base::Time::Now(); |
| // Request that the system not power-down the system, or the display hardware. |
| @@ -248,34 +162,34 @@ void ScreenCapturerWin::CaptureFrame() { |
| // Copy screen bits to the current buffer. |
| CaptureImage(); |
| - const ScreenCaptureFrame* current_buffer = queue_.current_frame(); |
| - const ScreenCaptureFrame* last_buffer = queue_.previous_frame(); |
| + const webrtc::DesktopFrame* current_buffer = queue_.current_frame(); |
| + const webrtc::DesktopFrame* last_buffer = queue_.previous_frame(); |
| if (last_buffer) { |
| // Make sure the differencer is set up correctly for these previous and |
| // current screens. |
| if (!differ_.get() || |
| - (differ_->width() != current_buffer->dimensions().width()) || |
| - (differ_->height() != current_buffer->dimensions().height()) || |
| - (differ_->bytes_per_row() != current_buffer->bytes_per_row())) { |
| - differ_.reset(new Differ(current_buffer->dimensions().width(), |
| - current_buffer->dimensions().height(), |
| - ScreenCaptureData::kBytesPerPixel, |
| - current_buffer->bytes_per_row())); |
| + (differ_->width() != current_buffer->size().width()) || |
| + (differ_->height() != current_buffer->size().height()) || |
| + (differ_->bytes_per_row() != current_buffer->stride())) { |
| + differ_.reset(new Differ(current_buffer->size().width(), |
| + current_buffer->size().height(), |
| + webrtc::DesktopFrame::kBytesPerPixel, |
| + current_buffer->stride())); |
| } |
| // Calculate difference between the two last captured frames. |
| - SkRegion region; |
| - differ_->CalcDirtyRegion(last_buffer->pixels(), current_buffer->pixels(), |
| + webrtc::DesktopRegion region; |
| + differ_->CalcDirtyRegion(last_buffer->data(), current_buffer->data(), |
| ®ion); |
| helper_.InvalidateRegion(region); |
| } else { |
| // No previous frame is available. Invalidate the whole screen. |
| - helper_.InvalidateScreen(current_buffer->dimensions()); |
| + helper_.InvalidateScreen(current_buffer->size()); |
| } |
| // Wrap the captured frame into ScreenCaptureData structure and invoke |
| // the completion callback. |
| - SkRegion invalid_region; |
| + webrtc::DesktopRegion invalid_region; |
| helper_.SwapInvalidRegion(&invalid_region); |
| CaptureRegion(invalid_region, capture_start_time); |
| @@ -283,10 +197,15 @@ void ScreenCapturerWin::CaptureFrame() { |
| CaptureCursor(); |
| } |
| -void ScreenCapturerWin::Start(Delegate* delegate) { |
| - DCHECK(delegate_ == NULL); |
| +void ScreenCapturerWin::SetMouseShapeObserver( |
| + MouseShapeObserver* mouse_shape_observer) { |
| + mouse_shape_observer_ = mouse_shape_observer; |
|
alexeypa (please no reviews)
2013/04/26 21:33:58
DCHECK(!mouse_shape_observer_);
DCHECK(mouse_shape
Sergey Ulanov
2013/05/07 22:25:50
Done.
|
| +} |
| + |
| +void ScreenCapturerWin::Start(Callback* callback) { |
| + DCHECK(callback_ == NULL); |
|
alexeypa (please no reviews)
2013/04/26 21:33:58
DCHECK(!callback_);
DCHECK(callback);
Sergey Ulanov
2013/05/07 22:25:50
Done.
|
| - delegate_ = delegate; |
| + callback_ = callback; |
| // Vote to disable Aero composited desktop effects while capturing. Windows |
| // will restore Aero automatically if the process exits. This has no effect |
| @@ -345,28 +264,19 @@ void ScreenCapturerWin::PrepareCaptureResources() { |
| } |
| void ScreenCapturerWin::CaptureRegion( |
|
Wez
2013/04/26 18:48:14
This needs renaming, e.g. EmitFrame().
Sergey Ulanov
2013/05/07 22:25:50
Just removed this method.
|
| - const SkRegion& region, |
| + const webrtc::DesktopRegion& region, |
| const base::Time& capture_start_time) { |
| - const ScreenCaptureFrame* current_buffer = queue_.current_frame(); |
| - |
| - scoped_refptr<ScreenCaptureData> data(new ScreenCaptureData( |
| - current_buffer->pixels(), current_buffer->bytes_per_row(), |
| - current_buffer->dimensions())); |
| - data->mutable_dirty_region() = region; |
| - data->set_shared_buffer(current_buffer->shared_buffer()); |
| - |
| - SkIPoint dpi = SkIPoint::Make( |
| + webrtc::DesktopFrame* frame = queue_.EmitCurrentFrameAndMoveToNext(); |
| + frame->set_dpi(webrtc::DesktopVector( |
| GetDeviceCaps(*desktop_dc_, LOGPIXELSX), |
| - GetDeviceCaps(*desktop_dc_, LOGPIXELSY)); |
| - data->set_dpi(dpi); |
| - |
| - helper_.set_size_most_recent(data->size()); |
| + GetDeviceCaps(*desktop_dc_, LOGPIXELSY))); |
| + *frame->mutable_updated_region() = region; |
| + frame->set_capture_time_ms( |
| + (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp()); |
| - queue_.DoneWithCurrentFrame(); |
| + helper_.set_size_most_recent(frame->size()); |
| - data->set_capture_time_ms( |
| - (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp()); |
| - delegate_->OnCaptureCompleted(data); |
| + callback_->OnCaptureCompleted(frame); |
| } |
| void ScreenCapturerWin::CaptureImage() { |
| @@ -377,18 +287,23 @@ void ScreenCapturerWin::CaptureImage() { |
| DCHECK(desktop_dc_.get() != NULL); |
| DCHECK(memory_dc_.Get() != NULL); |
| - SkISize size = SkISize::Make(desktop_dc_rect_.width(), |
| - desktop_dc_rect_.height()); |
| - scoped_ptr<ScreenCaptureFrameWin> buffer( |
| - new ScreenCaptureFrameWin(*desktop_dc_, size, delegate_)); |
| - queue_.ReplaceCurrentFrame(buffer.PassAs<ScreenCaptureFrame>()); |
| + webrtc::DesktopSize size = webrtc::DesktopSize( |
| + desktop_dc_rect_.width(), desktop_dc_rect_.height()); |
| + |
| + size_t buffer_size = size.width() * size.height() * |
| + webrtc::DesktopFrame::kBytesPerPixel; |
| + webrtc::SharedMemory* shared_memory = |
| + callback_->CreateSharedMemory(buffer_size); |
| + scoped_ptr<webrtc::DesktopFrameWin> buffer( |
| + webrtc::DesktopFrameWin::Create(size, shared_memory, *desktop_dc_)); |
| + queue_.ReplaceCurrentFrame(buffer.PassAs<webrtc::DesktopFrame>()); |
| } |
| // Select the target bitmap into the memory dc and copy the rect from desktop |
| // to memory. |
| - ScreenCaptureFrameWin* current = static_cast<ScreenCaptureFrameWin*>( |
| + webrtc::DesktopFrameWin* current = static_cast<webrtc::DesktopFrameWin*>( |
| queue_.current_frame()); |
| - HGDIOBJ previous_object = SelectObject(memory_dc_, current->GetBitmap()); |
| + HGDIOBJ previous_object = SelectObject(memory_dc_, current->bitmap()); |
| if (previous_object != NULL) { |
| BitBlt(memory_dc_, |
| 0, 0, desktop_dc_rect_.width(), desktop_dc_rect_.height(), |
| @@ -479,7 +394,7 @@ void ScreenCapturerWin::CaptureCursor() { |
| if (!color_bitmap) { |
| height /= 2; |
| } |
| - int data_size = height * width * ScreenCaptureData::kBytesPerPixel; |
| + int data_size = height * width * webrtc::DesktopFrame::kBytesPerPixel; |
| scoped_ptr<MouseCursorShape> cursor(new MouseCursorShape()); |
| cursor->data.resize(data_size); |
| @@ -507,10 +422,10 @@ void ScreenCapturerWin::CaptureCursor() { |
| dst[1] = SkAlphaMul(src[1], src[3]); |
| dst[2] = SkAlphaMul(src[2], src[3]); |
| dst[3] = src[3]; |
| - dst += ScreenCaptureData::kBytesPerPixel; |
| - src += ScreenCaptureData::kBytesPerPixel; |
| + dst += webrtc::DesktopFrame::kBytesPerPixel; |
| + src += webrtc::DesktopFrame::kBytesPerPixel; |
| } |
| - src -= row_bytes + (width * ScreenCaptureData::kBytesPerPixel); |
| + src -= row_bytes + (width * webrtc::DesktopFrame::kBytesPerPixel); |
| } |
| } else { |
| if (bitmap.bmPlanes != 1 || bitmap.bmBitsPixel != 1) { |
| @@ -567,8 +482,8 @@ void ScreenCapturerWin::CaptureCursor() { |
| // Compare the current cursor with the last one we sent to the client. If |
| // they're the same, then don't bother sending the cursor again. |
| - if (last_cursor_.size == cursor->size && |
| - last_cursor_.hotspot == cursor->hotspot && |
| + if (last_cursor_.size.equals(cursor->size) && |
| + last_cursor_.hotspot.equals(cursor->hotspot) && |
| last_cursor_.data == cursor->data) { |
| return; |
| } |
| @@ -578,20 +493,12 @@ void ScreenCapturerWin::CaptureCursor() { |
| // Record the last cursor image that we sent to the client. |
| last_cursor_ = *cursor; |
| - delegate_->OnCursorShapeChanged(cursor.Pass()); |
| + if (mouse_shape_observer_) |
|
alexeypa (please no reviews)
2013/04/26 21:33:58
Can it be NULL?
Sergey Ulanov
2013/05/07 22:25:50
yes
|
| + mouse_shape_observer_->OnCursorShapeChanged(cursor.Pass()); |
| } |
| } // namespace |
| -scoped_refptr<SharedBuffer> ScreenCapturer::Delegate::CreateSharedBuffer( |
| - uint32 size) { |
| - return scoped_refptr<SharedBuffer>(); |
| -} |
| - |
| -void ScreenCapturer::Delegate::ReleaseSharedBuffer( |
| - scoped_refptr<SharedBuffer> buffer) { |
| -} |
| - |
| // static |
| scoped_ptr<ScreenCapturer> ScreenCapturer::Create() { |
| return CreateWithDisableAero(true); |