diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-16 10:45:24 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-16 10:45:24 +0000 |
commit | b9ed58f046141b4610c1bdc966d962d5fb95ac6b (patch) | |
tree | b7dc10e49ea765b6ebc99985d3538a2e1363942e /media | |
parent | c1c88cf23606dd1ca2bfd9f57496aeec847e713f (diff) | |
download | chromium_src-b9ed58f046141b4610c1bdc966d962d5fb95ac6b.zip chromium_src-b9ed58f046141b4610c1bdc966d962d5fb95ac6b.tar.gz chromium_src-b9ed58f046141b4610c1bdc966d962d5fb95ac6b.tar.bz2 |
Use webrtc::DesktopCapturer for screen capturer implementation.
Screen capturers are being moved from media/video/capture/screen to
third_party/webrtc. This CL is an intermediate step in that process.
Depends on https://webrtc-codereview.appspot.com/1322007/
TBR=brettw@chromium.org (third_party/webrtc dependency)
Review URL: https://chromiumcodereview.appspot.com/13983010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@200504 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
37 files changed, 994 insertions, 1396 deletions
diff --git a/media/media.gyp b/media/media.gyp index d5335ec..0eb48c1 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -369,20 +369,13 @@ 'video/capture/screen/differ.h', 'video/capture/screen/differ_block.cc', 'video/capture/screen/differ_block.h', - 'video/capture/screen/x11/x_server_pixel_buffer.cc', - 'video/capture/screen/x11/x_server_pixel_buffer.h', - 'video/capture/screen/mac/desktop_configuration.mm', 'video/capture/screen/mac/desktop_configuration.h', + 'video/capture/screen/mac/desktop_configuration.mm', 'video/capture/screen/mac/scoped_pixel_buffer_object.cc', 'video/capture/screen/mac/scoped_pixel_buffer_object.h', - 'video/capture/screen/mouse_cursor_shape.cc', 'video/capture/screen/mouse_cursor_shape.h', - 'video/capture/screen/screen_capture_data.cc', - 'video/capture/screen/screen_capture_data.h', 'video/capture/screen/screen_capture_device.cc', 'video/capture/screen/screen_capture_device.h', - 'video/capture/screen/screen_capture_frame.cc', - 'video/capture/screen/screen_capture_frame.h', 'video/capture/screen/screen_capture_frame_queue.cc', 'video/capture/screen/screen_capture_frame_queue.h', 'video/capture/screen/screen_capturer.h', @@ -390,16 +383,18 @@ 'video/capture/screen/screen_capturer_fake.h', 'video/capture/screen/screen_capturer_helper.cc', 'video/capture/screen/screen_capturer_helper.h', - 'video/capture/screen/screen_capturer_x11.cc', 'video/capture/screen/screen_capturer_mac.mm', 'video/capture/screen/screen_capturer_null.cc', 'video/capture/screen/screen_capturer_win.cc', - 'video/capture/screen/shared_buffer.cc', - 'video/capture/screen/shared_buffer.h', + 'video/capture/screen/screen_capturer_x11.cc', + 'video/capture/screen/shared_desktop_frame.cc', + 'video/capture/screen/shared_desktop_frame.h', 'video/capture/screen/win/desktop.cc', 'video/capture/screen/win/desktop.h', 'video/capture/screen/win/scoped_thread_desktop.cc', 'video/capture/screen/win/scoped_thread_desktop.h', + 'video/capture/screen/x11/x_server_pixel_buffer.cc', + 'video/capture/screen/x11/x_server_pixel_buffer.h', 'video/capture/video_capture.h', 'video/capture/video_capture_device.h', 'video/capture/video_capture_device_dummy.cc', @@ -848,7 +843,11 @@ 'mp4/track_run_iterator.h', ], }], - [ 'screen_capture_supported==0', { + [ 'screen_capture_supported==1', { + 'dependencies': [ + '../third_party/webrtc/modules/modules.gyp:desktop_capture', + ], + }, { 'sources/': [ ['exclude', '^video/capture/screen/'], ], @@ -989,7 +988,6 @@ 'filters/video_renderer_base_unittest.cc', 'video/capture/screen/differ_block_unittest.cc', 'video/capture/screen/differ_unittest.cc', - 'video/capture/screen/shared_buffer_unittest.cc', 'video/capture/screen/screen_capture_device_unittest.cc', 'video/capture/screen/screen_capturer_helper_unittest.cc', 'video/capture/screen/screen_capturer_mac_unittest.cc', @@ -1093,7 +1091,11 @@ 'media_sse', ], }], - ['screen_capture_supported == 0', { + ['screen_capture_supported==1', { + 'dependencies': [ + '../third_party/webrtc/modules/modules.gyp:desktop_capture', + ], + }, { 'sources/': [ ['exclude', '^video/capture/screen/'], ], @@ -1148,7 +1150,11 @@ 'video/capture/screen/screen_capturer_mock_objects.h', ], 'conditions': [ - [ 'screen_capture_supported == 0', { + [ 'screen_capture_supported == 1', { + 'dependencies': [ + '../third_party/webrtc/modules/modules.gyp:desktop_capture', + ], + }, { 'sources/': [ ['exclude', '^video/capture/screen/'], ], diff --git a/media/video/capture/screen/DEPS b/media/video/capture/screen/DEPS index 2a3980b..3a4096f 100644 --- a/media/video/capture/screen/DEPS +++ b/media/video/capture/screen/DEPS @@ -1,3 +1,4 @@ include_rules = [ "+skia", + "+third_party/webrtc", ] diff --git a/media/video/capture/screen/differ.cc b/media/video/capture/screen/differ.cc index 3296903..addaea1 100644 --- a/media/video/capture/screen/differ.cc +++ b/media/video/capture/screen/differ.cc @@ -27,16 +27,7 @@ Differ::Differ(int width, int height, int bpp, int stride) { Differ::~Differ() {} void Differ::CalcDirtyRegion(const void* prev_buffer, const void* curr_buffer, - SkRegion* region) { - if (!region) { - return; - } - region->setEmpty(); - - if (!prev_buffer || !curr_buffer) { - return; - } - + webrtc::DesktopRegion* region) { // Identify all the blocks that contain changed pixels. MarkDirtyBlocks(prev_buffer, curr_buffer); @@ -131,9 +122,8 @@ DiffInfo Differ::DiffPartialBlock(const uint8* prev_buffer, return 0; } -void Differ::MergeBlocks(SkRegion* region) { - DCHECK(region); - region->setEmpty(); +void Differ::MergeBlocks(webrtc::DesktopRegion* region) { + region->Clear(); uint8* diff_info_row_start = static_cast<uint8*>(diff_info_.get()); int diff_info_stride = diff_info_width_ * sizeof(DiffInfo); @@ -195,8 +185,8 @@ void Differ::MergeBlocks(SkRegion* region) { if (top + height > height_) { height = height_ - top; } - region->op(SkIRect::MakeXYWH(left, top, width, height), - SkRegion::kUnion_Op); + region->AddRect( + webrtc::DesktopRect::MakeXYWH(left, top, width, height)); } // Increment to next block in this row. diff --git a/media/video/capture/screen/differ.h b/media/video/capture/screen/differ.h index 0ef3cc6..1676ecb 100644 --- a/media/video/capture/screen/differ.h +++ b/media/video/capture/screen/differ.h @@ -10,13 +10,13 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "media/base/media_export.h" -#include "third_party/skia/include/core/SkRegion.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_region.h" namespace media { typedef uint8 DiffInfo; -// TODO: Simplify differ now that we are working with SkRegions. +// TODO: Simplify differ now that we are working with webrtc::DesktopRegion. // diff_info_ should no longer be needed, as we can put our data directly into // the region that we are calculating. // http://crbug.com/92379 @@ -37,7 +37,7 @@ class MEDIA_EXPORT Differ { // Given the previous and current screen buffer, calculate the dirty region // that encloses all of the changed pixels in the new screen. void CalcDirtyRegion(const void* prev_buffer, const void* curr_buffer, - SkRegion* region); + webrtc::DesktopRegion* region); private: // Allow tests to access our private parts. @@ -49,7 +49,7 @@ class MEDIA_EXPORT Differ { // After the dirty blocks have been identified, this routine merges adjacent // blocks into a region. // The goal is to minimize the region that covers the dirty blocks. - void MergeBlocks(SkRegion* region); + void MergeBlocks(webrtc::DesktopRegion* region); // Check for diffs in upper-left portion of the block. The size of the portion // to check is specified by the |width| and |height| values. diff --git a/media/video/capture/screen/differ_unittest.cc b/media/video/capture/screen/differ_unittest.cc index 0210123..5a44315 100644 --- a/media/video/capture/screen/differ_unittest.cc +++ b/media/video/capture/screen/differ_unittest.cc @@ -49,14 +49,15 @@ class DifferTest : public testing::Test { differ_->MarkDirtyBlocks(prev_buffer, curr_buffer); } - void MergeBlocks(SkRegion* dirty) { + void MergeBlocks(webrtc::DesktopRegion* dirty) { differ_->MergeBlocks(dirty); } // Convenience method to count rectangles in a region. - int RegionRectCount(const SkRegion& region) { + int RegionRectCount(const webrtc::DesktopRegion& region) { int count = 0; - for(SkRegion::Iterator iter(region); !iter.done(); iter.next()) { + for (webrtc::DesktopRegion::Iterator iter(region); + !iter.IsAtEnd(); iter.Advance()) { ++count; } return count; @@ -144,15 +145,17 @@ class DifferTest : public testing::Test { // Verify that |region| contains a rectangle defined by |x|, |y|, |width| and // |height|. // |x|, |y|, |width| and |height| are specified in block (not pixel) units. - bool CheckDirtyRegionContainsRect(const SkRegion& region, int x, int y, + bool CheckDirtyRegionContainsRect(const webrtc::DesktopRegion& region, + int x, int y, int width, int height) { - SkIRect r = SkIRect::MakeXYWH(x * kBlockSize, y * kBlockSize, - width * kBlockSize, height * kBlockSize); - bool found = false; - for (SkRegion::Iterator i(region); !found && !i.done(); i.next()) { - found = (i.rect() == r); + webrtc::DesktopRect r = + webrtc::DesktopRect::MakeXYWH(x * kBlockSize, y * kBlockSize, + width * kBlockSize, height * kBlockSize); + for (webrtc::DesktopRegion::Iterator i(region); !i.IsAtEnd(); i.Advance()) { + if (i.rect().equals(r)) + return true; } - return found; + return false; } // Mark the range of blocks specified and then verify that they are @@ -163,15 +166,19 @@ class DifferTest : public testing::Test { ClearDiffInfo(); MarkBlocks(x_origin, y_origin, width, height); - SkRegion dirty; + webrtc::DesktopRegion dirty; MergeBlocks(&dirty); - bool is_good = dirty.isRect(); - if (is_good) { - is_good = CheckDirtyRegionContainsRect(dirty, x_origin, y_origin, - width, height); - } - return is_good; + + webrtc::DesktopRect expected_rect = webrtc::DesktopRect::MakeXYWH( + x_origin * kBlockSize, y_origin * kBlockSize, + width * kBlockSize, height * kBlockSize); + + // Verify that the region contains expected_rect and it's the only + // rectangle. + webrtc::DesktopRegion::Iterator it(dirty); + return !it.IsAtEnd() && expected_rect.equals(it.rect()) && + (it.Advance(), it.IsAtEnd()); } // The differ class we're testing. @@ -369,10 +376,10 @@ TEST_F(DifferTest, MergeBlocks_Empty) { // +---+---+---+---+ ClearDiffInfo(); - SkRegion dirty; + webrtc::DesktopRegion dirty; MergeBlocks(&dirty); - EXPECT_TRUE(dirty.isEmpty()); + EXPECT_TRUE(dirty.is_empty()); } TEST_F(DifferTest, MergeBlocks_SingleBlock) { @@ -525,7 +532,7 @@ TEST_F(DifferTest, MergeBlocks_BlockRect) { // may need to be updated if we modify how we merge blocks. TEST_F(DifferTest, MergeBlocks_MultiRect) { InitDiffer(kScreenWidth, kScreenHeight); - SkRegion dirty; + webrtc::DesktopRegion dirty; // +---+---+---+---+ +---+---+---+ // | | X | | _ | | | 0 | | @@ -541,7 +548,7 @@ TEST_F(DifferTest, MergeBlocks_MultiRect) { MarkBlocks(0, 1, 1, 1); MarkBlocks(2, 2, 1, 1); - dirty.setEmpty(); + dirty.Clear(); MergeBlocks(&dirty); ASSERT_EQ(3, RegionRectCount(dirty)); @@ -551,10 +558,10 @@ TEST_F(DifferTest, MergeBlocks_MultiRect) { // +---+---+---+---+ +---+---+---+ // | | | X | _ | | | | 0 | - // +---+---+---+---+ +---+---+---+ - // | X | X | X | _ | | 1 1 1 | - // +---+---+---+---+ => + + - // | X | X | X | _ | | 1 1 1 | + // +---+---+---+---+ +---+---+ + + // | X | X | X | _ | | 1 1 | 0 | + // +---+---+---+---+ => + | + + // | X | X | X | _ | | 1 1 | 0 | // +---+---+---+---+ +---+---+---+ // | _ | _ | _ | _ | // +---+---+---+---+ @@ -562,19 +569,19 @@ TEST_F(DifferTest, MergeBlocks_MultiRect) { MarkBlocks(2, 0, 1, 1); MarkBlocks(0, 1, 3, 2); - dirty.setEmpty(); + dirty.Clear(); MergeBlocks(&dirty); ASSERT_EQ(2, RegionRectCount(dirty)); - ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 2, 0, 1, 1)); - ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 1, 3, 2)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 2, 0, 1, 3)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 1, 2, 2)); // +---+---+---+---+ +---+---+---+ // | | | | _ | | | | | // +---+---+---+---+ +---+---+---+ // | X | | X | _ | | 0 | | 1 | // +---+---+---+---+ => + +---+ + - // | X | X | X | _ | | 2 | 2 | 2 | + // | X | X | X | _ | | 0 | 2 | 1 | // +---+---+---+---+ +---+---+---+ // | _ | _ | _ | _ | // +---+---+---+---+ @@ -583,20 +590,20 @@ TEST_F(DifferTest, MergeBlocks_MultiRect) { MarkBlocks(2, 1, 1, 1); MarkBlocks(0, 2, 3, 1); - dirty.setEmpty(); + dirty.Clear(); MergeBlocks(&dirty); ASSERT_EQ(3, RegionRectCount(dirty)); - ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 1, 1, 1)); - ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 2, 1, 1, 1)); - ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 2, 3, 1)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 1, 1, 2)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 2, 1, 1, 2)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 1, 2, 1, 1)); // +---+---+---+---+ +---+---+---+ // | X | X | X | _ | | 0 0 0 | // +---+---+---+---+ +---+---+---+ // | X | | X | _ | | 1 | | 2 | // +---+---+---+---+ => + +---+ + - // | X | X | X | _ | | 3 | 3 | 3 | + // | X | X | X | _ | | 1 | 3 | 2 | // +---+---+---+---+ +---+---+---+ // | _ | _ | _ | _ | // +---+---+---+---+ @@ -606,14 +613,14 @@ TEST_F(DifferTest, MergeBlocks_MultiRect) { MarkBlocks(2, 1, 1, 1); MarkBlocks(0, 2, 3, 1); - dirty.setEmpty(); + dirty.Clear(); MergeBlocks(&dirty); ASSERT_EQ(4, RegionRectCount(dirty)); ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 0, 3, 1)); - ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 1, 1, 1)); - ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 2, 1, 1, 1)); - ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 2, 3, 1)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 1, 1, 2)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 2, 1, 1, 2)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 1, 2, 1, 1)); // +---+---+---+---+ +---+---+---+ // | X | X | | _ | | 0 0 | | @@ -628,7 +635,7 @@ TEST_F(DifferTest, MergeBlocks_MultiRect) { MarkBlocks(0, 0, 2, 2); MarkBlocks(1, 2, 1, 1); - dirty.setEmpty(); + dirty.Clear(); MergeBlocks(&dirty); ASSERT_EQ(2, RegionRectCount(dirty)); diff --git a/media/video/capture/screen/mac/desktop_configuration.h b/media/video/capture/screen/mac/desktop_configuration.h index 3d03f39..dfa563f 100644 --- a/media/video/capture/screen/mac/desktop_configuration.h +++ b/media/video/capture/screen/mac/desktop_configuration.h @@ -11,8 +11,7 @@ #include "base/basictypes.h" #include "media/base/media_export.h" -#include "third_party/skia/include/core/SkPoint.h" -#include "third_party/skia/include/core/SkRect.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" namespace media { @@ -24,10 +23,10 @@ struct MEDIA_EXPORT MacDisplayConfiguration { CGDirectDisplayID id; // Bounds of this display in Density-Independent Pixels (DIPs). - SkIRect bounds; + webrtc::DesktopRect bounds; // Bounds of this display in physical pixels. - SkIRect pixel_bounds; + webrtc::DesktopRect pixel_bounds; // Scale factor from DIPs to physical pixels. float dip_to_pixel_scale; @@ -49,10 +48,10 @@ struct MEDIA_EXPORT MacDesktopConfiguration { MEDIA_EXPORT static MacDesktopConfiguration GetCurrent(Origin origin); // Bounds of the desktop in Density-Independent Pixels (DIPs). - SkIRect bounds; + webrtc::DesktopRect bounds; // Bounds of the desktop in physical pixels. - SkIRect pixel_bounds; + webrtc::DesktopRect pixel_bounds; // Scale factor from DIPs to physical pixels. float dip_to_pixel_scale; diff --git a/media/video/capture/screen/mac/desktop_configuration.mm b/media/video/capture/screen/mac/desktop_configuration.mm index fbece48..53b8e13 100644 --- a/media/video/capture/screen/mac/desktop_configuration.mm +++ b/media/video/capture/screen/mac/desktop_configuration.mm @@ -4,10 +4,11 @@ #include "media/video/capture/screen/mac/desktop_configuration.h" +#include <math.h> +#include <algorithm> #include <Cocoa/Cocoa.h> #include "base/logging.h" -#include "skia/ext/skia_utils_mac.h" #if !defined(MAC_OS_X_VERSION_10_7) || \ MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 @@ -23,18 +24,31 @@ namespace media { namespace { -SkIRect NSRectToSkIRect(const NSRect& ns_rect) { - SkIRect result; - gfx::CGRectToSkRect(NSRectToCGRect(ns_rect)).roundOut(&result); - return result; +webrtc::DesktopRect NSRectToDesktopRect(const NSRect& ns_rect) { + return webrtc::DesktopRect::MakeLTRB( + static_cast<int>(floor(ns_rect.origin.x)), + static_cast<int>(floor(ns_rect.origin.y)), + static_cast<int>(ceil(ns_rect.origin.x + ns_rect.size.width)), + static_cast<int>(ceil(ns_rect.origin.y + ns_rect.size.height))); +} + +webrtc::DesktopRect JoinRects(const webrtc::DesktopRect& a, + const webrtc::DesktopRect& b) { + return webrtc::DesktopRect::MakeLTRB( + std::min(a.left(), b.left()), + std::min(a.top(), b.top()), + std::max(a.right(), b.right()), + std::max(a.bottom(), b.bottom())); } // Inverts the position of |rect| from bottom-up coordinates to top-down, // relative to |bounds|. -void InvertRectYOrigin(const SkIRect& bounds, SkIRect* rect) { +void InvertRectYOrigin(const webrtc::DesktopRect& bounds, + webrtc::DesktopRect* rect) { DCHECK_EQ(0, bounds.top()); - rect->setXYWH(rect->x(), bounds.bottom() - rect->bottom(), - rect->width(), rect->height()); + *rect = webrtc::DesktopRect::MakeXYWH( + rect->left(), bounds.bottom() - rect->bottom(), + rect->width(), rect->height()); } MacDisplayConfiguration GetConfigurationForScreen(NSScreen* screen) { @@ -47,7 +61,7 @@ MacDisplayConfiguration GetConfigurationForScreen(NSScreen* screen) { // Determine the display's logical & physical dimensions. NSRect ns_bounds = [screen frame]; - display_config.bounds = NSRectToSkIRect(ns_bounds); + display_config.bounds = NSRectToDesktopRect(ns_bounds); // If the host is running Mac OS X 10.7+ or later, query the scaling factor // between logical and physical (aka "backing") pixels, otherwise assume 1:1. @@ -55,7 +69,7 @@ MacDisplayConfiguration GetConfigurationForScreen(NSScreen* screen) { [screen respondsToSelector:@selector(convertRectToBacking:)]) { display_config.dip_to_pixel_scale = [screen backingScaleFactor]; NSRect ns_pixel_bounds = [screen convertRectToBacking: ns_bounds]; - display_config.pixel_bounds = NSRectToSkIRect(ns_pixel_bounds); + display_config.pixel_bounds = NSRectToDesktopRect(ns_pixel_bounds); } else { display_config.pixel_bounds = display_config.bounds; } @@ -67,15 +81,11 @@ MacDisplayConfiguration GetConfigurationForScreen(NSScreen* screen) { MacDisplayConfiguration::MacDisplayConfiguration() : id(0), - bounds(SkIRect::MakeEmpty()), - pixel_bounds(SkIRect::MakeEmpty()), dip_to_pixel_scale(1.0f) { } MacDesktopConfiguration::MacDesktopConfiguration() - : bounds(SkIRect::MakeEmpty()), - pixel_bounds(SkIRect::MakeEmpty()), - dip_to_pixel_scale(1.0f) { + : dip_to_pixel_scale(1.0f) { } MacDesktopConfiguration::~MacDesktopConfiguration() { @@ -91,8 +101,8 @@ MacDesktopConfiguration MacDesktopConfiguration::GetCurrent(Origin origin) { // Iterator over the monitors, adding the primary monitor and monitors whose // DPI match that of the primary monitor. for (NSUInteger i = 0; i < [screens count]; ++i) { - MacDisplayConfiguration display_config - = GetConfigurationForScreen([screens objectAtIndex: i]); + MacDisplayConfiguration display_config = + GetConfigurationForScreen([screens objectAtIndex: i]); // Handling mixed-DPI is hard, so we only return displays that match the // "primary" display's DPI. The primary display is always the first in the @@ -118,8 +128,10 @@ MacDesktopConfiguration MacDesktopConfiguration::GetCurrent(Origin origin) { desktop_config.displays.push_back(display_config); // Update the desktop bounds to account for this display. - desktop_config.bounds.join(display_config.bounds); - desktop_config.pixel_bounds.join(display_config.pixel_bounds); + desktop_config.bounds = + JoinRects(desktop_config.bounds, display_config.bounds); + desktop_config.pixel_bounds = + JoinRects(desktop_config.pixel_bounds, display_config.pixel_bounds); } return desktop_config; diff --git a/media/video/capture/screen/mouse_cursor_shape.cc b/media/video/capture/screen/mouse_cursor_shape.cc deleted file mode 100644 index f57f7fb..0000000 --- a/media/video/capture/screen/mouse_cursor_shape.cc +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/video/capture/screen/mouse_cursor_shape.h" - -namespace media { - -MouseCursorShape::MouseCursorShape() - : size(SkISize::Make(0, 0)), - hotspot(SkIPoint::Make(0, 0)) { -} - -MouseCursorShape::~MouseCursorShape() { -} - -} // namespace media diff --git a/media/video/capture/screen/mouse_cursor_shape.h b/media/video/capture/screen/mouse_cursor_shape.h index e2d57f1..1e540562 100644 --- a/media/video/capture/screen/mouse_cursor_shape.h +++ b/media/video/capture/screen/mouse_cursor_shape.h @@ -7,22 +7,19 @@ #include <string> +#include "base/basictypes.h" #include "media/base/media_export.h" -#include "third_party/skia/include/core/SkPoint.h" -#include "third_party/skia/include/core/SkSize.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" namespace media { // Type used to return mouse cursor shape from video capturers. struct MEDIA_EXPORT MouseCursorShape { - MouseCursorShape(); - ~MouseCursorShape(); - // Size of the cursor in screen pixels. - SkISize size; + webrtc::DesktopSize size; // Coordinates of the cursor hotspot relative to upper-left corner. - SkIPoint hotspot; + webrtc::DesktopVector hotspot; // Cursor pixmap data in 32-bit BGRA format. std::string data; diff --git a/media/video/capture/screen/screen_capture_data.cc b/media/video/capture/screen/screen_capture_data.cc deleted file mode 100644 index 2869401..0000000 --- a/media/video/capture/screen/screen_capture_data.cc +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/video/capture/screen/screen_capture_data.h" - -namespace media { - -ScreenCaptureData::ScreenCaptureData(uint8* data, - int stride, - const SkISize& size) - : data_(data), - stride_(stride), - size_(size), - capture_time_ms_(0), - client_sequence_number_(0), - dpi_(SkIPoint::Make(0, 0)) { -} - -ScreenCaptureData::~ScreenCaptureData() {} - -} // namespace media diff --git a/media/video/capture/screen/screen_capture_data.h b/media/video/capture/screen/screen_capture_data.h deleted file mode 100644 index c5e4a09..0000000 --- a/media/video/capture/screen/screen_capture_data.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MEDIA_VIDEO_CAPTURE_SCREEN_CAPTURE_DATA_H_ -#define MEDIA_VIDEO_CAPTURE_SCREEN_CAPTURE_DATA_H_ - -#include <vector> - -#include "base/basictypes.h" -#include "base/memory/ref_counted.h" -#include "media/base/media_export.h" -#include "media/video/capture/screen/shared_buffer.h" -#include "third_party/skia/include/core/SkRegion.h" - -namespace media { - -class SharedBuffer; - -// Stores the data and information of a capture to pass off to the -// encoding thread. -class MEDIA_EXPORT ScreenCaptureData - : public base::RefCountedThreadSafe<ScreenCaptureData> { - public: - // 32 bit RGB is 4 bytes per pixel. - static const int kBytesPerPixel = 4; - - ScreenCaptureData(uint8* data, int stride, const SkISize& size); - - // Data buffer. - uint8* data() const { return data_; } - - // Distance in bytes between neighboring lines in the data buffer. - int stride() const { return stride_; } - - // Gets the dirty region from the previous capture. - const SkRegion& dirty_region() const { return dirty_region_; } - - // Returns the size of the image captured. - SkISize size() const { return size_; } - - SkRegion& mutable_dirty_region() { return dirty_region_; } - - // Returns the time spent on capturing. - int capture_time_ms() const { return capture_time_ms_; } - - // Sets the time spent on capturing. - void set_capture_time_ms(int capture_time_ms) { - capture_time_ms_ = capture_time_ms; - } - - int64 client_sequence_number() const { return client_sequence_number_; } - - void set_client_sequence_number(int64 client_sequence_number) { - client_sequence_number_ = client_sequence_number; - } - - SkIPoint dpi() const { return dpi_; } - - void set_dpi(const SkIPoint& dpi) { dpi_ = dpi; } - - // Returns the shared memory buffer pointed to by |data|. - scoped_refptr<SharedBuffer> shared_buffer() const { return shared_buffer_; } - - // Sets the shared memory buffer pointed to by |data|. - void set_shared_buffer(scoped_refptr<SharedBuffer> shared_buffer) { - shared_buffer_ = shared_buffer; - } - - private: - friend class base::RefCountedThreadSafe<ScreenCaptureData>; - virtual ~ScreenCaptureData(); - - uint8* data_; - int stride_; - SkRegion dirty_region_; - SkISize size_; - - // Time spent in capture. Unit is in milliseconds. - int capture_time_ms_; - - // Sequence number supplied by client for performance tracking. - int64 client_sequence_number_; - - // DPI for this frame. - SkIPoint dpi_; - - scoped_refptr<SharedBuffer> shared_buffer_; -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_SCREEN_CAPTURE_DATA_H_ diff --git a/media/video/capture/screen/screen_capture_device.cc b/media/video/capture/screen/screen_capture_device.cc index a4f55bd..546112b 100644 --- a/media/video/capture/screen/screen_capture_device.cc +++ b/media/video/capture/screen/screen_capture_device.cc @@ -10,9 +10,9 @@ #include "base/sequenced_task_runner.h" #include "base/synchronization/lock.h" #include "media/video/capture/screen/mouse_cursor_shape.h" -#include "media/video/capture/screen/screen_capture_data.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkDevice.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" namespace media { @@ -22,7 +22,7 @@ const int kBytesPerPixel = 4; class ScreenCaptureDevice::Core : public base::RefCountedThreadSafe<Core>, - public ScreenCapturer::Delegate { + public webrtc::DesktopCapturer::Callback { public: explicit Core(scoped_refptr<base::SequencedTaskRunner> task_runner); @@ -39,17 +39,14 @@ class ScreenCaptureDevice::Core void Stop(); void DeAllocate(); - // ScreenCapturer::Delegate interface. Called by |screen_capturer_| on the - // |task_runner_|. - virtual void OnCaptureCompleted( - scoped_refptr<ScreenCaptureData> capture_data) OVERRIDE; - virtual void OnCursorShapeChanged( - scoped_ptr<MouseCursorShape> cursor_shape) OVERRIDE; - private: friend class base::RefCountedThreadSafe<Core>; virtual ~Core(); + // webrtc::DesktopCapturer::Callback interface + virtual webrtc::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE; + virtual void OnCaptureCompleted(webrtc::DesktopFrame* frame) OVERRIDE; + // Helper methods that run on the |task_runner_|. Posted from the // corresponding public methods. void DoAllocate(int frame_rate); @@ -88,7 +85,7 @@ class ScreenCaptureDevice::Core // capture at least one frame. Once screen size is known it's stored in // |frame_size_|. bool waiting_for_frame_size_; - SkISize frame_size_; + webrtc::DesktopSize frame_size_; SkBitmap resized_bitmap_; // True between DoStart() and DoStop(). Can't just check |event_handler_| @@ -152,16 +149,28 @@ void ScreenCaptureDevice::Core::DeAllocate() { task_runner_->PostTask(FROM_HERE, base::Bind(&Core::DoDeAllocate, this)); } +webrtc::SharedMemory* +ScreenCaptureDevice::Core::CreateSharedMemory(size_t size) { + return NULL; +} + void ScreenCaptureDevice::Core::OnCaptureCompleted( - scoped_refptr<ScreenCaptureData> capture_data) { + webrtc::DesktopFrame* frame) { DCHECK(task_runner_->RunsTasksOnCurrentThread()); DCHECK(capture_in_progress_); - DCHECK(!capture_data->size().isEmpty()); capture_in_progress_ = false; + if (!frame) { + LOG(ERROR) << "Failed to capture a frame."; + event_handler_->OnError(); + return; + } + + scoped_ptr<webrtc::DesktopFrame> owned_frame(frame); + if (waiting_for_frame_size_) { - frame_size_ = capture_data->size(); + frame_size_ = frame->size(); waiting_for_frame_size_ = false; // Inform the EventHandler of the video frame dimensions and format. @@ -183,9 +192,9 @@ void ScreenCaptureDevice::Core::OnCaptureCompleted( return; size_t buffer_size = frame_size_.width() * frame_size_.height() * - ScreenCaptureData::kBytesPerPixel; + webrtc::DesktopFrame::kBytesPerPixel; - if (capture_data->size() == frame_size_) { + if (frame->size().equals(frame_size_)) { // If the captured frame matches the requested size, we don't need to // resize it. resized_bitmap_.reset(); @@ -193,8 +202,7 @@ void ScreenCaptureDevice::Core::OnCaptureCompleted( base::AutoLock auto_lock(event_handler_lock_); if (event_handler_) { event_handler_->OnIncomingCapturedFrame( - capture_data->data(), buffer_size, base::Time::Now(), - 0, false, false); + frame->data(), buffer_size, base::Time::Now(), 0, false, false); } return; } @@ -203,7 +211,7 @@ void ScreenCaptureDevice::Core::OnCaptureCompleted( // is stored to |resized_bitmap_|. Only regions of the screen that are // changing are copied. - SkRegion dirty_region = capture_data->dirty_region(); + webrtc::DesktopRegion dirty_region = frame->updated_region(); if (resized_bitmap_.width() != frame_size_.width() || resized_bitmap_.height() != frame_size_.height()) { @@ -211,13 +219,13 @@ void ScreenCaptureDevice::Core::OnCaptureCompleted( frame_size_.width(), frame_size_.height()); resized_bitmap_.setIsOpaque(true); resized_bitmap_.allocPixels(); - dirty_region.setRect(SkIRect::MakeSize(frame_size_)); + dirty_region.SetRect(webrtc::DesktopRect::MakeSize(frame_size_)); } float scale_x = static_cast<float>(frame_size_.width()) / - capture_data->size().width(); + frame->size().width(); float scale_y = static_cast<float>(frame_size_.height()) / - capture_data->size().height(); + frame->size().height(); float scale; float x, y; // Center the image in case aspect ratio is different. @@ -236,16 +244,17 @@ void ScreenCaptureDevice::Core::OnCaptureCompleted( SkCanvas canvas(&device); canvas.scale(scale, scale); - int source_stride = capture_data->stride(); - for (SkRegion::Iterator i(dirty_region); !i.done(); i.next()) { + int source_stride = frame->stride(); + for (webrtc::DesktopRegion::Iterator i(dirty_region); !i.IsAtEnd(); + i.Advance()) { SkBitmap source_bitmap; source_bitmap.setConfig(SkBitmap::kARGB_8888_Config, i.rect().width(), i.rect().height(), source_stride); source_bitmap.setIsOpaque(true); source_bitmap.setPixels( - capture_data->data() + i.rect().top() * source_stride + - i.rect().left() * ScreenCaptureData::kBytesPerPixel); + frame->data() + i.rect().top() * source_stride + + i.rect().left() * webrtc::DesktopFrame::kBytesPerPixel); canvas.drawBitmap(source_bitmap, i.rect().left() + x / scale, i.rect().top() + y / scale, NULL); } @@ -258,13 +267,6 @@ void ScreenCaptureDevice::Core::OnCaptureCompleted( } } -void ScreenCaptureDevice::Core::OnCursorShapeChanged( - scoped_ptr<MouseCursorShape> cursor_shape) { - // TODO(sergeyu): Store mouse cursor shape and then render it to each captured - // frame. crbug.com/173265 . - DCHECK(task_runner_->RunsTasksOnCurrentThread()); -} - void ScreenCaptureDevice::Core::DoAllocate(int frame_rate) { DCHECK(task_runner_->RunsTasksOnCurrentThread()); @@ -338,16 +340,14 @@ void ScreenCaptureDevice::Core::OnCaptureTimer() { } void ScreenCaptureDevice::Core::DoCapture() { + DCHECK(task_runner_->RunsTasksOnCurrentThread()); DCHECK(!capture_in_progress_); capture_in_progress_ = true; - screen_capturer_->CaptureFrame(); + screen_capturer_->Capture(webrtc::DesktopRegion()); - // Assume that ScreenCapturer always calls OnCaptureCompleted() - // callback before it returns. - // - // TODO(sergeyu): Fix ScreenCapturer to return video frame - // synchronously instead of using Delegate interface. + // Currently only synchronous implementations of DesktopCapturer are + // supported. DCHECK(!capture_in_progress_); } diff --git a/media/video/capture/screen/screen_capture_device_unittest.cc b/media/video/capture/screen/screen_capture_device_unittest.cc index 6b74465..0247bb9 100644 --- a/media/video/capture/screen/screen_capture_device_unittest.cc +++ b/media/video/capture/screen/screen_capture_device_unittest.cc @@ -10,9 +10,10 @@ #include "base/test/test_timeouts.h" #include "base/threading/sequenced_worker_pool.h" #include "base/time.h" -#include "media/video/capture/screen/screen_capture_data.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" using ::testing::_; using ::testing::DoAll; @@ -51,33 +52,33 @@ class MockFrameObserver : public VideoCaptureDevice::EventHandler { class FakeScreenCapturer : public ScreenCapturer { public: FakeScreenCapturer() - : delegate_(NULL), + : callback_(NULL), frame_index_(0) { - buffer_.reset(new uint8[kBufferSize]); - frames_[0] = new ScreenCaptureData( - buffer_.get(), kTestFrameWidth1 * ScreenCaptureData::kBytesPerPixel, - SkISize::Make(kTestFrameWidth1, kTestFrameHeight1)); - frames_[1] = new ScreenCaptureData( - buffer_.get(), kTestFrameWidth2 * ScreenCaptureData::kBytesPerPixel, - SkISize::Make(kTestFrameWidth2, kTestFrameHeight2)); } virtual ~FakeScreenCapturer() {} // VideoFrameCapturer interface. - virtual void Start(Delegate* delegate) OVERRIDE { - delegate_ = delegate; + virtual void Start(Callback* callback) OVERRIDE { + callback_ = callback; } - virtual void CaptureFrame() OVERRIDE { - scoped_refptr<ScreenCaptureData> frame = - frames_[frame_index_ % arraysize(frames_)]; + + virtual void Capture(const webrtc::DesktopRegion& region) OVERRIDE { + webrtc::DesktopSize size; + if (frame_index_ % 2 == 0) { + size = webrtc::DesktopSize(kTestFrameWidth1, kTestFrameHeight1); + } else { + size = webrtc::DesktopSize(kTestFrameWidth2, kTestFrameHeight2); + } frame_index_++; - delegate_->OnCaptureCompleted(frame); + callback_->OnCaptureCompleted(new webrtc::BasicDesktopFrame(size)); + } + + virtual void SetMouseShapeObserver( + MouseShapeObserver* mouse_shape_observer) OVERRIDE { } private: - Delegate* delegate_; - scoped_ptr<uint8[]> buffer_; - scoped_refptr<ScreenCaptureData> frames_[2]; + Callback* callback_; int frame_index_; }; diff --git a/media/video/capture/screen/screen_capture_frame.cc b/media/video/capture/screen/screen_capture_frame.cc deleted file mode 100644 index 4da28eb..0000000 --- a/media/video/capture/screen/screen_capture_frame.cc +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/video/capture/screen/screen_capture_frame.h" - -namespace media { - -ScreenCaptureFrame::~ScreenCaptureFrame() { -} - -ScreenCaptureFrame::ScreenCaptureFrame() - : bytes_per_row_(0), - dimensions_(SkISize::Make(0, 0)), - pixels_(NULL) { -} - -} // namespace media diff --git a/media/video/capture/screen/screen_capture_frame.h b/media/video/capture/screen/screen_capture_frame.h deleted file mode 100644 index 090501e..0000000 --- a/media/video/capture/screen/screen_capture_frame.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MEDIA_VIDEO_CAPTURE_SCREEN_SCREEN_CAPTURE_FRAME_H_ -#define MEDIA_VIDEO_CAPTURE_SCREEN_SCREEN_CAPTURE_FRAME_H_ - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/memory/ref_counted.h" -#include "media/base/media_export.h" -#include "media/video/capture/screen/shared_buffer.h" -#include "third_party/skia/include/core/SkSize.h" -#include "third_party/skia/include/core/SkTypes.h" - -namespace media { - -// Represents a video frame. -class MEDIA_EXPORT ScreenCaptureFrame { - public: - virtual ~ScreenCaptureFrame(); - - int bytes_per_row() const { return bytes_per_row_; } - const SkISize& dimensions() const { return dimensions_; } - uint8* pixels() const { return pixels_; } - const scoped_refptr<SharedBuffer>& shared_buffer() const { - return shared_buffer_; - } - - protected: - // Initializes an empty video frame. Derived classes are expected to allocate - // memory for the frame in a platform-specific way and set the properties of - // the allocated frame. - ScreenCaptureFrame(); - - void set_bytes_per_row(int bytes_per_row) { - bytes_per_row_ = bytes_per_row; - } - - void set_dimensions(const SkISize& dimensions) { dimensions_ = dimensions; } - void set_pixels(uint8* ptr) { pixels_ = ptr; } - void set_shared_buffer(scoped_refptr<SharedBuffer> shared_buffer) { - shared_buffer_ = shared_buffer; - } - - private: - // Bytes per row of pixels including necessary padding. - int bytes_per_row_; - - // Dimensions of the buffer in pixels. - SkISize dimensions_; - - // Points to the pixel buffer. - uint8* pixels_; - - // Points to an optional shared memory buffer that backs up |pixels_| buffer. - scoped_refptr<SharedBuffer> shared_buffer_; - - DISALLOW_COPY_AND_ASSIGN(ScreenCaptureFrame); -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_SCREEN_SCREEN_CAPTURE_FRAME_H_ diff --git a/media/video/capture/screen/screen_capture_frame_queue.cc b/media/video/capture/screen/screen_capture_frame_queue.cc index 610a062..5402acf 100644 --- a/media/video/capture/screen/screen_capture_frame_queue.cc +++ b/media/video/capture/screen/screen_capture_frame_queue.cc @@ -7,33 +7,33 @@ #include <algorithm> #include "base/basictypes.h" -#include "media/video/capture/screen/screen_capture_frame.h" +#include "base/logging.h" +#include "base/threading/non_thread_safe.h" +#include "media/video/capture/screen/shared_desktop_frame.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" namespace media { -ScreenCaptureFrameQueue::ScreenCaptureFrameQueue() - : current_(0), - previous_(NULL) { - SetAllFramesNeedUpdate(); -} +ScreenCaptureFrameQueue::ScreenCaptureFrameQueue() : current_(0) {} -ScreenCaptureFrameQueue::~ScreenCaptureFrameQueue() { -} +ScreenCaptureFrameQueue::~ScreenCaptureFrameQueue() {} -void ScreenCaptureFrameQueue::DoneWithCurrentFrame() { - previous_ = current_frame(); +void ScreenCaptureFrameQueue::MoveToNextFrame() { current_ = (current_ + 1) % kQueueLength; + + // Verify that the frame is not shared, i.e. that consumer has released it + // before attempting to capture again. + DCHECK(!frames_[current_] || !frames_[current_]->IsShared()); } void ScreenCaptureFrameQueue::ReplaceCurrentFrame( - scoped_ptr<ScreenCaptureFrame> frame) { - frames_[current_] = frame.Pass(); - needs_update_[current_] = false; + scoped_ptr<webrtc::DesktopFrame> frame) { + frames_[current_].reset(SharedDesktopFrame::Wrap(frame.release())); } -void ScreenCaptureFrameQueue::SetAllFramesNeedUpdate() { - std::fill(needs_update_, needs_update_ + arraysize(needs_update_), true); - previous_ = NULL; +void ScreenCaptureFrameQueue::Reset() { + for (int i = 0; i < kQueueLength; ++i) + frames_[i].reset(); } } // namespace media diff --git a/media/video/capture/screen/screen_capture_frame_queue.h b/media/video/capture/screen/screen_capture_frame_queue.h index d36f15a..c51c563 100644 --- a/media/video/capture/screen/screen_capture_frame_queue.h +++ b/media/video/capture/screen/screen_capture_frame_queue.h @@ -7,20 +7,27 @@ #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" +#include "media/video/capture/screen/shared_desktop_frame.h" -namespace media { +namespace webrtc { +class DesktopFrame; +} // namespace webrtc -class ScreenCaptureFrame; +namespace media { // Represents a queue of reusable video frames. Provides access to the 'current' -// frame - the frame that the caller is working with at the moment, and to -// the 'previous' frame - the predecessor of the current frame swapped by -// DoneWithCurrentFrame() call, if any. +// frame - the frame that the caller is working with at the moment, and to the +// 'previous' frame - the predecessor of the current frame swapped by +// MoveToNextFrame() call, if any. // -// The caller is expected to (re)allocate frames if current_frame_needs_update() -// is set. The caller can mark all frames in the queue for reallocation (when, -// say, frame dimensions change). The queue records which frames need updating +// The caller is expected to (re)allocate frames if current_frame() returns +// NULL. The caller can mark all frames in the queue for reallocation (when, +// say, frame dimensions change). The queue records which frames need updating // which the caller can query. +// +// Frame consumer is expected to never hold more than kQueueLength frames +// created by this function and it should release the earliest one before trying +// to capture a new frame (i.e. before MoveToNextFrame() is called). class ScreenCaptureFrameQueue { public: ScreenCaptureFrameQueue(); @@ -28,38 +35,30 @@ class ScreenCaptureFrameQueue { // Moves to the next frame in the queue, moving the 'current' frame to become // the 'previous' one. - void DoneWithCurrentFrame(); + void MoveToNextFrame(); // Replaces the current frame with a new one allocated by the caller. // The existing frame (if any) is destroyed. - void ReplaceCurrentFrame(scoped_ptr<ScreenCaptureFrame> frame); + void ReplaceCurrentFrame(scoped_ptr<webrtc::DesktopFrame> frame); // Marks all frames obsolete and resets the previous frame pointer. No // frames are freed though as the caller can still access them. - void SetAllFramesNeedUpdate(); + void Reset(); - ScreenCaptureFrame* current_frame() const { + SharedDesktopFrame* current_frame() const { return frames_[current_].get(); } - bool current_frame_needs_update() const { - return !current_frame() || needs_update_[current_]; + SharedDesktopFrame* previous_frame() const { + return frames_[(current_ + kQueueLength - 1) % kQueueLength].get(); } - ScreenCaptureFrame* previous_frame() const { return previous_; } - private: // Index of the current frame. int current_; static const int kQueueLength = 2; - scoped_ptr<ScreenCaptureFrame> frames_[kQueueLength]; - - // True if the corresponding frame needs to be re-allocated. - bool needs_update_[kQueueLength]; - - // Points to the previous frame if any. - ScreenCaptureFrame* previous_; + scoped_ptr<SharedDesktopFrame> frames_[kQueueLength]; DISALLOW_COPY_AND_ASSIGN(ScreenCaptureFrameQueue); }; diff --git a/media/video/capture/screen/screen_capturer.h b/media/video/capture/screen/screen_capturer.h index bc3d454..5fef2a1 100644 --- a/media/video/capture/screen/screen_capturer.h +++ b/media/video/capture/screen/screen_capturer.h @@ -8,15 +8,12 @@ #include "base/basictypes.h" #include "base/callback.h" #include "base/memory/ref_counted.h" -#include "base/shared_memory.h" #include "media/base/media_export.h" -#include "media/video/capture/screen/shared_buffer.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" namespace media { -class ScreenCaptureData; struct MouseCursorShape; -class SharedBuffer; // Class used to capture video frames asynchronously. // @@ -36,32 +33,22 @@ class SharedBuffer; // Implementation has to ensure the following guarantees: // 1. Double buffering // Since data can be read while another capture action is happening. -class MEDIA_EXPORT ScreenCapturer { +class MEDIA_EXPORT ScreenCapturer + : public NON_EXPORTED_BASE(webrtc::DesktopCapturer) { public: // Provides callbacks used by the capturer to pass captured video frames and // mouse cursor shapes to the processing pipeline. - class MEDIA_EXPORT Delegate { + // + // TODO(sergeyu): Move cursor shape capturing to a separate class because it's + // unrelated. + class MEDIA_EXPORT MouseShapeObserver { public: - // Creates a shared memory buffer of the given size. Returns NULL if shared - // buffers are not supported. - virtual scoped_refptr<SharedBuffer> CreateSharedBuffer(uint32 size); - - // Notifies the delegate that the buffer is no longer used and can be - // released. - virtual void ReleaseSharedBuffer(scoped_refptr<SharedBuffer> buffer); - - // Called when a video frame has been captured. |capture_data| describes - // a captured frame. - virtual void OnCaptureCompleted( - scoped_refptr<ScreenCaptureData> capture_data) = 0; - // Called when the cursor shape has changed. - // TODO(sergeyu): Move cursor shape capturing to a separate class. virtual void OnCursorShapeChanged( scoped_ptr<MouseCursorShape> cursor_shape) = 0; protected: - virtual ~Delegate() {} + virtual ~MouseShapeObserver() {} }; virtual ~ScreenCapturer() {} @@ -77,20 +64,12 @@ class MEDIA_EXPORT ScreenCapturer { // Creates Windows-specific capturer and instructs it whether or not to // disable desktop compositing. static scoped_ptr<ScreenCapturer> CreateWithDisableAero(bool disable_aero); -#endif - - // Called at the beginning of a capturing session. |delegate| must remain - // valid until Stop() is called. - virtual void Start(Delegate* delegate) = 0; +#endif // defined(OS_WIN) - // Captures the screen data associated with each of the accumulated - // dirty region. When the capture is complete, the delegate is notified even - // if the dirty region is empty. - // - // It is OK to call this method while another thread is reading - // data of the previous capture. There can be at most one concurrent read - // going on when this method is called. - virtual void CaptureFrame() = 0; + // Called at the beginning of a capturing session. |mouse_shape_observer| must + // remain valid until the capturer is destroyed. + virtual void SetMouseShapeObserver( + MouseShapeObserver* mouse_shape_observer) = 0; }; } // namespace media diff --git a/media/video/capture/screen/screen_capturer_fake.cc b/media/video/capture/screen/screen_capturer_fake.cc index ff4dedb..416bcbb 100644 --- a/media/video/capture/screen/screen_capturer_fake.cc +++ b/media/video/capture/screen/screen_capturer_fake.cc @@ -4,8 +4,9 @@ #include "media/video/capture/screen/screen_capturer_fake.h" +#include "base/logging.h" #include "base/time.h" -#include "media/video/capture/screen/screen_capture_data.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" namespace media { @@ -24,66 +25,73 @@ COMPILE_ASSERT((kBoxWidth % kSpeed == 0) && (kWidth % kSpeed == 0) && sizes_must_be_multiple_of_kSpeed); ScreenCapturerFake::ScreenCapturerFake() - : size_(SkISize::Make(0, 0)), + : callback_(NULL), + mouse_shape_observer_(NULL), bytes_per_row_(0), box_pos_x_(0), box_pos_y_(0), box_speed_x_(kSpeed), - box_speed_y_(kSpeed), - current_buffer_(0) { + box_speed_y_(kSpeed) { ScreenConfigurationChanged(); } ScreenCapturerFake::~ScreenCapturerFake() { } -void ScreenCapturerFake::Start(Delegate* delegate) { - delegate_ = delegate; +void ScreenCapturerFake::Start(Callback* callback) { + DCHECK(!callback_); + DCHECK(callback); + callback_ = callback; +} + +void ScreenCapturerFake::Capture(const webrtc::DesktopRegion& region) { + base::Time capture_start_time = base::Time::Now(); - // Create memory for the buffers. - int buffer_size = size_.height() * bytes_per_row_; - for (int i = 0; i < kNumBuffers; i++) { - shared_buffers_[i] = delegate_->CreateSharedBuffer(buffer_size); - if (shared_buffers_[i]) { - buffers_[i] = reinterpret_cast<uint8*>(shared_buffers_[i]->ptr()); + queue_.MoveToNextFrame(); + + if (!queue_.current_frame()) { + int buffer_size = size_.height() * bytes_per_row_; + webrtc::SharedMemory* shared_memory = + callback_->CreateSharedMemory(buffer_size); + scoped_ptr<webrtc::DesktopFrame> frame; + webrtc::DesktopSize frame_size(size_.width(), size_.height()); + if (shared_memory) { + frame.reset(new webrtc::SharedMemoryDesktopFrame( + frame_size, bytes_per_row_, shared_memory)); } else { - private_buffers_[i].reset(new uint8[buffer_size]); - buffers_[i] = private_buffers_[i].get(); + frame.reset(new webrtc::BasicDesktopFrame(frame_size)); } + queue_.ReplaceCurrentFrame(frame.Pass()); } -} - -void ScreenCapturerFake::CaptureFrame() { - base::Time capture_start_time = base::Time::Now(); + DCHECK(queue_.current_frame()); GenerateImage(); - helper_.InvalidateScreen(size_); - - SkRegion invalid_region; - helper_.SwapInvalidRegion(&invalid_region); - current_buffer_ = (current_buffer_ + 1) % kNumBuffers; - - scoped_refptr<ScreenCaptureData> capture_data(new ScreenCaptureData( - buffers_[current_buffer_], bytes_per_row_, size_)); - capture_data->mutable_dirty_region() = invalid_region; - - helper_.set_size_most_recent(size_); + queue_.current_frame()->mutable_updated_region()->SetRect( + webrtc::DesktopRect::MakeSize(size_)); + queue_.current_frame()->set_capture_time_ms( + (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp()); - capture_data->set_shared_buffer(shared_buffers_[current_buffer_]); + callback_->OnCaptureCompleted(queue_.current_frame()->Share()); +} - capture_data->set_capture_time_ms( - (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp()); - delegate_->OnCaptureCompleted(capture_data); +void ScreenCapturerFake::SetMouseShapeObserver( + MouseShapeObserver* mouse_shape_observer) { + DCHECK(!mouse_shape_observer_); + DCHECK(mouse_shape_observer); + mouse_shape_observer_ = mouse_shape_observer; } void ScreenCapturerFake::GenerateImage() { - memset(buffers_[current_buffer_], 0xff, - size_.width() * size_.height() * ScreenCaptureData::kBytesPerPixel); + webrtc::DesktopFrame* frame = queue_.current_frame(); + + const int kBytesPerPixel = webrtc::DesktopFrame::kBytesPerPixel; + + memset(frame->data(), 0xff, + size_.width() * size_.height() * kBytesPerPixel); - uint8* row = buffers_[current_buffer_] + - (box_pos_y_ * size_.width() + box_pos_x_) * - ScreenCaptureData::kBytesPerPixel; + uint8* row = frame->data() + + (box_pos_y_ * size_.width() + box_pos_x_) * kBytesPerPixel; box_pos_x_ += box_speed_x_; if (box_pos_x_ + kBoxWidth >= size_.width() || box_pos_x_ == 0) @@ -102,18 +110,19 @@ void ScreenCapturerFake::GenerateImage() { int r = x * 255 / kBoxWidth; int g = y * 255 / kBoxHeight; int b = 255 - (x * 255 / kBoxWidth); - row[x * ScreenCaptureData::kBytesPerPixel] = r; - row[x * ScreenCaptureData::kBytesPerPixel + 1] = g; - row[x * ScreenCaptureData::kBytesPerPixel + 2] = b; - row[x * ScreenCaptureData::kBytesPerPixel + 3] = 0xff; + row[x * kBytesPerPixel] = r; + row[x * kBytesPerPixel + 1] = g; + row[x * kBytesPerPixel + 2] = b; + row[x * kBytesPerPixel + 3] = 0xff; } row += bytes_per_row_; } } void ScreenCapturerFake::ScreenConfigurationChanged() { - size_ = SkISize::Make(kWidth, kHeight); - bytes_per_row_ = size_.width() * ScreenCaptureData::kBytesPerPixel; + size_.set(kWidth, kHeight); + queue_.Reset(); + bytes_per_row_ = size_.width() * webrtc::DesktopFrame::kBytesPerPixel; } } // namespace media diff --git a/media/video/capture/screen/screen_capturer_fake.h b/media/video/capture/screen/screen_capturer_fake.h index 9a8dba9..de67fbd 100644 --- a/media/video/capture/screen/screen_capturer_fake.h +++ b/media/video/capture/screen/screen_capturer_fake.h @@ -7,8 +7,9 @@ #include "base/memory/scoped_ptr.h" #include "media/base/media_export.h" +#include "media/video/capture/screen/screen_capture_frame_queue.h" #include "media/video/capture/screen/screen_capturer.h" -#include "media/video/capture/screen/screen_capturer_helper.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" namespace media { @@ -24,9 +25,13 @@ class MEDIA_EXPORT ScreenCapturerFake : public ScreenCapturer { ScreenCapturerFake(); virtual ~ScreenCapturerFake(); - // Overridden from ScreenCapturer: - virtual void Start(Delegate* delegate) OVERRIDE; - virtual void CaptureFrame() OVERRIDE; + // webrtc::DesktopCapturer interface. + virtual void Start(Callback* callback) OVERRIDE; + virtual void Capture(const webrtc::DesktopRegion& rect) OVERRIDE; + + // ScreenCapturer interface. + virtual void SetMouseShapeObserver( + MouseShapeObserver* mouse_shape_observer) OVERRIDE; private: // Generates an image in the front buffer. @@ -35,29 +40,17 @@ class MEDIA_EXPORT ScreenCapturerFake : public ScreenCapturer { // Called when the screen configuration is changed. void ScreenConfigurationChanged(); - Delegate* delegate_; + Callback* callback_; + MouseShapeObserver* mouse_shape_observer_; - SkISize size_; + webrtc::DesktopSize size_; int bytes_per_row_; int box_pos_x_; int box_pos_y_; int box_speed_x_; int box_speed_y_; - ScreenCapturerHelper helper_; - - // We have two buffers for the screen images as required by Capturer. - static const int kNumBuffers = 2; - uint8* buffers_[kNumBuffers]; - - // The current buffer with valid data for reading. - int current_buffer_; - - // Used when |delegate_| implements CreateSharedBuffer(). - scoped_refptr<SharedBuffer> shared_buffers_[kNumBuffers]; - - // Used when |delegate_| does not implement CreateSharedBuffer(). - scoped_ptr<uint8[]> private_buffers_[kNumBuffers]; + ScreenCaptureFrameQueue queue_; DISALLOW_COPY_AND_ASSIGN(ScreenCapturerFake); }; diff --git a/media/video/capture/screen/screen_capturer_helper.cc b/media/video/capture/screen/screen_capturer_helper.cc index 2f45342..e85cf3b 100644 --- a/media/video/capture/screen/screen_capturer_helper.cc +++ b/media/video/capture/screen/screen_capturer_helper.cc @@ -12,7 +12,6 @@ namespace media { ScreenCapturerHelper::ScreenCapturerHelper() : - size_most_recent_(SkISize::Make(0, 0)), log_grid_size_(0) { } @@ -25,33 +24,43 @@ void ScreenCapturerHelper::ClearInvalidRegion() { } void ScreenCapturerHelper::InvalidateRegion( - const SkRegion& invalid_region) { + const webrtc::DesktopRegion& invalid_region) { base::AutoLock auto_invalid_region_lock(invalid_region_lock_); - invalid_region_.op(invalid_region, SkRegion::kUnion_Op); + for (webrtc::DesktopRegion::Iterator it(invalid_region); + !it.IsAtEnd(); it.Advance()) { + invalid_region_.op(SkIRect::MakeLTRB(it.rect().left(), it.rect().top(), + it.rect().right(), it.rect().bottom()), + SkRegion::kUnion_Op); + } } -void ScreenCapturerHelper::InvalidateScreen(const SkISize& size) { +void ScreenCapturerHelper::InvalidateScreen(const webrtc::DesktopSize& size) { base::AutoLock auto_invalid_region_lock(invalid_region_lock_); invalid_region_.op(SkIRect::MakeWH(size.width(), size.height()), SkRegion::kUnion_Op); } -void ScreenCapturerHelper::InvalidateFullScreen() { - if (!size_most_recent_.isZero()) - InvalidateScreen(size_most_recent_); -} - -void ScreenCapturerHelper::SwapInvalidRegion(SkRegion* invalid_region) { +void ScreenCapturerHelper::TakeInvalidRegion( + webrtc::DesktopRegion* invalid_region) { + SkRegion sk_invalid_region; { base::AutoLock auto_invalid_region_lock(invalid_region_lock_); - invalid_region->swap(invalid_region_); + sk_invalid_region.swap(invalid_region_); } + if (log_grid_size_ > 0) { scoped_ptr<SkRegion> expanded_region( - ExpandToGrid(*invalid_region, log_grid_size_)); - invalid_region->swap(*expanded_region); - invalid_region->op(SkRegion(SkIRect::MakeSize(size_most_recent_)), - SkRegion::kIntersect_Op); + ExpandToGrid(sk_invalid_region, log_grid_size_)); + sk_invalid_region.swap(*expanded_region); + sk_invalid_region.op(SkIRect::MakeWH(size_most_recent_.width(), + size_most_recent_.height()), + SkRegion::kIntersect_Op); + } + invalid_region->Clear(); + for (SkRegion::Iterator it(sk_invalid_region); !it.done(); it.next()) { + invalid_region->AddRect(webrtc::DesktopRect::MakeLTRB( + it.rect().left(), it.rect().top(), + it.rect().right(), it.rect().bottom())); } } @@ -59,11 +68,12 @@ void ScreenCapturerHelper::SetLogGridSize(int log_grid_size) { log_grid_size_ = log_grid_size; } -const SkISize& ScreenCapturerHelper::size_most_recent() const { +const webrtc::DesktopSize& ScreenCapturerHelper::size_most_recent() const { return size_most_recent_; } -void ScreenCapturerHelper::set_size_most_recent(const SkISize& size) { +void ScreenCapturerHelper::set_size_most_recent( + const webrtc::DesktopSize& size) { size_most_recent_ = size; } diff --git a/media/video/capture/screen/screen_capturer_helper.h b/media/video/capture/screen/screen_capturer_helper.h index 7b5e27e..35260b2 100644 --- a/media/video/capture/screen/screen_capturer_helper.h +++ b/media/video/capture/screen/screen_capturer_helper.h @@ -9,6 +9,8 @@ #include "base/synchronization/lock.h" #include "media/base/media_export.h" #include "third_party/skia/include/core/SkRegion.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_region.h" namespace media { @@ -25,28 +27,25 @@ class MEDIA_EXPORT ScreenCapturerHelper { void ClearInvalidRegion(); // Invalidate the specified region. - void InvalidateRegion(const SkRegion& invalid_region); + void InvalidateRegion(const webrtc::DesktopRegion& invalid_region); // Invalidate the entire screen, of a given size. - void InvalidateScreen(const SkISize& size); + void InvalidateScreen(const webrtc::DesktopSize& size); - // Invalidate the entire screen, using the size of the most recently - // captured screen. - void InvalidateFullScreen(); - - // Swap the given region with the stored invalid region. - void SwapInvalidRegion(SkRegion* invalid_region); + // Copies current invalid region to |invalid_region| clears invalid region + // storage for the next frame. + void TakeInvalidRegion(webrtc::DesktopRegion* invalid_region); // Access the size of the most recently captured screen. - const SkISize& size_most_recent() const; - void set_size_most_recent(const SkISize& size); + const webrtc::DesktopSize& size_most_recent() const; + void set_size_most_recent(const webrtc::DesktopSize& size); // Lossy compression can result in color values leaking between pixels in one // block. If part of a block changes, then unchanged parts of that block can // be changed in the compressed output. So we need to re-render an entire // block whenever part of the block changes. // - // If |log_grid_size| is >= 1, then this function makes SwapInvalidRegion + // If |log_grid_size| is >= 1, then this function makes TakeInvalidRegion() // produce an invalid region expanded so that its vertices lie on a grid of // size 2 ^ |log_grid_size|. The expanded region is then clipped to the size // of the most recently captured screen, as previously set by @@ -69,7 +68,7 @@ class MEDIA_EXPORT ScreenCapturerHelper { base::Lock invalid_region_lock_; // The size of the most recently captured screen. - SkISize size_most_recent_; + webrtc::DesktopSize size_most_recent_; // The log (base 2) of the size of the grid to which the invalid region is // expanded. diff --git a/media/video/capture/screen/screen_capturer_helper_unittest.cc b/media/video/capture/screen/screen_capturer_helper_unittest.cc index dc22231..7477786 100644 --- a/media/video/capture/screen/screen_capturer_helper_unittest.cc +++ b/media/video/capture/screen/screen_capturer_helper_unittest.cc @@ -7,6 +7,10 @@ #include "base/memory/scoped_ptr.h" #include "testing/gtest/include/gtest/gtest.h" +using webrtc::DesktopRect; +using webrtc::DesktopRegion; +using webrtc::DesktopSize; + namespace media { class ScreenCapturerHelperTest : public testing::Test { @@ -14,114 +18,120 @@ class ScreenCapturerHelperTest : public testing::Test { ScreenCapturerHelper capturer_helper_; }; +bool Equals(const DesktopRegion& region1, const DesktopRegion& region2) { + DesktopRegion::Iterator iter1(region1); + DesktopRegion::Iterator iter2(region2); + while (!iter1.IsAtEnd() && !iter1.IsAtEnd()) { + if (!iter1.rect().equals(iter2.rect())) { + return false; + } + iter1.Advance(); + iter2.Advance(); + } + return iter1.IsAtEnd() && iter2.IsAtEnd(); +} + bool Equals(const SkRegion& region1, const SkRegion& region2) { SkRegion::Iterator iter1(region1); SkRegion::Iterator iter2(region2); - while (!iter1.done()) { - SkIRect rect1 = iter1.rect(); - iter1.next(); - if (iter2.done()) { + while (!iter1.done() && !iter2.done()) { + if (iter1.rect() != iter2.rect()) { return false; } - SkIRect rect2 = iter2.rect(); + iter1.next(); iter2.next(); - if (rect1 != rect2) { - return false; - } } - if (!iter2.done()) { - return false; - } - return true; + return iter1.done() && iter2.done(); +} + +DesktopRegion RectToRegion(const DesktopRect& rect) { + webrtc::DesktopRegion result; + result.SetRect(rect); + return result; } TEST_F(ScreenCapturerHelperTest, ClearInvalidRegion) { - SkRegion region; - capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(1, 2, 3, 4))); + DesktopRegion region; + region.SetRect(DesktopRect::MakeXYWH(1, 2, 3, 4)); + capturer_helper_.InvalidateRegion(region); capturer_helper_.ClearInvalidRegion(); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(region.isEmpty()); + capturer_helper_.TakeInvalidRegion(®ion); + ASSERT_TRUE(region.is_empty()); } TEST_F(ScreenCapturerHelperTest, InvalidateRegion) { - SkRegion region; - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeEmpty()), region)); - - capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(1, 2, 3, 4))); - region.setEmpty(); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(1, 2, 3, 4)), region)); - - capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(1, 2, 3, 4))); - capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(4, 2, 3, 4))); - region.setEmpty(); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(1, 2, 6, 4)), region)); + DesktopRegion region; + capturer_helper_.TakeInvalidRegion(®ion); + ASSERT_TRUE(region.is_empty()); + + region.SetRect(DesktopRect::MakeXYWH(1, 2, 3, 4)); + capturer_helper_.InvalidateRegion(region); + capturer_helper_.TakeInvalidRegion(®ion); + ASSERT_TRUE(Equals(RectToRegion(DesktopRect::MakeXYWH(1, 2, 3, 4)), region)); + + capturer_helper_.InvalidateRegion( + RectToRegion(DesktopRect::MakeXYWH(1, 2, 3, 4))); + capturer_helper_.InvalidateRegion( + RectToRegion(DesktopRect::MakeXYWH(4, 2, 3, 4))); + capturer_helper_.TakeInvalidRegion(®ion); + ASSERT_TRUE(Equals(RectToRegion(DesktopRect::MakeXYWH(1, 2, 6, 4)), region)); } TEST_F(ScreenCapturerHelperTest, InvalidateScreen) { - SkRegion region; - capturer_helper_.InvalidateScreen(SkISize::Make(12, 34)); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeWH(12, 34)), region)); -} - -TEST_F(ScreenCapturerHelperTest, InvalidateFullScreen) { - SkRegion region; - capturer_helper_.set_size_most_recent(SkISize::Make(12, 34)); - capturer_helper_.InvalidateFullScreen(); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeWH(12, 34)), region)); + DesktopRegion region; + capturer_helper_.InvalidateScreen(DesktopSize(12, 34)); + capturer_helper_.TakeInvalidRegion(®ion); + ASSERT_TRUE(Equals(RectToRegion(DesktopRect::MakeWH(12, 34)), region)); } TEST_F(ScreenCapturerHelperTest, SizeMostRecent) { - ASSERT_EQ(SkISize::Make(0, 0), capturer_helper_.size_most_recent()); - capturer_helper_.set_size_most_recent(SkISize::Make(12, 34)); - ASSERT_EQ(SkISize::Make(12, 34), capturer_helper_.size_most_recent()); + ASSERT_TRUE(capturer_helper_.size_most_recent().is_empty()); + capturer_helper_.set_size_most_recent(DesktopSize(12, 34)); + ASSERT_TRUE( + DesktopSize(12, 34).equals(capturer_helper_.size_most_recent())); } TEST_F(ScreenCapturerHelperTest, SetLogGridSize) { - capturer_helper_.set_size_most_recent(SkISize::Make(10, 10)); + capturer_helper_.set_size_most_recent(DesktopSize(10, 10)); - SkRegion region; - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeEmpty()), region)); + DesktopRegion region; + capturer_helper_.TakeInvalidRegion(®ion); + ASSERT_TRUE(Equals(RectToRegion(DesktopRect()), region)); - capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1))); - region.setEmpty(); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1)), region)); + capturer_helper_.InvalidateRegion( + RectToRegion(DesktopRect::MakeXYWH(7, 7, 1, 1))); + capturer_helper_.TakeInvalidRegion(®ion); + ASSERT_TRUE(Equals(RectToRegion(DesktopRect::MakeXYWH(7, 7, 1, 1)), region)); capturer_helper_.SetLogGridSize(-1); - capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1))); - region.setEmpty(); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1)), region)); + capturer_helper_.InvalidateRegion( + RectToRegion(DesktopRect::MakeXYWH(7, 7, 1, 1))); + capturer_helper_.TakeInvalidRegion(®ion); + ASSERT_TRUE(Equals(RectToRegion(DesktopRect::MakeXYWH(7, 7, 1, 1)), region)); capturer_helper_.SetLogGridSize(0); - capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1))); - region.setEmpty(); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1)), region)); + capturer_helper_.InvalidateRegion( + RectToRegion(DesktopRect::MakeXYWH(7, 7, 1, 1))); + capturer_helper_.TakeInvalidRegion(®ion); + ASSERT_TRUE(Equals(RectToRegion(DesktopRect::MakeXYWH(7, 7, 1, 1)), region)); capturer_helper_.SetLogGridSize(1); - capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1))); - region.setEmpty(); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(6, 6, 2, 2)), region)); + capturer_helper_.InvalidateRegion( + RectToRegion(DesktopRect::MakeXYWH(7, 7, 1, 1))); + capturer_helper_.TakeInvalidRegion(®ion); + ASSERT_TRUE(Equals(RectToRegion(DesktopRect::MakeXYWH(6, 6, 2, 2)), region)); capturer_helper_.SetLogGridSize(2); - capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1))); - region.setEmpty(); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(4, 4, 4, 4)), region)); + capturer_helper_.InvalidateRegion( + RectToRegion(DesktopRect::MakeXYWH(7, 7, 1, 1))); + capturer_helper_.TakeInvalidRegion(®ion); + ASSERT_TRUE(Equals(RectToRegion(DesktopRect::MakeXYWH(4, 4, 4, 4)), region)); capturer_helper_.SetLogGridSize(0); - capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1))); - region.setEmpty(); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1)), region)); + capturer_helper_.InvalidateRegion( + RectToRegion(DesktopRect::MakeXYWH(7, 7, 1, 1))); + capturer_helper_.TakeInvalidRegion(®ion); + ASSERT_TRUE(Equals(RectToRegion(DesktopRect::MakeXYWH(7, 7, 1, 1)), region)); } void TestExpandRegionToGrid(const SkRegion& region, int log_grid_size, diff --git a/media/video/capture/screen/screen_capturer_mac.mm b/media/video/capture/screen/screen_capturer_mac.mm index 8248e15..b90364c 100644 --- a/media/video/capture/screen/screen_capturer_mac.mm +++ b/media/video/capture/screen/screen_capturer_mac.mm @@ -24,11 +24,11 @@ #include "media/video/capture/screen/mac/desktop_configuration.h" #include "media/video/capture/screen/mac/scoped_pixel_buffer_object.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 "skia/ext/skia_utils_mac.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_region.h" namespace media { @@ -49,20 +49,13 @@ typedef CGLError (*CGLSetFullScreenFunc)(CGLContextObj); // consistency with Windows and Linux. const int kStandardDPI = 96; -// skia/ext/skia_utils_mac.h only defines CGRectToSkRect(). -SkIRect CGRectToSkIRect(const CGRect& rect) { - SkIRect result; - gfx::CGRectToSkRect(rect).round(&result); - return result; -} - -// Scales all coordinates of an SkRect by a specified factor. -SkRect ScaleSkRect(const SkRect& rect, float scale) { - SkRect result = { - rect.left() * scale, rect.top() * scale, - rect.right() * scale, rect.bottom() * scale - }; - return result; +// Scales all coordinates of a rect by a specified factor. +webrtc::DesktopRect ScaleAndRoundCGRect(const CGRect& rect, float scale) { + return webrtc::DesktopRect::MakeLTRB( + static_cast<int>(floor(rect.origin.x * scale)), + static_cast<int>(floor(rect.origin.y * scale)), + static_cast<int>(ceil((rect.origin.x + rect.size.width) * scale)), + static_cast<int>(ceil((rect.origin.y + rect.size.height) * scale))); } // Copy pixels in the |rect| from |src_place| to |dest_plane|. @@ -71,7 +64,7 @@ void CopyRect(const uint8* src_plane, uint8* dest_plane, int dest_plane_stride, int bytes_per_pixel, - const SkIRect& rect) { + const webrtc::DesktopRect& rect) { // Get the address of the starting point. const int src_y_offset = src_plane_stride * rect.top(); const int dest_y_offset = dest_plane_stride * rect.top(); @@ -92,24 +85,6 @@ void CopyRect(const uint8* src_plane, // The amount of time allowed for displays to reconfigure. const int64 kDisplayConfigurationEventTimeoutInSeconds = 10; -// A class representing a full-frame pixel buffer. -class ScreenCaptureFrameMac : public ScreenCaptureFrame { - public: - explicit ScreenCaptureFrameMac(const MacDesktopConfiguration& desktop_config); - virtual ~ScreenCaptureFrameMac(); - - const SkIPoint& dpi() const { return dpi_; } - - private: - // Allocated pixel buffer. - scoped_ptr<uint8[]> data_; - - // DPI settings for this buffer. - SkIPoint dpi_; - - DISALLOW_COPY_AND_ASSIGN(ScreenCaptureFrameMac); -}; - // A class to perform video frame capturing for mac. class ScreenCapturerMac : public ScreenCapturer { public: @@ -119,16 +94,21 @@ class ScreenCapturerMac : public ScreenCapturer { bool Init(); // 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: void CaptureCursor(); - void GlBlitFast(const ScreenCaptureFrame& buffer, const SkRegion& region); - void GlBlitSlow(const ScreenCaptureFrame& buffer); - void CgBlitPreLion(const ScreenCaptureFrame& buffer, const SkRegion& region); - void CgBlitPostLion(const ScreenCaptureFrame& buffer, const SkRegion& region); + void GlBlitFast(const webrtc::DesktopFrame& frame, + const webrtc::DesktopRegion& region); + void GlBlitSlow(const webrtc::DesktopFrame& frame); + void CgBlitPreLion(const webrtc::DesktopFrame& frame, + const webrtc::DesktopRegion& region); + void CgBlitPostLion(const webrtc::DesktopFrame& frame, + const webrtc::DesktopRegion& region); // Called when the screen configuration is changed. void ScreenConfigurationChanged(); @@ -155,7 +135,8 @@ class ScreenCapturerMac : public ScreenCapturer { void ReleaseBuffers(); - Delegate* delegate_; + Callback* callback_; + MouseShapeObserver* mouse_shape_observer_; CGLContextObj cgl_context_; ScopedPixelBufferObject pixel_buffer_object_; @@ -174,7 +155,7 @@ class ScreenCapturerMac : public ScreenCapturer { base::mac::ScopedCFTypeRef<CGImageRef> current_cursor_; // Contains an invalid region from the previous capture. - SkRegion last_invalid_region_; + webrtc::DesktopRegion last_invalid_region_; // Used to ensure that frame captures do not take place while displays // are being reconfigured. @@ -201,26 +182,22 @@ class ScreenCapturerMac : public ScreenCapturer { DISALLOW_COPY_AND_ASSIGN(ScreenCapturerMac); }; -ScreenCaptureFrameMac::ScreenCaptureFrameMac( +scoped_ptr<webrtc::DesktopFrame> CreateFrame( const MacDesktopConfiguration& desktop_config) { - SkISize size = SkISize::Make(desktop_config.pixel_bounds.width(), - desktop_config.pixel_bounds.height()); - set_bytes_per_row(size.width() * sizeof(uint32_t)); - set_dimensions(size); - - size_t buffer_size = size.width() * size.height() * sizeof(uint32_t); - data_.reset(new uint8[buffer_size]); - set_pixels(data_.get()); - dpi_ = SkIPoint::Make(kStandardDPI * desktop_config.dip_to_pixel_scale, - kStandardDPI * desktop_config.dip_to_pixel_scale); -} + webrtc::DesktopSize size(desktop_config.pixel_bounds.width(), + desktop_config.pixel_bounds.height()); + scoped_ptr<webrtc::DesktopFrame> frame(new webrtc::BasicDesktopFrame(size)); -ScreenCaptureFrameMac::~ScreenCaptureFrameMac() { + frame->set_dpi(webrtc::DesktopVector( + kStandardDPI * desktop_config.dip_to_pixel_scale, + kStandardDPI * desktop_config.dip_to_pixel_scale)); + return frame.Pass(); } ScreenCapturerMac::ScreenCapturerMac() - : delegate_(NULL), + : callback_(NULL), + mouse_shape_observer_(NULL), cgl_context_(NULL), display_configuration_capture_event_(false, true), power_assertion_id_display_(kIOPMNullAssertionID), @@ -228,8 +205,7 @@ ScreenCapturerMac::ScreenCapturerMac() cg_display_base_address_(NULL), cg_display_bytes_per_row_(NULL), cg_display_bits_per_pixel_(NULL), - cgl_set_full_screen_(NULL) -{ + cgl_set_full_screen_(NULL) { } ScreenCapturerMac::~ScreenCapturerMac() { @@ -276,13 +252,14 @@ void ScreenCapturerMac::ReleaseBuffers() { // The buffers might be in use by the encoder, so don't delete them here. // Instead, mark them as "needs update"; next time the buffers are used by // the capturer, they will be recreated if necessary. - queue_.SetAllFramesNeedUpdate(); + queue_.Reset(); } -void ScreenCapturerMac::Start(Delegate* delegate) { - DCHECK(delegate_ == NULL); +void ScreenCapturerMac::Start(Callback* callback) { + DCHECK(!callback_); + DCHECK(callback); - delegate_ = delegate; + callback_ = callback; // Create power management assertions to wake the display and prevent it from // going to sleep on user idle. @@ -300,12 +277,12 @@ void ScreenCapturerMac::Start(Delegate* delegate) { &power_assertion_id_user_); } -void ScreenCapturerMac::CaptureFrame() { - // Only allow captures when the display configuration is not occurring. - scoped_refptr<ScreenCaptureData> data; - +void ScreenCapturerMac::Capture( + const webrtc::DesktopRegion& region_to_capture) { base::Time capture_start_time = base::Time::Now(); + queue_.MoveToNextFrame(); + // Wait until the display configuration is stable. If one or more displays // are reconfiguring then |display_configuration_capture_event_| will not be // set until the reconfiguration completes. @@ -314,65 +291,64 @@ void ScreenCapturerMac::CaptureFrame() { base::TimeDelta::FromSeconds( kDisplayConfigurationEventTimeoutInSeconds))); - SkRegion region; - helper_.SwapInvalidRegion(®ion); + webrtc::DesktopRegion region; + helper_.TakeInvalidRegion(®ion); // 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()) { - scoped_ptr<ScreenCaptureFrameMac> buffer( - new ScreenCaptureFrameMac(desktop_config_)); - queue_.ReplaceCurrentFrame(buffer.PassAs<ScreenCaptureFrame>()); - } + if (!queue_.current_frame()) + queue_.ReplaceCurrentFrame(CreateFrame(desktop_config_)); - ScreenCaptureFrame* current_buffer = queue_.current_frame(); + webrtc::DesktopFrame* current_frame = queue_.current_frame(); bool flip = false; // GL capturers need flipping. if (base::mac::IsOSLionOrLater()) { // Lion requires us to use their new APIs for doing screen capture. These // APIS currently crash on 10.6.8 if there is no monitor attached. - CgBlitPostLion(*current_buffer, region); + CgBlitPostLion(*current_frame, region); } else if (cgl_context_) { flip = true; if (pixel_buffer_object_.get() != 0) { - GlBlitFast(*current_buffer, region); + GlBlitFast(*current_frame, region); } else { // See comment in ScopedPixelBufferObject::Init about why the slow // path is always used on 10.5. - GlBlitSlow(*current_buffer); + GlBlitSlow(*current_frame); } } else { - CgBlitPreLion(*current_buffer, region); + CgBlitPreLion(*current_frame, region); } - uint8* buffer = current_buffer->pixels(); - int stride = current_buffer->bytes_per_row(); + uint8* buffer = current_frame->data(); + int stride = current_frame->stride(); if (flip) { stride = -stride; - buffer += (current_buffer->dimensions().height() - 1) * - current_buffer->bytes_per_row(); + buffer += (current_frame->size().height() - 1) * current_frame->stride(); } - data = new ScreenCaptureData(buffer, stride, current_buffer->dimensions()); - data->set_dpi(static_cast<ScreenCaptureFrameMac*>(current_buffer)->dpi()); - data->mutable_dirty_region() = region; + webrtc::DesktopFrame* new_frame = queue_.current_frame()->Share(); + *new_frame->mutable_updated_region() = region; - helper_.set_size_most_recent(data->size()); + helper_.set_size_most_recent(new_frame->size()); // Signal that we are done capturing data from the display framebuffer, // and accessing display structures. display_configuration_capture_event_.Signal(); - // Capture the current cursor shape and notify |delegate_| if it has changed. + // Capture the current cursor shape and notify |callback_| if it has changed. CaptureCursor(); - // Move the capture frame buffer queue on to the next buffer. - queue_.DoneWithCurrentFrame(); - - data->set_capture_time_ms( + new_frame->set_capture_time_ms( (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp()); - delegate_->OnCaptureCompleted(data); + callback_->OnCaptureCompleted(new_frame); +} + +void ScreenCapturerMac::SetMouseShapeObserver( + MouseShapeObserver* mouse_shape_observer) { + DCHECK(!mouse_shape_observer_); + DCHECK(mouse_shape_observer); + mouse_shape_observer_ = mouse_shape_observer; } void ScreenCapturerMac::CaptureCursor() { @@ -448,16 +424,14 @@ void ScreenCapturerMac::CaptureCursor() { cursor_shape->hotspot.set(hotspot.x, hotspot.y); cursor_shape->data.assign(cursor_src_data, cursor_src_data + data_size); - delegate_->OnCursorShapeChanged(cursor_shape.Pass()); + if (mouse_shape_observer_) + mouse_shape_observer_->OnCursorShapeChanged(cursor_shape.Pass()); } -void ScreenCapturerMac::GlBlitFast(const ScreenCaptureFrame& buffer, - const SkRegion& region) { - const int buffer_height = buffer.dimensions().height(); - const int buffer_width = buffer.dimensions().width(); - +void ScreenCapturerMac::GlBlitFast(const webrtc::DesktopFrame& frame, + const webrtc::DesktopRegion& region) { // Clip to the size of our current screen. - SkIRect clip_rect = SkIRect::MakeWH(buffer_width, buffer_height); + webrtc::DesktopRect clip_rect = webrtc::DesktopRect::MakeSize(frame.size()); if (queue_.previous_frame()) { // We are doing double buffer for the capture data so we just need to copy // the invalid region from the previous capture in the current buffer. @@ -467,15 +441,17 @@ void ScreenCapturerMac::GlBlitFast(const ScreenCaptureFrame& buffer, // Since the image obtained from OpenGL is upside-down, need to do some // magic here to copy the correct rectangle. - const int y_offset = (buffer_height - 1) * buffer.bytes_per_row(); - for(SkRegion::Iterator i(last_invalid_region_); !i.done(); i.next()) { - SkIRect copy_rect = i.rect(); - if (copy_rect.intersect(clip_rect)) { - CopyRect(queue_.previous_frame()->pixels() + y_offset, - -buffer.bytes_per_row(), - buffer.pixels() + y_offset, - -buffer.bytes_per_row(), - 4, // Bytes for pixel for RGBA. + const int y_offset = (frame.size().width() - 1) * frame.stride(); + for (webrtc::DesktopRegion::Iterator i(last_invalid_region_); + !i.IsAtEnd(); i.Advance()) { + webrtc::DesktopRect copy_rect = i.rect(); + copy_rect.IntersectWith(clip_rect); + if (!copy_rect.is_empty()) { + CopyRect(queue_.previous_frame()->data() + y_offset, + -frame.stride(), + frame.data() + y_offset, + -frame.stride(), + webrtc::DesktopFrame::kBytesPerPixel, copy_rect); } } @@ -484,7 +460,8 @@ void ScreenCapturerMac::GlBlitFast(const ScreenCaptureFrame& buffer, CGLContextObj CGL_MACRO_CONTEXT = cgl_context_; glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pixel_buffer_object_.get()); - glReadPixels(0, 0, buffer_width, buffer_height, GL_BGRA, GL_UNSIGNED_BYTE, 0); + glReadPixels(0, 0, frame.size().height(), frame.size().width(), GL_BGRA, + GL_UNSIGNED_BYTE, 0); GLubyte* ptr = static_cast<GLubyte*>( glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB)); if (ptr == NULL) { @@ -494,16 +471,18 @@ void ScreenCapturerMac::GlBlitFast(const ScreenCaptureFrame& buffer, } else { // Copy only from the dirty rects. Since the image obtained from OpenGL is // upside-down we need to do some magic here to copy the correct rectangle. - const int y_offset = (buffer_height - 1) * buffer.bytes_per_row(); - for(SkRegion::Iterator i(region); !i.done(); i.next()) { - SkIRect copy_rect = i.rect(); - if (copy_rect.intersect(clip_rect)) { + const int y_offset = (frame.size().height() - 1) * frame.stride(); + for (webrtc::DesktopRegion::Iterator i(region); + !i.IsAtEnd(); i.Advance()) { + webrtc::DesktopRect copy_rect = i.rect(); + copy_rect.IntersectWith(clip_rect); + if (!copy_rect.is_empty()) { CopyRect(ptr + y_offset, - -buffer.bytes_per_row(), - buffer.pixels() + y_offset, - -buffer.bytes_per_row(), - 4, // Bytes for pixel for RGBA. - copy_rect); + -frame.stride(), + frame.data() + y_offset, + -frame.stride(), + webrtc::DesktopFrame::kBytesPerPixel, + copy_rect); } } } @@ -518,7 +497,7 @@ void ScreenCapturerMac::GlBlitFast(const ScreenCaptureFrame& buffer, glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); } -void ScreenCapturerMac::GlBlitSlow(const ScreenCaptureFrame& buffer) { +void ScreenCapturerMac::GlBlitSlow(const webrtc::DesktopFrame& frame) { CGLContextObj CGL_MACRO_CONTEXT = cgl_context_; glReadBuffer(GL_FRONT); glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); @@ -527,22 +506,20 @@ void ScreenCapturerMac::GlBlitSlow(const ScreenCaptureFrame& buffer) { glPixelStorei(GL_PACK_SKIP_ROWS, 0); glPixelStorei(GL_PACK_SKIP_PIXELS, 0); // Read a block of pixels from the frame buffer. - glReadPixels(0, 0, buffer.dimensions().width(), buffer.dimensions().height(), - GL_BGRA, GL_UNSIGNED_BYTE, buffer.pixels()); + glReadPixels(0, 0, frame.size().width(), frame.size().height(), + GL_BGRA, GL_UNSIGNED_BYTE, frame.data()); glPopClientAttrib(); } -void ScreenCapturerMac::CgBlitPreLion(const ScreenCaptureFrame& buffer, - const SkRegion& region) { - const int buffer_height = buffer.dimensions().height(); - +void ScreenCapturerMac::CgBlitPreLion(const webrtc::DesktopFrame& frame, + const webrtc::DesktopRegion& region) { // Copy the entire contents of the previous capture buffer, to capture over. // TODO(wez): Get rid of this as per crbug.com/145064, or implement // crbug.com/92354. if (queue_.previous_frame()) { - memcpy(buffer.pixels(), - queue_.previous_frame()->pixels(), - buffer.bytes_per_row() * buffer_height); + memcpy(frame.data(), + queue_.previous_frame()->data(), + frame.stride() * frame.size().height()); } for (size_t i = 0; i < desktop_config_.displays.size(); ++i) { @@ -559,63 +536,64 @@ void ScreenCapturerMac::CgBlitPreLion(const ScreenCaptureFrame& buffer, (*cg_display_bits_per_pixel_)(display_config.id) / 8; // Determine the display's position relative to the desktop, in pixels. - SkIRect display_bounds = display_config.pixel_bounds; - display_bounds.offset(-desktop_config_.pixel_bounds.left(), - -desktop_config_.pixel_bounds.top()); + webrtc::DesktopRect display_bounds = display_config.pixel_bounds; + display_bounds.Translate(-desktop_config_.pixel_bounds.left(), + -desktop_config_.pixel_bounds.top()); // Determine which parts of the blit region, if any, lay within the monitor. - SkRegion copy_region; - if (!copy_region.op(region, display_bounds, SkRegion::kIntersect_Op)) + webrtc::DesktopRegion copy_region = region; + copy_region.IntersectWith(display_bounds); + if (copy_region.is_empty()) continue; // Translate the region to be copied into display-relative coordinates. - copy_region.translate(-display_bounds.left(), -display_bounds.top()); + copy_region.Translate(-display_bounds.left(), -display_bounds.top()); // Calculate where in the output buffer the display's origin is. - uint8* out_ptr = buffer.pixels() + + uint8* out_ptr = frame.data() + (display_bounds.left() * src_bytes_per_pixel) + - (display_bounds.top() * buffer.bytes_per_row()); + (display_bounds.top() * frame.stride()); // Copy the dirty region from the display buffer into our desktop buffer. - for(SkRegion::Iterator i(copy_region); !i.done(); i.next()) { + for (webrtc::DesktopRegion::Iterator i(copy_region); + !i.IsAtEnd(); i.Advance()) { CopyRect(display_base_address, src_bytes_per_row, out_ptr, - buffer.bytes_per_row(), + frame.stride(), src_bytes_per_pixel, i.rect()); } } } -void ScreenCapturerMac::CgBlitPostLion(const ScreenCaptureFrame& buffer, - const SkRegion& region) { - const int buffer_height = buffer.dimensions().height(); - +void ScreenCapturerMac::CgBlitPostLion(const webrtc::DesktopFrame& frame, + const webrtc::DesktopRegion& region) { // Copy the entire contents of the previous capture buffer, to capture over. // TODO(wez): Get rid of this as per crbug.com/145064, or implement // crbug.com/92354. if (queue_.previous_frame()) { - memcpy(buffer.pixels(), - queue_.previous_frame()->pixels(), - buffer.bytes_per_row() * buffer_height); + memcpy(frame.data(), + queue_.previous_frame()->data(), + frame.stride() * frame.size().height()); } for (size_t i = 0; i < desktop_config_.displays.size(); ++i) { const MacDisplayConfiguration& display_config = desktop_config_.displays[i]; // Determine the display's position relative to the desktop, in pixels. - SkIRect display_bounds = display_config.pixel_bounds; - display_bounds.offset(-desktop_config_.pixel_bounds.left(), - -desktop_config_.pixel_bounds.top()); + webrtc::DesktopRect display_bounds = display_config.pixel_bounds; + display_bounds.Translate(-desktop_config_.pixel_bounds.left(), + -desktop_config_.pixel_bounds.top()); // Determine which parts of the blit region, if any, lay within the monitor. - SkRegion copy_region; - if (!copy_region.op(region, display_bounds, SkRegion::kIntersect_Op)) + webrtc::DesktopRegion copy_region = region; + copy_region.IntersectWith(display_bounds); + if (copy_region.is_empty()) continue; // Translate the region to be copied into display-relative coordinates. - copy_region.translate(-display_bounds.left(), -display_bounds.top()); + copy_region.Translate(-display_bounds.left(), -display_bounds.top()); // Create an image containing a snapshot of the display. base::mac::ScopedCFTypeRef<CGImageRef> image( @@ -635,16 +613,17 @@ void ScreenCapturerMac::CgBlitPostLion(const ScreenCaptureFrame& buffer, int src_bytes_per_pixel = CGImageGetBitsPerPixel(image) / 8; // Calculate where in the output buffer the display's origin is. - uint8* out_ptr = buffer.pixels() + + uint8* out_ptr = frame.data() + (display_bounds.left() * src_bytes_per_pixel) + - (display_bounds.top() * buffer.bytes_per_row()); + (display_bounds.top() * frame.stride()); // Copy the dirty region from the display buffer into our desktop buffer. - for (SkRegion::Iterator i(copy_region); !i.done(); i.next()) { + for (webrtc::DesktopRegion::Iterator i(copy_region); + !i.IsAtEnd(); i.Advance()) { CopyRect(display_base_address, src_bytes_per_row, out_ptr, - buffer.bytes_per_row(), + frame.stride(), src_bytes_per_pixel, i.rect()); } @@ -664,11 +643,11 @@ void ScreenCapturerMac::ScreenConfigurationChanged() { // Re-mark the entire desktop as dirty. helper_.InvalidateScreen( - SkISize::Make(desktop_config_.pixel_bounds.width(), - desktop_config_.pixel_bounds.height())); + webrtc::DesktopSize(desktop_config_.pixel_bounds.width(), + desktop_config_.pixel_bounds.height())); // Make sure the frame buffers will be reallocated. - queue_.SetAllFramesNeedUpdate(); + queue_.Reset(); // CgBlitPostLion uses CGDisplayCreateImage() to snapshot each display's // contents. Although the API exists in OS 10.6, it crashes the caller if @@ -768,25 +747,23 @@ void ScreenCapturerMac::UnregisterRefreshAndMoveHandlers() { void ScreenCapturerMac::ScreenRefresh(CGRectCount count, const CGRect* rect_array) { - if (desktop_config_.pixel_bounds.isEmpty()) { + if (desktop_config_.pixel_bounds.is_empty()) return; - } - SkIRect skirect_array[count]; - for (CGRectCount i = 0; i < count; ++i) { - SkRect sk_rect = gfx::CGRectToSkRect(rect_array[i]); + webrtc::DesktopRegion region; + for (CGRectCount i = 0; i < count; ++i) { // Convert from Density-Independent Pixel to physical pixel coordinates. - sk_rect = ScaleSkRect(sk_rect, desktop_config_.dip_to_pixel_scale); - sk_rect.round(&skirect_array[i]); + webrtc::DesktopRect rect = + ScaleAndRoundCGRect(rect_array[i], desktop_config_.dip_to_pixel_scale); // Translate from local desktop to capturer framebuffer coordinates. - skirect_array[i].offset(-desktop_config_.pixel_bounds.left(), - -desktop_config_.pixel_bounds.top()); + rect.Translate(-desktop_config_.pixel_bounds.left(), + -desktop_config_.pixel_bounds.top()); + + region.AddRect(rect); } - SkRegion region; - region.setRects(skirect_array, count); helper_.InvalidateRegion(region); } @@ -835,11 +812,11 @@ void ScreenCapturerMac::DisplaysReconfigured( } void ScreenCapturerMac::ScreenRefreshCallback(CGRectCount count, - const CGRect* rect_array, - void* user_parameter) { + const CGRect* rect_array, + void* user_parameter) { ScreenCapturerMac* capturer = reinterpret_cast<ScreenCapturerMac*>( user_parameter); - if (capturer->desktop_config_.pixel_bounds.isEmpty()) { + if (capturer->desktop_config_.pixel_bounds.is_empty()) { capturer->ScreenConfigurationChanged(); } capturer->ScreenRefresh(count, rect_array); @@ -866,15 +843,6 @@ void ScreenCapturerMac::DisplaysReconfiguredCallback( } // 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() { scoped_ptr<ScreenCapturerMac> capturer(new ScreenCapturerMac()); diff --git a/media/video/capture/screen/screen_capturer_mac_unittest.cc b/media/video/capture/screen/screen_capturer_mac_unittest.cc index b8fb5d9..72f2d69 100644 --- a/media/video/capture/screen/screen_capturer_mac_unittest.cc +++ b/media/video/capture/screen/screen_capturer_mac_unittest.cc @@ -12,9 +12,11 @@ #include "base/callback.h" #include "base/memory/scoped_ptr.h" #include "media/video/capture/screen/mac/desktop_configuration.h" -#include "media/video/capture/screen/screen_capture_data.h" #include "media/video/capture/screen/screen_capturer_mock_objects.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_region.h" using ::testing::_; using ::testing::AnyNumber; @@ -25,11 +27,11 @@ namespace media { class ScreenCapturerMacTest : public testing::Test { public: // Verifies that the whole screen is initially dirty. - void CaptureDoneCallback1(scoped_refptr<ScreenCaptureData> capture_data); + void CaptureDoneCallback1(webrtc::DesktopFrame* frame); // Verifies that a rectangle explicitly marked as dirty is propagated // correctly. - void CaptureDoneCallback2(scoped_refptr<ScreenCaptureData> capture_data); + void CaptureDoneCallback2(webrtc::DesktopFrame* frame); protected: virtual void SetUp() OVERRIDE { @@ -37,71 +39,57 @@ class ScreenCapturerMacTest : public testing::Test { } scoped_ptr<ScreenCapturer> capturer_; - MockScreenCapturerDelegate delegate_; + MockScreenCapturerCallback callback_; }; void ScreenCapturerMacTest::CaptureDoneCallback1( - scoped_refptr<ScreenCaptureData> capture_data) { + webrtc::DesktopFrame* frame) { + scoped_ptr<webrtc::DesktopFrame> owned_frame(frame); + MacDesktopConfiguration config = MacDesktopConfiguration::GetCurrent( MacDesktopConfiguration::BottomLeftOrigin); - int width = config.pixel_bounds.width(); - int height = config.pixel_bounds.height(); - SkRegion initial_region(SkIRect::MakeXYWH(0, 0, width, height)); - EXPECT_EQ(initial_region, capture_data->dirty_region()); + // Verify that the region contains full frame. + webrtc::DesktopRegion::Iterator it(frame->updated_region()); + EXPECT_TRUE(!it.IsAtEnd() && it.rect().equals(config.pixel_bounds)); } void ScreenCapturerMacTest::CaptureDoneCallback2( - scoped_refptr<ScreenCaptureData> capture_data) { + webrtc::DesktopFrame* frame) { + scoped_ptr<webrtc::DesktopFrame> owned_frame(frame); + MacDesktopConfiguration config = MacDesktopConfiguration::GetCurrent( MacDesktopConfiguration::BottomLeftOrigin); int width = config.pixel_bounds.width(); int height = config.pixel_bounds.height(); - EXPECT_EQ(width, capture_data->size().width()); - EXPECT_EQ(height, capture_data->size().height()); - EXPECT_TRUE(capture_data->data() != NULL); + EXPECT_EQ(width, frame->size().width()); + EXPECT_EQ(height, frame->size().height()); + EXPECT_TRUE(frame->data() != NULL); // Depending on the capture method, the screen may be flipped or not, so // the stride may be positive or negative. EXPECT_EQ(static_cast<int>(sizeof(uint32_t) * width), - abs(capture_data->stride())); + abs(frame->stride())); } TEST_F(ScreenCapturerMacTest, Capture) { - EXPECT_CALL(delegate_, OnCaptureCompleted(_)) + EXPECT_CALL(callback_, OnCaptureCompleted(_)) .Times(2) .WillOnce(Invoke(this, &ScreenCapturerMacTest::CaptureDoneCallback1)) .WillOnce(Invoke(this, &ScreenCapturerMacTest::CaptureDoneCallback2)); - EXPECT_CALL(delegate_, OnCursorShapeChangedPtr(_)) - .Times(AnyNumber()); - EXPECT_CALL(delegate_, CreateSharedBuffer(_)) + EXPECT_CALL(callback_, CreateSharedMemory(_)) .Times(AnyNumber()) - .WillRepeatedly(Return(scoped_refptr<SharedBuffer>())); + .WillRepeatedly(Return(static_cast<webrtc::SharedMemory*>(NULL))); SCOPED_TRACE(""); - capturer_->Start(&delegate_); + capturer_->Start(&callback_); // Check that we get an initial full-screen updated. - capturer_->CaptureFrame(); + capturer_->Capture(webrtc::DesktopRegion()); // Check that subsequent dirty rects are propagated correctly. - capturer_->CaptureFrame(); + capturer_->Capture(webrtc::DesktopRegion()); } } // namespace media - -namespace gfx { - -std::ostream& operator<<(std::ostream& out, const SkRegion& region) { - out << "SkRegion("; - for (SkRegion::Iterator i(region); !i.done(); i.next()) { - const SkIRect& r = i.rect(); - out << "(" << r.fLeft << "," << r.fTop << "," - << r.fRight << "," << r.fBottom << ")"; - } - out << ")"; - return out; -} - -} // namespace gfx diff --git a/media/video/capture/screen/screen_capturer_mock_objects.cc b/media/video/capture/screen/screen_capturer_mock_objects.cc index e4fa7fb..9e365ff 100644 --- a/media/video/capture/screen/screen_capturer_mock_objects.cc +++ b/media/video/capture/screen/screen_capturer_mock_objects.cc @@ -6,22 +6,20 @@ #include "media/video/capture/screen/screen_capturer.h" #include "testing/gmock/include/gmock/gmock.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_region.h" namespace media { -MockScreenCapturer::MockScreenCapturer() { -} +MockScreenCapturer::MockScreenCapturer() {} +MockScreenCapturer::~MockScreenCapturer() {} -MockScreenCapturer::~MockScreenCapturer() { -} +MockScreenCapturerCallback::MockScreenCapturerCallback() {} +MockScreenCapturerCallback::~MockScreenCapturerCallback() {} -MockScreenCapturerDelegate::MockScreenCapturerDelegate() { -} - -MockScreenCapturerDelegate::~MockScreenCapturerDelegate() { -} +MockMouseShapeObserver::MockMouseShapeObserver() {} +MockMouseShapeObserver::~MockMouseShapeObserver() {} -void MockScreenCapturerDelegate::OnCursorShapeChanged( +void MockMouseShapeObserver::OnCursorShapeChanged( scoped_ptr<MouseCursorShape> cursor_shape) { // Notify the mock method. OnCursorShapeChangedPtr(cursor_shape.get()); diff --git a/media/video/capture/screen/screen_capturer_mock_objects.h b/media/video/capture/screen/screen_capturer_mock_objects.h index 907fa12..95f0152 100644 --- a/media/video/capture/screen/screen_capturer_mock_objects.h +++ b/media/video/capture/screen/screen_capturer_mock_objects.h @@ -6,7 +6,6 @@ #define MEDIA_VIDEO_CAPTURE_SCREEN_SCREEN_CAPTURER_MOCK_OBJECTS_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_capturer.h" #include "testing/gmock/include/gmock/gmock.h" @@ -17,30 +16,43 @@ class MockScreenCapturer : public ScreenCapturer { MockScreenCapturer(); virtual ~MockScreenCapturer(); - MOCK_METHOD1(Start, void(Delegate* delegate)); - MOCK_METHOD0(CaptureFrame, void()); + MOCK_METHOD1(Start, void(Callback* callback)); + MOCK_METHOD1(Capture, void(const webrtc::DesktopRegion& region)); + MOCK_METHOD1(SetMouseShapeObserver, void( + MouseShapeObserver* mouse_shape_observer)); private: DISALLOW_COPY_AND_ASSIGN(MockScreenCapturer); }; -class MockScreenCapturerDelegate : public ScreenCapturer::Delegate { +class MockScreenCapturerCallback : public ScreenCapturer::Callback { public: - MockScreenCapturerDelegate(); - virtual ~MockScreenCapturerDelegate(); + MockScreenCapturerCallback(); + virtual ~MockScreenCapturerCallback(); + + MOCK_METHOD1(CreateSharedMemory, webrtc::SharedMemory*(size_t)); + MOCK_METHOD1(OnCaptureCompleted, void(webrtc::DesktopFrame*)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockScreenCapturerCallback); +}; + +class MockMouseShapeObserver : public ScreenCapturer::MouseShapeObserver { + public: + MockMouseShapeObserver(); + virtual ~MockMouseShapeObserver(); void OnCursorShapeChanged(scoped_ptr<MouseCursorShape> cursor_shape) OVERRIDE; - MOCK_METHOD1(CreateSharedBuffer, scoped_refptr<SharedBuffer>(uint32)); - MOCK_METHOD1(ReleaseSharedBuffer, void(scoped_refptr<SharedBuffer>)); - MOCK_METHOD1(OnCaptureCompleted, void(scoped_refptr<ScreenCaptureData>)); MOCK_METHOD1(OnCursorShapeChangedPtr, void(MouseCursorShape* cursor_shape)); private: - DISALLOW_COPY_AND_ASSIGN(MockScreenCapturerDelegate); + DISALLOW_COPY_AND_ASSIGN(MockMouseShapeObserver); + }; + } // namespace media #endif // MEDIA_VIDEO_CAPTURE_SCREEN_SCREEN_CAPTURER_MOCK_OBJECTS_H_ diff --git a/media/video/capture/screen/screen_capturer_unittest.cc b/media/video/capture/screen/screen_capturer_unittest.cc index 4ed45d9..7be07db 100644 --- a/media/video/capture/screen/screen_capturer_unittest.cc +++ b/media/video/capture/screen/screen_capturer_unittest.cc @@ -8,79 +8,111 @@ #if defined(OS_MACOSX) #include "base/mac/mac_util.h" #endif // defined(OS_MACOSX) -#include "media/video/capture/screen/screen_capture_data.h" #include "media/video/capture/screen/screen_capturer_mock_objects.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_region.h" using ::testing::_; using ::testing::AnyNumber; using ::testing::Return; +using ::testing::SaveArg; -namespace media { +const int kTestSharedMemoryId = 123; -MATCHER(DirtyRegionIsNonEmptyRect, "") { - const SkRegion& dirty_region = arg->dirty_region(); - const SkIRect& dirty_region_bounds = dirty_region.getBounds(); - if (dirty_region_bounds.isEmpty()) { - return false; - } - return dirty_region == SkRegion(dirty_region_bounds); -} +namespace media { class ScreenCapturerTest : public testing::Test { public: - scoped_refptr<SharedBuffer> CreateSharedBuffer(uint32 size); + webrtc::SharedMemory* CreateSharedMemory(size_t size); protected: scoped_ptr<ScreenCapturer> capturer_; - MockScreenCapturerDelegate delegate_; + MockMouseShapeObserver mouse_observer_; + MockScreenCapturerCallback callback_; +}; + +class FakeSharedMemory : public webrtc::SharedMemory { + public: + FakeSharedMemory(char* buffer, size_t size) + : SharedMemory(buffer, size, 0, kTestSharedMemoryId), + buffer_(buffer) { + } + virtual ~FakeSharedMemory() { + delete[] buffer_; + } + private: + char* buffer_; + DISALLOW_COPY_AND_ASSIGN(FakeSharedMemory); }; -scoped_refptr<SharedBuffer> ScreenCapturerTest::CreateSharedBuffer( - uint32 size) { - return scoped_refptr<SharedBuffer>(new SharedBuffer(size)); +webrtc::SharedMemory* ScreenCapturerTest::CreateSharedMemory(size_t size) { + return new FakeSharedMemory(new char[size], size); } TEST_F(ScreenCapturerTest, StartCapturer) { capturer_ = ScreenCapturer::Create(); - capturer_->Start(&delegate_); + capturer_->SetMouseShapeObserver(&mouse_observer_); + capturer_->Start(&callback_); } TEST_F(ScreenCapturerTest, Capture) { // Assume that Start() treats the screen as invalid initially. - EXPECT_CALL(delegate_, - OnCaptureCompleted(DirtyRegionIsNonEmptyRect())); - EXPECT_CALL(delegate_, OnCursorShapeChangedPtr(_)) + webrtc::DesktopFrame* frame = NULL; + EXPECT_CALL(callback_, OnCaptureCompleted(_)) + .WillOnce(SaveArg<0>(&frame)); + EXPECT_CALL(mouse_observer_, OnCursorShapeChangedPtr(_)) .Times(AnyNumber()); - EXPECT_CALL(delegate_, CreateSharedBuffer(_)) + EXPECT_CALL(callback_, CreateSharedMemory(_)) .Times(AnyNumber()) - .WillRepeatedly(Return(scoped_refptr<SharedBuffer>())); + .WillRepeatedly(Return(static_cast<webrtc::SharedMemory*>(NULL))); capturer_ = ScreenCapturer::Create(); - capturer_->Start(&delegate_); - capturer_->CaptureFrame(); + capturer_->Start(&callback_); + capturer_->Capture(webrtc::DesktopRegion()); + + ASSERT_TRUE(frame); + EXPECT_GT(frame->size().width(), 0); + EXPECT_GT(frame->size().height(), 0); + EXPECT_GE(frame->stride(), + frame->size().width() * webrtc::DesktopFrame::kBytesPerPixel); + EXPECT_TRUE(frame->shared_memory() == NULL); + + // Verify that the region contains whole screen. + EXPECT_FALSE(frame->updated_region().is_empty()); + webrtc::DesktopRegion::Iterator it(frame->updated_region()); + ASSERT_TRUE(!it.IsAtEnd()); + EXPECT_TRUE(it.rect().equals(webrtc::DesktopRect::MakeSize(frame->size()))); + it.Advance(); + EXPECT_TRUE(it.IsAtEnd()); + + delete frame; } #if defined(OS_WIN) TEST_F(ScreenCapturerTest, UseSharedBuffers) { - EXPECT_CALL(delegate_, - OnCaptureCompleted(DirtyRegionIsNonEmptyRect())); - EXPECT_CALL(delegate_, OnCursorShapeChangedPtr(_)) + webrtc::DesktopFrame* frame = NULL; + EXPECT_CALL(callback_, OnCaptureCompleted(_)) + .WillOnce(SaveArg<0>(&frame)); + EXPECT_CALL(mouse_observer_, OnCursorShapeChangedPtr(_)) .Times(AnyNumber()); - EXPECT_CALL(delegate_, CreateSharedBuffer(_)) + EXPECT_CALL(callback_, CreateSharedMemory(_)) .Times(AnyNumber()) - .WillRepeatedly(Invoke(this, &ScreenCapturerTest::CreateSharedBuffer)); - EXPECT_CALL(delegate_, ReleaseSharedBuffer(_)) - .Times(AnyNumber()); + .WillRepeatedly(Invoke(this, &ScreenCapturerTest::CreateSharedMemory)); capturer_ = ScreenCapturer::Create(); - capturer_->Start(&delegate_); - capturer_->CaptureFrame(); - capturer_.reset(); + capturer_->Start(&callback_); + capturer_->Capture(webrtc::DesktopRegion()); + + ASSERT_TRUE(frame); + ASSERT_TRUE(frame->shared_memory()); + EXPECT_EQ(frame->shared_memory()->id(), kTestSharedMemoryId); + + delete frame; } #endif // defined(OS_WIN) diff --git a/media/video/capture/screen/screen_capturer_win.cc b/media/video/capture/screen/screen_capturer_win.cc index ff148b1..05ec931 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); diff --git a/media/video/capture/screen/screen_capturer_x11.cc b/media/video/capture/screen/screen_capturer_x11.cc index f9da3b3..7d1ee78 100644 --- a/media/video/capture/screen/screen_capturer_x11.cc +++ b/media/video/capture/screen/screen_capturer_x11.cc @@ -15,32 +15,17 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/stl_util.h" -#include "base/time.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/x11/x_server_pixel_buffer.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" namespace media { namespace { -// A class representing a full-frame pixel buffer. -class ScreenCaptureFrameLinux : public ScreenCaptureFrame { - public: - explicit ScreenCaptureFrameLinux(const SkISize& window_size); - virtual ~ScreenCaptureFrameLinux(); - - private: - // Allocated pixel buffer. - scoped_ptr<uint8[]> data_; - - DISALLOW_COPY_AND_ASSIGN(ScreenCaptureFrameLinux); -}; - // A class to perform video frame capturing for Linux. class ScreenCapturerLinux : public ScreenCapturer { public: @@ -50,9 +35,13 @@ class ScreenCapturerLinux : public ScreenCapturer { // TODO(ajwong): Do we really want this to be synchronous? bool Init(bool use_x_damage); - // Capturer interface. - virtual void Start(Delegate* delegate) OVERRIDE; - virtual void CaptureFrame() OVERRIDE; + // DesktopCapturer interface. + virtual void Start(Callback* delegate) OVERRIDE; + virtual void Capture(const webrtc::DesktopRegion& region) OVERRIDE; + + // ScreenCapturer interface. + virtual void SetMouseShapeObserver( + MouseShapeObserver* mouse_shape_observer) OVERRIDE; private: void InitXDamage(); @@ -67,17 +56,16 @@ class ScreenCapturerLinux : public ScreenCapturer { // Capture the cursor image and notify the delegate if it was captured. void CaptureCursor(); - // Capture screen pixels, and return the data in a new ScreenCaptureData - // object, to be freed by the caller. In the DAMAGE case, the - // ScreenCapturerHelper already holds the list of invalid rectangles from - // ProcessPendingXEvents(). In the non-DAMAGE case, this captures the whole - // screen, then calculates some invalid rectangles that include any + // Capture screen pixels to the current buffer in the queue. In the DAMAGE + // case, the ScreenCapturerHelper already holds the list of invalid rectangles + // from ProcessPendingXEvents(). In the non-DAMAGE case, this captures the + // whole screen, then calculates some invalid rectangles that include any // differences between this and the previous capture. - scoped_refptr<ScreenCaptureData> CaptureScreen(); + webrtc::DesktopFrame* CaptureScreen(); // Called when the screen configuration is changed. |root_window_size| // specifies the most recent size of the root window. - void ScreenConfigurationChanged(const SkISize& root_window_size); + void ScreenConfigurationChanged(const webrtc::DesktopSize& root_window_size); // Synchronize the current buffer with |last_buffer_|, by copying pixels from // the area of |last_invalid_rects|. @@ -89,24 +77,26 @@ class ScreenCapturerLinux : public ScreenCapturer { void DeinitXlib(); // Capture a rectangle from |x_server_pixel_buffer_|, and copy the data into - // |capture_data|. - void CaptureRect(const SkIRect& rect, ScreenCaptureData* capture_data); + // |frame|. + void CaptureRect(const webrtc::DesktopRect& rect, + webrtc::DesktopFrame* frame); // We expose two forms of blitting to handle variations in the pixel format. // In FastBlit, the operation is effectively a memcpy. void FastBlit(uint8* image, - const SkIRect& rect, - ScreenCaptureData* capture_data); + const webrtc::DesktopRect& rect, + webrtc::DesktopFrame* frame); void SlowBlit(uint8* image, - const SkIRect& rect, - ScreenCaptureData* capture_data); + const webrtc::DesktopRect& rect, + webrtc::DesktopFrame* frame); // Returns the number of bits |mask| has to be shifted left so its last // (most-significant) bit set becomes the most-significant bit of the word. // When |mask| is 0 the function returns 31. static uint32 GetRgbShift(uint32 mask); - Delegate* delegate_; + Callback* callback_; + MouseShapeObserver* mouse_shape_observer_; // X11 graphics context. Display* display_; @@ -114,7 +104,7 @@ class ScreenCapturerLinux : public ScreenCapturer { Window root_window_; // Last known dimensions of the root window. - SkISize root_window_size_; + webrtc::DesktopSize root_window_size_; // XFixes. bool has_xfixes_; @@ -140,7 +130,7 @@ class ScreenCapturerLinux : public ScreenCapturer { // Invalid region from the previous capture. This is used to synchronize the // current with the last buffer used. - SkRegion last_invalid_region_; + webrtc::DesktopRegion last_invalid_region_; // |Differ| for use when polling for changes. scoped_ptr<Differ> differ_; @@ -148,24 +138,12 @@ class ScreenCapturerLinux : public ScreenCapturer { DISALLOW_COPY_AND_ASSIGN(ScreenCapturerLinux); }; -ScreenCaptureFrameLinux::ScreenCaptureFrameLinux(const SkISize& window_size) { - set_bytes_per_row(window_size.width() * ScreenCaptureData::kBytesPerPixel); - set_dimensions(window_size); - - size_t buffer_size = bytes_per_row() * window_size.height(); - data_.reset(new uint8[buffer_size]); - set_pixels(data_.get()); -} - -ScreenCaptureFrameLinux::~ScreenCaptureFrameLinux() { -} - ScreenCapturerLinux::ScreenCapturerLinux() - : delegate_(NULL), + : callback_(NULL), + mouse_shape_observer_(NULL), display_(NULL), gc_(NULL), root_window_(BadValue), - root_window_size_(SkISize::Make(0, 0)), has_xfixes_(false), xfixes_event_base_(-1), xfixes_error_base_(-1), @@ -270,50 +248,55 @@ void ScreenCapturerLinux::InitXDamage() { LOG(INFO) << "Using XDamage extension."; } -void ScreenCapturerLinux::Start(Delegate* delegate) { - DCHECK(delegate_ == NULL); +void ScreenCapturerLinux::Start(Callback* callback) { + DCHECK(!callback_); + DCHECK(callback); - delegate_ = delegate; + callback_ = callback; } -void ScreenCapturerLinux::CaptureFrame() { +void ScreenCapturerLinux::Capture(const webrtc::DesktopRegion& region) { base::Time capture_start_time = base::Time::Now(); + queue_.MoveToNextFrame(); + // Process XEvents for XDamage and cursor shape tracking. ProcessPendingXEvents(); - // If the current buffer is from an older generation then allocate a new one. + // If the current frame 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()) { - scoped_ptr<ScreenCaptureFrameLinux> buffer(new ScreenCaptureFrameLinux( - root_window_size_)); - queue_.ReplaceCurrentFrame(buffer.PassAs<ScreenCaptureFrame>()); + if (!queue_.current_frame()) { + scoped_ptr<webrtc::DesktopFrame> frame( + new webrtc::BasicDesktopFrame(root_window_size_)); + queue_.ReplaceCurrentFrame(frame.Pass()); } // Refresh the Differ helper used by CaptureFrame(), if needed. - const ScreenCaptureFrame* current_buffer = queue_.current_frame(); + webrtc::DesktopFrame* frame = queue_.current_frame(); if (!use_damage_ && ( !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() != frame->size().width()) || + (differ_->height() != frame->size().height()) || + (differ_->bytes_per_row() != frame->stride()))) { + differ_.reset(new Differ(frame->size().width(), frame->size().height(), + webrtc::DesktopFrame::kBytesPerPixel, + frame->stride())); } - scoped_refptr<ScreenCaptureData> capture_data(CaptureScreen()); - - // Swap the current & previous buffers ready for the next capture. - last_invalid_region_ = capture_data->dirty_region(); + webrtc::DesktopFrame* result = CaptureScreen(); + last_invalid_region_ = result->updated_region(); + result->set_capture_time_ms( + (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp()); + callback_->OnCaptureCompleted(result); +} - queue_.DoneWithCurrentFrame(); +void ScreenCapturerLinux::SetMouseShapeObserver( + MouseShapeObserver* mouse_shape_observer) { + DCHECK(!mouse_shape_observer_); + DCHECK(mouse_shape_observer); - capture_data->set_capture_time_ms( - (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp()); - delegate_->OnCaptureCompleted(capture_data); + mouse_shape_observer_ = mouse_shape_observer; } void ScreenCapturerLinux::ProcessPendingXEvents() { @@ -329,7 +312,8 @@ void ScreenCapturerLinux::ProcessPendingXEvents() { DCHECK(event->level == XDamageReportNonEmpty); } else if (e.type == ConfigureNotify) { const XConfigureEvent& event = e.xconfigure; - ScreenConfigurationChanged(SkISize::Make(event.width, event.height)); + ScreenConfigurationChanged( + webrtc::DesktopSize(event.width, event.height)); } else if (has_xfixes_ && e.type == xfixes_event_base_ + XFixesCursorNotify) { XFixesCursorNotifyEvent* cne; @@ -352,11 +336,11 @@ void ScreenCapturerLinux::CaptureCursor() { } scoped_ptr<MouseCursorShape> cursor(new MouseCursorShape()); - cursor->size.set(img->width, img->height); - cursor->hotspot.set(img->xhot, img->yhot); + cursor->size = webrtc::DesktopSize(img->width, img->height); + cursor->hotspot = webrtc::DesktopVector(img->xhot, img->yhot); - int total_bytes = cursor->size.width() * cursor->size.height() * - ScreenCaptureData::kBytesPerPixel; + int total_bytes = cursor->size.width ()* cursor->size.height() * + webrtc::DesktopFrame::kBytesPerPixel; cursor->data.resize(total_bytes); // Xlib stores 32-bit data in longs, even if longs are 64-bits long. @@ -368,17 +352,16 @@ void ScreenCapturerLinux::CaptureCursor() { } XFree(img); - delegate_->OnCursorShapeChanged(cursor.Pass()); + if (mouse_shape_observer_) + mouse_shape_observer_->OnCursorShapeChanged(cursor.Pass()); } -scoped_refptr<ScreenCaptureData> ScreenCapturerLinux::CaptureScreen() { - ScreenCaptureFrame* frame = queue_.current_frame(); - scoped_refptr<ScreenCaptureData> capture_data(new ScreenCaptureData( - frame->pixels(), frame->bytes_per_row(), frame->dimensions())); +webrtc::DesktopFrame* ScreenCapturerLinux::CaptureScreen() { + webrtc::DesktopFrame* frame = queue_.current_frame()->Share(); // Pass the screen size to the helper, so it can clip the invalid region if it // expands that region to a grid. - helper_.set_size_most_recent(capture_data->size()); + helper_.set_size_most_recent(frame->size()); // In the DAMAGE case, ensure the frame is up-to-date with the previous frame // if any. If there isn't a previous frame, that means a screen-resolution @@ -387,67 +370,67 @@ scoped_refptr<ScreenCaptureData> ScreenCapturerLinux::CaptureScreen() { if (use_damage_ && queue_.previous_frame()) SynchronizeFrame(); - SkRegion invalid_region; + webrtc::DesktopRegion* updated_region = frame->mutable_updated_region(); x_server_pixel_buffer_.Synchronize(); if (use_damage_ && queue_.previous_frame()) { // Atomically fetch and clear the damage region. XDamageSubtract(display_, damage_handle_, None, damage_region_); - int nRects = 0; + int rects_num = 0; XRectangle bounds; XRectangle* rects = XFixesFetchRegionAndBounds(display_, damage_region_, - &nRects, &bounds); - for (int i=0; i<nRects; ++i) { - invalid_region.op(SkIRect::MakeXYWH(rects[i].x, rects[i].y, - rects[i].width, rects[i].height), - SkRegion::kUnion_Op); + &rects_num, &bounds); + for (int i = 0; i < rects_num; ++i) { + updated_region->AddRect(webrtc::DesktopRect::MakeXYWH( + rects[i].x, rects[i].y, rects[i].width, rects[i].height)); } XFree(rects); - helper_.InvalidateRegion(invalid_region); + helper_.InvalidateRegion(*updated_region); // Capture the damaged portions of the desktop. - helper_.SwapInvalidRegion(&invalid_region); + helper_.TakeInvalidRegion(updated_region); // Clip the damaged portions to the current screen size, just in case some // spurious XDamage notifications were received for a previous (larger) // screen size. - invalid_region.op(SkIRect::MakeSize(root_window_size_), - SkRegion::kIntersect_Op); - for (SkRegion::Iterator it(invalid_region); !it.done(); it.next()) { - CaptureRect(it.rect(), capture_data); + updated_region->IntersectWith( + webrtc::DesktopRect::MakeSize(root_window_size_)); + for (webrtc::DesktopRegion::Iterator it(*updated_region); + !it.IsAtEnd(); it.Advance()) { + CaptureRect(it.rect(), frame); } } else { // Doing full-screen polling, or this is the first capture after a // screen-resolution change. In either case, need a full-screen capture. - SkIRect screen_rect = SkIRect::MakeWH(frame->dimensions().width(), - frame->dimensions().height()); - CaptureRect(screen_rect, capture_data); + webrtc::DesktopRect screen_rect = + webrtc::DesktopRect::MakeSize(frame->size()); + CaptureRect(screen_rect, frame); if (queue_.previous_frame()) { // Full-screen polling, so calculate the invalid rects here, based on the // changed pixels between current and previous buffers. DCHECK(differ_ != NULL); - differ_->CalcDirtyRegion(queue_.previous_frame()->pixels(), - frame->pixels(), &invalid_region); + DCHECK(queue_.previous_frame()->data()); + differ_->CalcDirtyRegion(queue_.previous_frame()->data(), + frame->data(), updated_region); } else { // No previous buffer, so always invalidate the whole screen, whether // or not DAMAGE is being used. DAMAGE doesn't necessarily send a // full-screen notification after a screen-resolution change, so // this is done here. - invalid_region.op(screen_rect, SkRegion::kUnion_Op); + updated_region->SetRect(screen_rect); } } - capture_data->mutable_dirty_region() = invalid_region; - return capture_data; + return frame; } void ScreenCapturerLinux::ScreenConfigurationChanged( - const SkISize& root_window_size) { + const webrtc::DesktopSize& root_window_size) { root_window_size_ = root_window_size; // Make sure the frame buffers will be reallocated. - queue_.SetAllFramesNeedUpdate(); + queue_.Reset(); helper_.ClearInvalidRegion(); x_server_pixel_buffer_.Init(display_, root_window_size_); @@ -464,18 +447,18 @@ void ScreenCapturerLinux::SynchronizeFrame() { // http://crbug.com/92354 DCHECK(queue_.previous_frame()); - ScreenCaptureFrame* current = queue_.current_frame(); - ScreenCaptureFrame* last = queue_.previous_frame(); + webrtc::DesktopFrame* current = queue_.current_frame(); + webrtc::DesktopFrame* last = queue_.previous_frame(); DCHECK_NE(current, last); - for (SkRegion::Iterator it(last_invalid_region_); !it.done(); it.next()) { - const SkIRect& r = it.rect(); - int offset = r.fTop * current->bytes_per_row() + - r.fLeft * ScreenCaptureData::kBytesPerPixel; + for (webrtc::DesktopRegion::Iterator it(last_invalid_region_); + !it.IsAtEnd(); it.Advance()) { + const webrtc::DesktopRect& r = it.rect(); + int offset = r.top() * current->stride() + + r.left() * webrtc::DesktopFrame::kBytesPerPixel; for (int i = 0; i < r.height(); ++i) { - memcpy(current->pixels() + offset, last->pixels() + offset, - r.width() * ScreenCaptureData::kBytesPerPixel); - offset += current->dimensions().width() * - ScreenCaptureData::kBytesPerPixel; + memcpy(current->data() + offset, last->data() + offset, + r.width() * webrtc::DesktopFrame::kBytesPerPixel); + offset += current->size().width() * webrtc::DesktopFrame::kBytesPerPixel; } } } @@ -500,8 +483,8 @@ void ScreenCapturerLinux::DeinitXlib() { } } -void ScreenCapturerLinux::CaptureRect(const SkIRect& rect, - ScreenCaptureData* capture_data) { +void ScreenCapturerLinux::CaptureRect(const webrtc::DesktopRect& rect, + webrtc::DesktopFrame* frame) { uint8* image = x_server_pixel_buffer_.CaptureRect(rect); int depth = x_server_pixel_buffer_.GetDepth(); if ((depth == 24 || depth == 32) && @@ -510,35 +493,37 @@ void ScreenCapturerLinux::CaptureRect(const SkIRect& rect, x_server_pixel_buffer_.GetGreenMask() == 0xff00 && x_server_pixel_buffer_.GetBlueMask() == 0xff) { DVLOG(3) << "Fast blitting"; - FastBlit(image, rect, capture_data); + FastBlit(image, rect, frame); } else { DVLOG(3) << "Slow blitting"; - SlowBlit(image, rect, capture_data); + SlowBlit(image, rect, frame); } } -void ScreenCapturerLinux::FastBlit(uint8* image, const SkIRect& rect, - ScreenCaptureData* capture_data) { +void ScreenCapturerLinux::FastBlit(uint8* image, + const webrtc::DesktopRect& rect, + webrtc::DesktopFrame* frame) { uint8* src_pos = image; int src_stride = x_server_pixel_buffer_.GetStride(); - int dst_x = rect.fLeft, dst_y = rect.fTop; + int dst_x = rect.left(), dst_y = rect.top(); - uint8* dst_pos = capture_data->data() + capture_data->stride() * dst_y; - dst_pos += dst_x * ScreenCaptureData::kBytesPerPixel; + uint8* dst_pos = frame->data() + frame->stride() * dst_y; + dst_pos += dst_x * webrtc::DesktopFrame::kBytesPerPixel; int height = rect.height(); - int row_bytes = rect.width() * ScreenCaptureData::kBytesPerPixel; + int row_bytes = rect.width() * webrtc::DesktopFrame::kBytesPerPixel; for (int y = 0; y < height; ++y) { memcpy(dst_pos, src_pos, row_bytes); src_pos += src_stride; - dst_pos += capture_data->stride(); + dst_pos += frame->stride(); } } -void ScreenCapturerLinux::SlowBlit(uint8* image, const SkIRect& rect, - ScreenCaptureData* capture_data) { +void ScreenCapturerLinux::SlowBlit(uint8* image, + const webrtc::DesktopRect& rect, + webrtc::DesktopFrame* frame) { int src_stride = x_server_pixel_buffer_.GetStride(); - int dst_x = rect.fLeft, dst_y = rect.fTop; + int dst_x = rect.left(), dst_y = rect.top(); int width = rect.width(), height = rect.height(); uint32 red_mask = x_server_pixel_buffer_.GetRedMask(); @@ -551,9 +536,9 @@ void ScreenCapturerLinux::SlowBlit(uint8* image, const SkIRect& rect, unsigned int bits_per_pixel = x_server_pixel_buffer_.GetBitsPerPixel(); - uint8* dst_pos = capture_data->data() + capture_data->stride() * dst_y; + uint8* dst_pos = frame->data() + frame->stride() * dst_y; uint8* src_pos = image; - dst_pos += dst_x * ScreenCaptureData::kBytesPerPixel; + dst_pos += dst_x * webrtc::DesktopFrame::kBytesPerPixel; // TODO(hclam): Optimize, perhaps using MMX code or by converting to // YUV directly for (int y = 0; y < height; y++) { @@ -577,7 +562,7 @@ void ScreenCapturerLinux::SlowBlit(uint8* image, const SkIRect& rect, dst_pos_32[x] = ((r >> 8) & 0xff0000) | ((g >> 16) & 0xff00) | ((b >> 24) & 0xff); } - dst_pos += capture_data->stride(); + dst_pos += frame->stride(); src_pos += src_stride; } } @@ -609,15 +594,6 @@ uint32 ScreenCapturerLinux::GetRgbShift(uint32 mask) { } // 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() { scoped_ptr<ScreenCapturerLinux> capturer(new ScreenCapturerLinux()); diff --git a/media/video/capture/screen/shared_buffer.cc b/media/video/capture/screen/shared_buffer.cc deleted file mode 100644 index 33eb5c3..0000000 --- a/media/video/capture/screen/shared_buffer.cc +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/video/capture/screen/shared_buffer.h" - -const bool kReadOnly = true; - -namespace media { - -SharedBuffer::SharedBuffer(uint32 size) - : id_(0), - size_(size) { - shared_memory_.CreateAndMapAnonymous(size); -} - -SharedBuffer::SharedBuffer( - int id, base::SharedMemoryHandle handle, uint32 size) - : id_(id), - shared_memory_(handle, kReadOnly), - size_(size) { - shared_memory_.Map(size); -} - -SharedBuffer::SharedBuffer( - int id, base::SharedMemoryHandle handle, base::ProcessHandle process, - uint32 size) - : id_(id), - shared_memory_(handle, kReadOnly, process), - size_(size) { - shared_memory_.Map(size); -} - -SharedBuffer::~SharedBuffer() { -} - -bool SharedBuffer::ShareToProcess(base::ProcessHandle process, - base::SharedMemoryHandle* new_handle) { - return shared_memory_.ShareToProcess(process, new_handle); -} - -} // namespace media diff --git a/media/video/capture/screen/shared_buffer.h b/media/video/capture/screen/shared_buffer.h deleted file mode 100644 index 4c77b6a0..0000000 --- a/media/video/capture/screen/shared_buffer.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MEDIA_VIDEO_CAPTURE_SCREEN_SHARED_BUFFER_H_ -#define MEDIA_VIDEO_CAPTURE_SCREEN_SHARED_BUFFER_H_ - -#include "base/basictypes.h" -#include "base/memory/ref_counted.h" -#include "base/process.h" -#include "base/shared_memory.h" -#include "media/base/media_export.h" - -namespace media { - -// Represents a memory buffer that can be shared between multiple processes. -// It is more or less a convenience wrapper around base::SharedMemory providing -// ref-counted lifetime management and unique buffer identifiers. -class MEDIA_EXPORT SharedBuffer - : public base::RefCountedThreadSafe<SharedBuffer> { - public: - // Creates a new shared memory buffer of the given size and maps it to - // the memory of the calling process. If the operation fails for any reason, - // ptr() method will return NULL. This constructor set the identifier of this - // buffer to 0. - explicit SharedBuffer(uint32 size); - - // Opens an existing shared memory buffer and maps it to the memory of - // the calling process (in read only mode). If the operation fails for any - // reason, ptr() method will return NULL. - SharedBuffer(int id, base::SharedMemoryHandle handle, uint32 size); - - // Opens an existing shared memory buffer created by a different process and - // maps it to the memory of the calling process (in read only mode). If - // the operation fails for any reason, ptr() method will return NULL. - SharedBuffer(int id, base::SharedMemoryHandle handle, - base::ProcessHandle process, uint32 size); - - // Returns pointer to the beginning of the allocated data buffer. Returns NULL - // if the object initialization failed for any reason. - void* ptr() const { return shared_memory_.memory(); } - - // Returns handle of the shared memory section containing the allocated - // data buffer. - base::SharedMemoryHandle handle() const { return shared_memory_.handle(); } - - // Calls SharedMemory::ShareToProcess to share the handle with a different - // process. - bool ShareToProcess(base::ProcessHandle process, - base::SharedMemoryHandle* new_handle); - - int id() const { return id_; } - uint32 size() const { return size_; } - - void set_id(int id) { id_ = id; } - - private: - friend class base::RefCountedThreadSafe<SharedBuffer>; - virtual ~SharedBuffer(); - - // Unique identifier of the buffer or 0 if ID hasn't been set. - int id_; - - // Shared memory section backing up the buffer. - base::SharedMemory shared_memory_; - - // Size of the buffer in bytes. - uint32 size_; - - DISALLOW_COPY_AND_ASSIGN(SharedBuffer); -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_SCREEN_SHARED_BUFFER_H_ diff --git a/media/video/capture/screen/shared_buffer_unittest.cc b/media/video/capture/screen/shared_buffer_unittest.cc deleted file mode 100644 index 1efc798..0000000 --- a/media/video/capture/screen/shared_buffer_unittest.cc +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/process_util.h" -#include "media/video/capture/screen/shared_buffer.h" -#include "testing/gtest/include/gtest/gtest.h" - -const uint32 kBufferSize = 4096; -const int kPattern = 0x12345678; - -const int kIdZero = 0; -const int kIdOne = 1; - -namespace media { - -TEST(SharedBufferTest, Basic) { - scoped_refptr<SharedBuffer> source(new SharedBuffer(kBufferSize)); - - // Make sure that the buffer is allocated, the size is recorded correctly and - // its ID is reset. - EXPECT_TRUE(source->ptr() != NULL); - EXPECT_EQ(source->id(), kIdZero); - EXPECT_EQ(source->size(), kBufferSize); - - // See if setting of the ID works. - source->set_id(kIdOne); - EXPECT_EQ(source->id(), kIdOne); - - base::SharedMemoryHandle copied_handle; - EXPECT_TRUE(source->ShareToProcess( - base::GetCurrentProcessHandle(), &copied_handle)); - - scoped_refptr<SharedBuffer> dest( - new SharedBuffer(kIdZero, copied_handle, kBufferSize)); - - // Make sure that the buffer is allocated, the size is recorded correctly and - // its ID is reset. - EXPECT_TRUE(dest->ptr() != NULL); - EXPECT_EQ(dest->id(), kIdZero); - EXPECT_EQ(dest->size(), kBufferSize); - - // Verify that the memory contents are the same for the two buffers. - int* source_ptr = reinterpret_cast<int*>(source->ptr()); - *source_ptr = kPattern; - int* dest_ptr = reinterpret_cast<int*>(dest->ptr()); - EXPECT_EQ(*source_ptr, *dest_ptr); - - // Check that the destination buffer is still mapped even when the source - // buffer is destroyed. - source = NULL; - EXPECT_EQ(0x12345678, *dest_ptr); -} - -} // namespace media diff --git a/media/video/capture/screen/shared_desktop_frame.cc b/media/video/capture/screen/shared_desktop_frame.cc new file mode 100644 index 0000000..b0a6f14 --- /dev/null +++ b/media/video/capture/screen/shared_desktop_frame.cc @@ -0,0 +1,56 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/video/capture/screen/shared_desktop_frame.h" + +#include "base/memory/scoped_ptr.h" + +namespace media { + +class SharedDesktopFrame::Core : public base::RefCountedThreadSafe<Core> { + public: + Core(webrtc::DesktopFrame* frame) : frame_(frame) {} + + webrtc::DesktopFrame* frame() { return frame_.get(); } + + private: + friend class base::RefCountedThreadSafe<Core>; + virtual ~Core() {} + + scoped_ptr<webrtc::DesktopFrame> frame_; + + DISALLOW_COPY_AND_ASSIGN(Core); +}; + +SharedDesktopFrame::~SharedDesktopFrame() {} + +// static +SharedDesktopFrame* SharedDesktopFrame::Wrap( + webrtc::DesktopFrame* desktop_frame) { + return new SharedDesktopFrame(new Core(desktop_frame)); +} + +webrtc::DesktopFrame* SharedDesktopFrame::GetUnderlyingFrame() { + return core_->frame(); +} + +SharedDesktopFrame* SharedDesktopFrame::Share() { + SharedDesktopFrame* result = new SharedDesktopFrame(core_); + result->set_dpi(dpi()); + result->set_capture_time_ms(capture_time_ms()); + *result->mutable_updated_region() = updated_region(); + return result; +} + +bool SharedDesktopFrame::IsShared() { + return !core_->HasOneRef(); +} + +SharedDesktopFrame::SharedDesktopFrame(scoped_refptr<Core> core) + : DesktopFrame(core->frame()->size(), core->frame()->stride(), + core->frame()->data(), core->frame()->shared_memory()), + core_(core) { +} + +} // namespace media diff --git a/media/video/capture/screen/shared_desktop_frame.h b/media/video/capture/screen/shared_desktop_frame.h new file mode 100644 index 0000000..861b5f0 --- /dev/null +++ b/media/video/capture/screen/shared_desktop_frame.h @@ -0,0 +1,43 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_VIDEO_CAPTURE_SCREEN_SHARED_DESKTOP_FRAME_H_ +#define MEDIA_VIDEO_CAPTURE_SCREEN_SHARED_DESKTOP_FRAME_H_ + +#include "base/memory/ref_counted.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" + +namespace media { + +// SharedDesktopFrame is a DesktopFrame that may have multiple instances all +// sharing the same buffer. +class SharedDesktopFrame : public webrtc::DesktopFrame { + public: + virtual ~SharedDesktopFrame(); + + static SharedDesktopFrame* Wrap(webrtc::DesktopFrame* desktop_frame); + + // Returns the underlying instance of DesktopFrame. + webrtc::DesktopFrame* GetUnderlyingFrame(); + + // Creates a clone of this object. + SharedDesktopFrame* Share(); + + // Checks if the frame is currently shared. If it returns false it's + // guaranteed that there are no clones of the object. + bool IsShared(); + + private: + class Core; + + SharedDesktopFrame(scoped_refptr<Core> core); + + scoped_refptr<Core> core_; + + DISALLOW_COPY_AND_ASSIGN(SharedDesktopFrame); +}; + +} // namespace media + +#endif // MEDIA_VIDEO_CAPTURE_SCREEN_SHARED_DESKTOP_FRAME_H_ diff --git a/media/video/capture/screen/x11/x_server_pixel_buffer.cc b/media/video/capture/screen/x11/x_server_pixel_buffer.cc index 980f1ca..4941666 100644 --- a/media/video/capture/screen/x11/x_server_pixel_buffer.cc +++ b/media/video/capture/screen/x11/x_server_pixel_buffer.cc @@ -60,7 +60,7 @@ namespace media { XServerPixelBuffer::XServerPixelBuffer() : display_(NULL), root_window_(0), - root_window_size_(SkISize::Make(0, 0)), x_image_(NULL), + x_image_(NULL), shm_segment_info_(NULL), shm_pixmap_(0), shm_gc_(NULL) { } @@ -92,7 +92,7 @@ void XServerPixelBuffer::Release() { } void XServerPixelBuffer::Init(Display* display, - const SkISize& screen_size) { + const webrtc::DesktopSize& screen_size) { Release(); display_ = display; root_window_size_ = screen_size; @@ -102,10 +102,10 @@ void XServerPixelBuffer::Init(Display* display, } // static -SkISize XServerPixelBuffer::GetRootWindowSize(Display* display) { +webrtc::DesktopSize XServerPixelBuffer::GetRootWindowSize(Display* display) { XWindowAttributes root_attr; XGetWindowAttributes(display, DefaultRootWindow(display), &root_attr); - return SkISize::Make(root_attr.width, root_attr.height); + return webrtc::DesktopSize(root_attr.width, root_attr.height); } void XServerPixelBuffer::InitShm(int screen) { @@ -211,22 +211,24 @@ void XServerPixelBuffer::Synchronize() { } } -uint8* XServerPixelBuffer::CaptureRect(const SkIRect& rect) { - DCHECK(SkIRect::MakeSize(root_window_size_).contains(rect)); +uint8* XServerPixelBuffer::CaptureRect(const webrtc::DesktopRect& rect) { + DCHECK_LE(rect.right(), root_window_size_.width()); + DCHECK_LE(rect.bottom(), root_window_size_.height()); + if (shm_segment_info_) { if (shm_pixmap_) { XCopyArea(display_, root_window_, shm_pixmap_, shm_gc_, - rect.fLeft, rect.fTop, rect.width(), rect.height(), - rect.fLeft, rect.fTop); + rect.left(), rect.top(), rect.width(), rect.height(), + rect.left(), rect.top()); XSync(display_, False); } return reinterpret_cast<uint8*>(x_image_->data) + - rect.fTop * x_image_->bytes_per_line + - rect.fLeft * x_image_->bits_per_pixel / 8; + rect.top() * x_image_->bytes_per_line + + rect.left() * x_image_->bits_per_pixel / 8; } else { if (x_image_) XDestroyImage(x_image_); - x_image_ = XGetImage(display_, root_window_, rect.fLeft, rect.fTop, + x_image_ = XGetImage(display_, root_window_, rect.left(), rect.top(), rect.width(), rect.height(), AllPlanes, ZPixmap); return reinterpret_cast<uint8*>(x_image_->data); } diff --git a/media/video/capture/screen/x11/x_server_pixel_buffer.h b/media/video/capture/screen/x11/x_server_pixel_buffer.h index 139fbbf..40a1678 100644 --- a/media/video/capture/screen/x11/x_server_pixel_buffer.h +++ b/media/video/capture/screen/x11/x_server_pixel_buffer.h @@ -8,7 +8,7 @@ #define MEDIA_VIDEO_CAPTURE_SCREEN_X11_X_SERVER_PIXEL_BUFFER_H_ #include "base/basictypes.h" -#include "third_party/skia/include/core/SkRect.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" #include <X11/Xutil.h> #include <X11/extensions/XShm.h> @@ -28,10 +28,10 @@ class XServerPixelBuffer { // assumed to be the current size of the root window. // |screen_size| should either come from GetRootWindowSize(), or // from a recent ConfigureNotify event on the root window. - void Init(Display* display, const SkISize& screen_size); + void Init(Display* display, const webrtc::DesktopSize& screen_size); // Request the current size of the root window from the X Server. - static SkISize GetRootWindowSize(Display* display); + static webrtc::DesktopSize GetRootWindowSize(Display* display); // If shared memory is being used without pixmaps, synchronize this pixel // buffer with the root window contents (otherwise, this is a no-op). @@ -47,7 +47,7 @@ class XServerPixelBuffer { // simply returns the pointer without doing any more work. // The caller must ensure that |rect| is no larger than the screen size // supplied to Init(). - uint8* CaptureRect(const SkIRect& rect); + uint8* CaptureRect(const webrtc::DesktopRect& rect); // Return information about the most recent capture. This is only guaranteed // to be valid between CaptureRect calls. @@ -64,7 +64,7 @@ class XServerPixelBuffer { Display* display_; Window root_window_; - SkISize root_window_size_; + webrtc::DesktopSize root_window_size_; XImage* x_image_; XShmSegmentInfo* shm_segment_info_; Pixmap shm_pixmap_; |