diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-28 23:54:03 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-28 23:54:03 +0000 |
commit | 497d8a9857e7383f979b89694aff8dd403c176fe (patch) | |
tree | 2f07bb42d4a7a8e94e959c90dacbfa62eed1debd /remoting | |
parent | bac4ae80a786d68bfc18ca46f0adfcc4a1c43b0f (diff) | |
download | chromium_src-497d8a9857e7383f979b89694aff8dd403c176fe.zip chromium_src-497d8a9857e7383f979b89694aff8dd403c176fe.tar.gz chromium_src-497d8a9857e7383f979b89694aff8dd403c176fe.tar.bz2 |
Move screen capturers from remoting/capturer to media/video/capturer/screen
Screen capturers will be used in content, and so they have to be moved to
avoid dependency on remoting/capturer in content.
Beside moving the files this CL also renames classes as follows:
remoting::VideoFrameCapturer -> media::ScreenCapturer
remoting::VideoFrame -> media::ScreenCaptureFrame
remoting::CaptureData -> media::ScreenCaptureData
BUG=134249
Review URL: https://codereview.chromium.org/12047101
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@179218 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
81 files changed, 218 insertions, 6034 deletions
diff --git a/remoting/capturer/DEPS b/remoting/capturer/DEPS deleted file mode 100644 index 6b0cdaa6..0000000 --- a/remoting/capturer/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -include_rules = [ - "-remoting/base", -] diff --git a/remoting/capturer/capture_data.cc b/remoting/capturer/capture_data.cc deleted file mode 100644 index 49511da..0000000 --- a/remoting/capturer/capture_data.cc +++ /dev/null @@ -1,20 +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 "remoting/capturer/capture_data.h" - -namespace remoting { - -CaptureData::CaptureData(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)) { -} - -CaptureData::~CaptureData() {} - -} // namespace remoting diff --git a/remoting/capturer/capture_data.h b/remoting/capturer/capture_data.h deleted file mode 100644 index a68ebe8..0000000 --- a/remoting/capturer/capture_data.h +++ /dev/null @@ -1,91 +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 REMOTING_CAPTURER_CAPTURE_DATA_H_ -#define REMOTING_CAPTURER_CAPTURE_DATA_H_ - -#include <vector> - -#include "base/basictypes.h" -#include "base/memory/ref_counted.h" -#include "remoting/capturer/shared_buffer.h" -#include "third_party/skia/include/core/SkRegion.h" - -namespace remoting { - -class SharedBuffer; - -// Stores the data and information of a capture to pass off to the -// encoding thread. -class CaptureData : public base::RefCountedThreadSafe<CaptureData> { - public: - // 32 bit RGB is 4 bytes per pixel. - static const int kBytesPerPixel = 4; - - CaptureData(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<CaptureData>; - virtual ~CaptureData(); - - 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 remoting - -#endif // REMOTING_CAPTURER_CAPTURE_DATA_H_ diff --git a/remoting/capturer/differ.cc b/remoting/capturer/differ.cc deleted file mode 100644 index 07421cf..0000000 --- a/remoting/capturer/differ.cc +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright (c) 2011 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 "remoting/capturer/differ.h" - -#include "base/logging.h" -#include "remoting/capturer/differ_block.h" - -namespace remoting { - -Differ::Differ(int width, int height, int bpp, int stride) { - // Dimensions of screen. - width_ = width; - height_ = height; - bytes_per_pixel_ = bpp; - bytes_per_row_ = stride; - - // Calc number of blocks (full and partial) required to cover entire image. - // One additional row/column is added as a boundary on the right & bottom. - diff_info_width_ = ((width_ + kBlockSize - 1) / kBlockSize) + 1; - diff_info_height_ = ((height_ + kBlockSize - 1) / kBlockSize) + 1; - diff_info_size_ = diff_info_width_ * diff_info_height_ * sizeof(DiffInfo); - diff_info_.reset(new DiffInfo[diff_info_size_]); -} - -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; - } - - // Identify all the blocks that contain changed pixels. - MarkDirtyBlocks(prev_buffer, curr_buffer); - - // Now that we've identified the blocks that have changed, merge adjacent - // blocks to minimize the number of rects that we return. - MergeBlocks(region); -} - -void Differ::MarkDirtyBlocks(const void* prev_buffer, const void* curr_buffer) { - memset(diff_info_.get(), 0, diff_info_size_); - - // Calc number of full blocks. - int x_full_blocks = width_ / kBlockSize; - int y_full_blocks = height_ / kBlockSize; - - // Calc size of partial blocks which may be present on right and bottom edge. - int partial_column_width = width_ - (x_full_blocks * kBlockSize); - int partial_row_height = height_ - (y_full_blocks * kBlockSize); - - // Offset from the start of one block-column to the next. - int block_x_offset = bytes_per_pixel_ * kBlockSize; - // Offset from the start of one block-row to the next. - int block_y_stride = (width_ * bytes_per_pixel_) * kBlockSize; - // Offset from the start of one diff_info row to the next. - int diff_info_stride = diff_info_width_ * sizeof(DiffInfo); - - const uint8* prev_block_row_start = static_cast<const uint8*>(prev_buffer); - const uint8* curr_block_row_start = static_cast<const uint8*>(curr_buffer); - DiffInfo* diff_info_row_start = static_cast<DiffInfo*>(diff_info_.get()); - - for (int y = 0; y < y_full_blocks; y++) { - const uint8* prev_block = prev_block_row_start; - const uint8* curr_block = curr_block_row_start; - DiffInfo* diff_info = diff_info_row_start; - - for (int x = 0; x < x_full_blocks; x++) { - // Mark this block as being modified so that it gets incorporated into - // a dirty rect. - *diff_info = BlockDifference(prev_block, curr_block, bytes_per_row_); - prev_block += block_x_offset; - curr_block += block_x_offset; - diff_info += sizeof(DiffInfo); - } - - // If there is a partial column at the end, handle it. - // This condition should rarely, if ever, occur. - if (partial_column_width != 0) { - *diff_info = DiffPartialBlock(prev_block, curr_block, bytes_per_row_, - partial_column_width, kBlockSize); - diff_info += sizeof(DiffInfo); - } - - // Update pointers for next row. - prev_block_row_start += block_y_stride; - curr_block_row_start += block_y_stride; - diff_info_row_start += diff_info_stride; - } - - // If the screen height is not a multiple of the block size, then this - // handles the last partial row. This situation is far more common than the - // 'partial column' case. - if (partial_row_height != 0) { - const uint8* prev_block = prev_block_row_start; - const uint8* curr_block = curr_block_row_start; - DiffInfo* diff_info = diff_info_row_start; - for (int x = 0; x < x_full_blocks; x++) { - *diff_info = DiffPartialBlock(prev_block, curr_block, - bytes_per_row_, - kBlockSize, partial_row_height); - prev_block += block_x_offset; - curr_block += block_x_offset; - diff_info += sizeof(DiffInfo); - } - if (partial_column_width != 0) { - *diff_info = DiffPartialBlock(prev_block, curr_block, bytes_per_row_, - partial_column_width, partial_row_height); - diff_info += sizeof(DiffInfo); - } - } -} - -DiffInfo Differ::DiffPartialBlock(const uint8* prev_buffer, - const uint8* curr_buffer, - int stride, int width, int height) { - int width_bytes = width * bytes_per_pixel_; - for (int y = 0; y < height; y++) { - if (memcmp(prev_buffer, curr_buffer, width_bytes) != 0) - return 1; - prev_buffer += bytes_per_row_; - curr_buffer += bytes_per_row_; - } - return 0; -} - -void Differ::MergeBlocks(SkRegion* region) { - DCHECK(region); - region->setEmpty(); - - uint8* diff_info_row_start = static_cast<uint8*>(diff_info_.get()); - int diff_info_stride = diff_info_width_ * sizeof(DiffInfo); - - for (int y = 0; y < diff_info_height_; y++) { - uint8* diff_info = diff_info_row_start; - for (int x = 0; x < diff_info_width_; x++) { - if (*diff_info != 0) { - // We've found a modified block. Look at blocks to the right and below - // to group this block with as many others as we can. - int left = x * kBlockSize; - int top = y * kBlockSize; - int width = 1; - int height = 1; - *diff_info = 0; - - // Group with blocks to the right. - // We can keep looking until we find an unchanged block because we - // have a boundary block which is never marked as having diffs. - uint8* right = diff_info + 1; - while (*right) { - *right++ = 0; - width++; - } - - // Group with blocks below. - // The entire width of blocks that we matched above much match for - // each row that we add. - uint8* bottom = diff_info; - bool found_new_row; - do { - found_new_row = true; - bottom += diff_info_stride; - right = bottom; - for (int x2 = 0; x2 < width; x2++) { - if (*right++ == 0) { - found_new_row = false; - } - } - - if (found_new_row) { - height++; - - // We need to go back and erase the diff markers so that we don't - // try to add these blocks a second time. - right = bottom; - for (int x2 = 0; x2 < width; x2++) { - *right++ = 0; - } - } - } while (found_new_row); - - // Add rect to list of dirty rects. - width *= kBlockSize; - if (left + width > width_) { - width = width_ - left; - } - height *= kBlockSize; - if (top + height > height_) { - height = height_ - top; - } - region->op(SkIRect::MakeXYWH(left, top, width, height), - SkRegion::kUnion_Op); - } - - // Increment to next block in this row. - diff_info++; - } - - // Go to start of next row. - diff_info_row_start += diff_info_stride; - } -} - -} // namespace remoting diff --git a/remoting/capturer/differ.h b/remoting/capturer/differ.h deleted file mode 100644 index 469384c..0000000 --- a/remoting/capturer/differ.h +++ /dev/null @@ -1,84 +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 REMOTING_CAPTURER_DIFFER_H_ -#define REMOTING_CAPTURER_DIFFER_H_ - -#include <vector> - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "third_party/skia/include/core/SkRegion.h" - -namespace remoting { - -typedef uint8 DiffInfo; - -// TODO: Simplify differ now that we are working with SkRegions. -// 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 -// TODO(sergeyu): Rename this class to something more sensible, e.g. -// VideoFrameDifferencer. -class Differ { - public: - // Create a differ that operates on bitmaps with the specified width, height - // and bytes_per_pixel. - Differ(int width, int height, int bytes_per_pixel, int stride); - ~Differ(); - - int width() { return width_; } - int height() { return height_; } - int bytes_per_pixel() { return bytes_per_pixel_; } - int bytes_per_row() { return bytes_per_row_; } - - // 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); - - private: - // Allow tests to access our private parts. - friend class DifferTest; - - // Identify all of the blocks that contain changed pixels. - void MarkDirtyBlocks(const void* prev_buffer, const void* curr_buffer); - - // 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); - - // 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. - // Note that if we force the capturer to always return images whose width and - // height are multiples of kBlockSize, then this will never be called. - DiffInfo DiffPartialBlock(const uint8* prev_buffer, const uint8* curr_buffer, - int stride, int width, int height); - - // Dimensions of screen. - int width_; - int height_; - - // Number of bytes for each pixel in source and dest bitmap. - // (Yes, they must match.) - int bytes_per_pixel_; - - // Number of bytes in each row of the image (AKA: stride). - int bytes_per_row_; - - // Diff information for each block in the image. - scoped_array<DiffInfo> diff_info_; - - // Dimensions and total size of diff info array. - int diff_info_width_; - int diff_info_height_; - int diff_info_size_; - - DISALLOW_COPY_AND_ASSIGN(Differ); -}; - -} // namespace remoting - -#endif // REMOTING_CAPTURER_DIFFER_H_ diff --git a/remoting/capturer/differ_block.cc b/remoting/capturer/differ_block.cc deleted file mode 100644 index 1386ba7..0000000 --- a/remoting/capturer/differ_block.cc +++ /dev/null @@ -1,49 +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 "remoting/capturer/differ_block.h" - -#include "base/cpu.h" -#include "build/build_config.h" -#include "remoting/capturer/differ_block_sse2.h" - -namespace remoting { - -int BlockDifference_C(const uint8* image1, const uint8* image2, int stride) { - int width_bytes = kBlockSize * kBytesPerPixel; - - for (int y = 0; y < kBlockSize; y++) { - if (memcmp(image1, image2, width_bytes) != 0) - return 1; - image1 += stride; - image2 += stride; - } - return 0; -} - -int BlockDifference(const uint8* image1, const uint8* image2, int stride) { - static int (*diff_proc)(const uint8*, const uint8*, int) = NULL; - - if (!diff_proc) { -#if defined(ARCH_CPU_ARM_FAMILY) - // For ARM processors, always use C version. - // TODO(hclam): Implement a NEON version. - diff_proc = &BlockDifference_C; -#else - base::CPU cpu; - // For x86 processors, check if SSE2 is supported. - if (cpu.has_sse2() && kBlockSize == 32) { - diff_proc = &BlockDifference_SSE2_W32; - } else if (cpu.has_sse2() && kBlockSize == 16) { - diff_proc = &BlockDifference_SSE2_W16; - } else { - diff_proc = &BlockDifference_C; - } -#endif - } - - return diff_proc(image1, image2, stride); -} - -} // namespace remoting diff --git a/remoting/capturer/differ_block.h b/remoting/capturer/differ_block.h deleted file mode 100644 index 4f78960..0000000 --- a/remoting/capturer/differ_block.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2011 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 REMOTING_HOST_DIFFER_BLOCK_H_ -#define REMOTING_HOST_DIFFER_BLOCK_H_ - -#include "base/basictypes.h" - -namespace remoting { - -// Size (in pixels) of each square block used for diffing. -// This must be a multiple of sizeof(uint64)/8. -static const int kBlockSize = 32; - -// Format: BGRA 32 bit. -static const int kBytesPerPixel = 4; - -// Low level functions to compare 2 blocks of pixels. -// zero means the blocks are identical. -// one means the blocks are different. -int BlockDifference(const uint8* image1, const uint8* image2, int stride); - -} // namespace remoting - -#endif // REMOTING_HOST_DIFFER_BLOCK_H_ diff --git a/remoting/capturer/differ_block_sse2.cc b/remoting/capturer/differ_block_sse2.cc deleted file mode 100644 index 9078a42..0000000 --- a/remoting/capturer/differ_block_sse2.cc +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2011 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 "remoting/capturer/differ_block_sse2.h" - -#if defined(_MSC_VER) -#include <intrin.h> -#else -#include <mmintrin.h> -#include <emmintrin.h> -#endif - -#include "remoting/capturer/differ_block.h" - -namespace remoting { - -extern int BlockDifference_SSE2_W16(const uint8* image1, const uint8* image2, - int stride) { - __m128i acc = _mm_setzero_si128(); - __m128i v0; - __m128i v1; - __m128i sad; - for (int y = 0; y < kBlockSize; ++y) { - const __m128i* i1 = reinterpret_cast<const __m128i*>(image1); - const __m128i* i2 = reinterpret_cast<const __m128i*>(image2); - v0 = _mm_loadu_si128(i1); - v1 = _mm_loadu_si128(i2); - sad = _mm_sad_epu8(v0, v1); - acc = _mm_adds_epu16(acc, sad); - v0 = _mm_loadu_si128(i1 + 1); - v1 = _mm_loadu_si128(i2 + 1); - sad = _mm_sad_epu8(v0, v1); - acc = _mm_adds_epu16(acc, sad); - v0 = _mm_loadu_si128(i1 + 2); - v1 = _mm_loadu_si128(i2 + 2); - sad = _mm_sad_epu8(v0, v1); - acc = _mm_adds_epu16(acc, sad); - v0 = _mm_loadu_si128(i1 + 3); - v1 = _mm_loadu_si128(i2 + 3); - sad = _mm_sad_epu8(v0, v1); - acc = _mm_adds_epu16(acc, sad); - - // This essential means sad = acc >> 64. We only care about the lower 16 - // bits. - sad = _mm_shuffle_epi32(acc, 0xEE); - sad = _mm_adds_epu16(sad, acc); - int diff = _mm_cvtsi128_si32(sad); - if (diff) - return 1; - image1 += stride; - image2 += stride; - } - return 0; -} - -extern int BlockDifference_SSE2_W32(const uint8* image1, const uint8* image2, - int stride) { - __m128i acc = _mm_setzero_si128(); - __m128i v0; - __m128i v1; - __m128i sad; - for (int y = 0; y < kBlockSize; ++y) { - const __m128i* i1 = reinterpret_cast<const __m128i*>(image1); - const __m128i* i2 = reinterpret_cast<const __m128i*>(image2); - v0 = _mm_loadu_si128(i1); - v1 = _mm_loadu_si128(i2); - sad = _mm_sad_epu8(v0, v1); - acc = _mm_adds_epu16(acc, sad); - v0 = _mm_loadu_si128(i1 + 1); - v1 = _mm_loadu_si128(i2 + 1); - sad = _mm_sad_epu8(v0, v1); - acc = _mm_adds_epu16(acc, sad); - v0 = _mm_loadu_si128(i1 + 2); - v1 = _mm_loadu_si128(i2 + 2); - sad = _mm_sad_epu8(v0, v1); - acc = _mm_adds_epu16(acc, sad); - v0 = _mm_loadu_si128(i1 + 3); - v1 = _mm_loadu_si128(i2 + 3); - sad = _mm_sad_epu8(v0, v1); - acc = _mm_adds_epu16(acc, sad); - v0 = _mm_loadu_si128(i1 + 4); - v1 = _mm_loadu_si128(i2 + 4); - sad = _mm_sad_epu8(v0, v1); - acc = _mm_adds_epu16(acc, sad); - v0 = _mm_loadu_si128(i1 + 5); - v1 = _mm_loadu_si128(i2 + 5); - sad = _mm_sad_epu8(v0, v1); - acc = _mm_adds_epu16(acc, sad); - v0 = _mm_loadu_si128(i1 + 6); - v1 = _mm_loadu_si128(i2 + 6); - sad = _mm_sad_epu8(v0, v1); - acc = _mm_adds_epu16(acc, sad); - v0 = _mm_loadu_si128(i1 + 7); - v1 = _mm_loadu_si128(i2 + 7); - sad = _mm_sad_epu8(v0, v1); - acc = _mm_adds_epu16(acc, sad); - - // This essential means sad = acc >> 64. We only care about the lower 16 - // bits. - sad = _mm_shuffle_epi32(acc, 0xEE); - sad = _mm_adds_epu16(sad, acc); - int diff = _mm_cvtsi128_si32(sad); - if (diff) - return 1; - image1 += stride; - image2 += stride; - } - return 0; -} - -} // namespace remoting diff --git a/remoting/capturer/differ_block_sse2.h b/remoting/capturer/differ_block_sse2.h deleted file mode 100644 index 2148f28..0000000 --- a/remoting/capturer/differ_block_sse2.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2010 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. - -// This header file is used only differ_block.h. It defines the SSE2 rountines -// for finding block difference. - -#ifndef REMOTING_HOST_DIFFER_BLOCK_SSE2_H_ -#define REMOTING_HOST_DIFFER_BLOCK_SSE2_H_ - -#include "base/basictypes.h" - -namespace remoting { - -// Find block difference of dimension 16x16. -extern int BlockDifference_SSE2_W16(const uint8* image1, const uint8* image2, - int stride); - -// Find block difference of dimension 32x32. -extern int BlockDifference_SSE2_W32(const uint8* image1, const uint8* image2, - int stride); - -} // namespace remoting - -#endif // REMOTING_HOST_DIFFER_BLOCK_SSE2_H_ diff --git a/remoting/capturer/differ_block_unittest.cc b/remoting/capturer/differ_block_unittest.cc deleted file mode 100644 index d7bb62a..0000000 --- a/remoting/capturer/differ_block_unittest.cc +++ /dev/null @@ -1,81 +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/memory/ref_counted.h" -#include "remoting/capturer/differ_block.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace remoting { - -// Run 900 times to mimic 1280x720. -// TODO(fbarchard): Remove benchmark once performance is non-issue. -static const int kTimesToRun = 900; - -static void GenerateData(uint8* data, int size) { - for (int i = 0; i < size; ++i) { - data[i] = i; - } -} - -// Memory buffer large enough for 2 blocks aligned to 16 bytes. -static const int kSizeOfBlock = kBlockSize * kBlockSize * kBytesPerPixel; -uint8 block_buffer[kSizeOfBlock * 2 + 16]; - -void PrepareBuffers(uint8* &block1, uint8* &block2) { - block1 = reinterpret_cast<uint8*> - ((reinterpret_cast<uintptr_t>(&block_buffer[0]) + 15) & ~15); - GenerateData(block1, kSizeOfBlock); - block2 = block1 + kSizeOfBlock; - memcpy(block2, block1, kSizeOfBlock); -} - -TEST(BlockDifferenceTestSame, BlockDifference) { - uint8* block1; - uint8* block2; - PrepareBuffers(block1, block2); - - // These blocks should match. - for (int i = 0; i < kTimesToRun; ++i) { - int result = BlockDifference(block1, block2, kBlockSize * kBytesPerPixel); - EXPECT_EQ(0, result); - } -} - -TEST(BlockDifferenceTestLast, BlockDifference) { - uint8* block1; - uint8* block2; - PrepareBuffers(block1, block2); - block2[kSizeOfBlock-2] += 1; - - for (int i = 0; i < kTimesToRun; ++i) { - int result = BlockDifference(block1, block2, kBlockSize * kBytesPerPixel); - EXPECT_EQ(1, result); - } -} - -TEST(BlockDifferenceTestMid, BlockDifference) { - uint8* block1; - uint8* block2; - PrepareBuffers(block1, block2); - block2[kSizeOfBlock/2+1] += 1; - - for (int i = 0; i < kTimesToRun; ++i) { - int result = BlockDifference(block1, block2, kBlockSize * kBytesPerPixel); - EXPECT_EQ(1, result); - } -} - -TEST(BlockDifferenceTestFirst, BlockDifference) { - uint8* block1; - uint8* block2; - PrepareBuffers(block1, block2); - block2[0] += 1; - - for (int i = 0; i < kTimesToRun; ++i) { - int result = BlockDifference(block1, block2, kBlockSize * kBytesPerPixel); - EXPECT_EQ(1, result); - } -} - -} // namespace remoting diff --git a/remoting/capturer/differ_unittest.cc b/remoting/capturer/differ_unittest.cc deleted file mode 100644 index 9d932cc..0000000 --- a/remoting/capturer/differ_unittest.cc +++ /dev/null @@ -1,639 +0,0 @@ -// Copyright (c) 2011 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/memory/scoped_ptr.h" -#include "remoting/capturer/differ.h" -#include "remoting/capturer/differ_block.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace remoting { - -// 96x96 screen gives a 4x4 grid of blocks. -const int kScreenWidth= 96; -const int kScreenHeight = 96; - -// To test partial blocks, we need a width and height that are not multiples -// of 16 (or 32, depending on current block size). -const int kPartialScreenWidth = 70; -const int kPartialScreenHeight = 70; - -class DifferTest : public testing::Test { - public: - DifferTest() { - } - - protected: - void InitDiffer(int width, int height) { - width_ = width; - height_ = height; - bytes_per_pixel_ = kBytesPerPixel; - stride_ = (kBytesPerPixel * width); - buffer_size_ = width_ * height_ * bytes_per_pixel_; - - differ_.reset(new Differ(width_, height_, bytes_per_pixel_, stride_)); - - prev_.reset(new uint8[buffer_size_]); - memset(prev_.get(), 0, buffer_size_); - - curr_.reset(new uint8[buffer_size_]); - memset(curr_.get(), 0, buffer_size_); - } - - void ClearBuffer(uint8* buffer) { - memset(buffer, 0, buffer_size_); - } - - // Here in DifferTest so that tests can access private methods of Differ. - void MarkDirtyBlocks(const void* prev_buffer, const void* curr_buffer) { - differ_->MarkDirtyBlocks(prev_buffer, curr_buffer); - } - - void MergeBlocks(SkRegion* dirty) { - differ_->MergeBlocks(dirty); - } - - // Convenience method to count rectangles in a region. - int RegionRectCount(const SkRegion& region) { - int count = 0; - for(SkRegion::Iterator iter(region); !iter.done(); iter.next()) { - ++count; - } - return count; - } - - // Convenience wrapper for Differ's DiffBlock that calculates the appropriate - // offset to the start of the desired block. - DiffInfo DiffBlock(int block_x, int block_y) { - // Offset from upper-left of buffer to upper-left of requested block. - int block_offset = ((block_y * stride_) + (block_x * bytes_per_pixel_)) - * kBlockSize; - return BlockDifference(prev_.get() + block_offset, - curr_.get() + block_offset, - stride_); - } - - // Write the pixel |value| into the specified block in the |buffer|. - // This is a convenience wrapper around WritePixel(). - void WriteBlockPixel(uint8* buffer, int block_x, int block_y, - int pixel_x, int pixel_y, uint32 value) { - WritePixel(buffer, (block_x * kBlockSize) + pixel_x, - (block_y * kBlockSize) + pixel_y, value); - } - - // Write the test pixel |value| into the |buffer| at the specified |x|,|y| - // location. - // Only the low-order bytes from |value| are written (assuming little-endian). - // So, for |value| = 0xaabbccdd: - // If bytes_per_pixel = 4, then ddccbbaa will be written as the pixel value. - // If = 3, ddccbb - // If = 2, ddcc - // If = 1, dd - void WritePixel(uint8* buffer, int x, int y, uint32 value) { - uint8* pixel = reinterpret_cast<uint8*>(&value); - buffer += (y * stride_) + (x * bytes_per_pixel_); - for (int b = bytes_per_pixel_ - 1; b >= 0; b--) { - *buffer++ = pixel[b]; - } - } - - // DiffInfo utility routines. - // These are here so that we don't have to make each DifferText_Xxx_Test - // class a friend class to Differ. - - // Clear out the entire |diff_info_| buffer. - void ClearDiffInfo() { - memset(differ_->diff_info_.get(), 0, differ_->diff_info_size_); - } - - // Get the value in the |diff_info_| array at (x,y). - DiffInfo GetDiffInfo(int x, int y) { - DiffInfo* diff_info = differ_->diff_info_.get(); - return diff_info[(y * GetDiffInfoWidth()) + x]; - } - - // Width of |diff_info_| array. - int GetDiffInfoWidth() { - return differ_->diff_info_width_; - } - - // Height of |diff_info_| array. - int GetDiffInfoHeight() { - return differ_->diff_info_height_; - } - - // Size of |diff_info_| array. - int GetDiffInfoSize() { - return differ_->diff_info_size_; - } - - void SetDiffInfo(int x, int y, const DiffInfo& value) { - DiffInfo* diff_info = differ_->diff_info_.get(); - diff_info[(y * GetDiffInfoWidth()) + x] = value; - } - - // Mark the range of blocks specified. - void MarkBlocks(int x_origin, int y_origin, int width, int height) { - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - SetDiffInfo(x_origin + x, y_origin + y, 1); - } - } - } - - // 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, - 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); - } - return found; - } - - // Mark the range of blocks specified and then verify that they are - // merged correctly. - // Only one rectangular region of blocks can be checked with this routine. - bool MarkBlocksAndCheckMerge(int x_origin, int y_origin, - int width, int height) { - ClearDiffInfo(); - MarkBlocks(x_origin, y_origin, width, height); - - SkRegion dirty; - MergeBlocks(&dirty); - - bool is_good = dirty.isRect(); - if (is_good) { - is_good = CheckDirtyRegionContainsRect(dirty, x_origin, y_origin, - width, height); - } - return is_good; - } - - // The differ class we're testing. - scoped_ptr<Differ> differ_; - - // Screen/buffer info. - int width_; - int height_; - int bytes_per_pixel_; - int stride_; - - // Size of each screen buffer. - int buffer_size_; - - // Previous and current screen buffers. - scoped_array<uint8> prev_; - scoped_array<uint8> curr_; - - private: - DISALLOW_COPY_AND_ASSIGN(DifferTest); -}; - -TEST_F(DifferTest, Setup) { - InitDiffer(kScreenWidth, kScreenHeight); - // 96x96 pixels results in 3x3 array. Add 1 to each dimension as boundary. - // +---+---+---+---+ - // | o | o | o | _ | - // +---+---+---+---+ o = blocks mapped to screen pixels - // | o | o | o | _ | - // +---+---+---+---+ _ = boundary blocks - // | o | o | o | _ | - // +---+---+---+---+ - // | _ | _ | _ | _ | - // +---+---+---+---+ - EXPECT_EQ(4, GetDiffInfoWidth()); - EXPECT_EQ(4, GetDiffInfoHeight()); - EXPECT_EQ(16, GetDiffInfoSize()); -} - -TEST_F(DifferTest, MarkDirtyBlocks_All) { - InitDiffer(kScreenWidth, kScreenHeight); - ClearDiffInfo(); - - // Update a pixel in each block. - for (int y = 0; y < GetDiffInfoHeight() - 1; y++) { - for (int x = 0; x < GetDiffInfoWidth() - 1; x++) { - WriteBlockPixel(curr_.get(), x, y, 10, 10, 0xff00ff); - } - } - - MarkDirtyBlocks(prev_.get(), curr_.get()); - - // Make sure each block is marked as dirty. - for (int y = 0; y < GetDiffInfoHeight() - 1; y++) { - for (int x = 0; x < GetDiffInfoWidth() - 1; x++) { - EXPECT_EQ(1, GetDiffInfo(x, y)) - << "when x = " << x << ", and y = " << y; - } - } -} - -TEST_F(DifferTest, MarkDirtyBlocks_Sampling) { - InitDiffer(kScreenWidth, kScreenHeight); - ClearDiffInfo(); - - // Update some pixels in image. - WriteBlockPixel(curr_.get(), 1, 0, 10, 10, 0xff00ff); - WriteBlockPixel(curr_.get(), 2, 1, 10, 10, 0xff00ff); - WriteBlockPixel(curr_.get(), 0, 2, 10, 10, 0xff00ff); - - MarkDirtyBlocks(prev_.get(), curr_.get()); - - // Make sure corresponding blocks are updated. - EXPECT_EQ(0, GetDiffInfo(0, 0)); - EXPECT_EQ(0, GetDiffInfo(0, 1)); - EXPECT_EQ(1, GetDiffInfo(0, 2)); - EXPECT_EQ(1, GetDiffInfo(1, 0)); - EXPECT_EQ(0, GetDiffInfo(1, 1)); - EXPECT_EQ(0, GetDiffInfo(1, 2)); - EXPECT_EQ(0, GetDiffInfo(2, 0)); - EXPECT_EQ(1, GetDiffInfo(2, 1)); - EXPECT_EQ(0, GetDiffInfo(2, 2)); -} - -TEST_F(DifferTest, DiffBlock) { - InitDiffer(kScreenWidth, kScreenHeight); - - // Verify no differences at start. - EXPECT_EQ(0, DiffBlock(0, 0)); - EXPECT_EQ(0, DiffBlock(1, 1)); - - // Write new data into the 4 corners of the middle block and verify that - // neighboring blocks are not affected. - int max = kBlockSize - 1; - WriteBlockPixel(curr_.get(), 1, 1, 0, 0, 0xffffff); - WriteBlockPixel(curr_.get(), 1, 1, 0, max, 0xffffff); - WriteBlockPixel(curr_.get(), 1, 1, max, 0, 0xffffff); - WriteBlockPixel(curr_.get(), 1, 1, max, max, 0xffffff); - EXPECT_EQ(0, DiffBlock(0, 0)); - EXPECT_EQ(0, DiffBlock(0, 1)); - EXPECT_EQ(0, DiffBlock(0, 2)); - EXPECT_EQ(0, DiffBlock(1, 0)); - EXPECT_EQ(1, DiffBlock(1, 1)); // Only this block should change. - EXPECT_EQ(0, DiffBlock(1, 2)); - EXPECT_EQ(0, DiffBlock(2, 0)); - EXPECT_EQ(0, DiffBlock(2, 1)); - EXPECT_EQ(0, DiffBlock(2, 2)); -} - -TEST_F(DifferTest, Partial_Setup) { - InitDiffer(kPartialScreenWidth, kPartialScreenHeight); - // 70x70 pixels results in 3x3 array: 2x2 full blocks + partials around - // the edge. One more is added to each dimension as a boundary. - // +---+---+---+---+ - // | o | o | + | _ | - // +---+---+---+---+ o = blocks mapped to screen pixels - // | o | o | + | _ | - // +---+---+---+---+ + = partial blocks (top/left mapped to screen pixels) - // | + | + | + | _ | - // +---+---+---+---+ _ = boundary blocks - // | _ | _ | _ | _ | - // +---+---+---+---+ - EXPECT_EQ(4, GetDiffInfoWidth()); - EXPECT_EQ(4, GetDiffInfoHeight()); - EXPECT_EQ(16, GetDiffInfoSize()); -} - -TEST_F(DifferTest, Partial_FirstPixel) { - InitDiffer(kPartialScreenWidth, kPartialScreenHeight); - ClearDiffInfo(); - - // Update the first pixel in each block. - for (int y = 0; y < GetDiffInfoHeight() - 1; y++) { - for (int x = 0; x < GetDiffInfoWidth() - 1; x++) { - WriteBlockPixel(curr_.get(), x, y, 0, 0, 0xff00ff); - } - } - - MarkDirtyBlocks(prev_.get(), curr_.get()); - - // Make sure each block is marked as dirty. - for (int y = 0; y < GetDiffInfoHeight() - 1; y++) { - for (int x = 0; x < GetDiffInfoWidth() - 1; x++) { - EXPECT_EQ(1, GetDiffInfo(x, y)) - << "when x = " << x << ", and y = " << y; - } - } -} - -TEST_F(DifferTest, Partial_BorderPixel) { - InitDiffer(kPartialScreenWidth, kPartialScreenHeight); - ClearDiffInfo(); - - // Update the right/bottom border pixels. - for (int y = 0; y < height_; y++) { - WritePixel(curr_.get(), width_ - 1, y, 0xff00ff); - } - for (int x = 0; x < width_; x++) { - WritePixel(curr_.get(), x, height_ - 1, 0xff00ff); - } - - MarkDirtyBlocks(prev_.get(), curr_.get()); - - // Make sure last (partial) block in each row/column is marked as dirty. - int x_last = GetDiffInfoWidth() - 2; - for (int y = 0; y < GetDiffInfoHeight() - 1; y++) { - EXPECT_EQ(1, GetDiffInfo(x_last, y)) - << "when x = " << x_last << ", and y = " << y; - } - int y_last = GetDiffInfoHeight() - 2; - for (int x = 0; x < GetDiffInfoWidth() - 1; x++) { - EXPECT_EQ(1, GetDiffInfo(x, y_last)) - << "when x = " << x << ", and y = " << y_last; - } - // All other blocks are clean. - for (int y = 0; y < GetDiffInfoHeight() - 2; y++) { - for (int x = 0; x < GetDiffInfoWidth() - 2; x++) { - EXPECT_EQ(0, GetDiffInfo(x, y)) << "when x = " << x << ", and y = " << y; - } - } -} - -TEST_F(DifferTest, MergeBlocks_Empty) { - InitDiffer(kScreenWidth, kScreenHeight); - - // No blocks marked: - // +---+---+---+---+ - // | | | | _ | - // +---+---+---+---+ - // | | | | _ | - // +---+---+---+---+ - // | | | | _ | - // +---+---+---+---+ - // | _ | _ | _ | _ | - // +---+---+---+---+ - ClearDiffInfo(); - - SkRegion dirty; - MergeBlocks(&dirty); - - EXPECT_TRUE(dirty.isEmpty()); -} - -TEST_F(DifferTest, MergeBlocks_SingleBlock) { - InitDiffer(kScreenWidth, kScreenHeight); - // Mark a single block and make sure that there is a single merged - // rect with the correct bounds. - for (int y = 0; y < GetDiffInfoHeight() - 1; y++) { - for (int x = 0; x < GetDiffInfoWidth() - 1; x++) { - ASSERT_TRUE(MarkBlocksAndCheckMerge(x, y, 1, 1)) << "x: " << x - << "y: " << y; - } - } -} - -TEST_F(DifferTest, MergeBlocks_BlockRow) { - InitDiffer(kScreenWidth, kScreenHeight); - - // +---+---+---+---+ - // | X | X | | _ | - // +---+---+---+---+ - // | | | | _ | - // +---+---+---+---+ - // | | | | _ | - // +---+---+---+---+ - // | _ | _ | _ | _ | - // +---+---+---+---+ - ASSERT_TRUE(MarkBlocksAndCheckMerge(0, 0, 2, 1)); - - // +---+---+---+---+ - // | | | | _ | - // +---+---+---+---+ - // | X | X | X | _ | - // +---+---+---+---+ - // | | | | _ | - // +---+---+---+---+ - // | _ | _ | _ | _ | - // +---+---+---+---+ - ASSERT_TRUE(MarkBlocksAndCheckMerge(0, 1, 3, 1)); - - // +---+---+---+---+ - // | | | | _ | - // +---+---+---+---+ - // | | | | _ | - // +---+---+---+---+ - // | | X | X | _ | - // +---+---+---+---+ - // | _ | _ | _ | _ | - // +---+---+---+---+ - ASSERT_TRUE(MarkBlocksAndCheckMerge(1, 2, 2, 1)); -} - -TEST_F(DifferTest, MergeBlocks_BlockColumn) { - InitDiffer(kScreenWidth, kScreenHeight); - - // +---+---+---+---+ - // | X | | | _ | - // +---+---+---+---+ - // | X | | | _ | - // +---+---+---+---+ - // | | | | _ | - // +---+---+---+---+ - // | _ | _ | _ | _ | - // +---+---+---+---+ - ASSERT_TRUE(MarkBlocksAndCheckMerge(0, 0, 1, 2)); - - // +---+---+---+---+ - // | | | | _ | - // +---+---+---+---+ - // | | X | | _ | - // +---+---+---+---+ - // | | X | | _ | - // +---+---+---+---+ - // | _ | _ | _ | _ | - // +---+---+---+---+ - ASSERT_TRUE(MarkBlocksAndCheckMerge(1, 1, 1, 2)); - - // +---+---+---+---+ - // | | | X | _ | - // +---+---+---+---+ - // | | | X | _ | - // +---+---+---+---+ - // | | | X | _ | - // +---+---+---+---+ - // | _ | _ | _ | _ | - // +---+---+---+---+ - ASSERT_TRUE(MarkBlocksAndCheckMerge(2, 0, 1, 3)); -} - -TEST_F(DifferTest, MergeBlocks_BlockRect) { - InitDiffer(kScreenWidth, kScreenHeight); - - // +---+---+---+---+ - // | X | X | | _ | - // +---+---+---+---+ - // | X | X | | _ | - // +---+---+---+---+ - // | | | | _ | - // +---+---+---+---+ - // | _ | _ | _ | _ | - // +---+---+---+---+ - ASSERT_TRUE(MarkBlocksAndCheckMerge(0, 0, 2, 2)); - - // +---+---+---+---+ - // | | | | _ | - // +---+---+---+---+ - // | | X | X | _ | - // +---+---+---+---+ - // | | X | X | _ | - // +---+---+---+---+ - // | _ | _ | _ | _ | - // +---+---+---+---+ - ASSERT_TRUE(MarkBlocksAndCheckMerge(1, 1, 2, 2)); - - // +---+---+---+---+ - // | | X | X | _ | - // +---+---+---+---+ - // | | X | X | _ | - // +---+---+---+---+ - // | | X | X | _ | - // +---+---+---+---+ - // | _ | _ | _ | _ | - // +---+---+---+---+ - ASSERT_TRUE(MarkBlocksAndCheckMerge(1, 0, 2, 3)); - - // +---+---+---+---+ - // | | | | _ | - // +---+---+---+---+ - // | X | X | X | _ | - // +---+---+---+---+ - // | X | X | X | _ | - // +---+---+---+---+ - // | _ | _ | _ | _ | - // +---+---+---+---+ - ASSERT_TRUE(MarkBlocksAndCheckMerge(0, 1, 3, 2)); - - // +---+---+---+---+ - // | X | X | X | _ | - // +---+---+---+---+ - // | X | X | X | _ | - // +---+---+---+---+ - // | X | X | X | _ | - // +---+---+---+---+ - // | _ | _ | _ | _ | - // +---+---+---+---+ - ASSERT_TRUE(MarkBlocksAndCheckMerge(0, 0, 3, 3)); -} - -// This tests marked regions that require more than 1 single dirty rect. -// The exact rects returned depend on the current implementation, so these -// may need to be updated if we modify how we merge blocks. -TEST_F(DifferTest, MergeBlocks_MultiRect) { - InitDiffer(kScreenWidth, kScreenHeight); - SkRegion dirty; - - // +---+---+---+---+ +---+---+---+ - // | | X | | _ | | | 0 | | - // +---+---+---+---+ +---+---+---+ - // | X | | | _ | | 1 | | | - // +---+---+---+---+ => +---+---+---+ - // | | | X | _ | | | | 2 | - // +---+---+---+---+ +---+---+---+ - // | _ | _ | _ | _ | - // +---+---+---+---+ - ClearDiffInfo(); - MarkBlocks(1, 0, 1, 1); - MarkBlocks(0, 1, 1, 1); - MarkBlocks(2, 2, 1, 1); - - dirty.setEmpty(); - MergeBlocks(&dirty); - - ASSERT_EQ(3, RegionRectCount(dirty)); - ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 1, 0, 1, 1)); - ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 1, 1, 1)); - ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 2, 2, 1, 1)); - - // +---+---+---+---+ +---+---+---+ - // | | | X | _ | | | | 0 | - // +---+---+---+---+ +---+---+---+ - // | X | X | X | _ | | 1 1 1 | - // +---+---+---+---+ => + + - // | X | X | X | _ | | 1 1 1 | - // +---+---+---+---+ +---+---+---+ - // | _ | _ | _ | _ | - // +---+---+---+---+ - ClearDiffInfo(); - MarkBlocks(2, 0, 1, 1); - MarkBlocks(0, 1, 3, 2); - - dirty.setEmpty(); - MergeBlocks(&dirty); - - ASSERT_EQ(2, RegionRectCount(dirty)); - ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 2, 0, 1, 1)); - ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 1, 3, 2)); - - // +---+---+---+---+ +---+---+---+ - // | | | | _ | | | | | - // +---+---+---+---+ +---+---+---+ - // | X | | X | _ | | 0 | | 1 | - // +---+---+---+---+ => + +---+ + - // | X | X | X | _ | | 2 | 2 | 2 | - // +---+---+---+---+ +---+---+---+ - // | _ | _ | _ | _ | - // +---+---+---+---+ - ClearDiffInfo(); - MarkBlocks(0, 1, 1, 1); - MarkBlocks(2, 1, 1, 1); - MarkBlocks(0, 2, 3, 1); - - dirty.setEmpty(); - 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)); - - // +---+---+---+---+ +---+---+---+ - // | X | X | X | _ | | 0 0 0 | - // +---+---+---+---+ +---+---+---+ - // | X | | X | _ | | 1 | | 2 | - // +---+---+---+---+ => + +---+ + - // | X | X | X | _ | | 3 | 3 | 3 | - // +---+---+---+---+ +---+---+---+ - // | _ | _ | _ | _ | - // +---+---+---+---+ - ClearDiffInfo(); - MarkBlocks(0, 0, 3, 1); - MarkBlocks(0, 1, 1, 1); - MarkBlocks(2, 1, 1, 1); - MarkBlocks(0, 2, 3, 1); - - dirty.setEmpty(); - 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)); - - // +---+---+---+---+ +---+---+---+ - // | X | X | | _ | | 0 0 | | - // +---+---+---+---+ + +---+ - // | X | X | | _ | | 0 0 | | - // +---+---+---+---+ => +---+---+---+ - // | | X | | _ | | | 1 | | - // +---+---+---+---+ +---+---+---+ - // | _ | _ | _ | _ | - // +---+---+---+---+ - ClearDiffInfo(); - MarkBlocks(0, 0, 2, 2); - MarkBlocks(1, 2, 1, 1); - - dirty.setEmpty(); - MergeBlocks(&dirty); - - ASSERT_EQ(2, RegionRectCount(dirty)); - ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 0, 2, 2)); - ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 1, 2, 1, 1)); -} - -} // namespace remoting diff --git a/remoting/capturer/linux/x_server_pixel_buffer.cc b/remoting/capturer/linux/x_server_pixel_buffer.cc deleted file mode 100644 index c495cbc..0000000 --- a/remoting/capturer/linux/x_server_pixel_buffer.cc +++ /dev/null @@ -1,275 +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 "remoting/capturer/linux/x_server_pixel_buffer.h" - -#include <sys/shm.h> - -#include "base/logging.h" - -#if defined(TOOLKIT_GTK) -#include <gdk/gdk.h> -#else // !defined(TOOLKIT_GTK) -#include <X11/Xlib.h> -#endif // !defined(TOOLKIT_GTK) - -namespace { - -#if defined(TOOLKIT_GTK) -// GDK sets error handler for Xlib errors, so we need to use it to -// trap X errors when this code is compiled with GTK. -void EnableXServerErrorTrap() { - gdk_error_trap_push(); -} - -int GetLastXServerError() { - return gdk_error_trap_pop(); -} - -#else // !defined(TOOLKIT_GTK) - -static bool g_xserver_error_trap_enabled = false; -static int g_last_xserver_error_code = 0; - -int XServerErrorHandler(Display* display, XErrorEvent* error_event) { - DCHECK(g_xserver_error_trap_enabled); - g_last_xserver_error_code = error_event->error_code; - return 0; -} - -void EnableXServerErrorTrap() { - DCHECK(!g_xserver_error_trap_enabled); - XSetErrorHandler(&XServerErrorHandler); - g_xserver_error_trap_enabled = true; - g_last_xserver_error_code = 0; -} - -int GetLastXServerError() { - DCHECK(g_xserver_error_trap_enabled); - XSetErrorHandler(NULL); - g_xserver_error_trap_enabled = false; - return g_last_xserver_error_code; -} - -#endif // !defined(TOOLKIT_GTK) - -} // namespace - -namespace remoting { - -XServerPixelBuffer::XServerPixelBuffer() - : display_(NULL), root_window_(0), - root_window_size_(SkISize::Make(0, 0)), x_image_(NULL), - shm_segment_info_(NULL), shm_pixmap_(0), shm_gc_(NULL) { -} - -XServerPixelBuffer::~XServerPixelBuffer() { - Release(); -} - -void XServerPixelBuffer::Release() { - if (x_image_) { - XDestroyImage(x_image_); - x_image_ = NULL; - } - if (shm_pixmap_) { - XFreePixmap(display_, shm_pixmap_); - shm_pixmap_ = 0; - } - if (shm_gc_) { - XFreeGC(display_, shm_gc_); - shm_gc_ = NULL; - } - if (shm_segment_info_) { - if (shm_segment_info_->shmaddr != reinterpret_cast<char*>(-1)) - shmdt(shm_segment_info_->shmaddr); - if (shm_segment_info_->shmid != -1) - shmctl(shm_segment_info_->shmid, IPC_RMID, 0); - delete shm_segment_info_; - shm_segment_info_ = NULL; - } -} - -void XServerPixelBuffer::Init(Display* display, - const SkISize& screen_size) { - Release(); - display_ = display; - root_window_size_ = screen_size; - int default_screen = DefaultScreen(display_); - root_window_ = RootWindow(display_, default_screen); - InitShm(default_screen); -} - -// static -SkISize XServerPixelBuffer::GetRootWindowSize(Display* display) { - XWindowAttributes root_attr; - XGetWindowAttributes(display, DefaultRootWindow(display), &root_attr); - return SkISize::Make(root_attr.width, root_attr.height); -} - -void XServerPixelBuffer::InitShm(int screen) { - Visual* default_visual = DefaultVisual(display_, screen); - int default_depth = DefaultDepth(display_, screen); - - int major, minor; - Bool havePixmaps; - if (!XShmQueryVersion(display_, &major, &minor, &havePixmaps)) - // Shared memory not supported. CaptureRect will use the XImage API instead. - return; - - bool using_shm = false; - shm_segment_info_ = new XShmSegmentInfo; - shm_segment_info_->shmid = -1; - shm_segment_info_->shmaddr = reinterpret_cast<char*>(-1); - shm_segment_info_->readOnly = False; - x_image_ = XShmCreateImage(display_, default_visual, default_depth, ZPixmap, - 0, shm_segment_info_, root_window_size_.width(), - root_window_size_.height()); - if (x_image_) { - shm_segment_info_->shmid = shmget( - IPC_PRIVATE, x_image_->bytes_per_line * x_image_->height, - IPC_CREAT | 0600); - if (shm_segment_info_->shmid != -1) { - shm_segment_info_->shmaddr = x_image_->data = - reinterpret_cast<char*>(shmat(shm_segment_info_->shmid, 0, 0)); - if (x_image_->data != reinterpret_cast<char*>(-1)) { - EnableXServerErrorTrap(); - using_shm = XShmAttach(display_, shm_segment_info_); - XSync(display_, False); - if (GetLastXServerError() != 0) - using_shm = false; - if (using_shm) { - VLOG(1) << "Using X shared memory segment " - << shm_segment_info_->shmid; - } - } - } else { - LOG(WARNING) << "Failed to get shared memory segment. " - "Performance may be degraded."; - } - } - - if (!using_shm) { - LOG(WARNING) << "Not using shared memory. Performance may be degraded."; - Release(); - return; - } - - if (havePixmaps) - havePixmaps = InitPixmaps(default_depth); - - shmctl(shm_segment_info_->shmid, IPC_RMID, 0); - shm_segment_info_->shmid = -1; - - VLOG(1) << "Using X shared memory extension v" << major << "." << minor - << " with" << (havePixmaps?"":"out") << " pixmaps."; -} - -bool XServerPixelBuffer::InitPixmaps(int depth) { - if (XShmPixmapFormat(display_) != ZPixmap) - return false; - - EnableXServerErrorTrap(); - shm_pixmap_ = XShmCreatePixmap(display_, root_window_, - shm_segment_info_->shmaddr, - shm_segment_info_, - root_window_size_.width(), - root_window_size_.height(), depth); - XSync(display_, False); - if (GetLastXServerError() != 0) { - // |shm_pixmap_| is not not valid because the request was not processed - // by the X Server, so zero it. - shm_pixmap_ = 0; - return false; - } - - EnableXServerErrorTrap(); - XGCValues shm_gc_values; - shm_gc_values.subwindow_mode = IncludeInferiors; - shm_gc_values.graphics_exposures = False; - shm_gc_ = XCreateGC(display_, root_window_, - GCSubwindowMode | GCGraphicsExposures, - &shm_gc_values); - XSync(display_, False); - if (GetLastXServerError() != 0) { - XFreePixmap(display_, shm_pixmap_); - shm_pixmap_ = 0; - shm_gc_ = 0; // See shm_pixmap_ comment above. - return false; - } - - return true; -} - -void XServerPixelBuffer::Synchronize() { - if (shm_segment_info_ && !shm_pixmap_) { - // XShmGetImage can fail if the display is being reconfigured. - EnableXServerErrorTrap(); - XShmGetImage(display_, root_window_, x_image_, 0, 0, AllPlanes); - GetLastXServerError(); - } -} - -uint8* XServerPixelBuffer::CaptureRect(const SkIRect& rect) { - DCHECK(SkIRect::MakeSize(root_window_size_).contains(rect)); - 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); - 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; - } else { - if (x_image_) - XDestroyImage(x_image_); - x_image_ = XGetImage(display_, root_window_, rect.fLeft, rect.fTop, - rect.width(), rect.height(), AllPlanes, ZPixmap); - return reinterpret_cast<uint8*>(x_image_->data); - } -} - -int XServerPixelBuffer::GetStride() const { - return x_image_->bytes_per_line; -} - -int XServerPixelBuffer::GetDepth() const { - return x_image_->depth; -} - -int XServerPixelBuffer::GetBitsPerPixel() const { - return x_image_->bits_per_pixel; -} - -int XServerPixelBuffer::GetRedMask() const { - return x_image_->red_mask; -} - -int XServerPixelBuffer::GetBlueMask() const { - return x_image_->blue_mask; -} - -int XServerPixelBuffer::GetGreenMask() const { - return x_image_->green_mask; -} - -int XServerPixelBuffer::GetRedShift() const { - return ffs(x_image_->red_mask) - 1; -} - -int XServerPixelBuffer::GetBlueShift() const { - return ffs(x_image_->blue_mask) - 1; -} - -int XServerPixelBuffer::GetGreenShift() const { - return ffs(x_image_->green_mask) - 1; -} - -bool XServerPixelBuffer::IsRgb() const { - return GetRedShift() == 16 && GetGreenShift() == 8 && GetBlueShift() == 0; -} - -} // namespace remoting diff --git a/remoting/capturer/linux/x_server_pixel_buffer.h b/remoting/capturer/linux/x_server_pixel_buffer.h deleted file mode 100644 index afd96b0..0000000 --- a/remoting/capturer/linux/x_server_pixel_buffer.h +++ /dev/null @@ -1,82 +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. - -// Don't include this file in any .h files because it pulls in some X headers. - -#ifndef REMOTING_CAPTURER_LINUX_X_SERVER_PIXEL_BUFFER_H_ -#define REMOTING_CAPTURER_LINUX_X_SERVER_PIXEL_BUFFER_H_ - -#include "base/basictypes.h" -#include "third_party/skia/include/core/SkRect.h" - -#include <X11/Xutil.h> -#include <X11/extensions/XShm.h> - -namespace remoting { - -// A class to allow the X server's pixel buffer to be accessed as efficiently -// as possible. -class XServerPixelBuffer { - public: - XServerPixelBuffer(); - ~XServerPixelBuffer(); - - void Release(); - - // Allocate (or reallocate) the pixel buffer with the given size, which is - // 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); - - // Request the current size of the root window from the X Server. - static SkISize 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). - // This is to avoid doing a full-screen capture for each individual - // rectangle in the capture list, when it only needs to be done once at the - // beginning. - void Synchronize(); - - // Capture the specified rectangle and return a pointer to its top-left pixel - // or NULL if capture fails. The returned pointer remains valid until the next - // call to CaptureRect. - // In the case where the full-screen data is captured by Synchronize(), this - // 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); - - // Return information about the most recent capture. This is only guaranteed - // to be valid between CaptureRect calls. - int GetStride() const; - int GetDepth() const; - int GetBitsPerPixel() const; - int GetRedMask() const; - int GetBlueMask() const; - int GetGreenMask() const; - int GetRedShift() const; - int GetBlueShift() const; - int GetGreenShift() const; - bool IsRgb() const; - - private: - void InitShm(int screen); - bool InitPixmaps(int depth); - - Display* display_; - Window root_window_; - SkISize root_window_size_; - XImage* x_image_; - XShmSegmentInfo* shm_segment_info_; - Pixmap shm_pixmap_; - GC shm_gc_; - - DISALLOW_COPY_AND_ASSIGN(XServerPixelBuffer); -}; - -} // namespace remoting - -#endif // REMOTING_CAPTURER_LINUX_X_SERVER_PIXEL_BUFFER_H_ diff --git a/remoting/capturer/mac/desktop_configuration.h b/remoting/capturer/mac/desktop_configuration.h deleted file mode 100644 index 7157d75..0000000 --- a/remoting/capturer/mac/desktop_configuration.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 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 REMOTING_CAPTURER_MAC_DESKTOP_CONFIGURATION_H_ -#define REMOTING_CAPTURER_MAC_DESKTOP_CONFIGURATION_H_ - -#include <ApplicationServices/ApplicationServices.h> -#include <Carbon/Carbon.h> -#include <vector> - -#include "base/basictypes.h" -#include "third_party/skia/include/core/SkPoint.h" -#include "third_party/skia/include/core/SkRect.h" - -namespace remoting { - -// Describes the configuration of a specific display. -struct MacDisplayConfiguration { - MacDisplayConfiguration(); - - // Returns the current configuration of the specified display. - static MacDisplayConfiguration ForDisplay(CGDirectDisplayID display_id); - - // Cocoa identifier for this display. - CGDirectDisplayID id; - - // Bounds of this display in Density-Independent Pixels (DIPs). - SkIRect bounds; - - // Bounds of this display in physical pixels. - SkIRect pixel_bounds; - - // Scale factor from DIPs to physical pixels. - float dip_to_pixel_scale; -}; - -typedef std::vector<MacDisplayConfiguration> MacDisplayConfigurations; - -// Describes the configuration of the whole desktop. -struct MacDesktopConfiguration { - MacDesktopConfiguration(); - ~MacDesktopConfiguration(); - - // Returns the current configuration of the desktop. - static MacDesktopConfiguration GetCurrent(); - - // Bounds of the desktop in Density-Independent Pixels (DIPs). - SkIRect bounds; - - // Bounds of the desktop in physical pixels. - SkIRect pixel_bounds; - - // Scale factor from DIPs to physical pixels. - float dip_to_pixel_scale; - - // Configurations of the displays making up the desktop area. - MacDisplayConfigurations displays; -}; - -} // namespace remoting - -#endif // REMOTING_CAPTURER_MAC_DESKTOP_CONFIGURATION_H_ diff --git a/remoting/capturer/mac/desktop_configuration.mm b/remoting/capturer/mac/desktop_configuration.mm deleted file mode 100644 index f14e3e4..0000000 --- a/remoting/capturer/mac/desktop_configuration.mm +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 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 "remoting/capturer/mac/desktop_configuration.h" - -#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 - -@interface NSScreen (LionAPI) -- (CGFloat)backingScaleFactor; -- (NSRect)convertRectToBacking:(NSRect)aRect; -@end - -#endif // 10.7 - -namespace remoting { - -MacDisplayConfiguration::MacDisplayConfiguration() - : id(0), - bounds(SkIRect::MakeEmpty()), - pixel_bounds(SkIRect::MakeEmpty()), - dip_to_pixel_scale(1.0f) { -} - -static SkIRect NSRectToSkIRect(const NSRect& ns_rect) { - SkIRect result; - gfx::CGRectToSkRect(NSRectToCGRect(ns_rect)).roundOut(&result); - return result; -} - -static MacDisplayConfiguration GetConfigurationForScreen(NSScreen* screen) { - MacDisplayConfiguration display_config; - - // Fetch the NSScreenNumber, which is also the CGDirectDisplayID. - NSDictionary* device_description = [screen deviceDescription]; - display_config.id = static_cast<CGDirectDisplayID>( - [[device_description objectForKey:@"NSScreenNumber"] intValue]); - - // Determine the display's logical & physical dimensions. - NSRect ns_bounds = [screen frame]; - display_config.bounds = NSRectToSkIRect(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. - if ([screen respondsToSelector:@selector(backingScaleFactor)] && - [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); - } else { - display_config.pixel_bounds = display_config.bounds; - } - - return display_config; -} - -MacDesktopConfiguration::MacDesktopConfiguration() - : bounds(SkIRect::MakeEmpty()), - pixel_bounds(SkIRect::MakeEmpty()), - dip_to_pixel_scale(1.0f) { -} - -MacDesktopConfiguration::~MacDesktopConfiguration() { -} - -// static -MacDesktopConfiguration MacDesktopConfiguration::GetCurrent() { - MacDesktopConfiguration desktop_config; - - NSArray* screens = [NSScreen screens]; - CHECK(screens != NULL); - - // 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]); - - // 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 - // list returned by [NSScreen screens]. - if (i == 0) { - desktop_config.dip_to_pixel_scale = display_config.dip_to_pixel_scale; - } else if (desktop_config.dip_to_pixel_scale != - display_config.dip_to_pixel_scale) { - continue; - } - - // Add the display to the configuration. - 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); - } - - return desktop_config; -} - -} // namespace remoting diff --git a/remoting/capturer/mac/scoped_pixel_buffer_object.cc b/remoting/capturer/mac/scoped_pixel_buffer_object.cc deleted file mode 100644 index 39afc3e..0000000 --- a/remoting/capturer/mac/scoped_pixel_buffer_object.cc +++ /dev/null @@ -1,47 +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 "remoting/capturer/mac/scoped_pixel_buffer_object.h" - -namespace remoting { - -ScopedPixelBufferObject::ScopedPixelBufferObject() - : cgl_context_(NULL), - pixel_buffer_object_(0) { -} - -ScopedPixelBufferObject::~ScopedPixelBufferObject() { - Release(); -} - -bool ScopedPixelBufferObject::Init(CGLContextObj cgl_context, - int size_in_bytes) { - cgl_context_ = cgl_context; - CGLContextObj CGL_MACRO_CONTEXT = cgl_context_; - glGenBuffersARB(1, &pixel_buffer_object_); - if (glGetError() == GL_NO_ERROR) { - glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pixel_buffer_object_); - glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, size_in_bytes, NULL, - GL_STREAM_READ_ARB); - glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); - if (glGetError() != GL_NO_ERROR) { - Release(); - } - } else { - cgl_context_ = NULL; - pixel_buffer_object_ = 0; - } - return pixel_buffer_object_ != 0; -} - -void ScopedPixelBufferObject::Release() { - if (pixel_buffer_object_) { - CGLContextObj CGL_MACRO_CONTEXT = cgl_context_; - glDeleteBuffersARB(1, &pixel_buffer_object_); - cgl_context_ = NULL; - pixel_buffer_object_ = 0; - } -} - -} // namespace remoting diff --git a/remoting/capturer/mac/scoped_pixel_buffer_object.h b/remoting/capturer/mac/scoped_pixel_buffer_object.h deleted file mode 100644 index f928ab5..0000000 --- a/remoting/capturer/mac/scoped_pixel_buffer_object.h +++ /dev/null @@ -1,33 +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 REMOTING_CAPTURER_SCOPED_PIXEL_BUFFER_OBJECT_H_ -#define REMOTING_CAPTURER_SCOPED_PIXEL_BUFFER_OBJECT_H_ - -#include <OpenGL/CGLMacro.h> -#include <OpenGL/OpenGL.h> -#include "base/basictypes.h" - -namespace remoting { - -class ScopedPixelBufferObject { - public: - ScopedPixelBufferObject(); - ~ScopedPixelBufferObject(); - - bool Init(CGLContextObj cgl_context, int size_in_bytes); - void Release(); - - GLuint get() const { return pixel_buffer_object_; } - - private: - CGLContextObj cgl_context_; - GLuint pixel_buffer_object_; - - DISALLOW_COPY_AND_ASSIGN(ScopedPixelBufferObject); -}; - -} // namespace remoting - -#endif // REMOTING_CAPTURER_SCOPED_PIXEL_BUFFER_OBJECT_H_ diff --git a/remoting/capturer/mouse_cursor_shape.cc b/remoting/capturer/mouse_cursor_shape.cc deleted file mode 100644 index 7381a2b0..0000000 --- a/remoting/capturer/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 "remoting/capturer/mouse_cursor_shape.h" - -namespace remoting { - -MouseCursorShape::MouseCursorShape() - : size(SkISize::Make(0, 0)), - hotspot(SkIPoint::Make(0, 0)) { -} - -MouseCursorShape::~MouseCursorShape() { -} - -} // namespace remoting diff --git a/remoting/capturer/mouse_cursor_shape.h b/remoting/capturer/mouse_cursor_shape.h deleted file mode 100644 index 136728a..0000000 --- a/remoting/capturer/mouse_cursor_shape.h +++ /dev/null @@ -1,33 +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 REMOTING_CAPTURER_MOUSE_CURSOR_SHAPE_H_ -#define REMOTING_CAPTURER_MOUSE_CURSOR_SHAPE_H_ - -#include <string> - -#include "third_party/skia/include/core/SkPoint.h" -#include "third_party/skia/include/core/SkRect.h" -#include "third_party/skia/include/core/SkSize.h" - -namespace remoting { - -// Type used to return mouse cursor shape from video capturers. -struct MouseCursorShape { - MouseCursorShape(); - ~MouseCursorShape(); - - // Size of the cursor in screen pixels. - SkISize size; - - // Coordinates of the cursor hotspot relative to upper-left corner. - SkIPoint hotspot; - - // Cursor pixmap data in 32-bit BGRA format. - std::string data; -}; - -} // namespace remoting - -#endif // REMOTING_CAPTURER_MOUSE_CURSOR_SHAPE_H_ diff --git a/remoting/capturer/shared_buffer.cc b/remoting/capturer/shared_buffer.cc deleted file mode 100644 index 8268299..0000000 --- a/remoting/capturer/shared_buffer.cc +++ /dev/null @@ -1,37 +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 "remoting/capturer/shared_buffer.h" - -const bool kReadOnly = true; - -namespace remoting { - -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() { -} - -} // namespace remoting diff --git a/remoting/capturer/shared_buffer.h b/remoting/capturer/shared_buffer.h deleted file mode 100644 index 16429b9..0000000 --- a/remoting/capturer/shared_buffer.h +++ /dev/null @@ -1,69 +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 REMOTING_CAPTURER_SHARED_BUFFER_H_ -#define REMOTING_CAPTURER_SHARED_BUFFER_H_ - -#include "base/basictypes.h" -#include "base/memory/ref_counted.h" -#include "base/process.h" -#include "base/shared_memory.h" - -namespace remoting { - -// 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 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(); } - - 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 remoting - -#endif // REMOTING_CAPTURER_SHARED_BUFFER_H_ diff --git a/remoting/capturer/shared_buffer_factory.h b/remoting/capturer/shared_buffer_factory.h deleted file mode 100644 index 008714b..0000000 --- a/remoting/capturer/shared_buffer_factory.h +++ /dev/null @@ -1,29 +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 REMOTING_CAPTURER_SHARED_BUFFER_FACTORY_H_ -#define REMOTING_CAPTURER_SHARED_BUFFER_FACTORY_H_ - -namespace remoting { - -class SharedBuffer; - -// Provides a way to create shared buffers accessible by two or more processes. -class SharedBufferFactory { - public: - // Creates a shared memory buffer of the given size. - virtual scoped_refptr<SharedBuffer> CreateSharedBuffer(uint32 size) = 0; - - // Notifies the factory that the buffer is no longer used by the caller and - // can be released. The caller still has to drop all references to free - // the memory. - virtual void ReleaseSharedBuffer(scoped_refptr<SharedBuffer> buffer) = 0; - - protected: - virtual ~SharedBufferFactory() {} -}; - -} // namespace remoting - -#endif // REMOTING_CAPTURER_SHARED_BUFFER_FACTORY_H_ diff --git a/remoting/capturer/shared_buffer_unittest.cc b/remoting/capturer/shared_buffer_unittest.cc deleted file mode 100644 index b065f5c..0000000 --- a/remoting/capturer/shared_buffer_unittest.cc +++ /dev/null @@ -1,62 +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 "ipc/ipc_platform_file.h" -#include "remoting/capturer/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 remoting { - -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); - -#if defined(OS_POSIX) - base::PlatformFile source_handle = source->handle().fd; -#else // !defined(OS_POSIX) - base::PlatformFile source_handle = source->handle(); -#endif // !defined(OS_POSIX) - - // Duplicate the source handle. - IPC::PlatformFileForTransit copied_handle = IPC::GetFileHandleForProcess( - source_handle, base::GetCurrentProcessHandle(), false); - - 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 remoting diff --git a/remoting/capturer/video_capturer_mock_objects.cc b/remoting/capturer/video_capturer_mock_objects.cc deleted file mode 100644 index 22a79f6..0000000 --- a/remoting/capturer/video_capturer_mock_objects.cc +++ /dev/null @@ -1,28 +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 "remoting/capturer/video_capturer_mock_objects.h" - -#include "remoting/capturer/video_frame_capturer.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace remoting { - -MockVideoFrameCapturer::MockVideoFrameCapturer() {} - -MockVideoFrameCapturer::~MockVideoFrameCapturer() {} - -MockVideoFrameCapturerDelegate::MockVideoFrameCapturerDelegate() { -} - -MockVideoFrameCapturerDelegate::~MockVideoFrameCapturerDelegate() { -} - -void MockVideoFrameCapturerDelegate::OnCursorShapeChanged( - scoped_ptr<MouseCursorShape> cursor_shape) { - // Notify the mock method. - OnCursorShapeChangedPtr(cursor_shape.get()); -} - -} // namespace remoting diff --git a/remoting/capturer/video_capturer_mock_objects.h b/remoting/capturer/video_capturer_mock_objects.h deleted file mode 100644 index f460c1f..0000000 --- a/remoting/capturer/video_capturer_mock_objects.h +++ /dev/null @@ -1,46 +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 REMOTING_CAPTURER_VIDEO_CAPTURER_MOCK_OBJECTS_H_ -#define REMOTING_CAPTURER_VIDEO_CAPTURER_MOCK_OBJECTS_H_ - -#include "remoting/capturer/capture_data.h" -#include "remoting/capturer/mouse_cursor_shape.h" -#include "remoting/capturer/video_frame_capturer.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace remoting { - -class MockVideoFrameCapturer : public VideoFrameCapturer { - public: - MockVideoFrameCapturer(); - virtual ~MockVideoFrameCapturer(); - - MOCK_METHOD1(Start, void(Delegate* delegate)); - MOCK_METHOD0(Stop, void()); - MOCK_METHOD1(InvalidateRegion, void(const SkRegion& invalid_region)); - MOCK_METHOD0(CaptureFrame, void()); - - private: - DISALLOW_COPY_AND_ASSIGN(MockVideoFrameCapturer); -}; - -class MockVideoFrameCapturerDelegate : public VideoFrameCapturer::Delegate { - public: - MockVideoFrameCapturerDelegate(); - virtual ~MockVideoFrameCapturerDelegate(); - - void OnCursorShapeChanged(scoped_ptr<MouseCursorShape> cursor_shape) OVERRIDE; - - MOCK_METHOD1(OnCaptureCompleted, void(scoped_refptr<CaptureData>)); - MOCK_METHOD1(OnCursorShapeChangedPtr, - void(MouseCursorShape* cursor_shape)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockVideoFrameCapturerDelegate); -}; - -} // namespace remoting - -#endif // REMOTING_CAPTURER_VIDEO_CAPTURER_MOCK_OBJECTS_H_ diff --git a/remoting/capturer/video_frame.cc b/remoting/capturer/video_frame.cc deleted file mode 100644 index b9d7278..0000000 --- a/remoting/capturer/video_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 "remoting/capturer/video_frame.h" - -namespace remoting { - -VideoFrame::~VideoFrame() { -} - -VideoFrame::VideoFrame() - : bytes_per_row_(0), - dimensions_(SkISize::Make(0, 0)), - pixels_(NULL) { -} - -} // namespace remoting diff --git a/remoting/capturer/video_frame.h b/remoting/capturer/video_frame.h deleted file mode 100644 index 77105b7..0000000 --- a/remoting/capturer/video_frame.h +++ /dev/null @@ -1,63 +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 REMOTING_CAPTURER_VIDEO_FRAME_H_ -#define REMOTING_CAPTURER_VIDEO_FRAME_H_ - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/memory/ref_counted.h" -#include "remoting/capturer/shared_buffer.h" -#include "third_party/skia/include/core/SkSize.h" -#include "third_party/skia/include/core/SkTypes.h" - -namespace remoting { - -// Represents a video frame. -class VideoFrame { - public: - virtual ~VideoFrame(); - - 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. - VideoFrame(); - - 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(VideoFrame); -}; - -} // namespace remoting - -#endif // REMOTING_CAPTURER_VIDEO_FRAME_H_ diff --git a/remoting/capturer/video_frame_capturer.h b/remoting/capturer/video_frame_capturer.h deleted file mode 100644 index 2b6c803..0000000 --- a/remoting/capturer/video_frame_capturer.h +++ /dev/null @@ -1,115 +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 REMOTING_CAPTURER_VIDEO_FRAME_CAPTURER_H_ -#define REMOTING_CAPTURER_VIDEO_FRAME_CAPTURER_H_ - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/shared_memory.h" -#include "third_party/skia/include/core/SkRegion.h" - -namespace remoting { - -class CaptureData; -struct MouseCursorShape; -class SharedBufferFactory; - -// Class used to capture video frames asynchronously. -// -// The full capture sequence is as follows: -// -// (1) Start -// This is when pre-capture steps are executed, such as flagging the -// display to prevent it from sleeping during a session. -// -// (2) InvalidateRegion -// This is an optional step where regions of the screen are marked as -// invalid. Some platforms (Windows, for now) won't use this and will -// instead calculate the diff-regions later (in step (2). Other -// platforms (Mac) will use this to mark all the changed regions of the -// screen. Some limited rect-merging (e.g., to eliminate exact -// duplicates) may be done here. -// -// (3) CaptureFrame -// This is where the bits for the invalid rects are packaged up and sent -// to the encoder. -// A screen capture is performed if needed. For example, Windows requires -// a capture to calculate the diff from the previous screen, whereas the -// Mac version does not. -// -// (4) Stop -// This is when post-capture steps are executed, such as releasing the -// assertion that prevents the display from sleeping. -// -// Implementation has to ensure the following guarantees: -// 1. Double buffering -// Since data can be read while another capture action is happening. -class VideoFrameCapturer { - public: - // Provides callbacks used by the capturer to pass captured video frames and - // mouse cursor shapes to the processing pipeline. - class Delegate { - public: - // Called when a video frame has been captured. |capture_data| describes - // a captured frame. - virtual void OnCaptureCompleted( - scoped_refptr<CaptureData> 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 ~VideoFrameCapturer() {} - - // Create platform-specific capturer. - static scoped_ptr<VideoFrameCapturer> Create(); - - // Create platform-specific capturer that uses shared memory buffers. - static scoped_ptr<VideoFrameCapturer> CreateWithFactory( - SharedBufferFactory* shared_buffer_factory); - -#if defined(OS_LINUX) - // Set whether the VideoFrameCapturer should try to use X DAMAGE support if it - // is available. This needs to be called before the VideoFrameCapturer is - // created. - // This is used by the Virtual Me2Me host, since the XDamage extension is - // known to work reliably in this case. - - // TODO(lambroslambrou): This currently sets a global flag, referenced during - // VideoFrameCapturer::Create(). This is a temporary solution, until the - // DesktopEnvironment class is refactored to allow applications to control - // the creation of various stubs (including the VideoFrameCapturer) - see - // http://crbug.com/104544 - static void EnableXDamage(bool enable); -#endif // defined(OS_LINUX) - - // Called at the beginning of a capturing session. |delegate| must remain - // valid until Stop() is called. - virtual void Start(Delegate* delegate) = 0; - - // Called at the end of a capturing session. - virtual void Stop() = 0; - - // Invalidates the specified region. - virtual void InvalidateRegion(const SkRegion& invalid_region) = 0; - - // 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; -}; - -} // namespace remoting - -#endif // REMOTING_CAPTURER_VIDEO_FRAME_CAPTURER_H_ diff --git a/remoting/capturer/video_frame_capturer_fake.cc b/remoting/capturer/video_frame_capturer_fake.cc deleted file mode 100644 index 8cdff43..0000000 --- a/remoting/capturer/video_frame_capturer_fake.cc +++ /dev/null @@ -1,117 +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 "remoting/capturer/video_frame_capturer_fake.h" - -#include "base/time.h" -#include "remoting/capturer/capture_data.h" - -namespace remoting { - -// VideoFrameCapturerFake generates a white picture of size kWidth x kHeight -// with a rectangle of size kBoxWidth x kBoxHeight. The rectangle moves kSpeed -// pixels per frame along both axes, and bounces off the sides of the screen. -static const int kWidth = VideoFrameCapturerFake::kWidth; -static const int kHeight = VideoFrameCapturerFake::kHeight; -static const int kBoxWidth = 140; -static const int kBoxHeight = 140; -static const int kSpeed = 20; - -COMPILE_ASSERT(kBoxWidth < kWidth && kBoxHeight < kHeight, bad_box_size); -COMPILE_ASSERT((kBoxWidth % kSpeed == 0) && (kWidth % kSpeed == 0) && - (kBoxHeight % kSpeed == 0) && (kHeight % kSpeed == 0), - sizes_must_be_multiple_of_kSpeed); - -VideoFrameCapturerFake::VideoFrameCapturerFake() - : size_(SkISize::Make(0, 0)), - bytes_per_row_(0), - box_pos_x_(0), - box_pos_y_(0), - box_speed_x_(kSpeed), - box_speed_y_(kSpeed), - current_buffer_(0) { - ScreenConfigurationChanged(); -} - -VideoFrameCapturerFake::~VideoFrameCapturerFake() { -} - -void VideoFrameCapturerFake::Start(Delegate* delegate) { - delegate_ = delegate; -} - -void VideoFrameCapturerFake::Stop() { -} - -void VideoFrameCapturerFake::InvalidateRegion(const SkRegion& invalid_region) { - helper_.InvalidateRegion(invalid_region); -} - -void VideoFrameCapturerFake::CaptureFrame() { - base::Time capture_start_time = base::Time::Now(); - - GenerateImage(); - helper_.InvalidateScreen(size_); - - SkRegion invalid_region; - helper_.SwapInvalidRegion(&invalid_region); - - current_buffer_ = (current_buffer_ + 1) % kNumBuffers; - - scoped_refptr<CaptureData> capture_data(new CaptureData( - buffers_[current_buffer_].get(), bytes_per_row_, size_)); - capture_data->mutable_dirty_region() = invalid_region; - - helper_.set_size_most_recent(capture_data->size()); - - capture_data->set_capture_time_ms( - (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp()); - delegate_->OnCaptureCompleted(capture_data); -} - -void VideoFrameCapturerFake::GenerateImage() { - memset(buffers_[current_buffer_].get(), 0xff, - size_.width() * size_.height() * CaptureData::kBytesPerPixel); - - uint8* row = buffers_[current_buffer_].get() + - (box_pos_y_ * size_.width() + box_pos_x_) * CaptureData::kBytesPerPixel; - - box_pos_x_ += box_speed_x_; - if (box_pos_x_ + kBoxWidth >= size_.width() || box_pos_x_ == 0) - box_speed_x_ = -box_speed_x_; - - box_pos_y_ += box_speed_y_; - if (box_pos_y_ + kBoxHeight >= size_.height() || box_pos_y_ == 0) - box_speed_y_ = -box_speed_y_; - - // Draw rectangle with the following colors in its corners: - // cyan....yellow - // .............. - // blue.......red - for (int y = 0; y < kBoxHeight; ++y) { - for (int x = 0; x < kBoxWidth; ++x) { - int r = x * 255 / kBoxWidth; - int g = y * 255 / kBoxHeight; - int b = 255 - (x * 255 / kBoxWidth); - row[x * CaptureData::kBytesPerPixel] = r; - row[x * CaptureData::kBytesPerPixel + 1] = g; - row[x * CaptureData::kBytesPerPixel + 2] = b; - row[x * CaptureData::kBytesPerPixel + 3] = 0xff; - } - row += bytes_per_row_; - } -} - -void VideoFrameCapturerFake::ScreenConfigurationChanged() { - size_ = SkISize::Make(kWidth, kHeight); - bytes_per_row_ = size_.width() * CaptureData::kBytesPerPixel; - - // Create memory for the buffers. - int buffer_size = size_.height() * bytes_per_row_; - for (int i = 0; i < kNumBuffers; i++) { - buffers_[i].reset(new uint8[buffer_size]); - } -} - -} // namespace remoting diff --git a/remoting/capturer/video_frame_capturer_fake.h b/remoting/capturer/video_frame_capturer_fake.h deleted file mode 100644 index b116967..0000000 --- a/remoting/capturer/video_frame_capturer_fake.h +++ /dev/null @@ -1,63 +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 REMOTING_CAPTURER_VIDEO_FRAME_CAPTURER_FAKE_H_ -#define REMOTING_CAPTURER_VIDEO_FRAME_CAPTURER_FAKE_H_ - -#include "base/memory/scoped_ptr.h" -#include "remoting/capturer/video_frame_capturer.h" -#include "remoting/capturer/video_frame_capturer_helper.h" - -namespace remoting { - -// A VideoFrameCapturerFake generates artificial image for testing purpose. -// -// VideoFrameCapturerFake is double-buffered as required by VideoFrameCapturer. -// See remoting/host/video_frame_capturer.h. -class VideoFrameCapturerFake : public VideoFrameCapturer { - public: - // VideoFrameCapturerFake generates a picture of size kWidth x kHeight. - static const int kWidth = 800; - static const int kHeight = 600; - - VideoFrameCapturerFake(); - virtual ~VideoFrameCapturerFake(); - - // Overridden from VideoFrameCapturer: - virtual void Start(Delegate* delegate) OVERRIDE; - virtual void Stop() OVERRIDE; - virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE; - virtual void CaptureFrame() OVERRIDE; - - private: - // Generates an image in the front buffer. - void GenerateImage(); - - // Called when the screen configuration is changed. - void ScreenConfigurationChanged(); - - Delegate* delegate_; - - SkISize size_; - int bytes_per_row_; - int box_pos_x_; - int box_pos_y_; - int box_speed_x_; - int box_speed_y_; - - VideoFrameCapturerHelper helper_; - - // We have two buffers for the screen images as required by Capturer. - static const int kNumBuffers = 2; - scoped_array<uint8> buffers_[kNumBuffers]; - - // The current buffer with valid data for reading. - int current_buffer_; - - DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerFake); -}; - -} // namespace remoting - -#endif // REMOTING_CAPTURER_VIDEO_FRAME_CAPTURER_FAKE_H_ diff --git a/remoting/capturer/video_frame_capturer_helper.cc b/remoting/capturer/video_frame_capturer_helper.cc deleted file mode 100644 index 7f05548..0000000 --- a/remoting/capturer/video_frame_capturer_helper.cc +++ /dev/null @@ -1,118 +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 "remoting/capturer/video_frame_capturer_helper.h" - -#include <algorithm> - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" - -namespace remoting { - -VideoFrameCapturerHelper::VideoFrameCapturerHelper() : - size_most_recent_(SkISize::Make(0, 0)), - log_grid_size_(0) { -} - -VideoFrameCapturerHelper::~VideoFrameCapturerHelper() { -} - -void VideoFrameCapturerHelper::ClearInvalidRegion() { - base::AutoLock auto_invalid_region_lock(invalid_region_lock_); - invalid_region_.setEmpty(); -} - -void VideoFrameCapturerHelper::InvalidateRegion( - const SkRegion& invalid_region) { - base::AutoLock auto_invalid_region_lock(invalid_region_lock_); - invalid_region_.op(invalid_region, SkRegion::kUnion_Op); -} - -void VideoFrameCapturerHelper::InvalidateScreen(const SkISize& size) { - base::AutoLock auto_invalid_region_lock(invalid_region_lock_); - invalid_region_.op(SkIRect::MakeWH(size.width(), size.height()), - SkRegion::kUnion_Op); -} - -void VideoFrameCapturerHelper::InvalidateFullScreen() { - if (!size_most_recent_.isZero()) - InvalidateScreen(size_most_recent_); -} - -void VideoFrameCapturerHelper::SwapInvalidRegion(SkRegion* invalid_region) { - { - base::AutoLock auto_invalid_region_lock(invalid_region_lock_); - 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); - } -} - -void VideoFrameCapturerHelper::SetLogGridSize(int log_grid_size) { - log_grid_size_ = log_grid_size; -} - -const SkISize& VideoFrameCapturerHelper::size_most_recent() const { - return size_most_recent_; -} - -void VideoFrameCapturerHelper::set_size_most_recent(const SkISize& size) { - size_most_recent_ = size; -} - -// Returns the largest multiple of |n| that is <= |x|. -// |n| must be a power of 2. |nMask| is ~(|n| - 1). -static int DownToMultiple(int x, int nMask) { - return (x & nMask); -} - -// Returns the smallest multiple of |n| that is >= |x|. -// |n| must be a power of 2. |nMask| is ~(|n| - 1). -static int UpToMultiple(int x, int n, int nMask) { - return ((x + n - 1) & nMask); -} - -scoped_ptr<SkRegion> VideoFrameCapturerHelper::ExpandToGrid( - const SkRegion& region, - int log_grid_size) { - DCHECK(log_grid_size >= 1); - int grid_size = 1 << log_grid_size; - int grid_size_mask = ~(grid_size - 1); - // Count the rects in the region. - int rectNum = 0; - SkRegion::Iterator iter(region); - while (!iter.done()) { - iter.next(); - ++rectNum; - } - // Expand each rect. - scoped_array<SkIRect> rects(new SkIRect[rectNum]); - iter.rewind(); - int rectI = 0; - while (!iter.done()) { - SkIRect rect = iter.rect(); - iter.next(); - int left = std::min(rect.left(), rect.right()); - int right = std::max(rect.left(), rect.right()); - int top = std::min(rect.top(), rect.bottom()); - int bottom = std::max(rect.top(), rect.bottom()); - left = DownToMultiple(left, grid_size_mask); - right = UpToMultiple(right, grid_size, grid_size_mask); - top = DownToMultiple(top, grid_size_mask); - bottom = UpToMultiple(bottom, grid_size, grid_size_mask); - rects[rectI++] = SkIRect::MakeLTRB(left, top, right, bottom); - } - // Make the union of the expanded rects. - scoped_ptr<SkRegion> regionNew(new SkRegion()); - regionNew->setRects(rects.get(), rectNum); - return regionNew.Pass(); -} - -} // namespace remoting diff --git a/remoting/capturer/video_frame_capturer_helper.h b/remoting/capturer/video_frame_capturer_helper.h deleted file mode 100644 index 79a4750..0000000 --- a/remoting/capturer/video_frame_capturer_helper.h +++ /dev/null @@ -1,83 +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 REMOTING_CAPTURER_VIDEO_FRAME_CAPTURER_HELPER_H_ -#define REMOTING_CAPTURER_VIDEO_FRAME_CAPTURER_HELPER_H_ - -#include "base/memory/scoped_ptr.h" -#include "base/synchronization/lock.h" -#include "third_party/skia/include/core/SkRegion.h" - -namespace remoting { - -// VideoFrameCapturerHelper is intended to be used by an implementation of the -// VideoFrameCapturer interface. It maintains a thread-safe invalid region, and -// the size of the most recently captured screen, on behalf of the -// VideoFrameCapturer that owns it. -class VideoFrameCapturerHelper { - public: - VideoFrameCapturerHelper(); - ~VideoFrameCapturerHelper(); - - // Clear out the invalid region. - void ClearInvalidRegion(); - - // Invalidate the specified region. - void InvalidateRegion(const SkRegion& invalid_region); - - // Invalidate the entire screen, of a given size. - void InvalidateScreen(const SkISize& 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); - - // Access the size of the most recently captured screen. - const SkISize& size_most_recent() const; - void set_size_most_recent(const SkISize& 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 - // 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 - // set_size_most_recent(). - // If |log_grid_size| is <= 0, then the invalid region is not expanded. - void SetLogGridSize(int log_grid_size); - - // Expands a region so that its vertices all lie on a grid. - // The grid size must be >= 2, so |log_grid_size| must be >= 1. - static scoped_ptr<SkRegion> ExpandToGrid(const SkRegion& region, - int log_grid_size); - - private: - // A region that has been manually invalidated (through InvalidateRegion). - // These will be returned as dirty_region in the capture data during the next - // capture. - SkRegion invalid_region_; - - // A lock protecting |invalid_region_| across threads. - base::Lock invalid_region_lock_; - - // The size of the most recently captured screen. - SkISize size_most_recent_; - - // The log (base 2) of the size of the grid to which the invalid region is - // expanded. - // If the value is <= 0, then the invalid region is not expanded to a grid. - int log_grid_size_; - - DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerHelper); -}; - -} // namespace remoting - -#endif // REMOTING_CAPTURER_VIDEO_FRAME_CAPTURER_HELPER_H_ diff --git a/remoting/capturer/video_frame_capturer_helper_unittest.cc b/remoting/capturer/video_frame_capturer_helper_unittest.cc deleted file mode 100644 index a362c34..0000000 --- a/remoting/capturer/video_frame_capturer_helper_unittest.cc +++ /dev/null @@ -1,215 +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 "remoting/capturer/video_frame_capturer_helper.h" - -#include "base/memory/scoped_ptr.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace remoting { - -class VideoFrameCapturerHelperTest : public testing::Test { - protected: - VideoFrameCapturerHelper capturer_helper_; -}; - -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()) { - return false; - } - SkIRect rect2 = iter2.rect(); - iter2.next(); - if (rect1 != rect2) { - return false; - } - } - if (!iter2.done()) { - return false; - } - return true; -} - -TEST_F(VideoFrameCapturerHelperTest, ClearInvalidRegion) { - SkRegion region; - capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(1, 2, 3, 4))); - capturer_helper_.ClearInvalidRegion(); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(region.isEmpty()); -} - -TEST_F(VideoFrameCapturerHelperTest, InvalidateRegion) { - SkRegion region; - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeEmpty()), region)); - - capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(1, 2, 3, 4))); - region.setEmpty(); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(1, 2, 3, 4)), region)); - - capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(1, 2, 3, 4))); - capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(4, 2, 3, 4))); - region.setEmpty(); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(1, 2, 6, 4)), region)); -} - -TEST_F(VideoFrameCapturerHelperTest, InvalidateScreen) { - SkRegion region; - capturer_helper_.InvalidateScreen(SkISize::Make(12, 34)); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeWH(12, 34)), region)); -} - -TEST_F(VideoFrameCapturerHelperTest, InvalidateFullScreen) { - SkRegion region; - capturer_helper_.set_size_most_recent(SkISize::Make(12, 34)); - capturer_helper_.InvalidateFullScreen(); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeWH(12, 34)), region)); -} - -TEST_F(VideoFrameCapturerHelperTest, 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()); -} - -TEST_F(VideoFrameCapturerHelperTest, SetLogGridSize) { - capturer_helper_.set_size_most_recent(SkISize::Make(10, 10)); - - SkRegion region; - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeEmpty()), region)); - - capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1))); - region.setEmpty(); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1)), region)); - - capturer_helper_.SetLogGridSize(-1); - capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1))); - region.setEmpty(); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1)), region)); - - capturer_helper_.SetLogGridSize(0); - capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1))); - region.setEmpty(); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1)), region)); - - capturer_helper_.SetLogGridSize(1); - capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1))); - region.setEmpty(); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(6, 6, 2, 2)), region)); - - capturer_helper_.SetLogGridSize(2); - capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1))); - region.setEmpty(); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(4, 4, 4, 4)), region)); - - capturer_helper_.SetLogGridSize(0); - capturer_helper_.InvalidateRegion(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1))); - region.setEmpty(); - capturer_helper_.SwapInvalidRegion(®ion); - ASSERT_TRUE(Equals(SkRegion(SkIRect::MakeXYWH(7, 7, 1, 1)), region)); -} - -void TestExpandRegionToGrid(const SkRegion& region, int log_grid_size, - const SkRegion& expandedRegionExpected) { - scoped_ptr<SkRegion> expandedRegion1( - VideoFrameCapturerHelper::ExpandToGrid(region, log_grid_size)); - ASSERT_TRUE(Equals(expandedRegionExpected, *expandedRegion1)); - scoped_ptr<SkRegion> expandedRegion2( - VideoFrameCapturerHelper::ExpandToGrid(*expandedRegion1, log_grid_size)); - ASSERT_TRUE(Equals(*expandedRegion1, *expandedRegion2)); -} - -void TestExpandRectToGrid(int l, int t, int r, int b, int log_grid_size, - int lExpanded, int tExpanded, - int rExpanded, int bExpanded) { - TestExpandRegionToGrid(SkRegion(SkIRect::MakeLTRB(l, t, r, b)), log_grid_size, - SkRegion(SkIRect::MakeLTRB(lExpanded, tExpanded, - rExpanded, bExpanded))); -} - -TEST_F(VideoFrameCapturerHelperTest, ExpandToGrid) { - const int LOG_GRID_SIZE = 4; - const int GRID_SIZE = 1 << LOG_GRID_SIZE; - for (int i = -2; i <= 2; i++) { - int x = i * GRID_SIZE; - for (int j = -2; j <= 2; j++) { - int y = j * GRID_SIZE; - TestExpandRectToGrid(x + 0, y + 0, x + 1, y + 1, LOG_GRID_SIZE, - x + 0, y + 0, x + GRID_SIZE, y + GRID_SIZE); - TestExpandRectToGrid(x + 0, y + GRID_SIZE - 1, x + 1, y + GRID_SIZE, - LOG_GRID_SIZE, - x + 0, y + 0, x + GRID_SIZE, y + GRID_SIZE); - TestExpandRectToGrid(x + GRID_SIZE - 1, y + GRID_SIZE - 1, - x + GRID_SIZE, y + GRID_SIZE, LOG_GRID_SIZE, - x + 0, y + 0, x + GRID_SIZE, y + GRID_SIZE); - TestExpandRectToGrid(x + GRID_SIZE - 1, y + 0, - x + GRID_SIZE, y + 1, LOG_GRID_SIZE, - x + 0, y + 0, x + GRID_SIZE, y + GRID_SIZE); - TestExpandRectToGrid(x - 1, y + 0, x + 1, y + 1, LOG_GRID_SIZE, - x - GRID_SIZE, y + 0, x + GRID_SIZE, y + GRID_SIZE); - TestExpandRectToGrid(x - 1, y - 1, x + 1, y + 0, LOG_GRID_SIZE, - x - GRID_SIZE, y - GRID_SIZE, x + GRID_SIZE, y); - TestExpandRectToGrid(x + 0, y - 1, x + 1, y + 1, LOG_GRID_SIZE, - x, y - GRID_SIZE, x + GRID_SIZE, y + GRID_SIZE); - TestExpandRectToGrid(x - 1, y - 1, x + 0, y + 1, LOG_GRID_SIZE, - x - GRID_SIZE, y - GRID_SIZE, x, y + GRID_SIZE); - - SkRegion region(SkIRect::MakeLTRB(x - 1, y - 1, x + 1, y + 1)); - region.op(SkIRect::MakeLTRB(x - 1, y - 1, x + 0, y + 0), - SkRegion::kDifference_Op); - SkRegion expandedRegionExpected(SkIRect::MakeLTRB( - x - GRID_SIZE, y - GRID_SIZE, x + GRID_SIZE, y + GRID_SIZE)); - expandedRegionExpected.op( - SkIRect::MakeLTRB(x - GRID_SIZE, y - GRID_SIZE, x + 0, y + 0), - SkRegion::kDifference_Op); - TestExpandRegionToGrid(region, LOG_GRID_SIZE, expandedRegionExpected); - - region.setRect(SkIRect::MakeLTRB(x - 1, y - 1, x + 1, y + 1)); - region.op(SkIRect::MakeLTRB(x - 1, y + 0, x + 0, y + 1), - SkRegion::kDifference_Op); - expandedRegionExpected.setRect(SkIRect::MakeLTRB( - x - GRID_SIZE, y - GRID_SIZE, x + GRID_SIZE, y + GRID_SIZE)); - expandedRegionExpected.op( - SkIRect::MakeLTRB(x - GRID_SIZE, y + 0, x + 0, y + GRID_SIZE), - SkRegion::kDifference_Op); - TestExpandRegionToGrid(region, LOG_GRID_SIZE, expandedRegionExpected); - - region.setRect(SkIRect::MakeLTRB(x - 1, y - 1, x + 1, y + 1)); - region.op(SkIRect::MakeLTRB(x + 0, y + 0, x + 1, y + 1), - SkRegion::kDifference_Op); - expandedRegionExpected.setRect(SkIRect::MakeLTRB( - x - GRID_SIZE, y - GRID_SIZE, x + GRID_SIZE, y + GRID_SIZE)); - expandedRegionExpected.op( - SkIRect::MakeLTRB(x + 0, y + 0, x + GRID_SIZE, y + GRID_SIZE), - SkRegion::kDifference_Op); - TestExpandRegionToGrid(region, LOG_GRID_SIZE, expandedRegionExpected); - - region.setRect(SkIRect::MakeLTRB(x - 1, y - 1, x + 1, y + 1)); - region.op(SkIRect::MakeLTRB(x + 0, y - 1, x + 1, y + 0), - SkRegion::kDifference_Op); - expandedRegionExpected.setRect(SkIRect::MakeLTRB( - x - GRID_SIZE, y - GRID_SIZE, x + GRID_SIZE, y + GRID_SIZE)); - expandedRegionExpected.op( - SkIRect::MakeLTRB(x + 0, y - GRID_SIZE, x + GRID_SIZE, y + 0), - SkRegion::kDifference_Op); - TestExpandRegionToGrid(region, LOG_GRID_SIZE, expandedRegionExpected); - } - } -} - -} // namespace remoting diff --git a/remoting/capturer/video_frame_capturer_linux.cc b/remoting/capturer/video_frame_capturer_linux.cc deleted file mode 100644 index edfa1a4..0000000 --- a/remoting/capturer/video_frame_capturer_linux.cc +++ /dev/null @@ -1,613 +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 "remoting/capturer/video_frame_capturer.h" - -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/extensions/Xdamage.h> -#include <X11/extensions/Xfixes.h> - -#include <set> - -#include "base/basictypes.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/stl_util.h" -#include "base/time.h" -#include "remoting/capturer/capture_data.h" -#include "remoting/capturer/differ.h" -#include "remoting/capturer/linux/x_server_pixel_buffer.h" -#include "remoting/capturer/mouse_cursor_shape.h" -#include "remoting/capturer/video_frame.h" -#include "remoting/capturer/video_frame_capturer_helper.h" -#include "remoting/capturer/video_frame_queue.h" - -namespace remoting { - -namespace { - -// Default to false, since many systems have broken XDamage support - see -// http://crbug.com/73423. -static bool g_should_use_x_damage = false; - -static bool ShouldUseXDamage() { - return g_should_use_x_damage; -} - -// A class representing a full-frame pixel buffer. -class VideoFrameLinux : public VideoFrame { - public: - explicit VideoFrameLinux(const SkISize& window_size); - virtual ~VideoFrameLinux(); - - private: - // Allocated pixel buffer. - scoped_array<uint8> data_; - - DISALLOW_COPY_AND_ASSIGN(VideoFrameLinux); -}; - -// A class to perform video frame capturing for Linux. -class VideoFrameCapturerLinux : public VideoFrameCapturer { - public: - VideoFrameCapturerLinux(); - virtual ~VideoFrameCapturerLinux(); - - bool Init(); // TODO(ajwong): Do we really want this to be synchronous? - - // Capturer interface. - virtual void Start(Delegate* delegate) OVERRIDE; - virtual void Stop() OVERRIDE; - virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE; - virtual void CaptureFrame() OVERRIDE; - - private: - void InitXDamage(); - - // Read and handle all currently-pending XEvents. - // In the DAMAGE case, process the XDamage events and store the resulting - // damage rectangles in the VideoFrameCapturerHelper. - // In all cases, call ScreenConfigurationChanged() in response to any - // ConfigNotify events. - void ProcessPendingXEvents(); - - // Capture the cursor image and notify the delegate if it was captured. - void CaptureCursor(); - - // Capture screen pixels, and return the data in a new CaptureData object, - // to be freed by the caller. - // In the DAMAGE case, the VideoFrameCapturerHelper 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<CaptureData> 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); - - // Synchronize the current buffer with |last_buffer_|, by copying pixels from - // the area of |last_invalid_rects|. - // Note this only works on the assumption that kNumBuffers == 2, as - // |last_invalid_rects| holds the differences from the previous buffer and - // the one prior to that (which will then be the current buffer). - void SynchronizeFrame(); - - void DeinitXlib(); - - // Capture a rectangle from |x_server_pixel_buffer_|, and copy the data into - // |capture_data|. - void CaptureRect(const SkIRect& rect, CaptureData* capture_data); - - // 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, CaptureData* capture_data); - void SlowBlit(uint8* image, const SkIRect& rect, CaptureData* capture_data); - - Delegate* delegate_; - - // X11 graphics context. - Display* display_; - GC gc_; - Window root_window_; - - // Last known dimensions of the root window. - SkISize root_window_size_; - - // XFixes. - bool has_xfixes_; - int xfixes_event_base_; - int xfixes_error_base_; - - // XDamage information. - bool use_damage_; - Damage damage_handle_; - int damage_event_base_; - int damage_error_base_; - XserverRegion damage_region_; - - // Access to the X Server's pixel buffer. - XServerPixelBuffer x_server_pixel_buffer_; - - // A thread-safe list of invalid rectangles, and the size of the most - // recently captured screen. - VideoFrameCapturerHelper helper_; - - // Queue of the frames buffers. - VideoFrameQueue queue_; - - // Invalid region from the previous capture. This is used to synchronize the - // current with the last buffer used. - SkRegion last_invalid_region_; - - // |Differ| for use when polling for changes. - scoped_ptr<Differ> differ_; - - DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerLinux); -}; - -VideoFrameLinux::VideoFrameLinux(const SkISize& window_size) { - set_bytes_per_row(window_size.width() * CaptureData::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()); -} - -VideoFrameLinux::~VideoFrameLinux() { -} - -VideoFrameCapturerLinux::VideoFrameCapturerLinux() - : delegate_(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), - use_damage_(false), - damage_handle_(0), - damage_event_base_(-1), - damage_error_base_(-1), - damage_region_(0) { - helper_.SetLogGridSize(4); -} - -VideoFrameCapturerLinux::~VideoFrameCapturerLinux() { - DeinitXlib(); -} - -bool VideoFrameCapturerLinux::Init() { - // TODO(ajwong): We should specify the display string we are attaching to - // in the constructor. - display_ = XOpenDisplay(NULL); - if (!display_) { - LOG(ERROR) << "Unable to open display"; - return false; - } - - root_window_ = RootWindow(display_, DefaultScreen(display_)); - if (root_window_ == BadValue) { - LOG(ERROR) << "Unable to get the root window"; - DeinitXlib(); - return false; - } - - gc_ = XCreateGC(display_, root_window_, 0, NULL); - if (gc_ == NULL) { - LOG(ERROR) << "Unable to get graphics context"; - DeinitXlib(); - return false; - } - - // Check for XFixes extension. This is required for cursor shape - // notifications, and for our use of XDamage. - if (XFixesQueryExtension(display_, &xfixes_event_base_, - &xfixes_error_base_)) { - has_xfixes_ = true; - } else { - LOG(INFO) << "X server does not support XFixes."; - } - - // Register for changes to the dimensions of the root window. - XSelectInput(display_, root_window_, StructureNotifyMask); - - root_window_size_ = XServerPixelBuffer::GetRootWindowSize(display_); - x_server_pixel_buffer_.Init(display_, root_window_size_); - - if (has_xfixes_) { - // Register for changes to the cursor shape. - XFixesSelectCursorInput(display_, root_window_, - XFixesDisplayCursorNotifyMask); - } - - if (ShouldUseXDamage()) { - InitXDamage(); - } - - return true; -} - -void VideoFrameCapturerLinux::InitXDamage() { - // Our use of XDamage requires XFixes. - if (!has_xfixes_) { - return; - } - - // Check for XDamage extension. - if (!XDamageQueryExtension(display_, &damage_event_base_, - &damage_error_base_)) { - LOG(INFO) << "X server does not support XDamage."; - return; - } - - // TODO(lambroslambrou): Disable DAMAGE in situations where it is known - // to fail, such as when Desktop Effects are enabled, with graphics - // drivers (nVidia, ATI) that fail to report DAMAGE notifications - // properly. - - // Request notifications every time the screen becomes damaged. - damage_handle_ = XDamageCreate(display_, root_window_, - XDamageReportNonEmpty); - if (!damage_handle_) { - LOG(ERROR) << "Unable to initialize XDamage."; - return; - } - - // Create an XFixes server-side region to collate damage into. - damage_region_ = XFixesCreateRegion(display_, 0, 0); - if (!damage_region_) { - XDamageDestroy(display_, damage_handle_); - LOG(ERROR) << "Unable to create XFixes region."; - return; - } - - use_damage_ = true; - LOG(INFO) << "Using XDamage extension."; -} - -void VideoFrameCapturerLinux::Start(Delegate* delegate) { - DCHECK(delegate_ == NULL); - - delegate_ = delegate; -} - -void VideoFrameCapturerLinux::Stop() { -} - -void VideoFrameCapturerLinux::InvalidateRegion(const SkRegion& invalid_region) { - helper_.InvalidateRegion(invalid_region); -} - -void VideoFrameCapturerLinux::CaptureFrame() { - base::Time capture_start_time = base::Time::Now(); - - // Process XEvents for XDamage and cursor shape tracking. - ProcessPendingXEvents(); - - // 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<VideoFrameLinux> buffer(new VideoFrameLinux( - root_window_size_)); - queue_.ReplaceCurrentFrame(buffer.PassAs<VideoFrame>()); - } - - // Refresh the Differ helper used by CaptureFrame(), if needed. - const VideoFrame* current_buffer = 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(), - CaptureData::kBytesPerPixel, - current_buffer->bytes_per_row())); - } - - scoped_refptr<CaptureData> capture_data(CaptureScreen()); - - // Swap the current & previous buffers ready for the next capture. - last_invalid_region_ = capture_data->dirty_region(); - - queue_.DoneWithCurrentFrame(); - - capture_data->set_capture_time_ms( - (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp()); - delegate_->OnCaptureCompleted(capture_data); -} - -void VideoFrameCapturerLinux::ProcessPendingXEvents() { - // Find the number of events that are outstanding "now." We don't just loop - // on XPending because we want to guarantee this terminates. - int events_to_process = XPending(display_); - XEvent e; - - for (int i = 0; i < events_to_process; i++) { - XNextEvent(display_, &e); - if (use_damage_ && (e.type == damage_event_base_ + XDamageNotify)) { - XDamageNotifyEvent* event = reinterpret_cast<XDamageNotifyEvent*>(&e); - DCHECK(event->level == XDamageReportNonEmpty); - } else if (e.type == ConfigureNotify) { - const XConfigureEvent& event = e.xconfigure; - ScreenConfigurationChanged(SkISize::Make(event.width, event.height)); - } else if (has_xfixes_ && - e.type == xfixes_event_base_ + XFixesCursorNotify) { - XFixesCursorNotifyEvent* cne; - cne = reinterpret_cast<XFixesCursorNotifyEvent*>(&e); - if (cne->subtype == XFixesDisplayCursorNotify) { - CaptureCursor(); - } - } else { - LOG(WARNING) << "Got unknown event type: " << e.type; - } - } -} - -void VideoFrameCapturerLinux::CaptureCursor() { - DCHECK(has_xfixes_); - - XFixesCursorImage* img = XFixesGetCursorImage(display_); - if (!img) { - return; - } - - scoped_ptr<MouseCursorShape> cursor(new MouseCursorShape()); - cursor->size.set(img->width, img->height); - cursor->hotspot.set(img->xhot, img->yhot); - - int total_bytes = cursor->size.width() * cursor->size.height() * - CaptureData::kBytesPerPixel; - cursor->data.resize(total_bytes); - - // Xlib stores 32-bit data in longs, even if longs are 64-bits long. - unsigned long* src = img->pixels; - uint32* dst = reinterpret_cast<uint32*>(string_as_array(&cursor->data)); - uint32* dst_end = dst + (img->width * img->height); - while (dst < dst_end) { - *dst++ = static_cast<uint32>(*src++); - } - XFree(img); - - delegate_->OnCursorShapeChanged(cursor.Pass()); -} - -scoped_refptr<CaptureData> VideoFrameCapturerLinux::CaptureScreen() { - VideoFrame* frame = queue_.current_frame(); - scoped_refptr<CaptureData> capture_data(new CaptureData( - frame->pixels(), frame->bytes_per_row(), frame->dimensions())); - - // 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()); - - // 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 - // change occurred, and |invalid_rects| will be updated to include the whole - // screen. - if (use_damage_ && queue_.previous_frame()) - SynchronizeFrame(); - - SkRegion invalid_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; - 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); - } - XFree(rects); - helper_.InvalidateRegion(invalid_region); - - // Capture the damaged portions of the desktop. - helper_.SwapInvalidRegion(&invalid_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); - } - } 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); - - 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); - } 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); - } - } - - capture_data->mutable_dirty_region() = invalid_region; - return capture_data; -} - -void VideoFrameCapturerLinux::ScreenConfigurationChanged( - const SkISize& root_window_size) { - root_window_size_ = root_window_size; - - // Make sure the frame buffers will be reallocated. - queue_.SetAllFramesNeedUpdate(); - - helper_.ClearInvalidRegion(); - x_server_pixel_buffer_.Init(display_, root_window_size_); -} - -void VideoFrameCapturerLinux::SynchronizeFrame() { - // Synchronize the current buffer with the previous one since we do not - // capture the entire desktop. Note that encoder may be reading from the - // previous buffer at this time so thread access complaints are false - // positives. - - // TODO(hclam): We can reduce the amount of copying here by subtracting - // |capturer_helper_|s region from |last_invalid_region_|. - // http://crbug.com/92354 - DCHECK(queue_.previous_frame()); - - VideoFrame* current = queue_.current_frame(); - VideoFrame* 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 * CaptureData::kBytesPerPixel; - for (int i = 0; i < r.height(); ++i) { - memcpy(current->pixels() + offset, last->pixels() + offset, - r.width() * CaptureData::kBytesPerPixel); - offset += current->dimensions().width() * CaptureData::kBytesPerPixel; - } - } -} - -void VideoFrameCapturerLinux::DeinitXlib() { - if (gc_) { - XFreeGC(display_, gc_); - gc_ = NULL; - } - - x_server_pixel_buffer_.Release(); - - if (display_) { - if (damage_handle_) - XDamageDestroy(display_, damage_handle_); - if (damage_region_) - XFixesDestroyRegion(display_, damage_region_); - XCloseDisplay(display_); - display_ = NULL; - damage_handle_ = 0; - damage_region_ = 0; - } -} - -void VideoFrameCapturerLinux::CaptureRect(const SkIRect& rect, - CaptureData* capture_data) { - uint8* image = x_server_pixel_buffer_.CaptureRect(rect); - int depth = x_server_pixel_buffer_.GetDepth(); - int bpp = x_server_pixel_buffer_.GetBitsPerPixel(); - bool is_rgb = x_server_pixel_buffer_.IsRgb(); - if ((depth == 24 || depth == 32) && bpp == 32 && is_rgb) { - DVLOG(3) << "Fast blitting"; - FastBlit(image, rect, capture_data); - } else { - DVLOG(3) << "Slow blitting"; - SlowBlit(image, rect, capture_data); - } -} - -void VideoFrameCapturerLinux::FastBlit(uint8* image, const SkIRect& rect, - CaptureData* capture_data) { - uint8* src_pos = image; - int src_stride = x_server_pixel_buffer_.GetStride(); - int dst_x = rect.fLeft, dst_y = rect.fTop; - - uint8* dst_pos = capture_data->data() + capture_data->stride() * dst_y; - dst_pos += dst_x * CaptureData::kBytesPerPixel; - - int height = rect.height(); - int row_bytes = rect.width() * CaptureData::kBytesPerPixel; - for (int y = 0; y < height; ++y) { - memcpy(dst_pos, src_pos, row_bytes); - src_pos += src_stride; - dst_pos += capture_data->stride(); - } -} - -void VideoFrameCapturerLinux::SlowBlit(uint8* image, const SkIRect& rect, - CaptureData* capture_data) { - int src_stride = x_server_pixel_buffer_.GetStride(); - int dst_x = rect.fLeft, dst_y = rect.fTop; - int width = rect.width(), height = rect.height(); - - unsigned int red_mask = x_server_pixel_buffer_.GetRedMask(); - unsigned int blue_mask = x_server_pixel_buffer_.GetBlueMask(); - unsigned int green_mask = x_server_pixel_buffer_.GetGreenMask(); - unsigned int red_shift = x_server_pixel_buffer_.GetRedShift(); - unsigned int blue_shift = x_server_pixel_buffer_.GetBlueShift(); - unsigned int green_shift = x_server_pixel_buffer_.GetGreenShift(); - - unsigned int max_red = red_mask >> red_shift; - unsigned int max_blue = blue_mask >> blue_shift; - unsigned int max_green = green_mask >> green_shift; - - unsigned int bits_per_pixel = x_server_pixel_buffer_.GetBitsPerPixel(); - - uint8* dst_pos = capture_data->data() + capture_data->stride() * dst_y; - uint8* src_pos = image; - dst_pos += dst_x * CaptureData::kBytesPerPixel; - // TODO(hclam): Optimize, perhaps using MMX code or by converting to - // YUV directly - for (int y = 0; y < height; y++) { - uint32_t* dst_pos_32 = reinterpret_cast<uint32_t*>(dst_pos); - uint32_t* src_pos_32 = reinterpret_cast<uint32_t*>(src_pos); - uint16_t* src_pos_16 = reinterpret_cast<uint16_t*>(src_pos); - for (int x = 0; x < width; x++) { - // Dereference through an appropriately-aligned pointer. - uint32_t pixel; - if (bits_per_pixel == 32) - pixel = src_pos_32[x]; - else if (bits_per_pixel == 16) - pixel = src_pos_16[x]; - else - pixel = src_pos[x]; - uint32_t r = (((pixel & red_mask) >> red_shift) * 255) / max_red; - uint32_t b = (((pixel & blue_mask) >> blue_shift) * 255) / max_blue; - uint32_t g = (((pixel & green_mask) >> green_shift) * 255) / max_green; - // Write as 32-bit RGB. - dst_pos_32[x] = r << 16 | g << 8 | b; - } - dst_pos += capture_data->stride(); - src_pos += src_stride; - } -} - -} // namespace - -// static -scoped_ptr<VideoFrameCapturer> VideoFrameCapturer::Create() { - scoped_ptr<VideoFrameCapturerLinux> capturer(new VideoFrameCapturerLinux()); - if (!capturer->Init()) - capturer.reset(); - return capturer.PassAs<VideoFrameCapturer>(); -} - -// static -scoped_ptr<VideoFrameCapturer> VideoFrameCapturer::CreateWithFactory( - SharedBufferFactory* shared_buffer_factory) { - NOTIMPLEMENTED(); - return scoped_ptr<VideoFrameCapturer>(); -} - -// static -void VideoFrameCapturer::EnableXDamage(bool enable) { - g_should_use_x_damage = enable; -} - -} // namespace remoting diff --git a/remoting/capturer/video_frame_capturer_mac.mm b/remoting/capturer/video_frame_capturer_mac.mm deleted file mode 100644 index d77dd15..0000000 --- a/remoting/capturer/video_frame_capturer_mac.mm +++ /dev/null @@ -1,869 +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 "remoting/capturer/video_frame_capturer.h" - -#include <ApplicationServices/ApplicationServices.h> -#include <Cocoa/Cocoa.h> -#include <dlfcn.h> -#include <IOKit/pwr_mgt/IOPMLib.h> -#include <OpenGL/CGLMacro.h> -#include <OpenGL/OpenGL.h> -#include <set> -#include <stddef.h> - -#include "base/logging.h" -#include "base/file_path.h" -#include "base/mac/mac_util.h" -#include "base/mac/scoped_cftyperef.h" -#include "base/memory/scoped_ptr.h" -#include "base/scoped_native_library.h" -#include "base/synchronization/waitable_event.h" -#include "base/time.h" -#include "remoting/capturer/capture_data.h" -#include "remoting/capturer/mac/desktop_configuration.h" -#include "remoting/capturer/mac/scoped_pixel_buffer_object.h" -#include "remoting/capturer/mouse_cursor_shape.h" -#include "remoting/capturer/video_frame.h" -#include "remoting/capturer/video_frame_capturer_helper.h" -#include "remoting/capturer/video_frame_queue.h" -#include "skia/ext/skia_utils_mac.h" - -namespace remoting { - -namespace { - -// Definitions used to dynamic-link to deprecated OS 10.6 functions. -const char* kApplicationServicesLibraryName = - "/System/Library/Frameworks/ApplicationServices.framework/" - "ApplicationServices"; -typedef void* (*CGDisplayBaseAddressFunc)(CGDirectDisplayID); -typedef size_t (*CGDisplayBytesPerRowFunc)(CGDirectDisplayID); -typedef size_t (*CGDisplayBitsPerPixelFunc)(CGDirectDisplayID); -const char* kOpenGlLibraryName = - "/System/Library/Frameworks/OpenGL.framework/OpenGL"; -typedef CGLError (*CGLSetFullScreenFunc)(CGLContextObj); - -// Standard DPI for Mac OS X displays with 1:1 backing scale. -const int kStandardDPI = 72; - -// 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; -} - -// Copy pixels in the |rect| from |src_place| to |dest_plane|. -void CopyRect(const uint8* src_plane, - int src_plane_stride, - uint8* dest_plane, - int dest_plane_stride, - int bytes_per_pixel, - const SkIRect& 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(); - const int x_offset = bytes_per_pixel * rect.left(); - src_plane += src_y_offset + x_offset; - dest_plane += dest_y_offset + x_offset; - - // Copy pixels in the rectangle line by line. - const int bytes_per_line = bytes_per_pixel * rect.width(); - const int height = rect.height(); - for (int i = 0 ; i < height; ++i) { - memcpy(dest_plane, src_plane, bytes_per_line); - src_plane += src_plane_stride; - dest_plane += dest_plane_stride; - } -} - -// The amount of time allowed for displays to reconfigure. -const int64 kDisplayConfigurationEventTimeoutInSeconds = 10; - -// A class representing a full-frame pixel buffer. -class VideoFrameMac : public VideoFrame { - public: - explicit VideoFrameMac(const MacDesktopConfiguration& desktop_config); - virtual ~VideoFrameMac(); - - const SkIPoint& dpi() const { return dpi_; } - - private: - // Allocated pixel buffer. - scoped_array<uint8> data_; - - // DPI settings for this buffer. - SkIPoint dpi_; - - DISALLOW_COPY_AND_ASSIGN(VideoFrameMac); -}; - -// A class to perform video frame capturing for mac. -class VideoFrameCapturerMac : public VideoFrameCapturer { - public: - VideoFrameCapturerMac(); - virtual ~VideoFrameCapturerMac(); - - bool Init(); - - // Overridden from VideoFrameCapturer: - virtual void Start(Delegate* delegate) OVERRIDE; - virtual void Stop() OVERRIDE; - virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE; - virtual void CaptureFrame() OVERRIDE; - - private: - void CaptureCursor(); - - void GlBlitFast(const VideoFrame& buffer, const SkRegion& region); - void GlBlitSlow(const VideoFrame& buffer); - void CgBlitPreLion(const VideoFrame& buffer, const SkRegion& region); - void CgBlitPostLion(const VideoFrame& buffer, const SkRegion& region); - - // Called when the screen configuration is changed. - void ScreenConfigurationChanged(); - - void ScreenRefresh(CGRectCount count, const CGRect *rect_array); - void ScreenUpdateMove(CGScreenUpdateMoveDelta delta, - size_t count, - const CGRect *rect_array); - void DisplaysReconfigured(CGDirectDisplayID display, - CGDisplayChangeSummaryFlags flags); - static void ScreenRefreshCallback(CGRectCount count, - const CGRect *rect_array, - void *user_parameter); - static void ScreenUpdateMoveCallback(CGScreenUpdateMoveDelta delta, - size_t count, - const CGRect *rect_array, - void *user_parameter); - static void DisplaysReconfiguredCallback(CGDirectDisplayID display, - CGDisplayChangeSummaryFlags flags, - void *user_parameter); - - void ReleaseBuffers(); - - Delegate* delegate_; - - CGLContextObj cgl_context_; - ScopedPixelBufferObject pixel_buffer_object_; - - // Queue of the frames buffers. - VideoFrameQueue queue_; - - // Current display configuration. - MacDesktopConfiguration desktop_config_; - - // A thread-safe list of invalid rectangles, and the size of the most - // recently captured screen. - VideoFrameCapturerHelper helper_; - - // Image of the last cursor that we sent to the client. - base::mac::ScopedCFTypeRef<CGImageRef> current_cursor_; - - // Contains an invalid region from the previous capture. - SkRegion last_invalid_region_; - - // Used to ensure that frame captures do not take place while displays - // are being reconfigured. - base::WaitableEvent display_configuration_capture_event_; - - // Records the Ids of attached displays which are being reconfigured. - // Accessed on the thread on which we are notified of display events. - std::set<CGDirectDisplayID> reconfiguring_displays_; - - // Power management assertion to prevent the screen from sleeping. - IOPMAssertionID power_assertion_id_display_; - - // Power management assertion to indicate that the user is active. - IOPMAssertionID power_assertion_id_user_; - - // Dynamically link to deprecated APIs for Mac OS X 10.6 support. - base::ScopedNativeLibrary app_services_library_; - CGDisplayBaseAddressFunc cg_display_base_address_; - CGDisplayBytesPerRowFunc cg_display_bytes_per_row_; - CGDisplayBitsPerPixelFunc cg_display_bits_per_pixel_; - base::ScopedNativeLibrary opengl_library_; - CGLSetFullScreenFunc cgl_set_full_screen_; - - DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerMac); -}; - -VideoFrameMac::VideoFrameMac(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); -} - -VideoFrameMac::~VideoFrameMac() { -} - -VideoFrameCapturerMac::VideoFrameCapturerMac() - : delegate_(NULL), - cgl_context_(NULL), - display_configuration_capture_event_(false, true), - power_assertion_id_display_(kIOPMNullAssertionID), - power_assertion_id_user_(kIOPMNullAssertionID), - cg_display_base_address_(NULL), - cg_display_bytes_per_row_(NULL), - cg_display_bits_per_pixel_(NULL), - cgl_set_full_screen_(NULL) -{ -} - -VideoFrameCapturerMac::~VideoFrameCapturerMac() { - ReleaseBuffers(); - CGUnregisterScreenRefreshCallback( - VideoFrameCapturerMac::ScreenRefreshCallback, this); - CGScreenUnregisterMoveCallback( - VideoFrameCapturerMac::ScreenUpdateMoveCallback, this); - CGError err = CGDisplayRemoveReconfigurationCallback( - VideoFrameCapturerMac::DisplaysReconfiguredCallback, this); - if (err != kCGErrorSuccess) { - LOG(ERROR) << "CGDisplayRemoveReconfigurationCallback " << err; - } -} - -bool VideoFrameCapturerMac::Init() { - CGError err = CGRegisterScreenRefreshCallback( - VideoFrameCapturerMac::ScreenRefreshCallback, this); - if (err != kCGErrorSuccess) { - LOG(ERROR) << "CGRegisterScreenRefreshCallback " << err; - return false; - } - - err = CGScreenRegisterMoveCallback( - VideoFrameCapturerMac::ScreenUpdateMoveCallback, this); - if (err != kCGErrorSuccess) { - LOG(ERROR) << "CGScreenRegisterMoveCallback " << err; - return false; - } - err = CGDisplayRegisterReconfigurationCallback( - VideoFrameCapturerMac::DisplaysReconfiguredCallback, this); - if (err != kCGErrorSuccess) { - LOG(ERROR) << "CGDisplayRegisterReconfigurationCallback " << err; - return false; - } - - ScreenConfigurationChanged(); - return true; -} - -void VideoFrameCapturerMac::ReleaseBuffers() { - if (cgl_context_) { - pixel_buffer_object_.Release(); - CGLDestroyContext(cgl_context_); - cgl_context_ = NULL; - } - // 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(); -} - -void VideoFrameCapturerMac::Start(Delegate* delegate) { - DCHECK(delegate_ == NULL); - - delegate_ = delegate; - - // Create power management assertions to wake the display and prevent it from - // going to sleep on user idle. - // TODO(jamiewalch): Use IOPMAssertionDeclareUserActivity on 10.7.3 and above - // instead of the following two assertions. - IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, - kIOPMAssertionLevelOn, - CFSTR("Chrome Remote Desktop connection active"), - &power_assertion_id_display_); - // This assertion ensures that the display is woken up if it already asleep - // (as used by Apple Remote Desktop). - IOPMAssertionCreateWithName(CFSTR("UserIsActive"), - kIOPMAssertionLevelOn, - CFSTR("Chrome Remote Desktop connection active"), - &power_assertion_id_user_); -} - -void VideoFrameCapturerMac::Stop() { - if (power_assertion_id_display_ != kIOPMNullAssertionID) { - IOPMAssertionRelease(power_assertion_id_display_); - power_assertion_id_display_ = kIOPMNullAssertionID; - } - if (power_assertion_id_user_ != kIOPMNullAssertionID) { - IOPMAssertionRelease(power_assertion_id_user_); - power_assertion_id_user_ = kIOPMNullAssertionID; - } -} - -void VideoFrameCapturerMac::InvalidateRegion(const SkRegion& invalid_region) { - helper_.InvalidateRegion(invalid_region); -} - -void VideoFrameCapturerMac::CaptureFrame() { - // Only allow captures when the display configuration is not occurring. - scoped_refptr<CaptureData> data; - - base::Time capture_start_time = base::Time::Now(); - - // 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. - // TODO(wez): Replace this with an early-exit (See crbug.com/104542). - CHECK(display_configuration_capture_event_.TimedWait( - base::TimeDelta::FromSeconds( - kDisplayConfigurationEventTimeoutInSeconds))); - - SkRegion region; - helper_.SwapInvalidRegion(®ion); - - // If the current buffer is from an older generation then allocate a new one. - // Note that we can't reallocate other buffers at this point, since the caller - // may still be reading from them. - if (queue_.current_frame_needs_update()) { - scoped_ptr<VideoFrameMac> buffer(new VideoFrameMac(desktop_config_)); - queue_.ReplaceCurrentFrame(buffer.PassAs<VideoFrame>()); - } - - VideoFrame* current_buffer = 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); - } else if (cgl_context_) { - flip = true; - if (pixel_buffer_object_.get() != 0) { - GlBlitFast(*current_buffer, region); - } else { - // See comment in ScopedPixelBufferObject::Init about why the slow - // path is always used on 10.5. - GlBlitSlow(*current_buffer); - } - } else { - CgBlitPreLion(*current_buffer, region); - } - - uint8* buffer = current_buffer->pixels(); - int stride = current_buffer->bytes_per_row(); - if (flip) { - stride = -stride; - buffer += (current_buffer->dimensions().height() - 1) * - current_buffer->bytes_per_row(); - } - - data = new CaptureData(buffer, stride, current_buffer->dimensions()); - data->set_dpi(static_cast<VideoFrameMac*>(current_buffer)->dpi()); - data->mutable_dirty_region() = region; - - helper_.set_size_most_recent(data->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. - CaptureCursor(); - - // Move the capture frame buffer queue on to the next buffer. - queue_.DoneWithCurrentFrame(); - - data->set_capture_time_ms( - (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp()); - delegate_->OnCaptureCompleted(data); -} - -void VideoFrameCapturerMac::CaptureCursor() { - NSCursor* cursor = [NSCursor currentSystemCursor]; - if (cursor == nil) { - return; - } - - NSImage* nsimage = [cursor image]; - NSPoint hotspot = [cursor hotSpot]; - NSSize size = [nsimage size]; - CGImageRef image = [nsimage CGImageForProposedRect:NULL - context:nil - hints:nil]; - if (image == nil) { - return; - } - - if (CGImageGetBitsPerPixel(image) != 32 || - CGImageGetBytesPerRow(image) != (size.width * 4) || - CGImageGetBitsPerComponent(image) != 8) { - return; - } - - // Compare the current cursor with the last one we sent to the client - // and exit if the cursor is the same. - if (current_cursor_.get() != NULL) { - CGImageRef current = current_cursor_.get(); - if (CGImageGetWidth(image) == CGImageGetWidth(current) && - CGImageGetHeight(image) == CGImageGetHeight(current) && - CGImageGetBitsPerPixel(image) == CGImageGetBitsPerPixel(current) && - CGImageGetBytesPerRow(image) == CGImageGetBytesPerRow(current) && - CGImageGetBitsPerComponent(image) == - CGImageGetBitsPerComponent(current)) { - CGDataProviderRef provider_new = CGImageGetDataProvider(image); - base::mac::ScopedCFTypeRef<CFDataRef> data_ref_new( - CGDataProviderCopyData(provider_new)); - CGDataProviderRef provider_current = CGImageGetDataProvider(current); - base::mac::ScopedCFTypeRef<CFDataRef> data_ref_current( - CGDataProviderCopyData(provider_current)); - - if (data_ref_new.get() != NULL && data_ref_current.get() != NULL) { - int data_size = CFDataGetLength(data_ref_new); - CHECK(data_size == CFDataGetLength(data_ref_current)); - const uint8* data_new = CFDataGetBytePtr(data_ref_new); - const uint8* data_current = CFDataGetBytePtr(data_ref_current); - if (memcmp(data_new, data_current, data_size) == 0) { - return; - } - } - } - } - - // Record the last cursor image. - current_cursor_.reset(CGImageCreateCopy(image)); - - VLOG(3) << "Sending cursor: " << size.width << "x" << size.height; - - CGDataProviderRef provider = CGImageGetDataProvider(image); - base::mac::ScopedCFTypeRef<CFDataRef> image_data_ref( - CGDataProviderCopyData(provider)); - if (image_data_ref.get() == NULL) { - return; - } - const char* cursor_src_data = - reinterpret_cast<const char*>(CFDataGetBytePtr(image_data_ref)); - int data_size = CFDataGetLength(image_data_ref); - - // Create a MouseCursorShape that describes the cursor and pass it to - // the client. - scoped_ptr<MouseCursorShape> cursor_shape(new MouseCursorShape()); - cursor_shape->size.set(size.width, size.height); - 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()); -} - -void VideoFrameCapturerMac::GlBlitFast(const VideoFrame& buffer, - const SkRegion& region) { - const int buffer_height = buffer.dimensions().height(); - const int buffer_width = buffer.dimensions().width(); - - // Clip to the size of our current screen. - SkIRect clip_rect = SkIRect::MakeWH(buffer_width, buffer_height); - 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. - // TODO(hclam): We can reduce the amount of copying here by subtracting - // |capturer_helper_|s region from |last_invalid_region_|. - // http://crbug.com/92354 - - // 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. - copy_rect); - } - } - } - last_invalid_region_ = region; - - 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); - GLubyte* ptr = static_cast<GLubyte*>( - glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB)); - if (ptr == NULL) { - // If the buffer can't be mapped, assume that it's no longer valid and - // release it. - pixel_buffer_object_.Release(); - } 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)) { - CopyRect(ptr + y_offset, - -buffer.bytes_per_row(), - buffer.pixels() + y_offset, - -buffer.bytes_per_row(), - 4, // Bytes for pixel for RGBA. - copy_rect); - } - } - } - if (!glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB)) { - // If glUnmapBuffer returns false, then the contents of the data store are - // undefined. This might be because the screen mode has changed, in which - // case it will be recreated in ScreenConfigurationChanged, but releasing - // the object here is the best option. Capturing will fall back on - // GlBlitSlow until such time as the pixel buffer object is recreated. - pixel_buffer_object_.Release(); - } - glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); -} - -void VideoFrameCapturerMac::GlBlitSlow(const VideoFrame& buffer) { - CGLContextObj CGL_MACRO_CONTEXT = cgl_context_; - glReadBuffer(GL_FRONT); - glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); - glPixelStorei(GL_PACK_ALIGNMENT, 4); // Force 4-byte alignment. - glPixelStorei(GL_PACK_ROW_LENGTH, 0); - 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()); - glPopClientAttrib(); -} - -void VideoFrameCapturerMac::CgBlitPreLion(const VideoFrame& buffer, - const SkRegion& region) { - const int buffer_height = buffer.dimensions().height(); - - // 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); - } - - for (size_t i = 0; i < desktop_config_.displays.size(); ++i) { - const MacDisplayConfiguration& display_config = desktop_config_.displays[i]; - - // Use deprecated APIs to determine the display buffer layout. - DCHECK(cg_display_base_address_ && cg_display_bytes_per_row_ && - cg_display_bits_per_pixel_); - uint8* display_base_address = - reinterpret_cast<uint8*>((*cg_display_base_address_)(display_config.id)); - CHECK(display_base_address); - int src_bytes_per_row = (*cg_display_bytes_per_row_)(display_config.id); - int src_bytes_per_pixel = - (*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()); - - // 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)) - continue; - - // Translate the region to be copied into display-relative coordinates. - copy_region.translate(-desktop_config_.pixel_bounds.left(), - -desktop_config_.pixel_bounds.top()); - - // Calculate where in the output buffer the display's origin is. - uint8* out_ptr = buffer.pixels() + - (display_bounds.left() * src_bytes_per_pixel) + - (display_bounds.top() * buffer.bytes_per_row()); - - // Copy the dirty region from the display buffer into our desktop buffer. - for(SkRegion::Iterator i(copy_region); !i.done(); i.next()) { - CopyRect(display_base_address, - src_bytes_per_row, - out_ptr, - buffer.bytes_per_row(), - src_bytes_per_pixel, - i.rect()); - } - } -} - -void VideoFrameCapturerMac::CgBlitPostLion(const VideoFrame& buffer, - const SkRegion& region) { - const int buffer_height = buffer.dimensions().height(); - - // 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); - } - - 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()); - - // 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)) - continue; - - // Translate the region to be copied into display-relative coordinates. - copy_region.translate(-desktop_config_.pixel_bounds.left(), - -desktop_config_.pixel_bounds.top()); - - // Create an image containing a snapshot of the display. - base::mac::ScopedCFTypeRef<CGImageRef> image( - CGDisplayCreateImage(display_config.id)); - if (image.get() == NULL) - continue; - - // Request access to the raw pixel data via the image's DataProvider. - CGDataProviderRef provider = CGImageGetDataProvider(image); - base::mac::ScopedCFTypeRef<CFDataRef> data( - CGDataProviderCopyData(provider)); - if (data.get() == NULL) - continue; - - const uint8* display_base_address = CFDataGetBytePtr(data); - int src_bytes_per_row = CGImageGetBytesPerRow(image); - int src_bytes_per_pixel = CGImageGetBitsPerPixel(image) / 8; - - // Calculate where in the output buffer the display's origin is. - uint8* out_ptr = buffer.pixels() + - (display_bounds.left() * src_bytes_per_pixel) + - (display_bounds.top() * buffer.bytes_per_row()); - - // Copy the dirty region from the display buffer into our desktop buffer. - for(SkRegion::Iterator i(copy_region); !i.done(); i.next()) { - CopyRect(display_base_address, - src_bytes_per_row, - out_ptr, - buffer.bytes_per_row(), - src_bytes_per_pixel, - i.rect()); - } - } -} - -void VideoFrameCapturerMac::ScreenConfigurationChanged() { - // Release existing buffers, which will be of the wrong size. - ReleaseBuffers(); - - // Clear the dirty region, in case the display is down-sizing. - helper_.ClearInvalidRegion(); - - // Refresh the cached desktop configuration. - desktop_config_ = MacDesktopConfiguration::GetCurrent(); - - // Re-mark the entire desktop as dirty. - helper_.InvalidateScreen( - SkISize::Make(desktop_config_.pixel_bounds.width(), - desktop_config_.pixel_bounds.height())); - - // Make sure the frame buffers will be reallocated. - queue_.SetAllFramesNeedUpdate(); - - // CgBlitPostLion uses CGDisplayCreateImage() to snapshot each display's - // contents. Although the API exists in OS 10.6, it crashes the caller if - // the machine has no monitor connected, so we fall back to depcreated APIs - // when running on 10.6. - if (base::mac::IsOSLionOrLater()) { - LOG(INFO) << "Using CgBlitPostLion."; - // No need for any OpenGL support on Lion - return; - } - - // Dynamically link to the deprecated pre-Lion capture APIs. - std::string app_services_library_error; - FilePath app_services_path(kApplicationServicesLibraryName); - app_services_library_.Reset( - base::LoadNativeLibrary(app_services_path, &app_services_library_error)); - CHECK(app_services_library_.is_valid()) << app_services_library_error; - - std::string opengl_library_error; - FilePath opengl_path(kOpenGlLibraryName); - opengl_library_.Reset( - base::LoadNativeLibrary(opengl_path, &opengl_library_error)); - CHECK(opengl_library_.is_valid()) << opengl_library_error; - - cg_display_base_address_ = reinterpret_cast<CGDisplayBaseAddressFunc>( - app_services_library_.GetFunctionPointer("CGDisplayBaseAddress")); - cg_display_bytes_per_row_ = reinterpret_cast<CGDisplayBytesPerRowFunc>( - app_services_library_.GetFunctionPointer("CGDisplayBytesPerRow")); - cg_display_bits_per_pixel_ = reinterpret_cast<CGDisplayBitsPerPixelFunc>( - app_services_library_.GetFunctionPointer("CGDisplayBitsPerPixel")); - cgl_set_full_screen_ = reinterpret_cast<CGLSetFullScreenFunc>( - opengl_library_.GetFunctionPointer("CGLSetFullScreen")); - CHECK(cg_display_base_address_ && cg_display_bytes_per_row_ && - cg_display_bits_per_pixel_ && cgl_set_full_screen_); - - if (desktop_config_.displays.size() > 1) { - LOG(INFO) << "Using CgBlitPreLion (Multi-monitor)."; - return; - } - - CGDirectDisplayID mainDevice = CGMainDisplayID(); - if (!CGDisplayUsesOpenGLAcceleration(mainDevice)) { - LOG(INFO) << "Using CgBlitPreLion (OpenGL unavailable)."; - return; - } - - LOG(INFO) << "Using GlBlit"; - - CGLPixelFormatAttribute attributes[] = { - kCGLPFAFullScreen, - kCGLPFADisplayMask, - (CGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(mainDevice), - (CGLPixelFormatAttribute)0 - }; - CGLPixelFormatObj pixel_format = NULL; - GLint matching_pixel_format_count = 0; - CGLError err = CGLChoosePixelFormat(attributes, - &pixel_format, - &matching_pixel_format_count); - DCHECK_EQ(err, kCGLNoError); - err = CGLCreateContext(pixel_format, NULL, &cgl_context_); - DCHECK_EQ(err, kCGLNoError); - CGLDestroyPixelFormat(pixel_format); - (*cgl_set_full_screen_)(cgl_context_); - CGLSetCurrentContext(cgl_context_); - - size_t buffer_size = desktop_config_.pixel_bounds.width() * - desktop_config_.pixel_bounds.height() * - sizeof(uint32_t); - pixel_buffer_object_.Init(cgl_context_, buffer_size); -} - -void VideoFrameCapturerMac::ScreenRefresh(CGRectCount count, - const CGRect* rect_array) { - if (desktop_config_.pixel_bounds.isEmpty()) { - return; - } - SkIRect skirect_array[count]; - - for (CGRectCount i = 0; i < count; ++i) { - SkRect sk_rect = gfx::CGRectToSkRect(rect_array[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]); - - // Translate from local desktop to capturer framebuffer coordinates. - skirect_array[i].offset(-desktop_config_.pixel_bounds.left(), - -desktop_config_.pixel_bounds.top()); - } - - SkRegion region; - region.setRects(skirect_array, count); - InvalidateRegion(region); -} - -void VideoFrameCapturerMac::ScreenUpdateMove(CGScreenUpdateMoveDelta delta, - size_t count, - const CGRect* rect_array) { - // Translate |rect_array| to identify the move's destination. - CGRect refresh_rects[count]; - for (CGRectCount i = 0; i < count; ++i) { - refresh_rects[i] = CGRectOffset(rect_array[i], delta.dX, delta.dY); - } - - // Currently we just treat move events the same as refreshes. - ScreenRefresh(count, refresh_rects); -} - -void VideoFrameCapturerMac::DisplaysReconfigured( - CGDirectDisplayID display, - CGDisplayChangeSummaryFlags flags) { - if (flags & kCGDisplayBeginConfigurationFlag) { - if (reconfiguring_displays_.empty()) { - // If this is the first display to start reconfiguring then wait on - // |display_configuration_capture_event_| to block the capture thread - // from accessing display memory until the reconfiguration completes. - CHECK(display_configuration_capture_event_.TimedWait( - base::TimeDelta::FromSeconds( - kDisplayConfigurationEventTimeoutInSeconds))); - } - - reconfiguring_displays_.insert(display); - } else { - reconfiguring_displays_.erase(display); - - if (reconfiguring_displays_.empty()) { - // If no other displays are reconfiguring then refresh capturer data - // structures and un-block the capturer thread. - ScreenConfigurationChanged(); - display_configuration_capture_event_.Signal(); - } - } -} - -void VideoFrameCapturerMac::ScreenRefreshCallback(CGRectCount count, - const CGRect* rect_array, - void* user_parameter) { - VideoFrameCapturerMac* capturer = reinterpret_cast<VideoFrameCapturerMac*>( - user_parameter); - if (capturer->desktop_config_.pixel_bounds.isEmpty()) { - capturer->ScreenConfigurationChanged(); - } - capturer->ScreenRefresh(count, rect_array); -} - -void VideoFrameCapturerMac::ScreenUpdateMoveCallback( - CGScreenUpdateMoveDelta delta, - size_t count, - const CGRect* rect_array, - void* user_parameter) { - VideoFrameCapturerMac* capturer = reinterpret_cast<VideoFrameCapturerMac*>( - user_parameter); - capturer->ScreenUpdateMove(delta, count, rect_array); -} - -void VideoFrameCapturerMac::DisplaysReconfiguredCallback( - CGDirectDisplayID display, - CGDisplayChangeSummaryFlags flags, - void* user_parameter) { - VideoFrameCapturerMac* capturer = reinterpret_cast<VideoFrameCapturerMac*>( - user_parameter); - capturer->DisplaysReconfigured(display, flags); -} - -} // namespace - -// static -scoped_ptr<VideoFrameCapturer> VideoFrameCapturer::Create() { - scoped_ptr<VideoFrameCapturerMac> capturer(new VideoFrameCapturerMac()); - if (!capturer->Init()) - capturer.reset(); - return capturer.PassAs<VideoFrameCapturer>(); -} - -// static -scoped_ptr<VideoFrameCapturer> VideoFrameCapturer::CreateWithFactory( - SharedBufferFactory* shared_buffer_factory) { - NOTIMPLEMENTED(); - return scoped_ptr<VideoFrameCapturer>(); -} - -} // namespace remoting diff --git a/remoting/capturer/video_frame_capturer_mac_unittest.cc b/remoting/capturer/video_frame_capturer_mac_unittest.cc deleted file mode 100644 index 12435b3..0000000 --- a/remoting/capturer/video_frame_capturer_mac_unittest.cc +++ /dev/null @@ -1,121 +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 "remoting/capturer/video_frame_capturer.h" - -#include <ApplicationServices/ApplicationServices.h> - -#include <ostream> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/memory/scoped_ptr.h" -#include "remoting/capturer/capture_data.h" -#include "remoting/capturer/video_capturer_mock_objects.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::_; -using ::testing::AnyNumber; - -namespace remoting { - -// Verify that the OS is at least Snow Leopard (10.6). -// Chromoting doesn't support 10.5 or earlier. -bool CheckSnowLeopard() { - long minorVersion, majorVersion; - Gestalt(gestaltSystemVersionMajor, &majorVersion); - Gestalt(gestaltSystemVersionMinor, &minorVersion); - return majorVersion == 10 && minorVersion > 5; -} - -class VideoFrameCapturerMacTest : public testing::Test { - public: - // Verifies that the whole screen is initially dirty. - void CaptureDoneCallback1(scoped_refptr<CaptureData> capture_data); - - // Verifies that a rectangle explicitly marked as dirty is propagated - // correctly. - void CaptureDoneCallback2(scoped_refptr<CaptureData> capture_data); - - protected: - virtual void SetUp() OVERRIDE { - capturer_ = VideoFrameCapturer::Create(); - } - - void AddDirtyRect() { - SkIRect rect = SkIRect::MakeXYWH(0, 0, 10, 10); - region_.op(rect, SkRegion::kUnion_Op); - } - - scoped_ptr<VideoFrameCapturer> capturer_; - MockVideoFrameCapturerDelegate delegate_; - SkRegion region_; -}; - -void VideoFrameCapturerMacTest::CaptureDoneCallback1( - scoped_refptr<CaptureData> capture_data) { - CGDirectDisplayID mainDevice = CGMainDisplayID(); - int width = CGDisplayPixelsWide(mainDevice); - int height = CGDisplayPixelsHigh(mainDevice); - SkRegion initial_region(SkIRect::MakeXYWH(0, 0, width, height)); - EXPECT_EQ(initial_region, capture_data->dirty_region()); -} - -void VideoFrameCapturerMacTest::CaptureDoneCallback2( - scoped_refptr<CaptureData> capture_data) { - CGDirectDisplayID mainDevice = CGMainDisplayID(); - int width = CGDisplayPixelsWide(mainDevice); - int height = CGDisplayPixelsHigh(mainDevice); - - EXPECT_EQ(region_, capture_data->dirty_region()); - EXPECT_EQ(width, capture_data->size().width()); - EXPECT_EQ(height, capture_data->size().height()); - EXPECT_TRUE(capture_data->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())); -} - -TEST_F(VideoFrameCapturerMacTest, Capture) { - if (!CheckSnowLeopard()) { - return; - } - - EXPECT_CALL(delegate_, OnCaptureCompleted(_)) - .Times(2) - .WillOnce(Invoke(this, &VideoFrameCapturerMacTest::CaptureDoneCallback1)) - .WillOnce(Invoke(this, &VideoFrameCapturerMacTest::CaptureDoneCallback2)); - EXPECT_CALL(delegate_, OnCursorShapeChangedPtr(_)) - .Times(AnyNumber()); - - SCOPED_TRACE(""); - capturer_->Start(&delegate_); - - // Check that we get an initial full-screen updated. - capturer_->CaptureFrame(); - - // Check that subsequent dirty rects are propagated correctly. - AddDirtyRect(); - capturer_->InvalidateRegion(region_); - capturer_->CaptureFrame(); - capturer_->Stop(); -} - -} // namespace remoting - -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/remoting/capturer/video_frame_capturer_unittest.cc b/remoting/capturer/video_frame_capturer_unittest.cc deleted file mode 100644 index 11f71f5..0000000 --- a/remoting/capturer/video_frame_capturer_unittest.cc +++ /dev/null @@ -1,106 +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 "remoting/capturer/video_frame_capturer.h" - -#include "base/bind.h" -#if defined(OS_MACOSX) -#include "base/mac/mac_util.h" -#endif // defined(OS_MACOSX) -#include "remoting/capturer/capture_data.h" -#include "remoting/capturer/shared_buffer_factory.h" -#include "remoting/capturer/video_capturer_mock_objects.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::_; -using ::testing::AnyNumber; - -namespace remoting { - -class MockSharedBufferFactory : public SharedBufferFactory { - public: - MockSharedBufferFactory() {} - virtual ~MockSharedBufferFactory() {} - - MOCK_METHOD1(CreateSharedBuffer, scoped_refptr<SharedBuffer>(uint32)); - MOCK_METHOD1(ReleaseSharedBuffer, void(scoped_refptr<SharedBuffer>)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockSharedBufferFactory); -}; - -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); -} - -class VideoFrameCapturerTest : public testing::Test { - public: - scoped_refptr<SharedBuffer> CreateSharedBuffer(uint32 size); - - protected: - scoped_ptr<VideoFrameCapturer> capturer_; - MockSharedBufferFactory shared_buffer_factory_; - MockVideoFrameCapturerDelegate delegate_; -}; - -scoped_refptr<SharedBuffer> VideoFrameCapturerTest::CreateSharedBuffer( - uint32 size) { - return scoped_refptr<SharedBuffer>(new SharedBuffer(size)); -} - -TEST_F(VideoFrameCapturerTest, StartCapturer) { - capturer_ = VideoFrameCapturer::Create(); - capturer_->Start(&delegate_); - capturer_->Stop(); -} - -#if defined(THREAD_SANITIZER) -// ThreadSanitizer v2 reports a use-after-free, see http://crbug.com/163641. -#define MAYBE_Capture DISABLED_Capture -#else -#define MAYBE_Capture Capture -#endif -TEST_F(VideoFrameCapturerTest, MAYBE_Capture) { - // Assume that Start() treats the screen as invalid initially. - EXPECT_CALL(delegate_, - OnCaptureCompleted(DirtyRegionIsNonEmptyRect())); - EXPECT_CALL(delegate_, OnCursorShapeChangedPtr(_)) - .Times(AnyNumber()); - - capturer_ = VideoFrameCapturer::Create(); - capturer_->Start(&delegate_); - capturer_->CaptureFrame(); - capturer_->Stop(); -} - -#if defined(OS_WIN) - -TEST_F(VideoFrameCapturerTest, UseSharedBuffers) { - EXPECT_CALL(delegate_, - OnCaptureCompleted(DirtyRegionIsNonEmptyRect())); - EXPECT_CALL(delegate_, OnCursorShapeChangedPtr(_)) - .Times(AnyNumber()); - - EXPECT_CALL(shared_buffer_factory_, CreateSharedBuffer(_)) - .Times(1) - .WillOnce(Invoke(this, &VideoFrameCapturerTest::CreateSharedBuffer)); - EXPECT_CALL(shared_buffer_factory_, ReleaseSharedBuffer(_)) - .Times(1); - - capturer_ = VideoFrameCapturer::CreateWithFactory(&shared_buffer_factory_); - capturer_->Start(&delegate_); - capturer_->CaptureFrame(); - capturer_->Stop(); - capturer_.reset(); -} - -#endif // defined(OS_WIN) - -} // namespace remoting diff --git a/remoting/capturer/video_frame_capturer_win.cc b/remoting/capturer/video_frame_capturer_win.cc deleted file mode 100644 index 59e978c..0000000 --- a/remoting/capturer/video_frame_capturer_win.cc +++ /dev/null @@ -1,598 +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 "remoting/capturer/video_frame_capturer.h" - -#include <windows.h> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/file_path.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/scoped_native_library.h" -#include "base/stl_util.h" -#include "base/time.h" -#include "base/utf_string_conversions.h" -#include "base/win/scoped_gdi_object.h" -#include "base/win/scoped_hdc.h" -#include "remoting/capturer/capture_data.h" -#include "remoting/capturer/differ.h" -#include "remoting/capturer/mouse_cursor_shape.h" -#include "remoting/capturer/shared_buffer_factory.h" -#include "remoting/capturer/video_frame.h" -#include "remoting/capturer/video_frame_capturer_helper.h" -#include "remoting/capturer/video_frame_queue.h" -#include "remoting/capturer/win/desktop.h" -#include "remoting/capturer/win/scoped_thread_desktop.h" -#include "third_party/skia/include/core/SkColorPriv.h" - -namespace remoting { - -namespace { - -// Constants from dwmapi.h. -const UINT DWM_EC_DISABLECOMPOSITION = 0; -const UINT DWM_EC_ENABLECOMPOSITION = 1; - -typedef HRESULT (WINAPI * DwmEnableCompositionFunc)(UINT); - -const char kDwmapiLibraryName[] = "dwmapi"; - -// Pixel colors used when generating cursor outlines. -const uint32 kPixelBgraBlack = 0xff000000; -const uint32 kPixelBgraWhite = 0xffffffff; -const uint32 kPixelBgraTransparent = 0x00000000; - -// A class representing a full-frame pixel buffer. -class VideoFrameWin : public VideoFrame { - public: - VideoFrameWin(HDC desktop_dc, const SkISize& size, - SharedBufferFactory* shared_buffer_factory); - virtual ~VideoFrameWin(); - - // 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 allocate shared memory buffers if set. - SharedBufferFactory* shared_buffer_factory_; - - DISALLOW_COPY_AND_ASSIGN(VideoFrameWin); -}; - -// VideoFrameCapturerWin captures 32bit RGB using GDI. -// -// VideoFrameCapturerWin is double-buffered as required by VideoFrameCapturer. -// See remoting/host/video_frame_capturer.h. -class VideoFrameCapturerWin : public VideoFrameCapturer { - public: - VideoFrameCapturerWin(); - explicit VideoFrameCapturerWin(SharedBufferFactory* shared_buffer_factory); - virtual ~VideoFrameCapturerWin(); - - // Overridden from VideoFrameCapturer: - virtual void Start(Delegate* delegate) OVERRIDE; - virtual void Stop() OVERRIDE; - virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE; - virtual void CaptureFrame() OVERRIDE; - - private: - // Make sure that the device contexts match the screen configuration. - void PrepareCaptureResources(); - - // Creates a CaptureData 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(); - - // Expand the cursor shape to add a white outline for visibility against - // dark backgrounds. - void AddCursorOutline(int width, int height, uint32* dst); - - // Capture the current cursor shape. - void CaptureCursor(); - - // Used to allocate shared memory buffers if set. - SharedBufferFactory* shared_buffer_factory_; - - Delegate* delegate_; - - // A thread-safe list of invalid rectangles, and the size of the most - // recently captured screen. - VideoFrameCapturerHelper helper_; - - // Snapshot of the last cursor bitmap we sent to the client. This is used - // to diff against the current cursor so we only send a cursor-change - // message when the shape has changed. - MouseCursorShape last_cursor_; - - ScopedThreadDesktop desktop_; - - // GDI resources used for screen capture. - scoped_ptr<base::win::ScopedGetDC> desktop_dc_; - base::win::ScopedCreateDC memory_dc_; - - // Queue of the frames buffers. - VideoFrameQueue queue_; - - // Rectangle describing the bounds of the desktop device context. - SkIRect desktop_dc_rect_; - - // Class to calculate the difference between two screen bitmaps. - scoped_ptr<Differ> differ_; - - base::ScopedNativeLibrary dwmapi_library_; - DwmEnableCompositionFunc composition_func_; - - DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerWin); -}; - -// 3780 pixels per meter is equivalent to 96 DPI, typical on desktop monitors. -static const int kPixelsPerMeter = 3780; - -VideoFrameWin::VideoFrameWin( - HDC desktop_dc, - const SkISize& size, - SharedBufferFactory* shared_buffer_factory) - : shared_buffer_factory_(shared_buffer_factory) { - // Allocate a shared memory buffer. - uint32 buffer_size = - size.width() * size.height() * CaptureData::kBytesPerPixel; - if (shared_buffer_factory_) { - scoped_refptr<SharedBuffer> shared_buffer = - shared_buffer_factory_->CreateSharedBuffer(buffer_size); - CHECK(shared_buffer->ptr() != NULL); - set_shared_buffer(shared_buffer); - } - - AllocateBitmap(desktop_dc, size); -} - -VideoFrameWin::~VideoFrameWin() { - if (shared_buffer()) - shared_buffer_factory_->ReleaseSharedBuffer(shared_buffer()); -} - -HBITMAP VideoFrameWin::GetBitmap() { - return bitmap_; -} - -void VideoFrameWin::AllocateBitmap(HDC desktop_dc, const SkISize& size) { - int bytes_per_row = size.width() * CaptureData::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 = CaptureData::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)); -} - -VideoFrameCapturerWin::VideoFrameCapturerWin() - : shared_buffer_factory_(NULL), - delegate_(NULL), - desktop_dc_rect_(SkIRect::MakeEmpty()), - composition_func_(NULL) { -} - -VideoFrameCapturerWin::VideoFrameCapturerWin( - SharedBufferFactory* shared_buffer_factory) - : shared_buffer_factory_(shared_buffer_factory), - delegate_(NULL), - desktop_dc_rect_(SkIRect::MakeEmpty()), - composition_func_(NULL) { -} - -VideoFrameCapturerWin::~VideoFrameCapturerWin() { -} - -void VideoFrameCapturerWin::InvalidateRegion(const SkRegion& invalid_region) { - helper_.InvalidateRegion(invalid_region); -} - -void VideoFrameCapturerWin::CaptureFrame() { - base::Time capture_start_time = base::Time::Now(); - - // Force the system to power-up display hardware, if it has been suspended. - SetThreadExecutionState(ES_DISPLAY_REQUIRED); - - // Make sure the GDI capture resources are up-to-date. - PrepareCaptureResources(); - - // Copy screen bits to the current buffer. - CaptureImage(); - - const VideoFrame* current_buffer = queue_.current_frame(); - const VideoFrame* last_buffer = queue_.previous_frame(); - if (last_buffer) { - // 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(), - CaptureData::kBytesPerPixel, - current_buffer->bytes_per_row())); - } - - // Calculate difference between the two last captured frames. - SkRegion region; - differ_->CalcDirtyRegion(last_buffer->pixels(), current_buffer->pixels(), - ®ion); - InvalidateRegion(region); - } else { - // No previous frame is available. Invalidate the whole screen. - helper_.InvalidateScreen(current_buffer->dimensions()); - } - - // Wrap the captured frame into CaptureData structure and invoke - // the completion callback. - SkRegion invalid_region; - helper_.SwapInvalidRegion(&invalid_region); - CaptureRegion(invalid_region, capture_start_time); - - // Check for cursor shape update. - CaptureCursor(); -} - -void VideoFrameCapturerWin::Start(Delegate* delegate) { - DCHECK(delegate_ == NULL); - - delegate_ = delegate; - - // Load dwmapi.dll dynamically since it is not available on XP. - if (!dwmapi_library_.is_valid()) { - FilePath path(base::GetNativeLibraryName(UTF8ToUTF16(kDwmapiLibraryName))); - dwmapi_library_.Reset(base::LoadNativeLibrary(path, NULL)); - } - - if (dwmapi_library_.is_valid() && composition_func_ == NULL) { - composition_func_ = static_cast<DwmEnableCompositionFunc>( - dwmapi_library_.GetFunctionPointer("DwmEnableComposition")); - } - - // Vote to disable Aero composited desktop effects while capturing. Windows - // will restore Aero automatically if the process exits. This has no effect - // under Windows 8 or higher. See crbug.com/124018. - if (composition_func_ != NULL) { - (*composition_func_)(DWM_EC_DISABLECOMPOSITION); - } -} - -void VideoFrameCapturerWin::Stop() { - // Restore Aero. - if (composition_func_ != NULL) { - (*composition_func_)(DWM_EC_ENABLECOMPOSITION); - } - - delegate_ = NULL; -} - -void VideoFrameCapturerWin::PrepareCaptureResources() { - // Switch to the desktop receiving user input if different from the current - // one. - scoped_ptr<Desktop> input_desktop = Desktop::GetInputDesktop(); - if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) { - // Release GDI resources otherwise SetThreadDesktop will fail. - desktop_dc_.reset(); - memory_dc_.Set(NULL); - - // If SetThreadDesktop() fails, the thread is still assigned a desktop. - // So we can continue capture screen bits, just from the wrong desktop. - desktop_.SetThreadDesktop(input_desktop.Pass()); - } - - // If the display bounds have changed then recreate GDI resources. - // TODO(wez): Also check for pixel format changes. - SkIRect screen_rect(SkIRect::MakeXYWH( - GetSystemMetrics(SM_XVIRTUALSCREEN), - GetSystemMetrics(SM_YVIRTUALSCREEN), - GetSystemMetrics(SM_CXVIRTUALSCREEN), - GetSystemMetrics(SM_CYVIRTUALSCREEN))); - if (screen_rect != desktop_dc_rect_) { - desktop_dc_.reset(); - memory_dc_.Set(NULL); - desktop_dc_rect_.setEmpty(); - } - - if (desktop_dc_.get() == NULL) { - DCHECK(memory_dc_.Get() == NULL); - - // Create GDI device contexts to capture from the desktop into memory. - desktop_dc_.reset(new base::win::ScopedGetDC(NULL)); - memory_dc_.Set(CreateCompatibleDC(*desktop_dc_)); - desktop_dc_rect_ = screen_rect; - - // Make sure the frame buffers will be reallocated. - queue_.SetAllFramesNeedUpdate(); - - helper_.ClearInvalidRegion(); - } -} - -void VideoFrameCapturerWin::CaptureRegion( - const SkRegion& region, - const base::Time& capture_start_time) { - const VideoFrame* current_buffer = queue_.current_frame(); - - scoped_refptr<CaptureData> data( - new CaptureData(current_buffer->pixels(), current_buffer->bytes_per_row(), - current_buffer->dimensions())); - data->mutable_dirty_region() = region; - data->set_shared_buffer(current_buffer->shared_buffer()); - - 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 VideoFrameCapturerWin::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()) { - DCHECK(desktop_dc_.get() != NULL); - DCHECK(memory_dc_.Get() != NULL); - - SkISize size = SkISize::Make(desktop_dc_rect_.width(), - desktop_dc_rect_.height()); - scoped_ptr<VideoFrameWin> buffer( - new VideoFrameWin(*desktop_dc_, size, shared_buffer_factory_)); - queue_.ReplaceCurrentFrame(buffer.PassAs<VideoFrame>()); - } - - // Select the target bitmap into the memory dc and copy the rect from desktop - // to memory. - VideoFrameWin* current = static_cast<VideoFrameWin*>(queue_.current_frame()); - HGDIOBJ previous_object = SelectObject(memory_dc_, current->GetBitmap()); - if (previous_object != NULL) { - BitBlt(memory_dc_, - 0, 0, desktop_dc_rect_.width(), desktop_dc_rect_.height(), - *desktop_dc_, - desktop_dc_rect_.x(), desktop_dc_rect_.y(), - SRCCOPY | CAPTUREBLT); - - // Select back the previously selected object to that the device contect - // could be destroyed independently of the bitmap if needed. - SelectObject(memory_dc_, previous_object); - } -} - -void VideoFrameCapturerWin::AddCursorOutline(int width, - int height, - uint32* dst) { - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - // If this is a transparent pixel (bgr == 0 and alpha = 0), check the - // neighbor pixels to see if this should be changed to an outline pixel. - if (*dst == kPixelBgraTransparent) { - // Change to white pixel if any neighbors (top, bottom, left, right) - // are black. - if ((y > 0 && dst[-width] == kPixelBgraBlack) || - (y < height - 1 && dst[width] == kPixelBgraBlack) || - (x > 0 && dst[-1] == kPixelBgraBlack) || - (x < width - 1 && dst[1] == kPixelBgraBlack)) { - *dst = kPixelBgraWhite; - } - } - dst++; - } - } -} - -void VideoFrameCapturerWin::CaptureCursor() { - CURSORINFO cursor_info; - cursor_info.cbSize = sizeof(CURSORINFO); - if (!GetCursorInfo(&cursor_info)) { - VLOG(3) << "Unable to get cursor info. Error = " << GetLastError(); - return; - } - - // Note that this does not need to be freed. - HCURSOR hcursor = cursor_info.hCursor; - ICONINFO iinfo; - if (!GetIconInfo(hcursor, &iinfo)) { - VLOG(3) << "Unable to get cursor icon info. Error = " << GetLastError(); - return; - } - int hotspot_x = iinfo.xHotspot; - int hotspot_y = iinfo.yHotspot; - - // Get the cursor bitmap. - base::win::ScopedBitmap hbitmap; - BITMAP bitmap; - bool color_bitmap; - if (iinfo.hbmColor) { - // Color cursor bitmap. - color_bitmap = true; - hbitmap.Set((HBITMAP)CopyImage(iinfo.hbmColor, IMAGE_BITMAP, 0, 0, - LR_CREATEDIBSECTION)); - if (!hbitmap.Get()) { - VLOG(3) << "Unable to copy color cursor image. Error = " - << GetLastError(); - return; - } - - // Free the color and mask bitmaps since we only need our copy. - DeleteObject(iinfo.hbmColor); - DeleteObject(iinfo.hbmMask); - } else { - // Black and white (xor) cursor. - color_bitmap = false; - hbitmap.Set(iinfo.hbmMask); - } - - if (!GetObject(hbitmap.Get(), sizeof(BITMAP), &bitmap)) { - VLOG(3) << "Unable to get cursor bitmap. Error = " << GetLastError(); - return; - } - - int width = bitmap.bmWidth; - int height = bitmap.bmHeight; - // For non-color cursors, the mask contains both an AND and an XOR mask and - // the height includes both. Thus, the width is correct, but we need to - // divide by 2 to get the correct mask height. - if (!color_bitmap) { - height /= 2; - } - int data_size = height * width * CaptureData::kBytesPerPixel; - - scoped_ptr<MouseCursorShape> cursor(new MouseCursorShape()); - cursor->data.resize(data_size); - uint8* cursor_dst_data = - reinterpret_cast<uint8*>(string_as_array(&cursor->data)); - - // Copy/convert cursor bitmap into format needed by chromotocol. - int row_bytes = bitmap.bmWidthBytes; - if (color_bitmap) { - if (bitmap.bmPlanes != 1 || bitmap.bmBitsPixel != 32) { - VLOG(3) << "Unsupported color cursor format. Error = " << GetLastError(); - return; - } - - // Copy across colour cursor imagery. - // MouseCursorShape stores imagery top-down, and premultiplied - // by the alpha channel, whereas windows stores them bottom-up - // and not premultiplied. - uint8* cursor_src_data = reinterpret_cast<uint8*>(bitmap.bmBits); - uint8* src = cursor_src_data + ((height - 1) * row_bytes); - uint8* dst = cursor_dst_data; - for (int row = 0; row < height; ++row) { - for (int column = 0; column < width; ++column) { - dst[0] = SkAlphaMul(src[0], src[3]); - dst[1] = SkAlphaMul(src[1], src[3]); - dst[2] = SkAlphaMul(src[2], src[3]); - dst[3] = src[3]; - dst += CaptureData::kBytesPerPixel; - src += CaptureData::kBytesPerPixel; - } - src -= row_bytes + (width * CaptureData::kBytesPerPixel); - } - } else { - if (bitmap.bmPlanes != 1 || bitmap.bmBitsPixel != 1) { - VLOG(3) << "Unsupported cursor mask format. Error = " << GetLastError(); - return; - } - - // x2 because there are 2 masks in the bitmap: AND and XOR. - int mask_bytes = height * row_bytes * 2; - scoped_array<uint8> mask(new uint8[mask_bytes]); - if (!GetBitmapBits(hbitmap.Get(), mask_bytes, mask.get())) { - VLOG(3) << "Unable to get cursor mask bits. Error = " << GetLastError(); - return; - } - uint8* and_mask = mask.get(); - uint8* xor_mask = mask.get() + height * row_bytes; - uint8* dst = cursor_dst_data; - bool add_outline = false; - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - int byte = y * row_bytes + x / 8; - int bit = 7 - x % 8; - int and = and_mask[byte] & (1 << bit); - int xor = xor_mask[byte] & (1 << bit); - - // The two cursor masks combine as follows: - // AND XOR Windows Result Our result RGB Alpha - // 0 0 Black Black 00 ff - // 0 1 White White ff ff - // 1 0 Screen Transparent 00 00 - // 1 1 Reverse-screen Black 00 ff - // Since we don't support XOR cursors, we replace the "Reverse Screen" - // with black. In this case, we also add an outline around the cursor - // so that it is visible against a dark background. - int rgb = (!and && xor) ? 0xff : 0x00; - int alpha = (and && !xor) ? 0x00 : 0xff; - *dst++ = rgb; - *dst++ = rgb; - *dst++ = rgb; - *dst++ = alpha; - if (and && xor) { - add_outline = true; - } - } - } - if (add_outline) { - AddCursorOutline(width, height, - reinterpret_cast<uint32*>(cursor_dst_data)); - } - } - - cursor->size.set(width, height); - cursor->hotspot.set(hotspot_x, hotspot_y); - - // 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 && - last_cursor_.data == cursor->data) { - return; - } - - VLOG(3) << "Sending updated cursor: " << width << "x" << height; - - // Record the last cursor image that we sent to the client. - last_cursor_ = *cursor; - - delegate_->OnCursorShapeChanged(cursor.Pass()); -} - -} // namespace - -// static -scoped_ptr<VideoFrameCapturer> VideoFrameCapturer::Create() { - return scoped_ptr<VideoFrameCapturer>(new VideoFrameCapturerWin()); -} - -// static -scoped_ptr<VideoFrameCapturer> VideoFrameCapturer::CreateWithFactory( - SharedBufferFactory* shared_buffer_factory) { - scoped_ptr<VideoFrameCapturerWin> capturer( - new VideoFrameCapturerWin(shared_buffer_factory)); - return capturer.PassAs<VideoFrameCapturer>(); -} - -} // namespace remoting diff --git a/remoting/capturer/video_frame_queue.cc b/remoting/capturer/video_frame_queue.cc deleted file mode 100644 index 1d23f4e..0000000 --- a/remoting/capturer/video_frame_queue.cc +++ /dev/null @@ -1,38 +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 "remoting/capturer/video_frame_queue.h" - -#include <algorithm> - -#include "base/basictypes.h" -#include "remoting/capturer/video_frame.h" - -namespace remoting { - -VideoFrameQueue::VideoFrameQueue() - : current_(0), - previous_(NULL) { - SetAllFramesNeedUpdate(); -} - -VideoFrameQueue::~VideoFrameQueue() { -} - -void VideoFrameQueue::DoneWithCurrentFrame() { - previous_ = current_frame(); - current_ = (current_ + 1) % kQueueLength; -} - -void VideoFrameQueue::ReplaceCurrentFrame(scoped_ptr<VideoFrame> frame) { - frames_[current_] = frame.Pass(); - needs_update_[current_] = false; -} - -void VideoFrameQueue::SetAllFramesNeedUpdate() { - std::fill(needs_update_, needs_update_ + arraysize(needs_update_), true); - previous_ = NULL; -} - -} // namespace remoting diff --git a/remoting/capturer/video_frame_queue.h b/remoting/capturer/video_frame_queue.h deleted file mode 100644 index 44aee7c..0000000 --- a/remoting/capturer/video_frame_queue.h +++ /dev/null @@ -1,69 +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 REMOTING_CAPTURER_VIDEO_FRAME_QUEUE_H_ -#define REMOTING_CAPTURER_VIDEO_FRAME_QUEUE_H_ - -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" - -namespace remoting { - -class VideoFrame; - -// 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. -// -// 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 -// which the caller can query. -class VideoFrameQueue { - public: - VideoFrameQueue(); - ~VideoFrameQueue(); - - // Moves to the next frame in the queue, moving the 'current' frame to become - // the 'previous' one. - void DoneWithCurrentFrame(); - - // Replaces the current frame with a new one allocated by the caller. - // The existing frame (if any) is destroyed. - void ReplaceCurrentFrame(scoped_ptr<VideoFrame> 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(); - - VideoFrame* current_frame() const { - return frames_[current_].get(); - } - - bool current_frame_needs_update() const { - return !current_frame() || needs_update_[current_]; - } - - VideoFrame* previous_frame() const { return previous_; } - - private: - // Index of the current frame. - int current_; - - static const int kQueueLength = 2; - scoped_ptr<VideoFrame> frames_[kQueueLength]; - - // True if the corresponding frame needs to be re-allocated. - bool needs_update_[kQueueLength]; - - // Points to the previous frame if any. - VideoFrame* previous_; - - DISALLOW_COPY_AND_ASSIGN(VideoFrameQueue); -}; - -} // namespace remoting - -#endif // REMOTING_CAPTURER_VIDEO_FRAME_QUEUE_H_ diff --git a/remoting/capturer/win/desktop.cc b/remoting/capturer/win/desktop.cc deleted file mode 100644 index e7dbe4d..0000000 --- a/remoting/capturer/win/desktop.cc +++ /dev/null @@ -1,104 +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 "remoting/capturer/win/desktop.h" - -#include <vector> - -#include "base/logging.h" - -namespace remoting { - -Desktop::Desktop(HDESK desktop, bool own) : desktop_(desktop), own_(own) { -} - -Desktop::~Desktop() { - if (own_ && desktop_ != NULL) { - if (!::CloseDesktop(desktop_)) { - LOG_GETLASTERROR(ERROR) - << "Failed to close the owned desktop handle"; - } - } -} - -bool Desktop::GetName(string16* desktop_name_out) const { - if (desktop_ == NULL) - return false; - - DWORD length; - CHECK(!GetUserObjectInformationW(desktop_, UOI_NAME, NULL, 0, &length)); - CHECK(GetLastError() == ERROR_INSUFFICIENT_BUFFER); - - length /= sizeof(char16); - std::vector<char16> buffer(length); - if (!GetUserObjectInformationW(desktop_, UOI_NAME, &buffer[0], - length * sizeof(char16), &length)) { - LOG_GETLASTERROR(ERROR) - << "Failed to query the desktop name"; - return false; - } - - desktop_name_out->assign(&buffer[0], length / sizeof(char16)); - return true; -} - -bool Desktop::IsSame(const Desktop& other) const { - string16 name; - if (!GetName(&name)) - return false; - - string16 other_name; - if (!other.GetName(&other_name)) - return false; - - return name == other_name; -} - -bool Desktop::SetThreadDesktop() const { - if (!::SetThreadDesktop(desktop_)) { - LOG_GETLASTERROR(ERROR) - << "Failed to assign the desktop to the current thread"; - return false; - } - - return true; -} - -scoped_ptr<Desktop> Desktop::GetDesktop(const wchar_t* desktop_name) { - ACCESS_MASK desired_access = - DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_ENUMERATE | - DESKTOP_HOOKCONTROL | DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS | - DESKTOP_SWITCHDESKTOP | GENERIC_WRITE; - HDESK desktop = OpenDesktop(desktop_name, 0, FALSE, desired_access); - if (desktop == NULL) { - LOG_GETLASTERROR(ERROR) - << "Failed to open the desktop '" << desktop_name << "'"; - return scoped_ptr<Desktop>(); - } - - return scoped_ptr<Desktop>(new Desktop(desktop, true)); -} - -scoped_ptr<Desktop> Desktop::GetInputDesktop() { - HDESK desktop = OpenInputDesktop( - 0, FALSE, GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE); - if (desktop == NULL) - return scoped_ptr<Desktop>(); - - return scoped_ptr<Desktop>(new Desktop(desktop, true)); -} - -scoped_ptr<Desktop> Desktop::GetThreadDesktop() { - HDESK desktop = ::GetThreadDesktop(GetCurrentThreadId()); - if (desktop == NULL) { - LOG_GETLASTERROR(ERROR) - << "Failed to retrieve the handle of the desktop assigned to " - "the current thread"; - return scoped_ptr<Desktop>(); - } - - return scoped_ptr<Desktop>(new Desktop(desktop, false)); -} - -} // namespace remoting diff --git a/remoting/capturer/win/desktop.h b/remoting/capturer/win/desktop.h deleted file mode 100644 index f50a047..0000000 --- a/remoting/capturer/win/desktop.h +++ /dev/null @@ -1,58 +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 REMOTING_CAPTURER_WIN_DESKTOP_H_ -#define REMOTING_CAPTURER_WIN_DESKTOP_H_ - -#include <windows.h> - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "base/string16.h" - -namespace remoting { - -class Desktop { - public: - ~Desktop(); - - // Returns the name of the desktop represented by the object. Return false if - // quering the name failed for any reason. - bool GetName(string16* desktop_name_out) const; - - // Returns true if |other| has the same name as this desktop. Returns false - // in any other case including failing Win32 APIs and uninitialized desktop - // handles. - bool IsSame(const Desktop& other) const; - - // Assigns the desktop to the current thread. Returns false is the operation - // failed for any reason. - bool SetThreadDesktop() const; - - // Returns the desktop by its name or NULL if an error occurs. - static scoped_ptr<Desktop> GetDesktop(const wchar_t* desktop_name); - - // Returns the desktop currently receiving user input or NULL if an error - // occurs. - static scoped_ptr<Desktop> GetInputDesktop(); - - // Returns the desktop currently assigned to the calling thread or NULL if - // an error occurs. - static scoped_ptr<Desktop> GetThreadDesktop(); - - private: - Desktop(HDESK desktop, bool own); - - // The desktop handle. - HDESK desktop_; - - // True if |desktop_| must be closed on teardown. - bool own_; - - DISALLOW_COPY_AND_ASSIGN(Desktop); -}; - -} // namespace remoting - -#endif // REMOTING_CAPTURER_WIN_DESKTOP_H_ diff --git a/remoting/capturer/win/scoped_thread_desktop.cc b/remoting/capturer/win/scoped_thread_desktop.cc deleted file mode 100644 index bbde520..0000000 --- a/remoting/capturer/win/scoped_thread_desktop.cc +++ /dev/null @@ -1,49 +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 "remoting/capturer/win/scoped_thread_desktop.h" - -#include "base/logging.h" - -#include "remoting/capturer/win/desktop.h" - -namespace remoting { - -ScopedThreadDesktop::ScopedThreadDesktop() - : initial_(Desktop::GetThreadDesktop()) { -} - -ScopedThreadDesktop::~ScopedThreadDesktop() { - Revert(); -} - -bool ScopedThreadDesktop::IsSame(const Desktop& desktop) { - if (assigned_.get() != NULL) { - return assigned_->IsSame(desktop); - } else { - return initial_->IsSame(desktop); - } -} - -void ScopedThreadDesktop::Revert() { - if (assigned_.get() != NULL) { - initial_->SetThreadDesktop(); - assigned_.reset(); - } -} - -bool ScopedThreadDesktop::SetThreadDesktop(scoped_ptr<Desktop> desktop) { - Revert(); - - if (initial_->IsSame(*desktop)) - return true; - - if (!desktop->SetThreadDesktop()) - return false; - - assigned_ = desktop.Pass(); - return true; -} - -} // namespace remoting diff --git a/remoting/capturer/win/scoped_thread_desktop.h b/remoting/capturer/win/scoped_thread_desktop.h deleted file mode 100644 index 5f2378b..0000000 --- a/remoting/capturer/win/scoped_thread_desktop.h +++ /dev/null @@ -1,47 +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 REMOTING_CAPTURER_WIN_SCOPED_THREAD_DESKTOP_H_ -#define REMOTING_CAPTURER_WIN_SCOPED_THREAD_DESKTOP_H_ - -#include <windows.h> - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" - -namespace remoting { - -class Desktop; - -class ScopedThreadDesktop { - public: - ScopedThreadDesktop(); - ~ScopedThreadDesktop(); - - // Returns true if |desktop| has the same desktop name as the currently - // assigned desktop (if assigned) or as the initial desktop (if not assigned). - // Returns false in any other case including failing Win32 APIs and - // uninitialized desktop handles. - bool IsSame(const Desktop& desktop); - - // Reverts the calling thread to use the initial desktop. - void Revert(); - - // Assigns |desktop| to be the calling thread. Returns true if the thread has - // been switched to |desktop| successfully. - bool SetThreadDesktop(scoped_ptr<Desktop> desktop); - - private: - // The desktop handle assigned to the calling thread by Set - scoped_ptr<Desktop> assigned_; - - // The desktop handle assigned to the calling thread at creation. - scoped_ptr<Desktop> initial_; - - DISALLOW_COPY_AND_ASSIGN(ScopedThreadDesktop); -}; - -} // namespace remoting - -#endif // REMOTING_CAPTURER_WIN_SCOPED_THREAD_DESKTOP_H_ diff --git a/remoting/codec/DEPS b/remoting/codec/DEPS index 7f88e41..61e5c26 100644 --- a/remoting/codec/DEPS +++ b/remoting/codec/DEPS @@ -1,5 +1,5 @@ include_rules = [ - "+remoting/capturer", + "+media/video/capture/screen", "+remoting/protocol", "+google/protobuf", diff --git a/remoting/codec/codec_test.cc b/remoting/codec/codec_test.cc index 7f45828..7c87307 100644 --- a/remoting/codec/codec_test.cc +++ b/remoting/codec/codec_test.cc @@ -180,7 +180,7 @@ class VideoDecoderTester { strict_ = strict; } - void set_capture_data(scoped_refptr<CaptureData> data) { + void set_capture_data(scoped_refptr<media::ScreenCaptureData> data) { capture_data_ = data; } @@ -272,7 +272,7 @@ class VideoDecoderTester { SkRegion update_region_; VideoDecoder* decoder_; scoped_array<uint8> image_data_; - scoped_refptr<CaptureData> capture_data_; + scoped_refptr<media::ScreenCaptureData> capture_data_; DISALLOW_COPY_AND_ASSIGN(VideoDecoderTester); }; @@ -317,8 +317,9 @@ class VideoEncoderTester { DISALLOW_COPY_AND_ASSIGN(VideoEncoderTester); }; -scoped_refptr<CaptureData> PrepareEncodeData(const SkISize& size, - scoped_array<uint8>* memory) { +scoped_refptr<media::ScreenCaptureData> PrepareEncodeData( + const SkISize& size, + scoped_array<uint8>* memory) { int memory_size = size.width() * size.height() * kBytesPerPixel; memory->reset(new uint8[memory_size]); @@ -328,14 +329,14 @@ scoped_refptr<CaptureData> PrepareEncodeData(const SkISize& size, (*memory)[i] = rand() % 256; } - scoped_refptr<CaptureData> data = - new CaptureData(memory->get(), size.width() * kBytesPerPixel, size); + scoped_refptr<media::ScreenCaptureData> data = new media::ScreenCaptureData( + memory->get(), size.width() * kBytesPerPixel, size); return data; } static void TestEncodingRects(VideoEncoder* encoder, VideoEncoderTester* tester, - scoped_refptr<CaptureData> data, + scoped_refptr<media::ScreenCaptureData> data, const SkIRect* rects, int count) { data->mutable_dirty_region().setEmpty(); for (int i = 0; i < count; ++i) { @@ -360,7 +361,7 @@ void TestVideoEncoder(VideoEncoder* encoder, bool strict) { for (size_t xi = 0; xi < arraysize(kSizes); ++xi) { for (size_t yi = 0; yi < arraysize(kSizes); ++yi) { SkISize size = SkISize::Make(kSizes[xi], kSizes[yi]); - scoped_refptr<CaptureData> data = + scoped_refptr<media::ScreenCaptureData> data = PrepareEncodeData(size, &memory); std::vector<std::vector<SkIRect> > test_rect_lists = MakeTestRectLists(size); @@ -376,7 +377,7 @@ void TestVideoEncoder(VideoEncoder* encoder, bool strict) { static void TestEncodeDecodeRects(VideoEncoder* encoder, VideoEncoderTester* encoder_tester, VideoDecoderTester* decoder_tester, - scoped_refptr<CaptureData> data, + scoped_refptr<media::ScreenCaptureData> data, const SkIRect* rects, int count) { data->mutable_dirty_region().setRects(rects, count); encoder_tester->AddRects(rects, count); @@ -413,7 +414,8 @@ void TestVideoEncoderDecoder( VideoEncoderTester encoder_tester(&message_tester); scoped_array<uint8> memory; - scoped_refptr<CaptureData> data = PrepareEncodeData(kSize, &memory); + scoped_refptr<media::ScreenCaptureData> data = + PrepareEncodeData(kSize, &memory); VideoDecoderTester decoder_tester(decoder, kSize, kSize); decoder_tester.set_strict(strict); @@ -458,9 +460,9 @@ void TestVideoEncoderDecoderGradient(VideoEncoder* encoder, view_size.width() * view_size.height() * kBytesPerPixel]); FillWithGradient(expected_view_data.get(), view_size, view_rect); - scoped_refptr<CaptureData> capture_data = - new CaptureData(screen_data.get(), screen_size.width() * kBytesPerPixel, - screen_size); + scoped_refptr<media::ScreenCaptureData> capture_data = + new media::ScreenCaptureData( + screen_data.get(), screen_size.width() * kBytesPerPixel, screen_size); capture_data->mutable_dirty_region().op(screen_rect, SkRegion::kUnion_Op); VideoDecoderTester decoder_tester(decoder, screen_size, view_size); diff --git a/remoting/codec/codec_test.h b/remoting/codec/codec_test.h index 86c52f2..d2bda83 100644 --- a/remoting/codec/codec_test.h +++ b/remoting/codec/codec_test.h @@ -7,7 +7,7 @@ #include "base/memory/ref_counted.h" #include "media/base/video_frame.h" -#include "remoting/capturer/capture_data.h" +#include "media/video/capture/screen/screen_capture_data.h" namespace remoting { diff --git a/remoting/codec/video_encoder.h b/remoting/codec/video_encoder.h index 5cc4c10..81179c4 100644 --- a/remoting/codec/video_encoder.h +++ b/remoting/codec/video_encoder.h @@ -10,12 +10,11 @@ #include "media/base/data_buffer.h" namespace media { - class DataBuffer; -} +class ScreenCaptureData; +} // namespace media namespace remoting { -class CaptureData; class VideoPacket; // A class to perform the task of encoding a continous stream of @@ -37,7 +36,7 @@ class VideoEncoder { // // When encoded data is available, partial or full |data_available_callback| // is called. - virtual void Encode(scoped_refptr<CaptureData> capture_data, + virtual void Encode(scoped_refptr<media::ScreenCaptureData> capture_data, bool key_frame, const DataAvailableCallback& data_available_callback) = 0; }; diff --git a/remoting/codec/video_encoder_verbatim.cc b/remoting/codec/video_encoder_verbatim.cc index 0633ac2..2e7f6d0 100644 --- a/remoting/codec/video_encoder_verbatim.cc +++ b/remoting/codec/video_encoder_verbatim.cc @@ -5,8 +5,8 @@ #include "remoting/codec/video_encoder_verbatim.h" #include "base/logging.h" +#include "media/video/capture/screen/screen_capture_data.h" #include "remoting/base/util.h" -#include "remoting/capturer/capture_data.h" #include "remoting/proto/video.pb.h" namespace remoting { @@ -26,7 +26,7 @@ VideoEncoderVerbatim::~VideoEncoderVerbatim() { } void VideoEncoderVerbatim::Encode( - scoped_refptr<CaptureData> capture_data, + scoped_refptr<media::ScreenCaptureData> capture_data, bool key_frame, const DataAvailableCallback& data_available_callback) { capture_data_ = capture_data; diff --git a/remoting/codec/video_encoder_verbatim.h b/remoting/codec/video_encoder_verbatim.h index 6477b2a..2b6250b 100644 --- a/remoting/codec/video_encoder_verbatim.h +++ b/remoting/codec/video_encoder_verbatim.h @@ -24,7 +24,7 @@ class VideoEncoderVerbatim : public VideoEncoder { // VideoEncoder interface. virtual void Encode( - scoped_refptr<CaptureData> capture_data, + scoped_refptr<media::ScreenCaptureData> capture_data, bool key_frame, const DataAvailableCallback& data_available_callback) OVERRIDE; @@ -43,7 +43,7 @@ class VideoEncoderVerbatim : public VideoEncoder { // Submit |packet| to |callback_|. void SubmitMessage(VideoPacket* packet, size_t rect_index); - scoped_refptr<CaptureData> capture_data_; + scoped_refptr<media::ScreenCaptureData> capture_data_; DataAvailableCallback callback_; base::Time encode_start_time_; diff --git a/remoting/codec/video_encoder_vp8.cc b/remoting/codec/video_encoder_vp8.cc index ace549b..a4e4d1a 100644 --- a/remoting/codec/video_encoder_vp8.cc +++ b/remoting/codec/video_encoder_vp8.cc @@ -8,8 +8,8 @@ #include "base/sys_info.h" #include "base/time.h" #include "media/base/yuv_convert.h" +#include "media/video/capture/screen/screen_capture_data.h" #include "remoting/base/util.h" -#include "remoting/capturer/capture_data.h" #include "remoting/proto/video.pb.h" extern "C" { @@ -146,8 +146,9 @@ bool VideoEncoderVp8::Init(const SkISize& size) { return true; } -void VideoEncoderVp8::PrepareImage(scoped_refptr<CaptureData> capture_data, - SkRegion* updated_region) { +void VideoEncoderVp8::PrepareImage( + scoped_refptr<media::ScreenCaptureData> capture_data, + SkRegion* updated_region) { const SkRegion& region = capture_data->dirty_region(); if (region.isEmpty()) { updated_region->setEmpty(); @@ -212,7 +213,7 @@ void VideoEncoderVp8::PrepareActiveMap(const SkRegion& updated_region) { } void VideoEncoderVp8::Encode( - scoped_refptr<CaptureData> capture_data, + scoped_refptr<media::ScreenCaptureData> capture_data, bool key_frame, const DataAvailableCallback& data_available_callback) { DCHECK_LE(32, capture_data->size().width()); diff --git a/remoting/codec/video_encoder_vp8.h b/remoting/codec/video_encoder_vp8.h index 83559e1..4b3f903 100644 --- a/remoting/codec/video_encoder_vp8.h +++ b/remoting/codec/video_encoder_vp8.h @@ -21,7 +21,7 @@ class VideoEncoderVp8 : public VideoEncoder { virtual ~VideoEncoderVp8(); virtual void Encode( - scoped_refptr<CaptureData> capture_data, + scoped_refptr<media::ScreenCaptureData> capture_data, bool key_frame, const DataAvailableCallback& data_available_callback) OVERRIDE; @@ -36,7 +36,7 @@ class VideoEncoderVp8 : public VideoEncoder { // Prepare |image_| for encoding. Write updated rectangles into // |updated_region|. - void PrepareImage(scoped_refptr<CaptureData> capture_data, + void PrepareImage(scoped_refptr<media::ScreenCaptureData> capture_data, SkRegion* updated_region); // Update the active map according to |updated_region|. Active map is then diff --git a/remoting/codec/video_encoder_vp8_unittest.cc b/remoting/codec/video_encoder_vp8_unittest.cc index 11d5ded..9a32fe2 100644 --- a/remoting/codec/video_encoder_vp8_unittest.cc +++ b/remoting/codec/video_encoder_vp8_unittest.cc @@ -10,7 +10,7 @@ #include "base/bind.h" #include "base/callback.h" #include "base/memory/scoped_ptr.h" -#include "remoting/capturer/capture_data.h" +#include "media/video/capture/screen/screen_capture_data.h" #include "remoting/codec/codec_test.h" #include "remoting/proto/video.pb.h" #include "testing/gtest/include/gtest/gtest.h" @@ -34,8 +34,8 @@ class VideoEncoderCallback { } }; -// Test that calling Encode with a differently-sized CaptureData does not -// leak memory. +// Test that calling Encode with a differently-sized media::ScreenCaptureData +// does not leak memory. TEST(VideoEncoderVp8Test, TestSizeChangeNoLeak) { int height = 1000; int width = 1000; @@ -45,14 +45,15 @@ TEST(VideoEncoderVp8Test, TestSizeChangeNoLeak) { VideoEncoderCallback callback; std::vector<uint8> buffer(width * height * kBytesPerPixel); - scoped_refptr<CaptureData> capture_data(new CaptureData( - &buffer.front(), width * kBytesPerPixel, SkISize::Make(width, height))); + scoped_refptr<media::ScreenCaptureData> capture_data( + new media::ScreenCaptureData(&buffer.front(), width * kBytesPerPixel, + SkISize::Make(width, height))); encoder.Encode(capture_data, false, base::Bind(&VideoEncoderCallback::DataAvailable, base::Unretained(&callback))); height /= 2; - capture_data = new CaptureData( + capture_data = new media::ScreenCaptureData( &buffer.front(), width * kBytesPerPixel, SkISize::Make(width, height)); encoder.Encode(capture_data, false, base::Bind(&VideoEncoderCallback::DataAvailable, @@ -67,8 +68,8 @@ class VideoEncoderDpiCallback { } }; -// Test that the DPI information is correctly propagated from the CaptureData -// to the VideoPacket. +// Test that the DPI information is correctly propagated from the +// media::ScreenCaptureData to the VideoPacket. TEST(VideoEncoderVp8Test, TestDpiPropagation) { int height = 32; int width = 32; @@ -78,8 +79,9 @@ TEST(VideoEncoderVp8Test, TestDpiPropagation) { VideoEncoderDpiCallback callback; std::vector<uint8> buffer(width * height * kBytesPerPixel); - scoped_refptr<CaptureData> capture_data(new CaptureData( - &buffer.front(), width * kBytesPerPixel, SkISize::Make(width, height))); + scoped_refptr<media::ScreenCaptureData> capture_data( + new media::ScreenCaptureData(&buffer.front(), width * kBytesPerPixel, + SkISize::Make(width, height))); capture_data->set_dpi(SkIPoint::Make(96, 97)); encoder.Encode(capture_data, false, base::Bind(&VideoEncoderDpiCallback::DataAvailable, diff --git a/remoting/host/DEPS b/remoting/host/DEPS index 9936357..5cfd1e5 100644 --- a/remoting/host/DEPS +++ b/remoting/host/DEPS @@ -1,4 +1,5 @@ include_rules = [ + "+media/video/capture/screen", "+net/base", "+net/ftp", "+net/http", @@ -10,7 +11,6 @@ include_rules = [ # at process start. "+net/socket", - "+remoting/capturer", "+remoting/codec", "+remoting/protocol", "+remoting/jingle_glue", diff --git a/remoting/host/basic_desktop_environment.cc b/remoting/host/basic_desktop_environment.cc index 040fe88..5c41ef1 100644 --- a/remoting/host/basic_desktop_environment.cc +++ b/remoting/host/basic_desktop_environment.cc @@ -5,7 +5,7 @@ #include "remoting/host/basic_desktop_environment.h" #include "base/logging.h" -#include "remoting/capturer/video_frame_capturer.h" +#include "media/video/capture/screen/screen_capturer.h" #include "remoting/host/audio_capturer.h" #include "remoting/host/event_executor.h" @@ -33,12 +33,12 @@ scoped_ptr<EventExecutor> BasicDesktopEnvironment::CreateEventExecutor( return EventExecutor::Create(input_task_runner, ui_task_runner); } -scoped_ptr<VideoFrameCapturer> BasicDesktopEnvironment::CreateVideoCapturer( +scoped_ptr<media::ScreenCapturer> BasicDesktopEnvironment::CreateVideoCapturer( scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner) { DCHECK(CalledOnValidThread()); - return VideoFrameCapturer::Create(); + return media::ScreenCapturer::Create(); } BasicDesktopEnvironmentFactory::BasicDesktopEnvironmentFactory() { diff --git a/remoting/host/basic_desktop_environment.h b/remoting/host/basic_desktop_environment.h index 4d0c08e..e3ac2bf 100644 --- a/remoting/host/basic_desktop_environment.h +++ b/remoting/host/basic_desktop_environment.h @@ -29,7 +29,7 @@ class BasicDesktopEnvironment virtual scoped_ptr<EventExecutor> CreateEventExecutor( scoped_refptr<base::SingleThreadTaskRunner> input_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) OVERRIDE; - virtual scoped_ptr<VideoFrameCapturer> CreateVideoCapturer( + virtual scoped_ptr<media::ScreenCapturer> CreateVideoCapturer( scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner) OVERRIDE; diff --git a/remoting/host/chromoting_host.h b/remoting/host/chromoting_host.h index 31b8bba..7e1a935 100644 --- a/remoting/host/chromoting_host.h +++ b/remoting/host/chromoting_host.h @@ -46,7 +46,7 @@ class DesktopEnvironmentFactory; // // 2. We listen for incoming connection using libjingle. We will create // a ConnectionToClient object that wraps around linjingle for transport. -// A ScreenRecorder is created with an Encoder and a VideoFrameCapturer. +// A VideoScheduler is created with an Encoder and a media::ScreenCapturer. // A ConnectionToClient is added to the ScreenRecorder for transporting // the screen captures. An InputStub is created and registered with the // ConnectionToClient to receive mouse / keyboard events from the remote diff --git a/remoting/host/chromoting_host_unittest.cc b/remoting/host/chromoting_host_unittest.cc index 4d1f00d..97c490a 100644 --- a/remoting/host/chromoting_host_unittest.cc +++ b/remoting/host/chromoting_host_unittest.cc @@ -6,8 +6,8 @@ #include "base/bind_helpers.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop_proxy.h" +#include "media/video/capture/screen/screen_capturer_fake.h" #include "remoting/base/auto_thread_task_runner.h" -#include "remoting/capturer/video_frame_capturer_fake.h" #include "remoting/host/audio_capturer.h" #include "remoting/host/chromoting_host.h" #include "remoting/host/chromoting_host_context.h" @@ -19,8 +19,8 @@ #include "remoting/protocol/errors.h" #include "remoting/protocol/protocol_mock_objects.h" #include "remoting/protocol/session_config.h" -#include "testing/gmock_mutant.h" #include "testing/gmock/include/gmock/gmock.h" +#include "testing/gmock_mutant.h" #include "testing/gtest/include/gtest/gtest.h" using ::remoting::protocol::MockClientStub; @@ -285,7 +285,7 @@ class ChromotingHostTest : public testing::Test { host_->OnSessionRouteChange(get_client(0), channel_name, route); } - // Creates a DesktopEnvironment with a fake VideoFrameCapturer, to mock + // Creates a DesktopEnvironment with a fake media::ScreenCapturer, to mock // DesktopEnvironmentFactory::Create(). DesktopEnvironment* CreateDesktopEnvironment() { MockDesktopEnvironment* desktop_environment = new MockDesktopEnvironment(); @@ -311,12 +311,12 @@ class ChromotingHostTest : public testing::Test { return event_executor; } - // Creates a fake VideoFrameCapturer, to mock + // Creates a fake media::ScreenCapturer, to mock // DesktopEnvironment::CreateVideoCapturer(). - VideoFrameCapturer* CreateVideoCapturer( + media::ScreenCapturer* CreateVideoCapturer( scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner) { - return new VideoFrameCapturerFake(); + return new media::ScreenCapturerFake(); } void DisconnectAllClients() { diff --git a/remoting/host/chromoting_messages.h b/remoting/host/chromoting_messages.h index 4407f49..f62bfbb 100644 --- a/remoting/host/chromoting_messages.h +++ b/remoting/host/chromoting_messages.h @@ -6,7 +6,7 @@ #define REMOTING_HOST_CHROMOTING_MESSAGES_H_ #include "ipc/ipc_platform_file.h" -#include "remoting/capturer/mouse_cursor_shape.h" +#include "media/video/capture/screen/mouse_cursor_shape.h" #include "third_party/skia/include/core/SkPoint.h" #include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/core/SkSize.h" @@ -128,13 +128,13 @@ IPC_STRUCT_TRAITS_BEGIN(SkISize) IPC_STRUCT_TRAITS_MEMBER(fHeight) IPC_STRUCT_TRAITS_END() -IPC_STRUCT_TRAITS_BEGIN(remoting::MouseCursorShape) +IPC_STRUCT_TRAITS_BEGIN(media::MouseCursorShape) IPC_STRUCT_TRAITS_MEMBER(size) IPC_STRUCT_TRAITS_MEMBER(hotspot) IPC_STRUCT_TRAITS_MEMBER(data) IPC_STRUCT_TRAITS_END() -// Serialized CaptureData structure. +// Serialized media::ScreenCaptureData structure. IPC_STRUCT_BEGIN(SerializedCapturedData) // ID of the shared memory buffer containing the pixels. IPC_STRUCT_MEMBER(int, shared_buffer_id) @@ -164,7 +164,7 @@ IPC_MESSAGE_CONTROL1(ChromotingDesktopNetworkMsg_CaptureCompleted, // Carries a cursor share update from the desktop session agent to the client. IPC_MESSAGE_CONTROL1(ChromotingDesktopNetworkMsg_CursorShapeChanged, - remoting::MouseCursorShape /* cursor_shape */ ) + media::MouseCursorShape /* cursor_shape */ ) // Carries a clipboard event from the desktop session agent to the client. // |serialized_event| is a serialized protocol::ClipboardEvent. diff --git a/remoting/host/client_session.cc b/remoting/host/client_session.cc index 1e27128..b62b2e4 100644 --- a/remoting/host/client_session.cc +++ b/remoting/host/client_session.cc @@ -7,7 +7,7 @@ #include <algorithm> #include "base/message_loop_proxy.h" -#include "remoting/capturer/video_frame_capturer.h" +#include "media/video/capture/screen/screen_capturer.h" #include "remoting/codec/audio_encoder.h" #include "remoting/codec/audio_encoder_opus.h" #include "remoting/codec/audio_encoder_speex.h" diff --git a/remoting/host/client_session_unittest.cc b/remoting/host/client_session_unittest.cc index 1720382..abe7eee 100644 --- a/remoting/host/client_session_unittest.cc +++ b/remoting/host/client_session_unittest.cc @@ -3,10 +3,10 @@ // found in the LICENSE file. #include "base/message_loop.h" +#include "media/video/capture/screen/screen_capturer_fake.h" +#include "media/video/capture/screen/screen_capturer_mock_objects.h" #include "remoting/base/auto_thread_task_runner.h" #include "remoting/base/constants.h" -#include "remoting/capturer/video_capturer_mock_objects.h" -#include "remoting/capturer/video_frame_capturer_fake.h" #include "remoting/host/audio_capturer.h" #include "remoting/host/client_session.h" #include "remoting/host/desktop_environment.h" @@ -67,7 +67,7 @@ class ClientSessionTest : public testing::Test { void StopClientSession(); protected: - // Creates a DesktopEnvironment with a fake VideoFrameCapturer, to mock + // Creates a DesktopEnvironment with a fake media::ScreenCapturer, to mock // DesktopEnvironmentFactory::Create(). DesktopEnvironment* CreateDesktopEnvironment(); @@ -77,9 +77,9 @@ class ClientSessionTest : public testing::Test { scoped_refptr<base::SingleThreadTaskRunner> input_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner); - // Creates a fake VideoFrameCapturer, to mock + // Creates a fake media::ScreenCapturer, to mock // DesktopEnvironment::CreateVideoCapturer(). - VideoFrameCapturer* CreateVideoCapturer( + media::ScreenCapturer* CreateVideoCapturer( scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner); @@ -208,10 +208,10 @@ EventExecutor* ClientSessionTest::CreateEventExecutor( return event_executor_.release(); } -VideoFrameCapturer* ClientSessionTest::CreateVideoCapturer( +media::ScreenCapturer* ClientSessionTest::CreateVideoCapturer( scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner) { - return new VideoFrameCapturerFake(); + return new media::ScreenCapturerFake(); } void ClientSessionTest::ConnectClientSession() { @@ -437,9 +437,9 @@ TEST_F(ClientSessionTest, ClampMouseEvents) { EXPECT_CALL(session_event_handler_, OnSessionClosed(_)); int input_x[3] = { -999, 100, 999 }; - int expected_x[3] = { 0, 100, VideoFrameCapturerFake::kWidth - 1 }; + int expected_x[3] = { 0, 100, media::ScreenCapturerFake::kWidth - 1 }; int input_y[3] = { -999, 50, 999 }; - int expected_y[3] = { 0, 50, VideoFrameCapturerFake::kHeight - 1 }; + int expected_y[3] = { 0, 50, media::ScreenCapturerFake::kHeight - 1 }; protocol::MouseEvent expected_event; for (int j = 0; j < 3; j++) { diff --git a/remoting/host/desktop_environment.h b/remoting/host/desktop_environment.h index 06b0b373..f91fb85 100644 --- a/remoting/host/desktop_environment.h +++ b/remoting/host/desktop_environment.h @@ -16,11 +16,14 @@ namespace base { class SingleThreadTaskRunner; } // namespace base +namespace media { +class ScreenCapturer; +} // namespace media + namespace remoting { class AudioCapturer; class EventExecutor; -class VideoFrameCapturer; // Provides factory methods for creation of audio/video capturers and event // executor for a given desktop environment. @@ -35,7 +38,7 @@ class DesktopEnvironment { virtual scoped_ptr<EventExecutor> CreateEventExecutor( scoped_refptr<base::SingleThreadTaskRunner> input_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) = 0; - virtual scoped_ptr<VideoFrameCapturer> CreateVideoCapturer( + virtual scoped_ptr<media::ScreenCapturer> CreateVideoCapturer( scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner) = 0; }; diff --git a/remoting/host/desktop_session_agent.cc b/remoting/host/desktop_session_agent.cc index 39a2aec..878ae4f 100644 --- a/remoting/host/desktop_session_agent.cc +++ b/remoting/host/desktop_session_agent.cc @@ -8,10 +8,10 @@ #include "ipc/ipc_channel_proxy.h" #include "ipc/ipc_message.h" #include "ipc/ipc_message_macros.h" +#include "media/video/capture/screen/screen_capture_data.h" #include "remoting/base/auto_thread_task_runner.h" #include "remoting/base/constants.h" #include "remoting/base/util.h" -#include "remoting/capturer/capture_data.h" #include "remoting/host/audio_capturer.h" #include "remoting/host/chromoting_messages.h" #include "remoting/host/disconnect_window.h" @@ -137,11 +137,11 @@ void DesktopSessionAgent::OnLocalMouseMoved(const SkIPoint& new_pos) { remote_input_filter_->LocalMouseMoved(new_pos); } -scoped_refptr<SharedBuffer> DesktopSessionAgent::CreateSharedBuffer( +scoped_refptr<media::SharedBuffer> DesktopSessionAgent::CreateSharedBuffer( uint32 size) { DCHECK(video_capture_task_runner()->BelongsToCurrentThread()); - scoped_refptr<SharedBuffer> buffer = new SharedBuffer(size); + scoped_refptr<media::SharedBuffer> buffer = new media::SharedBuffer(size); if (buffer->ptr() != NULL) { buffer->set_id(next_shared_buffer_id_); shared_buffers_.push_back(buffer); @@ -164,7 +164,7 @@ scoped_refptr<SharedBuffer> DesktopSessionAgent::CreateSharedBuffer( } void DesktopSessionAgent::ReleaseSharedBuffer( - scoped_refptr<SharedBuffer> buffer) { + scoped_refptr<media::SharedBuffer> buffer) { DCHECK(video_capture_task_runner()->BelongsToCurrentThread()); DCHECK(buffer->id() != 0); @@ -214,12 +214,12 @@ void DesktopSessionAgent::OnStartSessionAgent( } void DesktopSessionAgent::OnCaptureCompleted( - scoped_refptr<CaptureData> capture_data) { + scoped_refptr<media::ScreenCaptureData> capture_data) { DCHECK(video_capture_task_runner()->BelongsToCurrentThread()); current_size_ = capture_data->size(); - // Serialize CaptureData + // Serialize media::ScreenCaptureData SerializedCapturedData serialized_data; serialized_data.shared_buffer_id = capture_data->shared_buffer()->id(); serialized_data.bytes_per_row = capture_data->stride(); @@ -236,7 +236,7 @@ void DesktopSessionAgent::OnCaptureCompleted( } void DesktopSessionAgent::OnCursorShapeChanged( - scoped_ptr<MouseCursorShape> cursor_shape) { + scoped_ptr<media::MouseCursorShape> cursor_shape) { DCHECK(video_capture_task_runner()->BelongsToCurrentThread()); SendToNetwork(new ChromotingDesktopNetworkMsg_CursorShapeChanged( @@ -325,10 +325,10 @@ void DesktopSessionAgent::OnCaptureFrame() { return; } - // VideoFrameCapturer supports a very few (currently 2) outstanding capture + // media::ScreenCapturer supports a very few (currently 2) outstanding capture // requests. The requests are serialized on |video_capture_task_runner()| task // runner. If the client issues more requests, pixel data in captured frames - // will likely be corrupted but stability of VideoFrameCapturer will not be + // will likely be corrupted but stability of media::ScreenCapturer will not be // affected. video_capturer_->CaptureFrame(); } @@ -486,7 +486,7 @@ void DesktopSessionAgent::StopAudioCapturer() { void DesktopSessionAgent::StartVideoCapturer() { DCHECK(video_capture_task_runner()->BelongsToCurrentThread()); - video_capturer_ = VideoFrameCapturer::CreateWithFactory(this); + video_capturer_ = media::ScreenCapturer::CreateWithFactory(this); if (video_capturer_) video_capturer_->Start(this); } diff --git a/remoting/host/desktop_session_agent.h b/remoting/host/desktop_session_agent.h index b5e6556..b315b50 100644 --- a/remoting/host/desktop_session_agent.h +++ b/remoting/host/desktop_session_agent.h @@ -15,9 +15,9 @@ #include "base/memory/weak_ptr.h" #include "ipc/ipc_listener.h" #include "ipc/ipc_platform_file.h" -#include "remoting/capturer/shared_buffer.h" -#include "remoting/capturer/shared_buffer_factory.h" -#include "remoting/capturer/video_frame_capturer.h" +#include "media/video/capture/screen/screen_capturer.h" +#include "media/video/capture/screen/shared_buffer.h" +#include "media/video/capture/screen/shared_buffer_factory.h" #include "remoting/host/mouse_move_observer.h" #include "remoting/host/ui_strings.h" #include "remoting/protocol/clipboard_stub.h" @@ -49,8 +49,8 @@ class DesktopSessionAgent : public base::RefCountedThreadSafe<DesktopSessionAgent>, public IPC::Listener, public MouseMoveObserver, - public SharedBufferFactory, - public VideoFrameCapturer::Delegate { + public media::SharedBufferFactory, + public media::ScreenCapturer::Delegate { public: class Delegate { public: @@ -80,14 +80,16 @@ class DesktopSessionAgent virtual void OnLocalMouseMoved(const SkIPoint& new_pos) OVERRIDE; // SharedBufferFactory implementation. - virtual scoped_refptr<SharedBuffer> CreateSharedBuffer(uint32 size) OVERRIDE; - virtual void ReleaseSharedBuffer(scoped_refptr<SharedBuffer> buffer) OVERRIDE; + virtual scoped_refptr<media::SharedBuffer> CreateSharedBuffer( + uint32 size) OVERRIDE; + virtual void ReleaseSharedBuffer( + scoped_refptr<media::SharedBuffer> buffer) OVERRIDE; - // VideoFrameCapturer::Delegate implementation. + // media::ScreenCapturer::Delegate implementation. virtual void OnCaptureCompleted( - scoped_refptr<CaptureData> capture_data) OVERRIDE; + scoped_refptr<media::ScreenCaptureData> capture_data) OVERRIDE; virtual void OnCursorShapeChanged( - scoped_ptr<MouseCursorShape> cursor_shape) OVERRIDE; + scoped_ptr<media::MouseCursorShape> cursor_shape) OVERRIDE; // Forwards a local clipboard event though the IPC channel to the network // process. @@ -233,14 +235,14 @@ class DesktopSessionAgent int next_shared_buffer_id_; // List of the shared buffers registered via |SharedBufferFactory| interface. - typedef std::list<scoped_refptr<SharedBuffer> > SharedBuffers; + typedef std::list<scoped_refptr<media::SharedBuffer> > SharedBuffers; SharedBuffers shared_buffers_; // True if the desktop session agent has been started. bool started_; // Captures the screen. - scoped_ptr<VideoFrameCapturer> video_capturer_; + scoped_ptr<media::ScreenCapturer> video_capturer_; UiStrings ui_strings_; diff --git a/remoting/host/desktop_session_proxy.cc b/remoting/host/desktop_session_proxy.cc index 48e1547..c557853 100644 --- a/remoting/host/desktop_session_proxy.cc +++ b/remoting/host/desktop_session_proxy.cc @@ -10,7 +10,7 @@ #include "base/single_thread_task_runner.h" #include "ipc/ipc_channel_proxy.h" #include "ipc/ipc_message_macros.h" -#include "remoting/capturer/capture_data.h" +#include "media/video/capture/screen/screen_capture_data.h" #include "remoting/host/audio_capturer.h" #include "remoting/host/chromoting_messages.h" #include "remoting/host/client_session.h" @@ -59,14 +59,14 @@ scoped_ptr<EventExecutor> DesktopSessionProxy::CreateEventExecutor( return scoped_ptr<EventExecutor>(new IpcEventExecutor(this)); } -scoped_ptr<VideoFrameCapturer> DesktopSessionProxy::CreateVideoCapturer( +scoped_ptr<media::ScreenCapturer> DesktopSessionProxy::CreateVideoCapturer( scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner) { DCHECK(caller_task_runner_->BelongsToCurrentThread()); DCHECK(!video_capture_task_runner_.get()); video_capture_task_runner_ = capture_task_runner; - return scoped_ptr<VideoFrameCapturer>(new IpcVideoFrameCapturer(this)); + return scoped_ptr<media::ScreenCapturer>(new IpcVideoFrameCapturer(this)); } bool DesktopSessionProxy::OnMessageReceived(const IPC::Message& message) { @@ -169,7 +169,7 @@ void DesktopSessionProxy::DetachFromDesktop() { // Generate fake responses to keep the video capturer in sync. while (pending_capture_frame_requests_) { --pending_capture_frame_requests_; - PostCaptureCompleted(scoped_refptr<CaptureData>()); + PostCaptureCompleted(scoped_refptr<media::ScreenCaptureData>()); } } @@ -284,7 +284,8 @@ void DesktopSessionProxy::StartEventExecutor( DesktopSessionProxy::~DesktopSessionProxy() { } -scoped_refptr<SharedBuffer> DesktopSessionProxy::GetSharedBuffer(int id) { +scoped_refptr<media::SharedBuffer> DesktopSessionProxy::GetSharedBuffer( + int id) { DCHECK(caller_task_runner_->BelongsToCurrentThread()); SharedBuffers::const_iterator i = shared_buffers_.find(id); @@ -292,7 +293,7 @@ scoped_refptr<SharedBuffer> DesktopSessionProxy::GetSharedBuffer(int id) { return i->second; } else { LOG(ERROR) << "Failed to find the shared buffer " << id; - return scoped_refptr<SharedBuffer>(); + return scoped_refptr<media::SharedBuffer>(); } } @@ -316,12 +317,12 @@ void DesktopSessionProxy::OnCreateSharedBuffer( uint32 size) { DCHECK(caller_task_runner_->BelongsToCurrentThread()); - scoped_refptr<SharedBuffer> shared_buffer; + scoped_refptr<media::SharedBuffer> shared_buffer; #if defined(OS_WIN) - shared_buffer = new SharedBuffer(id, handle, desktop_process_, size); + shared_buffer = new media::SharedBuffer(id, handle, desktop_process_, size); #elif defined(OS_POSIX) - shared_buffer = new SharedBuffer(id, handle, size); + shared_buffer = new media::SharedBuffer(id, handle, size); #else #error Unsupported platform. #endif @@ -363,14 +364,15 @@ void DesktopSessionProxy::OnCaptureCompleted( // Assume that |serialized_data| is well formed because it was received from // a more privileged process. - scoped_refptr<CaptureData> capture_data; - scoped_refptr<SharedBuffer> shared_buffer = + scoped_refptr<media::ScreenCaptureData> capture_data; + scoped_refptr<media::SharedBuffer> shared_buffer = GetSharedBuffer(serialized_data.shared_buffer_id); CHECK(shared_buffer); - capture_data = new CaptureData(reinterpret_cast<uint8*>(shared_buffer->ptr()), - serialized_data.bytes_per_row, - serialized_data.dimensions); + capture_data = new media::ScreenCaptureData( + reinterpret_cast<uint8*>(shared_buffer->ptr()), + serialized_data.bytes_per_row, + serialized_data.dimensions); capture_data->set_capture_time_ms(serialized_data.capture_time_ms); capture_data->set_client_sequence_number( serialized_data.client_sequence_number); @@ -388,10 +390,10 @@ void DesktopSessionProxy::OnCaptureCompleted( } void DesktopSessionProxy::OnCursorShapeChanged( - const MouseCursorShape& cursor_shape) { + const media::MouseCursorShape& cursor_shape) { DCHECK(caller_task_runner_->BelongsToCurrentThread()); - PostCursorShape( - scoped_ptr<MouseCursorShape>(new MouseCursorShape(cursor_shape))); + PostCursorShape(scoped_ptr<media::MouseCursorShape>( + new media::MouseCursorShape(cursor_shape))); } void DesktopSessionProxy::OnInjectClipboardEvent( @@ -422,7 +424,7 @@ void DesktopSessionProxy::PostAudioPacket(scoped_ptr<AudioPacket> packet) { } void DesktopSessionProxy::PostCaptureCompleted( - scoped_refptr<CaptureData> capture_data) { + scoped_refptr<media::ScreenCaptureData> capture_data) { if (!video_capture_task_runner_->BelongsToCurrentThread()) { video_capture_task_runner_->PostTask( FROM_HERE, base::Bind(&DesktopSessionProxy::PostCaptureCompleted, @@ -435,7 +437,7 @@ void DesktopSessionProxy::PostCaptureCompleted( } void DesktopSessionProxy::PostCursorShape( - scoped_ptr<MouseCursorShape> cursor_shape) { + scoped_ptr<media::MouseCursorShape> cursor_shape) { if (!video_capture_task_runner_->BelongsToCurrentThread()) { video_capture_task_runner_->PostTask( FROM_HERE, base::Bind(&DesktopSessionProxy::PostCursorShape, diff --git a/remoting/host/desktop_session_proxy.h b/remoting/host/desktop_session_proxy.h index db4f26b..7988ce6 100644 --- a/remoting/host/desktop_session_proxy.h +++ b/remoting/host/desktop_session_proxy.h @@ -13,8 +13,8 @@ #include "base/memory/weak_ptr.h" #include "ipc/ipc_listener.h" #include "ipc/ipc_platform_file.h" -#include "remoting/capturer/shared_buffer.h" -#include "remoting/capturer/video_frame_capturer.h" +#include "media/video/capture/screen/screen_capturer.h" +#include "media/video/capture/screen/shared_buffer.h" #include "remoting/host/desktop_environment.h" #include "remoting/proto/event.pb.h" #include "remoting/protocol/clipboard_stub.h" @@ -60,7 +60,7 @@ class DesktopSessionProxy scoped_ptr<EventExecutor> CreateEventExecutor( scoped_refptr<base::SingleThreadTaskRunner> input_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner); - scoped_ptr<VideoFrameCapturer> CreateVideoCapturer( + scoped_ptr<media::ScreenCapturer> CreateVideoCapturer( scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner); @@ -88,7 +88,7 @@ class DesktopSessionProxy // StopAudioCapturer() has been called will be silently dropped. void StopAudioCapturer(); - // APIs used to implement the VideoFrameCapturer interface. These must be + // APIs used to implement the media::ScreenCapturer interface. These must be // called on |video_capture_task_runner_|. void InvalidateRegion(const SkRegion& invalid_region); void CaptureFrame(); @@ -112,7 +112,7 @@ class DesktopSessionProxy virtual ~DesktopSessionProxy(); // Returns a shared buffer from the list of known buffers. - scoped_refptr<SharedBuffer> GetSharedBuffer(int id); + scoped_refptr<media::SharedBuffer> GetSharedBuffer(int id); // Handles AudioPacket notification from the desktop session agent. void OnAudioPacket(const std::string& serialized_packet); @@ -129,7 +129,7 @@ class DesktopSessionProxy void OnCaptureCompleted(const SerializedCapturedData& serialized_data); // Handles CursorShapeChanged notification from the desktop session agent. - void OnCursorShapeChanged(const MouseCursorShape& cursor_shape); + void OnCursorShapeChanged(const media::MouseCursorShape& cursor_shape); // Handles InjectClipboardEvent request from the desktop integration process. void OnInjectClipboardEvent(const std::string& serialized_event); @@ -140,11 +140,12 @@ class DesktopSessionProxy // Posted to |video_capture_task_runner_| to pass a captured video frame back // to |video_capturer_|. - void PostCaptureCompleted(scoped_refptr<CaptureData> capture_data); + void PostCaptureCompleted( + scoped_refptr<media::ScreenCaptureData> capture_data); // Posted to |video_capture_task_runner_| to pass |cursor_shape| back to // |video_capturer_|. - void PostCursorShape(scoped_ptr<MouseCursorShape> cursor_shape); + void PostCursorShape(scoped_ptr<media::MouseCursorShape> cursor_shape); // Sends a message to the desktop session agent. The message is silently // deleted if the channel is broken. @@ -182,7 +183,7 @@ class DesktopSessionProxy int pending_capture_frame_requests_; - typedef std::map<int, scoped_refptr<SharedBuffer> > SharedBuffers; + typedef std::map<int, scoped_refptr<media::SharedBuffer> > SharedBuffers; SharedBuffers shared_buffers_; // Points to the video capturer receiving captured video frames. diff --git a/remoting/host/event_executor_mac.cc b/remoting/host/event_executor_mac.cc index 6eca1f6..b917ecc 100644 --- a/remoting/host/event_executor_mac.cc +++ b/remoting/host/event_executor_mac.cc @@ -14,7 +14,7 @@ #include "base/mac/scoped_cftyperef.h" #include "base/memory/ref_counted.h" #include "base/single_thread_task_runner.h" -#include "remoting/capturer/mac/desktop_configuration.h" +#include "media/video/capture/screen/mac/desktop_configuration.h" #include "remoting/host/clipboard.h" #include "remoting/proto/internal.pb.h" #include "remoting/protocol/message_decoder.h" @@ -192,8 +192,8 @@ void EventExecutorMac::Core::InjectMouseEvent(const MouseEvent& event) { // response to display-changed events. VideoFrameCapturer's VideoFrames // could be augmented to include native cursor coordinates for use by // MouseClampingFilter, removing the need for translation here. - MacDesktopConfiguration desktop_config - = MacDesktopConfiguration::GetCurrent(); + media::MacDesktopConfiguration desktop_config = + media::MacDesktopConfiguration::GetCurrent(); // Translate the mouse position into desktop coordinates. mouse_pos_ += SkIPoint::Make(desktop_config.pixel_bounds.left(), diff --git a/remoting/host/host_mock_objects.cc b/remoting/host/host_mock_objects.cc index 881683d..f8f1062 100644 --- a/remoting/host/host_mock_objects.cc +++ b/remoting/host/host_mock_objects.cc @@ -6,9 +6,9 @@ #include "base/message_loop_proxy.h" #include "base/single_thread_task_runner.h" +#include "media/video/capture/screen/screen_capturer.h" #include "net/base/ip_endpoint.h" #include "remoting/base/auto_thread_task_runner.h" -#include "remoting/capturer/video_frame_capturer.h" #include "remoting/codec/audio_encoder.h" #include "remoting/codec/video_encoder.h" #include "remoting/host/audio_capturer.h" @@ -34,10 +34,10 @@ scoped_ptr<EventExecutor> MockDesktopEnvironment::CreateEventExecutor( ui_task_runner)); } -scoped_ptr<VideoFrameCapturer> MockDesktopEnvironment::CreateVideoCapturer( +scoped_ptr<media::ScreenCapturer> MockDesktopEnvironment::CreateVideoCapturer( scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner) { - return scoped_ptr<VideoFrameCapturer>(CreateVideoCapturerPtr( + return scoped_ptr<media::ScreenCapturer>(CreateVideoCapturerPtr( capture_task_runner, encode_task_runner)); } diff --git a/remoting/host/host_mock_objects.h b/remoting/host/host_mock_objects.h index 4ca939d..1c32dab 100644 --- a/remoting/host/host_mock_objects.h +++ b/remoting/host/host_mock_objects.h @@ -35,7 +35,7 @@ class MockDesktopEnvironment : public DesktopEnvironment { scoped_refptr<base::SingleThreadTaskRunner>)); MOCK_METHOD2( CreateVideoCapturerPtr, - VideoFrameCapturer*(scoped_refptr<base::SingleThreadTaskRunner>, + media::ScreenCapturer*(scoped_refptr<base::SingleThreadTaskRunner>, scoped_refptr<base::SingleThreadTaskRunner>)); // DesktopEnvironment implementation. @@ -44,7 +44,7 @@ class MockDesktopEnvironment : public DesktopEnvironment { virtual scoped_ptr<EventExecutor> CreateEventExecutor( scoped_refptr<base::SingleThreadTaskRunner> input_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) OVERRIDE; - virtual scoped_ptr<VideoFrameCapturer> CreateVideoCapturer( + virtual scoped_ptr<media::ScreenCapturer> CreateVideoCapturer( scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner) OVERRIDE; }; diff --git a/remoting/host/ipc_desktop_environment.cc b/remoting/host/ipc_desktop_environment.cc index bc657a5..d94a381 100644 --- a/remoting/host/ipc_desktop_environment.cc +++ b/remoting/host/ipc_desktop_environment.cc @@ -11,7 +11,7 @@ #include "base/logging.h" #include "base/single_thread_task_runner.h" #include "ipc/ipc_channel_proxy.h" -#include "remoting/capturer/video_frame_capturer.h" +#include "media/video/capture/screen/screen_capturer.h" #include "remoting/host/audio_capturer.h" #include "remoting/host/chromoting_messages.h" #include "remoting/host/desktop_session_proxy.h" @@ -58,7 +58,7 @@ scoped_ptr<EventExecutor> IpcDesktopEnvironment::CreateEventExecutor( ui_task_runner); } -scoped_ptr<VideoFrameCapturer> IpcDesktopEnvironment::CreateVideoCapturer( +scoped_ptr<media::ScreenCapturer> IpcDesktopEnvironment::CreateVideoCapturer( scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner) { DCHECK(caller_task_runner_->BelongsToCurrentThread()); diff --git a/remoting/host/ipc_desktop_environment.h b/remoting/host/ipc_desktop_environment.h index c851221..10268c1 100644 --- a/remoting/host/ipc_desktop_environment.h +++ b/remoting/host/ipc_desktop_environment.h @@ -48,7 +48,7 @@ class IpcDesktopEnvironment : public DesktopEnvironment { virtual scoped_ptr<EventExecutor> CreateEventExecutor( scoped_refptr<base::SingleThreadTaskRunner> input_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) OVERRIDE; - virtual scoped_ptr<VideoFrameCapturer> CreateVideoCapturer( + virtual scoped_ptr<media::ScreenCapturer> CreateVideoCapturer( scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner) OVERRIDE; diff --git a/remoting/host/ipc_video_frame_capturer.cc b/remoting/host/ipc_video_frame_capturer.cc index ce35bc1..21aed74 100644 --- a/remoting/host/ipc_video_frame_capturer.cc +++ b/remoting/host/ipc_video_frame_capturer.cc @@ -4,8 +4,8 @@ #include "remoting/host/ipc_video_frame_capturer.h" -#include "remoting/capturer/capture_data.h" -#include "remoting/capturer/mouse_cursor_shape.h" +#include "media/video/capture/screen/mouse_cursor_shape.h" +#include "media/video/capture/screen/screen_capture_data.h" #include "remoting/host/desktop_session_proxy.h" namespace remoting { @@ -38,13 +38,13 @@ void IpcVideoFrameCapturer::CaptureFrame() { } void IpcVideoFrameCapturer::OnCaptureCompleted( - scoped_refptr<CaptureData> capture_data) { + scoped_refptr<media::ScreenCaptureData> capture_data) { if (delegate_) delegate_->OnCaptureCompleted(capture_data); } void IpcVideoFrameCapturer::OnCursorShapeChanged( - scoped_ptr<MouseCursorShape> cursor_shape) { + scoped_ptr<media::MouseCursorShape> cursor_shape) { if (delegate_) delegate_->OnCursorShapeChanged(cursor_shape.Pass()); } diff --git a/remoting/host/ipc_video_frame_capturer.h b/remoting/host/ipc_video_frame_capturer.h index ba5c517..681361b 100644 --- a/remoting/host/ipc_video_frame_capturer.h +++ b/remoting/host/ipc_video_frame_capturer.h @@ -6,26 +6,29 @@ #define REMOTING_HOST_IPC_VIDEO_FRAME_CAPTURER_H_ #include "base/memory/ref_counted.h" -#include "remoting/capturer/video_frame_capturer.h" +#include "media/video/capture/screen/screen_capturer.h" namespace IPC { class Message; } // namespace IPC +namespace media { +struct MouseCursorShape; +} // namespace media + namespace remoting { class DesktopSessionProxy; -struct MouseCursorShape; -// Routes VideoFrameCapturer calls though the IPC channel to the desktop session -// agent running in the desktop integration process. -class IpcVideoFrameCapturer : public VideoFrameCapturer { +// Routes media::ScreenCapturer calls though the IPC channel to the desktop +// session agent running in the desktop integration process. +class IpcVideoFrameCapturer : public media::ScreenCapturer { public: explicit IpcVideoFrameCapturer( scoped_refptr<DesktopSessionProxy> desktop_session_proxy); virtual ~IpcVideoFrameCapturer(); - // VideoFrameCapturer interface. + // media::ScreenCapturer interface. virtual void Start(Delegate* delegate) OVERRIDE; virtual void Stop() OVERRIDE; virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE; @@ -33,14 +36,14 @@ class IpcVideoFrameCapturer : public VideoFrameCapturer { // Called when a video frame has been captured. |capture_data| describes // a captured frame. - void OnCaptureCompleted(scoped_refptr<CaptureData> capture_data); + void OnCaptureCompleted(scoped_refptr<media::ScreenCaptureData> capture_data); // Called when the cursor shape has changed. - void OnCursorShapeChanged(scoped_ptr<MouseCursorShape> cursor_shape); + void OnCursorShapeChanged(scoped_ptr<media::MouseCursorShape> cursor_shape); private: - // Points to the delegate passed to VideoFrameCapturer::Start(). - VideoFrameCapturer::Delegate* delegate_; + // Points to the delegate passed to media::ScreenCapturer::Start(). + media::ScreenCapturer::Delegate* delegate_; // Wraps the IPC channel to the desktop session agent. scoped_refptr<DesktopSessionProxy> desktop_session_proxy_; diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc index 67b1045..3d692d7 100644 --- a/remoting/host/remoting_me2me_host.cc +++ b/remoting/host/remoting_me2me_host.cc @@ -28,12 +28,12 @@ #include "ipc/ipc_channel.h" #include "ipc/ipc_channel_proxy.h" #include "ipc/ipc_listener.h" +#include "media/video/capture/screen/screen_capturer.h" #include "net/base/network_change_notifier.h" #include "net/socket/ssl_server_socket.h" #include "remoting/base/auto_thread_task_runner.h" #include "remoting/base/breakpad.h" #include "remoting/base/constants.h" -#include "remoting/capturer/video_frame_capturer.h" #include "remoting/host/basic_desktop_environment.h" #include "remoting/host/branding.h" #include "remoting/host/chromoting_host.h" @@ -552,7 +552,7 @@ void HostProcess::StartOnUiThread() { #if defined(OS_LINUX) // TODO(sergeyu): Pass configuration parameters to the Linux-specific version // of DesktopEnvironmentFactory when we have it. - remoting::VideoFrameCapturer::EnableXDamage(true); + media::ScreenCapturer::EnableXDamage(true); // If an audio pipe is specific on the command-line then initialize // AudioCapturerLinux to capture from it. diff --git a/remoting/host/sas_injector_win.cc b/remoting/host/sas_injector_win.cc index 3a4ad6f..efab8e6 100644 --- a/remoting/host/sas_injector_win.cc +++ b/remoting/host/sas_injector_win.cc @@ -14,8 +14,8 @@ #include "base/utf_string_conversions.h" #include "base/win/registry.h" #include "base/win/windows_version.h" -#include "remoting/capturer/win/desktop.h" -#include "remoting/capturer/win/scoped_thread_desktop.h" +#include "media/video/capture/screen/win/desktop.h" +#include "media/video/capture/screen/win/scoped_thread_desktop.h" namespace remoting { @@ -190,15 +190,15 @@ bool SasInjectorXp::InjectSas() { const wchar_t kSasWindowClassName[] = L"SAS window class"; const wchar_t kSasWindowTitle[] = L"SAS window"; - scoped_ptr<remoting::Desktop> winlogon_desktop( - remoting::Desktop::GetDesktop(kWinlogonDesktopName)); + scoped_ptr<media::Desktop> winlogon_desktop( + media::Desktop::GetDesktop(kWinlogonDesktopName)); if (!winlogon_desktop.get()) { LOG_GETLASTERROR(ERROR) << "Failed to open '" << kWinlogonDesktopName << "' desktop"; return false; } - remoting::ScopedThreadDesktop desktop; + media::ScopedThreadDesktop desktop; if (!desktop.SetThreadDesktop(winlogon_desktop.Pass())) { LOG_GETLASTERROR(ERROR) << "Failed to switch to '" << kWinlogonDesktopName << "' desktop"; diff --git a/remoting/host/video_scheduler.cc b/remoting/host/video_scheduler.cc index 5f2acae..90e635f 100644 --- a/remoting/host/video_scheduler.cc +++ b/remoting/host/video_scheduler.cc @@ -14,9 +14,9 @@ #include "base/stl_util.h" #include "base/sys_info.h" #include "base/time.h" -#include "remoting/capturer/capture_data.h" -#include "remoting/capturer/mouse_cursor_shape.h" -#include "remoting/capturer/video_frame_capturer.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 "remoting/proto/control.pb.h" #include "remoting/proto/internal.pb.h" #include "remoting/proto/video.pb.h" @@ -36,7 +36,7 @@ scoped_refptr<VideoScheduler> VideoScheduler::Create( scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner, scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, - scoped_ptr<VideoFrameCapturer> capturer, + scoped_ptr<media::ScreenCapturer> capturer, scoped_ptr<VideoEncoder> encoder, protocol::CursorShapeStub* cursor_stub, protocol::VideoStub* video_stub) { @@ -58,7 +58,7 @@ scoped_refptr<VideoScheduler> VideoScheduler::Create( // Public methods -------------------------------------------------------------- void VideoScheduler::OnCaptureCompleted( - scoped_refptr<CaptureData> capture_data) { + scoped_refptr<media::ScreenCaptureData> capture_data) { DCHECK(capture_task_runner_->BelongsToCurrentThread()); if (capture_data) { @@ -78,7 +78,7 @@ void VideoScheduler::OnCaptureCompleted( } void VideoScheduler::OnCursorShapeChanged( - scoped_ptr<MouseCursorShape> cursor_shape) { + scoped_ptr<media::MouseCursorShape> cursor_shape) { DCHECK(capture_task_runner_->BelongsToCurrentThread()); scoped_ptr<protocol::CursorShapeInfo> cursor_proto( @@ -140,7 +140,7 @@ VideoScheduler::VideoScheduler( scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner, scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, - scoped_ptr<VideoFrameCapturer> capturer, + scoped_ptr<media::ScreenCapturer> capturer, scoped_ptr<VideoEncoder> encoder, protocol::CursorShapeStub* cursor_stub, protocol::VideoStub* video_stub) @@ -279,7 +279,7 @@ void VideoScheduler::SendCursorShape( } void VideoScheduler::StopOnNetworkThread( - scoped_ptr<VideoFrameCapturer> capturer) { + scoped_ptr<media::ScreenCapturer> capturer) { DCHECK(network_task_runner_->BelongsToCurrentThread()); // This is posted by StopOnEncodeThread meaning that both capture and encode @@ -289,7 +289,7 @@ void VideoScheduler::StopOnNetworkThread( // Encoder thread -------------------------------------------------------------- void VideoScheduler::EncodeFrame( - scoped_refptr<CaptureData> capture_data) { + scoped_refptr<media::ScreenCaptureData> capture_data) { DCHECK(encode_task_runner_->BelongsToCurrentThread()); // If there is nothing to encode then send an empty keep-alive packet. @@ -323,7 +323,7 @@ void VideoScheduler::EncodedDataAvailableCallback( } void VideoScheduler::StopOnEncodeThread( - scoped_ptr<VideoFrameCapturer> capturer) { + scoped_ptr<media::ScreenCapturer> capturer) { DCHECK(encode_task_runner_->BelongsToCurrentThread()); // This is posted by StopOnCaptureThread, so we know that by the time we diff --git a/remoting/host/video_scheduler.h b/remoting/host/video_scheduler.h index 752dcbe..0e47713 100644 --- a/remoting/host/video_scheduler.h +++ b/remoting/host/video_scheduler.h @@ -12,7 +12,7 @@ #include "base/memory/scoped_ptr.h" #include "base/time.h" #include "base/timer.h" -#include "remoting/capturer/video_frame_capturer.h" +#include "media/video/capture/screen/screen_capturer.h" #include "remoting/codec/video_encoder.h" #include "remoting/host/capture_scheduler.h" #include "remoting/proto/video.pb.h" @@ -22,11 +22,14 @@ namespace base { class SingleThreadTaskRunner; } // namespace base +namespace media { +class ScreenCaptureData; +class ScreenCapturer; +} // namespace media + namespace remoting { -class CaptureData; class CursorShapeInfo; -class VideoFrameCapturer; namespace protocol { class CursorShapeInfo; @@ -34,7 +37,7 @@ class CursorShapeStub; class VideoStub; } // namespace protocol -// Class responsible for scheduling frame captures from a VideoFrameCapturer, +// Class responsible for scheduling frame captures from a media::ScreenCapturer, // delivering them to a VideoEncoder to encode, and finally passing the encoded // video packets to the specified VideoStub to send on the network. // @@ -71,7 +74,7 @@ class VideoStub; // too much CPU, or hogging the host's graphics subsystem. class VideoScheduler : public base::RefCountedThreadSafe<VideoScheduler>, - public VideoFrameCapturer::Delegate { + public media::ScreenCapturer::Delegate { public: // Creates a VideoScheduler running capture, encode and network tasks on the // supplied TaskRunners. Video and cursor shape updates will be pumped to @@ -81,16 +84,16 @@ class VideoScheduler : public base::RefCountedThreadSafe<VideoScheduler>, scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner, scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, - scoped_ptr<VideoFrameCapturer> capturer, + scoped_ptr<media::ScreenCapturer> capturer, scoped_ptr<VideoEncoder> encoder, protocol::CursorShapeStub* cursor_stub, protocol::VideoStub* video_stub); - // VideoFrameCapturer::Delegate implementation. + // media::ScreenCapturer::Delegate implementation. virtual void OnCaptureCompleted( - scoped_refptr<CaptureData> capture_data) OVERRIDE; + scoped_refptr<media::ScreenCaptureData> capture_data) OVERRIDE; virtual void OnCursorShapeChanged( - scoped_ptr<MouseCursorShape> cursor_shape) OVERRIDE; + scoped_ptr<media::MouseCursorShape> cursor_shape) OVERRIDE; // Stop scheduling frame captures. This object cannot be re-used once // it has been stopped. @@ -111,7 +114,7 @@ class VideoScheduler : public base::RefCountedThreadSafe<VideoScheduler>, scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner, scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, - scoped_ptr<VideoFrameCapturer> capturer, + scoped_ptr<media::ScreenCapturer> capturer, scoped_ptr<VideoEncoder> encoder, protocol::CursorShapeStub* cursor_stub, protocol::VideoStub* video_stub); @@ -149,18 +152,18 @@ class VideoScheduler : public base::RefCountedThreadSafe<VideoScheduler>, // Posted to the network thread to delete |capturer| on the thread that // created it. - void StopOnNetworkThread(scoped_ptr<VideoFrameCapturer> capturer); + void StopOnNetworkThread(scoped_ptr<media::ScreenCapturer> capturer); // Encoder thread ----------------------------------------------------------- // Encode a frame, passing generated VideoPackets to SendVideoPacket(). - void EncodeFrame(scoped_refptr<CaptureData> capture_data); + void EncodeFrame(scoped_refptr<media::ScreenCaptureData> capture_data); void EncodedDataAvailableCallback(scoped_ptr<VideoPacket> packet); // Used to synchronize capture and encode thread teardown, notifying the // network thread when done. - void StopOnEncodeThread(scoped_ptr<VideoFrameCapturer> capturer); + void StopOnEncodeThread(scoped_ptr<media::ScreenCapturer> capturer); // Task runners used by this class. scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner_; @@ -168,7 +171,7 @@ class VideoScheduler : public base::RefCountedThreadSafe<VideoScheduler>, scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_; // Used to capture frames. Always accessed on the capture thread. - scoped_ptr<VideoFrameCapturer> capturer_; + scoped_ptr<media::ScreenCapturer> capturer_; // Used to encode captured frames. Always accessed on the encode thread. scoped_ptr<VideoEncoder> encoder_; diff --git a/remoting/host/video_scheduler_unittest.cc b/remoting/host/video_scheduler_unittest.cc index 04e1b0a..80b2b332 100644 --- a/remoting/host/video_scheduler_unittest.cc +++ b/remoting/host/video_scheduler_unittest.cc @@ -7,9 +7,9 @@ #include "base/bind.h" #include "base/message_loop.h" #include "base/run_loop.h" +#include "media/video/capture/screen/screen_capture_data.h" +#include "media/video/capture/screen/screen_capturer_mock_objects.h" #include "remoting/base/auto_thread_task_runner.h" -#include "remoting/capturer/capture_data.h" -#include "remoting/capturer/video_capturer_mock_objects.h" #include "remoting/codec/video_encoder.h" #include "remoting/proto/video.pb.h" #include "remoting/protocol/protocol_mock_objects.h" @@ -56,7 +56,7 @@ class MockVideoEncoder : public VideoEncoder { virtual ~MockVideoEncoder(); MOCK_METHOD3(Encode, void( - scoped_refptr<CaptureData> capture_data, + scoped_refptr<media::ScreenCaptureData> capture_data, bool key_frame, const DataAvailableCallback& data_available_callback)); @@ -74,11 +74,11 @@ class VideoSchedulerTest : public testing::Test { virtual void SetUp() OVERRIDE; - void StartVideoScheduler(scoped_ptr<VideoFrameCapturer> capturer); + void StartVideoScheduler(scoped_ptr<media::ScreenCapturer> capturer); void StopVideoScheduler(); - // VideoFrameCapturer mocks. - void OnCapturerStart(VideoFrameCapturer::Delegate* delegate); + // media::ScreenCapturer mocks. + void OnCapturerStart(media::ScreenCapturer::Delegate* delegate); void OnCapturerStop(); void OnCaptureFrame(); @@ -94,10 +94,10 @@ class VideoSchedulerTest : public testing::Test { // The following mock objects are owned by VideoScheduler. MockVideoEncoder* encoder_; - scoped_refptr<CaptureData> data_; + scoped_refptr<media::ScreenCaptureData> data_; - // Points to the delegate passed to VideoFrameCapturer::Start(). - VideoFrameCapturer::Delegate* capturer_delegate_; + // Points to the delegate passed to media::ScreenCapturer::Start(). + media::ScreenCapturer::Delegate* capturer_delegate_; private: DISALLOW_COPY_AND_ASSIGN(VideoSchedulerTest); @@ -116,7 +116,7 @@ void VideoSchedulerTest::SetUp() { } void VideoSchedulerTest::StartVideoScheduler( - scoped_ptr<VideoFrameCapturer> capturer) { + scoped_ptr<media::ScreenCapturer> capturer) { scheduler_ = VideoScheduler::Create( task_runner_, // Capture task_runner_, // Encode @@ -133,7 +133,7 @@ void VideoSchedulerTest::StopVideoScheduler() { } void VideoSchedulerTest::OnCapturerStart( - VideoFrameCapturer::Delegate* delegate) { + media::ScreenCapturer::Delegate* delegate) { EXPECT_FALSE(capturer_delegate_); EXPECT_TRUE(delegate); @@ -156,16 +156,18 @@ void VideoSchedulerTest::OnCaptureFrame() { // VideoScheduler is instructed to come to a complete stop. We expect the stop // sequence to be executed successfully. TEST_F(VideoSchedulerTest, StartAndStop) { - scoped_ptr<MockVideoFrameCapturer> capturer_(new MockVideoFrameCapturer()); + scoped_ptr<media::MockScreenCapturer> capturer( + new media::MockScreenCapturer()); Expectation capturer_start = - EXPECT_CALL(*capturer_, Start(_)) + EXPECT_CALL(*capturer, Start(_)) .WillOnce(Invoke(this, &VideoSchedulerTest::OnCapturerStart)); - data_ = new CaptureData(NULL, kWidth * CaptureData::kBytesPerPixel, - SkISize::Make(kWidth, kHeight)); + data_ = new media::ScreenCaptureData( + NULL, kWidth * media::ScreenCaptureData::kBytesPerPixel, + SkISize::Make(kWidth, kHeight)); // First the capturer is called. - Expectation capturer_capture = EXPECT_CALL(*capturer_, CaptureFrame()) + Expectation capturer_capture = EXPECT_CALL(*capturer, CaptureFrame()) .After(capturer_start) .WillRepeatedly(Invoke(this, &VideoSchedulerTest::OnCaptureFrame)); @@ -185,12 +187,12 @@ TEST_F(VideoSchedulerTest, StartAndStop) { InvokeWithoutArgs(this, &VideoSchedulerTest::StopVideoScheduler))) .RetiresOnSaturation(); - EXPECT_CALL(*capturer_, Stop()) + EXPECT_CALL(*capturer, Stop()) .After(capturer_capture) .WillOnce(Invoke(this, &VideoSchedulerTest::OnCapturerStop)); // Start video frame capture. - StartVideoScheduler(capturer_.PassAs<VideoFrameCapturer>()); + StartVideoScheduler(capturer.PassAs<media::ScreenCapturer>()); task_runner_ = NULL; run_loop_.Run(); diff --git a/remoting/host/win/session_desktop_environment.cc b/remoting/host/win/session_desktop_environment.cc index 35e28bf..fd6ee85 100644 --- a/remoting/host/win/session_desktop_environment.cc +++ b/remoting/host/win/session_desktop_environment.cc @@ -6,7 +6,7 @@ #include "base/logging.h" #include "base/single_thread_task_runner.h" -#include "remoting/capturer/video_frame_capturer.h" +#include "media/video/capture/screen/screen_capturer.h" #include "remoting/host/audio_capturer.h" #include "remoting/host/event_executor.h" #include "remoting/host/win/session_event_executor.h" diff --git a/remoting/host/win/session_event_executor.cc b/remoting/host/win/session_event_executor.cc index 5afb41e..78121f1 100644 --- a/remoting/host/win/session_event_executor.cc +++ b/remoting/host/win/session_event_executor.cc @@ -13,8 +13,8 @@ #include "base/location.h" #include "base/single_thread_task_runner.h" #include "base/win/windows_version.h" -#include "remoting/capturer/win/desktop.h" -#include "remoting/capturer/win/scoped_thread_desktop.h" +#include "media/video/capture/screen/win/desktop.h" +#include "media/video/capture/screen/win/scoped_thread_desktop.h" #include "remoting/host/sas_injector.h" #include "remoting/proto/event.pb.h" @@ -80,7 +80,7 @@ class SessionEventExecutorWin::Core scoped_refptr<base::SingleThreadTaskRunner> inject_sas_task_runner_; - ScopedThreadDesktop desktop_; + media::ScopedThreadDesktop desktop_; // Used to inject Secure Attention Sequence on Vista+. base::Closure inject_sas_; @@ -182,7 +182,7 @@ SessionEventExecutorWin::Core::~Core() { void SessionEventExecutorWin::Core::SwitchToInputDesktop() { // Switch to the desktop receiving user input if different from the current // one. - scoped_ptr<Desktop> input_desktop = Desktop::GetInputDesktop(); + scoped_ptr<media::Desktop> input_desktop = media::Desktop::GetInputDesktop(); if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) { // If SetThreadDesktop() fails, the thread is still assigned a desktop. // So we can continue capture screen bits, just from a diffected desktop. diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index 1382a7c..99d983f 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp @@ -246,80 +246,6 @@ }, 'conditions': [ - ['OS=="win" or OS=="mac" or OS=="linux"', { - 'targets': [ - { - 'target_name': 'remoting_screen_capturer', - 'type': 'static_library', - 'variables': { 'enable_wexit_time_destructors': 1, }, - 'dependencies': [ - '../skia/skia.gyp:skia', - ], - 'sources': [ - 'capturer/capture_data.cc', - 'capturer/capture_data.h', - 'capturer/shared_buffer.cc', - 'capturer/shared_buffer.h', - 'capturer/shared_buffer_factory.h', - 'capturer/differ.cc', - 'capturer/differ.h', - 'capturer/differ_block.cc', - 'capturer/differ_block.h', - 'capturer/linux/x_server_pixel_buffer.cc', - 'capturer/linux/x_server_pixel_buffer.h', - 'capturer/mac/desktop_configuration.mm', - 'capturer/mac/desktop_configuration.h', - 'capturer/mac/scoped_pixel_buffer_object.cc', - 'capturer/mac/scoped_pixel_buffer_object.h', - 'capturer/mouse_cursor_shape.cc', - 'capturer/mouse_cursor_shape.h', - 'capturer/video_frame.cc', - 'capturer/video_frame.h', - 'capturer/video_frame_capturer.h', - 'capturer/video_frame_capturer_fake.cc', - 'capturer/video_frame_capturer_fake.h', - 'capturer/video_frame_capturer_helper.cc', - 'capturer/video_frame_capturer_helper.h', - 'capturer/video_frame_capturer_linux.cc', - 'capturer/video_frame_capturer_mac.mm', - 'capturer/video_frame_capturer_win.cc', - 'capturer/video_frame_queue.cc', - 'capturer/video_frame_queue.h', - 'capturer/win/desktop.cc', - 'capturer/win/desktop.h', - 'capturer/win/scoped_thread_desktop.cc', - 'capturer/win/scoped_thread_desktop.h', - ], - 'conditions': [ - [ 'target_arch == "ia32" or target_arch == "x64"', { - 'dependencies': [ - 'differ_block_sse2', - ], - }], - ['OS=="linux"', { - 'link_settings': { - 'libraries': [ - '-lX11', - '-lXdamage', - '-lXext', - '-lXfixes', - ], - }, - }], - ['toolkit_uses_gtk==1', { - 'dependencies': [ - '../build/linux/system.gyp:gtk', - ], - }, { # else toolkit_uses_gtk!=1 - 'sources!': [ - '*_gtk.cc', - ], - }], - ], - }, # end of target remoting_screen_capturer - ], # end of 'targets' - }], # 'OS==win or OS==mac or OS==linux' - ['enable_remoting_host==1', { 'targets': [ { @@ -330,9 +256,9 @@ 'remoting_base', 'remoting_jingle_glue', 'remoting_protocol', - 'remoting_screen_capturer', '../crypto/crypto.gyp:crypto', '../google_apis/google_apis.gyp:google_apis', + '../media/media.gyp:media', '../ipc/ipc.gyp:ipc', ], 'defines': [ @@ -527,12 +453,6 @@ '../third_party/GTM/DebugUtils', '../third_party/GTM/Foundation', ], - 'link_settings': { - 'libraries': [ - '$(SDKROOT)/System/Library/Frameworks/OpenGL.framework', - 'libpam.a', - ], - }, }], ['OS=="win"', { 'dependencies': [ @@ -2179,22 +2099,6 @@ ], }, # end of target 'remoting_protocol' - { - 'target_name': 'differ_block_sse2', - 'type': 'static_library', - 'conditions': [ - [ 'os_posix == 1 and OS != "mac"', { - 'cflags': [ - '-msse2', - ], - }], - ], - 'sources': [ - 'capturer/differ_block_sse2.cc', - 'capturer/differ_block_sse2.h', - ], - }, # end of target differ_block_sse2 - # Remoting unit tests { 'target_name': 'remoting_unittests', @@ -2208,13 +2112,13 @@ 'remoting_host', 'remoting_jingle_glue', 'remoting_protocol', - 'remoting_screen_capturer', 'remoting_host_setup_base', '../base/base.gyp:base', '../base/base.gyp:base_i18n', '../base/base.gyp:test_support_base', '../ipc/ipc.gyp:ipc', '../media/media.gyp:media', + '../media/media.gyp:media_test_support', '../net/net.gyp:net_test_support', '../ppapi/ppapi.gyp:ppapi_cpp', '../testing/gmock.gyp:gmock', @@ -2237,14 +2141,6 @@ 'base/resources_unittest.cc', 'base/typed_buffer_unittest.cc', 'base/util_unittest.cc', - 'capturer/video_capturer_mock_objects.cc', - 'capturer/video_capturer_mock_objects.h', - 'capturer/differ_block_unittest.cc', - 'capturer/differ_unittest.cc', - 'capturer/shared_buffer_unittest.cc', - 'capturer/video_frame_capturer_helper_unittest.cc', - 'capturer/video_frame_capturer_mac_unittest.cc', - 'capturer/video_frame_capturer_unittest.cc', 'client/audio_player_unittest.cc', 'client/key_event_mapper_unittest.cc', 'client/plugin/mac_key_event_processor_unittest.cc', |