| Index: remoting/host/video_frame_capturer_mac_unittest.cc
|
| diff --git a/remoting/host/video_frame_capturer_mac_unittest.cc b/remoting/host/video_frame_capturer_mac_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..0bd3e117306ce720211364ecd0a86bbc1ab9844a
|
| --- /dev/null
|
| +++ b/remoting/host/video_frame_capturer_mac_unittest.cc
|
| @@ -0,0 +1,155 @@
|
| +// 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/host/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/base/capture_data.h"
|
| +#include "remoting/proto/control.pb.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +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 {
|
| + protected:
|
| + virtual void SetUp() OVERRIDE {
|
| + capturer_.reset(VideoFrameCapturer::Create());
|
| + }
|
| +
|
| + void AddDirtyRect() {
|
| + SkIRect rect = SkIRect::MakeXYWH(0, 0, 10, 10);
|
| + region_.op(rect, SkRegion::kUnion_Op);
|
| + }
|
| +
|
| + scoped_ptr<VideoFrameCapturer> capturer_;
|
| + SkRegion region_;
|
| +};
|
| +
|
| +// CapturerCallback1 verifies that the whole screen is initially dirty.
|
| +class VideoFrameCapturerCallback1 {
|
| + public:
|
| + VideoFrameCapturerCallback1() {}
|
| +
|
| + void CaptureDoneCallback(scoped_refptr<CaptureData> capture_data);
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerCallback1);
|
| +};
|
| +
|
| +void VideoFrameCapturerCallback1::CaptureDoneCallback(
|
| + 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());
|
| +}
|
| +
|
| +// VideoFrameCapturerCallback2 verifies that a rectangle explicitly marked as
|
| +// dirty is propagated correctly.
|
| +class VideoFrameCapturerCallback2 {
|
| + public:
|
| + explicit VideoFrameCapturerCallback2(const SkRegion& expected_dirty_region)
|
| + : expected_dirty_region_(expected_dirty_region) {}
|
| +
|
| + void CaptureDoneCallback(scoped_refptr<CaptureData> capture_data);
|
| +
|
| + protected:
|
| + SkRegion expected_dirty_region_;
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerCallback2);
|
| +};
|
| +
|
| +void VideoFrameCapturerCallback2::CaptureDoneCallback(
|
| + scoped_refptr<CaptureData> capture_data) {
|
| + CGDirectDisplayID mainDevice = CGMainDisplayID();
|
| + int width = CGDisplayPixelsWide(mainDevice);
|
| + int height = CGDisplayPixelsHigh(mainDevice);
|
| +
|
| + EXPECT_EQ(expected_dirty_region_, capture_data->dirty_region());
|
| + EXPECT_EQ(width, capture_data->size().width());
|
| + EXPECT_EQ(height, capture_data->size().height());
|
| + const DataPlanes &planes = capture_data->data_planes();
|
| + EXPECT_TRUE(planes.data[0] != NULL);
|
| + EXPECT_TRUE(planes.data[1] == NULL);
|
| + EXPECT_TRUE(planes.data[2] == 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(planes.strides[0]));
|
| + EXPECT_EQ(0, planes.strides[1]);
|
| + EXPECT_EQ(0, planes.strides[2]);
|
| +}
|
| +
|
| +class CursorCallback {
|
| + public:
|
| + CursorCallback() {}
|
| +
|
| + void CursorShapeChangedCallback(
|
| + scoped_ptr<protocol::CursorShapeInfo> cursor_data);
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(CursorCallback);
|
| +};
|
| +
|
| +void CursorCallback::CursorShapeChangedCallback(
|
| + scoped_ptr<protocol::CursorShapeInfo> cursor_data) {
|
| +}
|
| +
|
| +TEST_F(VideoFrameCapturerMacTest, Capture) {
|
| + if (!CheckSnowLeopard()) {
|
| + return;
|
| + }
|
| +
|
| + SCOPED_TRACE("");
|
| + CursorCallback cursor_callback;
|
| + capturer_->Start(base::Bind(&CursorCallback::CursorShapeChangedCallback,
|
| + base::Unretained(&cursor_callback)));
|
| + // Check that we get an initial full-screen updated.
|
| + VideoFrameCapturerCallback1 callback1;
|
| + capturer_->CaptureInvalidRegion(base::Bind(
|
| + &VideoFrameCapturerCallback1::CaptureDoneCallback,
|
| + base::Unretained(&callback1)));
|
| + // Check that subsequent dirty rects are propagated correctly.
|
| + AddDirtyRect();
|
| + VideoFrameCapturerCallback2 callback2(region_);
|
| + capturer_->InvalidateRegion(region_);
|
| + capturer_->CaptureInvalidRegion(base::Bind(
|
| + &VideoFrameCapturerCallback2::CaptureDoneCallback,
|
| + base::Unretained(&callback2)));
|
| + 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
|
|
|