- add sources.
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / media / desktop_capture_device_unittest.cc
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.
4
5 #include "content/browser/renderer_host/media/desktop_capture_device.h"
6
7 #include "base/basictypes.h"
8 #include "base/sequenced_task_runner.h"
9 #include "base/synchronization/waitable_event.h"
10 #include "base/test/test_timeouts.h"
11 #include "base/threading/sequenced_worker_pool.h"
12 #include "base/time/time.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
16 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
17 #include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
18
19 using ::testing::_;
20 using ::testing::AnyNumber;
21 using ::testing::DoAll;
22 using ::testing::Expectation;
23 using ::testing::InvokeWithoutArgs;
24 using ::testing::SaveArg;
25
26 namespace content {
27
28 namespace {
29
30 MATCHER_P2(EqualsCaptureCapability, width, height, "") {
31   return arg.width == width && arg.height == height;
32 }
33
34 const int kTestFrameWidth1 = 100;
35 const int kTestFrameHeight1 = 100;
36 const int kTestFrameWidth2 = 200;
37 const int kTestFrameHeight2 = 150;
38
39 const int kFrameRate = 30;
40
41 class MockDeviceClient : public media::VideoCaptureDevice::Client {
42  public:
43   MOCK_METHOD1(ReserveOutputBuffer,
44                scoped_refptr<media::VideoFrame>(const gfx::Size& size));
45   MOCK_METHOD0(OnError, void());
46   MOCK_METHOD1(OnFrameInfo, void(const media::VideoCaptureCapability& info));
47   MOCK_METHOD1(OnFrameInfoChanged,
48       void(const media::VideoCaptureCapability& info));
49   MOCK_METHOD6(OnIncomingCapturedFrame, void(const uint8* data,
50                                              int length,
51                                              base::Time timestamp,
52                                              int rotation,
53                                              bool flip_vert,
54                                              bool flip_horiz));
55   MOCK_METHOD2(OnIncomingCapturedVideoFrame,
56       void(const scoped_refptr<media::VideoFrame>& frame,
57            base::Time timestamp));
58 };
59
60 // TODO(sergeyu): Move this to a separate file where it can be reused.
61 class FakeScreenCapturer : public webrtc::ScreenCapturer {
62  public:
63   FakeScreenCapturer()
64       : callback_(NULL),
65         frame_index_(0) {
66   }
67   virtual ~FakeScreenCapturer() {}
68
69   // VideoFrameCapturer interface.
70   virtual void Start(Callback* callback) OVERRIDE {
71     callback_ = callback;
72   }
73
74   virtual void Capture(const webrtc::DesktopRegion& region) OVERRIDE {
75     webrtc::DesktopSize size;
76     if (frame_index_ % 2 == 0) {
77       size = webrtc::DesktopSize(kTestFrameWidth1, kTestFrameHeight1);
78     } else {
79       size = webrtc::DesktopSize(kTestFrameWidth2, kTestFrameHeight2);
80     }
81     frame_index_++;
82     callback_->OnCaptureCompleted(new webrtc::BasicDesktopFrame(size));
83   }
84
85   virtual void SetMouseShapeObserver(
86       MouseShapeObserver* mouse_shape_observer) OVERRIDE {
87   }
88
89  private:
90   Callback* callback_;
91   int frame_index_;
92 };
93
94 class DesktopCaptureDeviceTest : public testing::Test {
95  public:
96   virtual void SetUp() OVERRIDE {
97     worker_pool_ = new base::SequencedWorkerPool(3, "TestCaptureThread");
98   }
99
100  protected:
101   scoped_refptr<base::SequencedWorkerPool> worker_pool_;
102 };
103
104 }  // namespace
105
106 // There is currently no screen capturer implementation for ozone. So disable
107 // the test that uses a real screen-capturer instead of FakeScreenCapturer.
108 // http://crbug.com/260318
109 #if defined(USE_OZONE)
110 #define MAYBE_Capture DISABLED_Capture
111 #else
112 #define MAYBE_Capture Capture
113 #endif
114 TEST_F(DesktopCaptureDeviceTest, MAYBE_Capture) {
115   scoped_ptr<webrtc::DesktopCapturer> capturer(
116       webrtc::ScreenCapturer::Create());
117   DesktopCaptureDevice capture_device(
118       worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()),
119       capturer.Pass());
120   media::VideoCaptureCapability caps;
121   base::WaitableEvent done_event(false, false);
122   int frame_size;
123
124   scoped_ptr<MockDeviceClient> client(new MockDeviceClient());
125   EXPECT_CALL(*client, OnFrameInfo(_)).WillOnce(SaveArg<0>(&caps));
126   EXPECT_CALL(*client, OnError()).Times(0);
127   EXPECT_CALL(*client, OnIncomingCapturedFrame(_, _, _, _, _, _))
128       .WillRepeatedly(
129            DoAll(SaveArg<1>(&frame_size),
130                  InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
131
132   media::VideoCaptureCapability capture_format(
133       640, 480, kFrameRate, media::PIXEL_FORMAT_I420,
134       media::ConstantResolutionVideoCaptureDevice);
135   capture_device.AllocateAndStart(
136       capture_format, client.PassAs<media::VideoCaptureDevice::Client>());
137   EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
138   capture_device.StopAndDeAllocate();
139
140   EXPECT_GT(caps.width, 0);
141   EXPECT_GT(caps.height, 0);
142   EXPECT_EQ(kFrameRate, caps.frame_rate);
143   EXPECT_EQ(media::PIXEL_FORMAT_ARGB, caps.color);
144
145   EXPECT_EQ(caps.width * caps.height * 4, frame_size);
146   worker_pool_->FlushForTesting();
147 }
148
149 // Test that screen capturer behaves correctly if the source frame size changes
150 // but the caller cannot cope with variable resolution output.
151 TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeConstantResolution) {
152   FakeScreenCapturer* mock_capturer = new FakeScreenCapturer();
153
154   DesktopCaptureDevice capture_device(
155       worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()),
156       scoped_ptr<webrtc::DesktopCapturer>(mock_capturer));
157
158   media::VideoCaptureCapability caps;
159   base::WaitableEvent done_event(false, false);
160   int frame_size;
161
162   scoped_ptr<MockDeviceClient> client(new MockDeviceClient());
163   Expectation frame_info_called =
164       EXPECT_CALL(*client, OnFrameInfo(_)).WillOnce(SaveArg<0>(&caps));
165   EXPECT_CALL(*client, OnFrameInfoChanged(_)).Times(0);
166   EXPECT_CALL(*client, OnError()).Times(0);
167   EXPECT_CALL(*client, OnIncomingCapturedFrame(_, _, _, _, _, _))
168       .After(frame_info_called)
169       .WillRepeatedly(
170            DoAll(SaveArg<1>(&frame_size),
171                  InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
172
173   media::VideoCaptureCapability capture_format(
174       kTestFrameWidth1,
175       kTestFrameHeight1,
176       kFrameRate,
177       media::PIXEL_FORMAT_I420,
178       media::ConstantResolutionVideoCaptureDevice);
179
180   capture_device.AllocateAndStart(
181       capture_format, client.PassAs<media::VideoCaptureDevice::Client>());
182
183   // Capture at least two frames, to ensure that the source frame size has
184   // changed while capturing.
185   EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
186   done_event.Reset();
187   EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
188
189   capture_device.StopAndDeAllocate();
190
191   EXPECT_EQ(kTestFrameWidth1, caps.width);
192   EXPECT_EQ(kTestFrameHeight1, caps.height);
193   EXPECT_EQ(kFrameRate, caps.frame_rate);
194   EXPECT_EQ(media::PIXEL_FORMAT_ARGB, caps.color);
195
196   EXPECT_EQ(caps.width * caps.height * 4, frame_size);
197   worker_pool_->FlushForTesting();
198 }
199
200 // Test that screen capturer behaves correctly if the source frame size changes
201 // and the caller can cope with variable resolution output.
202 TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeVariableResolution) {
203   FakeScreenCapturer* mock_capturer = new FakeScreenCapturer();
204
205   DesktopCaptureDevice capture_device(
206       worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()),
207       scoped_ptr<webrtc::DesktopCapturer>(mock_capturer));
208
209   media::VideoCaptureCapability caps;
210   base::WaitableEvent done_event(false, false);
211
212   scoped_ptr<MockDeviceClient> client(new MockDeviceClient());
213   Expectation frame_info_called =
214       EXPECT_CALL(*client, OnFrameInfo(_)).WillOnce(SaveArg<0>(&caps));
215   Expectation first_info_changed = EXPECT_CALL(
216       *client,
217       OnFrameInfoChanged(EqualsCaptureCapability(
218           kTestFrameWidth2, kTestFrameHeight2))).After(frame_info_called);
219   Expectation second_info_changed = EXPECT_CALL(
220       *client,
221       OnFrameInfoChanged(EqualsCaptureCapability(
222           kTestFrameWidth1, kTestFrameHeight1))).After(first_info_changed);
223   EXPECT_CALL(*client, OnFrameInfoChanged(_)).Times(AnyNumber()).After(
224       second_info_changed);
225   EXPECT_CALL(*client, OnError()).Times(0);
226   EXPECT_CALL(*client, OnIncomingCapturedFrame(_, _, _, _, _, _))
227       .After(frame_info_called)
228       .WillRepeatedly(
229            InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal));
230
231   media::VideoCaptureCapability capture_format(
232       kTestFrameWidth2,
233       kTestFrameHeight2,
234       kFrameRate,
235       media::PIXEL_FORMAT_I420,
236       media::VariableResolutionVideoCaptureDevice);
237
238   capture_device.AllocateAndStart(
239       capture_format, client.PassAs<media::VideoCaptureDevice::Client>());
240
241   // Capture at least three frames, to ensure that the source frame size has
242   // changed at least twice while capturing.
243   EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
244   done_event.Reset();
245   EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
246   done_event.Reset();
247   EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
248
249   capture_device.StopAndDeAllocate();
250
251   EXPECT_EQ(kTestFrameWidth1, caps.width);
252   EXPECT_EQ(kTestFrameHeight1, caps.height);
253   EXPECT_EQ(kFrameRate, caps.frame_rate);
254   EXPECT_EQ(media::PIXEL_FORMAT_ARGB, caps.color);
255   worker_pool_->FlushForTesting();
256 }
257
258 }  // namespace content