summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-16 10:45:24 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-16 10:45:24 +0000
commitb9ed58f046141b4610c1bdc966d962d5fb95ac6b (patch)
treeb7dc10e49ea765b6ebc99985d3538a2e1363942e /media
parentc1c88cf23606dd1ca2bfd9f57496aeec847e713f (diff)
downloadchromium_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')
-rw-r--r--media/media.gyp36
-rw-r--r--media/video/capture/screen/DEPS1
-rw-r--r--media/video/capture/screen/differ.cc20
-rw-r--r--media/video/capture/screen/differ.h8
-rw-r--r--media/video/capture/screen/differ_unittest.cc85
-rw-r--r--media/video/capture/screen/mac/desktop_configuration.h11
-rw-r--r--media/video/capture/screen/mac/desktop_configuration.mm50
-rw-r--r--media/video/capture/screen/mouse_cursor_shape.cc17
-rw-r--r--media/video/capture/screen/mouse_cursor_shape.h11
-rw-r--r--media/video/capture/screen/screen_capture_data.cc22
-rw-r--r--media/video/capture/screen/screen_capture_data.h93
-rw-r--r--media/video/capture/screen/screen_capture_device.cc76
-rw-r--r--media/video/capture/screen/screen_capture_device_unittest.cc37
-rw-r--r--media/video/capture/screen/screen_capture_frame.cc18
-rw-r--r--media/video/capture/screen/screen_capture_frame.h64
-rw-r--r--media/video/capture/screen/screen_capture_frame_queue.cc32
-rw-r--r--media/video/capture/screen/screen_capture_frame_queue.h45
-rw-r--r--media/video/capture/screen/screen_capturer.h47
-rw-r--r--media/video/capture/screen/screen_capturer_fake.cc97
-rw-r--r--media/video/capture/screen/screen_capturer_fake.h33
-rw-r--r--media/video/capture/screen/screen_capturer_helper.cc44
-rw-r--r--media/video/capture/screen/screen_capturer_helper.h23
-rw-r--r--media/video/capture/screen/screen_capturer_helper_unittest.cc156
-rw-r--r--media/video/capture/screen/screen_capturer_mac.mm334
-rw-r--r--media/video/capture/screen/screen_capturer_mac_unittest.cc62
-rw-r--r--media/video/capture/screen/screen_capturer_mock_objects.cc18
-rw-r--r--media/video/capture/screen/screen_capturer_mock_objects.h32
-rw-r--r--media/video/capture/screen/screen_capturer_unittest.cc98
-rw-r--r--media/video/capture/screen/screen_capturer_win.cc251
-rw-r--r--media/video/capture/screen/screen_capturer_x11.cc264
-rw-r--r--media/video/capture/screen/shared_buffer.cc42
-rw-r--r--media/video/capture/screen/shared_buffer.h75
-rw-r--r--media/video/capture/screen/shared_buffer_unittest.cc55
-rw-r--r--media/video/capture/screen/shared_desktop_frame.cc56
-rw-r--r--media/video/capture/screen/shared_desktop_frame.h43
-rw-r--r--media/video/capture/screen/x11/x_server_pixel_buffer.cc24
-rw-r--r--media/video/capture/screen/x11/x_server_pixel_buffer.h10
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(&region);
- ASSERT_TRUE(region.isEmpty());
+ capturer_helper_.TakeInvalidRegion(&region);
+ ASSERT_TRUE(region.is_empty());
}
TEST_F(ScreenCapturerHelperTest, InvalidateRegion) {
- SkRegion region;
- capturer_helper_.SwapInvalidRegion(&region);
- ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeEmpty()), region));
-
- capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(1, 2, 3, 4)));
- region.setEmpty();
- capturer_helper_.SwapInvalidRegion(&region);
- 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(&region);
- ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(1, 2, 6, 4)), region));
+ DesktopRegion region;
+ capturer_helper_.TakeInvalidRegion(&region);
+ ASSERT_TRUE(region.is_empty());
+
+ region.SetRect(DesktopRect::MakeXYWH(1, 2, 3, 4));
+ capturer_helper_.InvalidateRegion(region);
+ capturer_helper_.TakeInvalidRegion(&region);
+ 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(&region);
+ 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(&region);
- 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(&region);
- ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeWH(12, 34)), region));
+ DesktopRegion region;
+ capturer_helper_.InvalidateScreen(DesktopSize(12, 34));
+ capturer_helper_.TakeInvalidRegion(&region);
+ 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(&region);
- ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeEmpty()), region));
+ DesktopRegion region;
+ capturer_helper_.TakeInvalidRegion(&region);
+ ASSERT_TRUE(Equals(RectToRegion(DesktopRect()), region));
- capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1)));
- region.setEmpty();
- capturer_helper_.SwapInvalidRegion(&region);
- ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1)), region));
+ capturer_helper_.InvalidateRegion(
+ RectToRegion(DesktopRect::MakeXYWH(7, 7, 1, 1)));
+ capturer_helper_.TakeInvalidRegion(&region);
+ 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(&region);
- ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1)), region));
+ capturer_helper_.InvalidateRegion(
+ RectToRegion(DesktopRect::MakeXYWH(7, 7, 1, 1)));
+ capturer_helper_.TakeInvalidRegion(&region);
+ 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(&region);
- ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1)), region));
+ capturer_helper_.InvalidateRegion(
+ RectToRegion(DesktopRect::MakeXYWH(7, 7, 1, 1)));
+ capturer_helper_.TakeInvalidRegion(&region);
+ 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(&region);
- ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(6, 6, 2, 2)), region));
+ capturer_helper_.InvalidateRegion(
+ RectToRegion(DesktopRect::MakeXYWH(7, 7, 1, 1)));
+ capturer_helper_.TakeInvalidRegion(&region);
+ 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(&region);
- ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(4, 4, 4, 4)), region));
+ capturer_helper_.InvalidateRegion(
+ RectToRegion(DesktopRect::MakeXYWH(7, 7, 1, 1)));
+ capturer_helper_.TakeInvalidRegion(&region);
+ 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(&region);
- ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1)), region));
+ capturer_helper_.InvalidateRegion(
+ RectToRegion(DesktopRect::MakeXYWH(7, 7, 1, 1)));
+ capturer_helper_.TakeInvalidRegion(&region);
+ 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(&region);
+ webrtc::DesktopRegion region;
+ helper_.TakeInvalidRegion(&region);
// 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(),
&region);
helper_.InvalidateRegion(region);
} else {
// No previous frame is available. Invalidate the whole screen.
- helper_.InvalidateScreen(current_buffer->dimensions());
+ helper_.InvalidateScreen(current_frame->size());
}
- // Wrap the captured frame into ScreenCaptureData structure and invoke
- // the completion callback.
- SkRegion invalid_region;
- helper_.SwapInvalidRegion(&invalid_region);
- CaptureRegion(invalid_region, capture_start_time);
+ helper_.set_size_most_recent(current_frame->size());
+
+ // Emit 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_;