| 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..05ec931bd0ab6f0053802faa35dff6666cd7c30b 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,18 +54,15 @@ 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,
|
| - const base::Time& capture_start_time);
|
| -
|
| // Captures the current screen contents into the current buffer.
|
| void CaptureImage();
|
|
|
| @@ -101,7 +73,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 +109,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 +135,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 +157,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 the current frame.
|
| + webrtc::DesktopFrame* frame = queue_.current_frame()->Share();
|
| + 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;
|
| +}
|
|
|
| - delegate_ = delegate;
|
| +void ScreenCapturerWin::Start(Callback* callback) {
|
| + DCHECK(!callback_);
|
| + DCHECK(callback);
|
| +
|
| + 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 +263,37 @@ 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(
|
| - const SkRegion& 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*>(
|
| - queue_.current_frame());
|
| - HGDIOBJ previous_object = SelectObject(memory_dc_, current->GetBitmap());
|
| + webrtc::DesktopFrameWin* current = static_cast<webrtc::DesktopFrameWin*>(
|
| + queue_.current_frame()->GetUnderlyingFrame());
|
| + 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 +384,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 +412,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 +472,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 +483,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);
|
|
|