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

Unified Diff: media/video/capture/screen/screen_capturer_win.cc

Issue 13983010: Use webrtc::DesktopCapturer for screen capturer implementation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 7 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 side-by-side diff with in-line comments
Download patch
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(),
&region);
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);

Powered by Google App Engine
This is Rietveld 408576698