Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / content / browser / media / capture / desktop_capture_device_unittest.cc
blob5d37d117a18068f9488a2e78ed326267ee036cde
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/media/capture/desktop_capture_device.h"
7 #include "base/basictypes.h"
8 #include "base/synchronization/waitable_event.h"
9 #include "base/test/test_timeouts.h"
10 #include "base/time/time.h"
11 #include "content/public/test/test_browser_thread_bundle.h"
12 #include "testing/gmock/include/gmock/gmock.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
15 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
16 #include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
18 using ::testing::_;
19 using ::testing::AnyNumber;
20 using ::testing::DoAll;
21 using ::testing::Expectation;
22 using ::testing::InvokeWithoutArgs;
23 using ::testing::SaveArg;
25 namespace content {
27 namespace {
29 MATCHER_P2(EqualsCaptureCapability, width, height, "") {
30 return arg.width == width && arg.height == height;
33 const int kTestFrameWidth1 = 100;
34 const int kTestFrameHeight1 = 100;
35 const int kTestFrameWidth2 = 200;
36 const int kTestFrameHeight2 = 150;
38 const int kFrameRate = 30;
40 class MockDeviceClient : public media::VideoCaptureDevice::Client {
41 public:
42 MOCK_METHOD2(ReserveOutputBuffer,
43 scoped_refptr<Buffer>(media::VideoFrame::Format format,
44 const gfx::Size& dimensions));
45 MOCK_METHOD1(OnError, void(const std::string& reason));
46 MOCK_METHOD5(OnIncomingCapturedData,
47 void(const uint8* data,
48 int length,
49 const media::VideoCaptureFormat& frame_format,
50 int rotation,
51 base::TimeTicks timestamp));
52 MOCK_METHOD4(OnIncomingCapturedVideoFrame,
53 void(const scoped_refptr<Buffer>& buffer,
54 const media::VideoCaptureFormat& buffer_format,
55 const scoped_refptr<media::VideoFrame>& frame,
56 base::TimeTicks timestamp));
59 // DesktopFrame wrapper that flips wrapped frame upside down by inverting
60 // stride.
61 class InvertedDesktopFrame : public webrtc::DesktopFrame {
62 public:
63 // Takes ownership of |frame|.
64 InvertedDesktopFrame(webrtc::DesktopFrame* frame)
65 : webrtc::DesktopFrame(
66 frame->size(), -frame->stride(),
67 frame->data() + (frame->size().height() - 1) * frame->stride(),
68 frame->shared_memory()),
69 original_frame_(frame) {
70 set_dpi(frame->dpi());
71 set_capture_time_ms(frame->capture_time_ms());
72 mutable_updated_region()->Swap(frame->mutable_updated_region());
74 virtual ~InvertedDesktopFrame() {}
76 private:
77 scoped_ptr<webrtc::DesktopFrame> original_frame_;
79 DISALLOW_COPY_AND_ASSIGN(InvertedDesktopFrame);
82 // TODO(sergeyu): Move this to a separate file where it can be reused.
83 class FakeScreenCapturer : public webrtc::ScreenCapturer {
84 public:
85 FakeScreenCapturer()
86 : callback_(NULL),
87 frame_index_(0),
88 generate_inverted_frames_(false) {
90 virtual ~FakeScreenCapturer() {}
92 void set_generate_inverted_frames(bool generate_inverted_frames) {
93 generate_inverted_frames_ = generate_inverted_frames;
96 // VideoFrameCapturer interface.
97 virtual void Start(Callback* callback) OVERRIDE {
98 callback_ = callback;
101 virtual void Capture(const webrtc::DesktopRegion& region) OVERRIDE {
102 webrtc::DesktopSize size;
103 if (frame_index_ % 2 == 0) {
104 size = webrtc::DesktopSize(kTestFrameWidth1, kTestFrameHeight1);
105 } else {
106 size = webrtc::DesktopSize(kTestFrameWidth2, kTestFrameHeight2);
108 frame_index_++;
110 webrtc::DesktopFrame* frame = new webrtc::BasicDesktopFrame(size);
111 if (generate_inverted_frames_)
112 frame = new InvertedDesktopFrame(frame);
113 callback_->OnCaptureCompleted(frame);
116 virtual void SetMouseShapeObserver(
117 MouseShapeObserver* mouse_shape_observer) OVERRIDE {
120 virtual bool GetScreenList(ScreenList* screens) OVERRIDE {
121 return false;
124 virtual bool SelectScreen(webrtc::ScreenId id) OVERRIDE {
125 return false;
128 private:
129 Callback* callback_;
130 int frame_index_;
131 bool generate_inverted_frames_;
134 } // namespace
136 class DesktopCaptureDeviceTest : public testing::Test {
137 public:
138 void CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer> capturer) {
139 capture_device_.reset(
140 new DesktopCaptureDevice(capturer.Pass(), DesktopMediaID::TYPE_SCREEN));
143 protected:
144 scoped_ptr<DesktopCaptureDevice> capture_device_;
147 // There is currently no screen capturer implementation for ozone. So disable
148 // the test that uses a real screen-capturer instead of FakeScreenCapturer.
149 // http://crbug.com/260318
150 #if defined(USE_OZONE)
151 #define MAYBE_Capture DISABLED_Capture
152 #else
153 #define MAYBE_Capture Capture
154 #endif
155 TEST_F(DesktopCaptureDeviceTest, MAYBE_Capture) {
156 scoped_ptr<webrtc::DesktopCapturer> capturer(
157 webrtc::ScreenCapturer::Create());
158 CreateScreenCaptureDevice(capturer.Pass());
160 media::VideoCaptureFormat format;
161 base::WaitableEvent done_event(false, false);
162 int frame_size;
164 scoped_ptr<MockDeviceClient> client(new MockDeviceClient());
165 EXPECT_CALL(*client, OnError(_)).Times(0);
166 EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly(
167 DoAll(SaveArg<1>(&frame_size),
168 SaveArg<2>(&format),
169 InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
171 media::VideoCaptureParams capture_params;
172 capture_params.requested_format.frame_size.SetSize(640, 480);
173 capture_params.requested_format.frame_rate = kFrameRate;
174 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
175 capture_params.allow_resolution_change = false;
176 capture_device_->AllocateAndStart(
177 capture_params, client.PassAs<media::VideoCaptureDevice::Client>());
178 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
179 capture_device_->StopAndDeAllocate();
181 EXPECT_GT(format.frame_size.width(), 0);
182 EXPECT_GT(format.frame_size.height(), 0);
183 EXPECT_EQ(kFrameRate, format.frame_rate);
184 EXPECT_EQ(media::PIXEL_FORMAT_ARGB, format.pixel_format);
186 EXPECT_EQ(format.frame_size.GetArea() * 4, frame_size);
189 // Test that screen capturer behaves correctly if the source frame size changes
190 // but the caller cannot cope with variable resolution output.
191 TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeConstantResolution) {
192 FakeScreenCapturer* mock_capturer = new FakeScreenCapturer();
194 CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer>(mock_capturer));
196 media::VideoCaptureFormat format;
197 base::WaitableEvent done_event(false, false);
198 int frame_size;
200 scoped_ptr<MockDeviceClient> client(new MockDeviceClient());
201 EXPECT_CALL(*client, OnError(_)).Times(0);
202 EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly(
203 DoAll(SaveArg<1>(&frame_size),
204 SaveArg<2>(&format),
205 InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
207 media::VideoCaptureParams capture_params;
208 capture_params.requested_format.frame_size.SetSize(kTestFrameWidth1,
209 kTestFrameHeight1);
210 capture_params.requested_format.frame_rate = kFrameRate;
211 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
212 capture_params.allow_resolution_change = false;
214 capture_device_->AllocateAndStart(
215 capture_params, client.PassAs<media::VideoCaptureDevice::Client>());
217 // Capture at least two frames, to ensure that the source frame size has
218 // changed while capturing.
219 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
220 done_event.Reset();
221 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
223 capture_device_->StopAndDeAllocate();
225 EXPECT_EQ(kTestFrameWidth1, format.frame_size.width());
226 EXPECT_EQ(kTestFrameHeight1, format.frame_size.height());
227 EXPECT_EQ(kFrameRate, format.frame_rate);
228 EXPECT_EQ(media::PIXEL_FORMAT_ARGB, format.pixel_format);
230 EXPECT_EQ(format.frame_size.GetArea() * 4, frame_size);
233 // Test that screen capturer behaves correctly if the source frame size changes
234 // and the caller can cope with variable resolution output.
235 TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeVariableResolution) {
236 FakeScreenCapturer* mock_capturer = new FakeScreenCapturer();
238 CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer>(mock_capturer));
240 media::VideoCaptureFormat format;
241 base::WaitableEvent done_event(false, false);
243 scoped_ptr<MockDeviceClient> client(new MockDeviceClient());
244 EXPECT_CALL(*client, OnError(_)).Times(0);
245 EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly(
246 DoAll(SaveArg<2>(&format),
247 InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
249 media::VideoCaptureParams capture_params;
250 capture_params.requested_format.frame_size.SetSize(kTestFrameWidth2,
251 kTestFrameHeight2);
252 capture_params.requested_format.frame_rate = kFrameRate;
253 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
254 capture_params.allow_resolution_change = false;
256 capture_device_->AllocateAndStart(
257 capture_params, client.PassAs<media::VideoCaptureDevice::Client>());
259 // Capture at least three frames, to ensure that the source frame size has
260 // changed at least twice while capturing.
261 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
262 done_event.Reset();
263 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
264 done_event.Reset();
265 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
267 capture_device_->StopAndDeAllocate();
269 EXPECT_EQ(kTestFrameWidth1, format.frame_size.width());
270 EXPECT_EQ(kTestFrameHeight1, format.frame_size.height());
271 EXPECT_EQ(kFrameRate, format.frame_rate);
272 EXPECT_EQ(media::PIXEL_FORMAT_ARGB, format.pixel_format);
275 } // namespace content