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..9b54f0b6a5edfe8f0d8f02cc0c8b96746456b7ed 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) { |
@@ -226,13 +140,13 @@ ScreenCapturerWin::~ScreenCapturerWin() { |
if (composition_func_ != NULL) { |
(*composition_func_)(DWM_EC_ENABLECOMPOSITION); |
} |
- |
- delegate_ = NULL; |
} |
-void ScreenCapturerWin::CaptureFrame() { |
+void ScreenCapturerWin::Capture(const webrtc::DesktopRegion& region) { |
base::Time capture_start_time = base::Time::Now(); |
+ queue_.MoveToNextFrame(); |
+ |
// Request that the system not power-down the system, or the display hardware. |
if (!SetThreadExecutionState(ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED)) { |
if (!set_thread_execution_state_failed_) { |
@@ -248,45 +162,61 @@ 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(); |
- if (last_buffer) { |
+ const webrtc::DesktopFrame* current_frame = queue_.current_frame(); |
+ const webrtc::DesktopFrame* last_frame = queue_.previous_frame(); |
+ if (last_frame) { |
// 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_frame->size().width()) || |
+ (differ_->height() != current_frame->size().height()) || |
+ (differ_->bytes_per_row() != current_frame->stride())) { |
+ differ_.reset(new Differ(current_frame->size().width(), |
+ current_frame->size().height(), |
+ webrtc::DesktopFrame::kBytesPerPixel, |
+ current_frame->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_frame->data(), current_frame->data(), |
®ion); |
helper_.InvalidateRegion(region); |
} else { |
// No previous frame is available. Invalidate the whole screen. |
- helper_.InvalidateScreen(current_buffer->dimensions()); |
+ helper_.InvalidateScreen(current_frame->size()); |
} |
- // Wrap the captured frame into ScreenCaptureData structure and invoke |
- // the completion callback. |
- SkRegion invalid_region; |
- helper_.SwapInvalidRegion(&invalid_region); |
- CaptureRegion(invalid_region, capture_start_time); |
+ helper_.set_size_most_recent(current_frame->size()); |
+ |
+ // Emit current frame. |
alexeypa (please no reviews)
2013/05/08 22:24:59
nit: the current frame
Sergey Ulanov
2013/05/09 18:49:02
Done.
|
+ webrtc::DesktopFrame* frame = queue_.EmitCurrentFrame(); |
+ frame->set_dpi(webrtc::DesktopVector( |
+ GetDeviceCaps(*desktop_dc_, LOGPIXELSX), |
+ GetDeviceCaps(*desktop_dc_, LOGPIXELSY))); |
+ frame->mutable_updated_region()->Clear(); |
+ helper_.TakeInvalidRegion(&frame->mutable_updated_region()); |
+ frame->set_capture_time_ms( |
+ (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp()); |
+ callback_->OnCaptureCompleted(frame); |
// Check for cursor shape update. |
CaptureCursor(); |
} |
-void ScreenCapturerWin::Start(Delegate* delegate) { |
- DCHECK(delegate_ == NULL); |
+void ScreenCapturerWin::SetMouseShapeObserver( |
+ MouseShapeObserver* mouse_shape_observer) { |
+ DCHECK(!mouse_shape_observer_); |
+ DCHECK(mouse_shape_observer); |
+ |
+ mouse_shape_observer_ = mouse_shape_observer; |
+} |
+ |
+void ScreenCapturerWin::Start(Callback* callback) { |
+ DCHECK(!callback_); |
+ DCHECK(callback); |
- 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 |
@@ -338,57 +268,42 @@ void ScreenCapturerWin::PrepareCaptureResources() { |
desktop_dc_rect_ = screen_rect; |
// Make sure the frame buffers will be reallocated. |
- queue_.SetAllFramesNeedUpdate(); |
+ queue_.Reset(); |
helper_.ClearInvalidRegion(); |
} |
} |
void ScreenCapturerWin::CaptureRegion( |
alexeypa (please no reviews)
2013/05/08 22:24:59
nit: The method is still here. It is just empty.
Sergey Ulanov
2013/05/09 18:49:02
Done.
|
- 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( |
- GetDeviceCaps(*desktop_dc_, LOGPIXELSX), |
- GetDeviceCaps(*desktop_dc_, LOGPIXELSY)); |
- data->set_dpi(dpi); |
- |
- helper_.set_size_most_recent(data->size()); |
- |
- queue_.DoneWithCurrentFrame(); |
- |
- data->set_capture_time_ms( |
- (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp()); |
- delegate_->OnCaptureCompleted(data); |
} |
void ScreenCapturerWin::CaptureImage() { |
// If the current buffer is from an older generation then allocate a new one. |
// Note that we can't reallocate other buffers at this point, since the caller |
// may still be reading from them. |
- if (queue_.current_frame_needs_update()) { |
+ if (queue_.current_frame()) { |
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_) |
+ 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); |