Ignore non-active fullscreen windows for shelf state.
[chromium-blink-merge.git] / content / browser / renderer_host / media / video_capture_controller_unittest.cc
blob20cc4e41a891644a66e1cf45f041961302f52d4f
1 // Copyright (c) 2012 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 // Unit test for VideoCaptureController.
7 #include <string>
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/run_loop.h"
15 #include "content/browser/renderer_host/media/media_stream_provider.h"
16 #include "content/browser/renderer_host/media/video_capture_controller.h"
17 #include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
18 #include "content/browser/renderer_host/media/video_capture_manager.h"
19 #include "content/common/media/media_stream_options.h"
20 #include "content/public/test/test_browser_thread_bundle.h"
21 #include "media/base/video_frame.h"
22 #include "media/base/video_util.h"
23 #include "media/video/capture/video_capture_types.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
27 using ::testing::InSequence;
28 using ::testing::Mock;
30 namespace content {
32 class MockVideoCaptureControllerEventHandler
33 : public VideoCaptureControllerEventHandler {
34 public:
35 explicit MockVideoCaptureControllerEventHandler(
36 VideoCaptureController* controller)
37 : controller_(controller) {}
38 virtual ~MockVideoCaptureControllerEventHandler() {}
40 // These mock methods are delegated to by our fake implementation of
41 // VideoCaptureControllerEventHandler, to be used in EXPECT_CALL().
42 MOCK_METHOD1(DoBufferCreated, void(const VideoCaptureControllerID&));
43 MOCK_METHOD1(DoBufferDestroyed, void(const VideoCaptureControllerID&));
44 MOCK_METHOD1(DoBufferReady, void(const VideoCaptureControllerID&));
45 MOCK_METHOD1(DoEnded, void(const VideoCaptureControllerID&));
46 MOCK_METHOD1(DoError, void(const VideoCaptureControllerID&));
48 virtual void OnError(const VideoCaptureControllerID& id) OVERRIDE {
49 DoError(id);
51 virtual void OnBufferCreated(const VideoCaptureControllerID& id,
52 base::SharedMemoryHandle handle,
53 int length, int buffer_id) OVERRIDE {
54 DoBufferCreated(id);
56 virtual void OnBufferDestroyed(const VideoCaptureControllerID& id,
57 int buffer_id) OVERRIDE {
58 DoBufferDestroyed(id);
60 virtual void OnBufferReady(const VideoCaptureControllerID& id,
61 int buffer_id,
62 base::Time timestamp,
63 const media::VideoCaptureFormat& format) OVERRIDE {
64 DoBufferReady(id);
65 base::MessageLoop::current()->PostTask(FROM_HERE,
66 base::Bind(&VideoCaptureController::ReturnBuffer,
67 base::Unretained(controller_), id, this, buffer_id));
69 virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE {
70 DoEnded(id);
71 // OnEnded() must respond by (eventually) unregistering the client.
72 base::MessageLoop::current()->PostTask(FROM_HERE,
73 base::Bind(base::IgnoreResult(&VideoCaptureController::RemoveClient),
74 base::Unretained(controller_), id, this));
77 VideoCaptureController* controller_;
80 // Test class.
81 class VideoCaptureControllerTest : public testing::Test {
82 public:
83 VideoCaptureControllerTest() {}
84 virtual ~VideoCaptureControllerTest() {}
86 protected:
87 static const int kPoolSize = 3;
89 virtual void SetUp() OVERRIDE {
90 controller_.reset(new VideoCaptureController());
91 device_ = controller_->NewDeviceClient().Pass();
92 client_a_.reset(new MockVideoCaptureControllerEventHandler(
93 controller_.get()));
94 client_b_.reset(new MockVideoCaptureControllerEventHandler(
95 controller_.get()));
98 virtual void TearDown() OVERRIDE {
99 base::RunLoop().RunUntilIdle();
102 TestBrowserThreadBundle bindle_;
103 scoped_ptr<MockVideoCaptureControllerEventHandler> client_a_;
104 scoped_ptr<MockVideoCaptureControllerEventHandler> client_b_;
105 scoped_ptr<VideoCaptureController> controller_;
106 scoped_ptr<media::VideoCaptureDevice::Client> device_;
108 private:
109 DISALLOW_COPY_AND_ASSIGN(VideoCaptureControllerTest);
112 // A simple test of VideoCaptureController's ability to add, remove, and keep
113 // track of clients.
114 TEST_F(VideoCaptureControllerTest, AddAndRemoveClients) {
115 media::VideoCaptureParams session_100;
116 session_100.requested_format = media::VideoCaptureFormat(
117 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
118 media::VideoCaptureParams session_200 = session_100;
120 media::VideoCaptureParams session_300 = session_100;
122 media::VideoCaptureParams session_400 = session_100;
124 // Intentionally use the same route ID for two of the clients: the device_ids
125 // are a per-VideoCaptureHost namespace, and can overlap across hosts.
126 const VideoCaptureControllerID client_a_route_1(44);
127 const VideoCaptureControllerID client_a_route_2(30);
128 const VideoCaptureControllerID client_b_route_1(30);
129 const VideoCaptureControllerID client_b_route_2(1);
131 // Clients in controller: []
132 ASSERT_EQ(0, controller_->GetClientCount())
133 << "Client count should initially be zero.";
134 controller_->AddClient(client_a_route_1,
135 client_a_.get(),
136 base::kNullProcessHandle,
137 100,
138 session_100);
139 // Clients in controller: [A/1]
140 ASSERT_EQ(1, controller_->GetClientCount())
141 << "Adding client A/1 should bump client count.";;
142 controller_->AddClient(client_a_route_2,
143 client_a_.get(),
144 base::kNullProcessHandle,
145 200,
146 session_200);
147 // Clients in controller: [A/1, A/2]
148 ASSERT_EQ(2, controller_->GetClientCount())
149 << "Adding client A/2 should bump client count.";
150 controller_->AddClient(client_b_route_1,
151 client_b_.get(),
152 base::kNullProcessHandle,
153 300,
154 session_300);
155 // Clients in controller: [A/1, A/2, B/1]
156 ASSERT_EQ(3, controller_->GetClientCount())
157 << "Adding client B/1 should bump client count.";
158 ASSERT_EQ(200,
159 controller_->RemoveClient(client_a_route_2, client_a_.get()))
160 << "Removing client A/1 should return its session_id.";
161 // Clients in controller: [A/1, B/1]
162 ASSERT_EQ(2, controller_->GetClientCount());
163 ASSERT_EQ(static_cast<int>(kInvalidMediaCaptureSessionId),
164 controller_->RemoveClient(client_a_route_2, client_a_.get()))
165 << "Removing a nonexistant client should fail.";
166 // Clients in controller: [A/1, B/1]
167 ASSERT_EQ(2, controller_->GetClientCount());
168 ASSERT_EQ(300,
169 controller_->RemoveClient(client_b_route_1, client_b_.get()))
170 << "Removing client B/1 should return its session_id.";
171 // Clients in controller: [A/1]
172 ASSERT_EQ(1, controller_->GetClientCount());
173 controller_->AddClient(client_b_route_2,
174 client_b_.get(),
175 base::kNullProcessHandle,
176 400,
177 session_400);
178 // Clients in controller: [A/1, B/2]
180 EXPECT_CALL(*client_a_, DoEnded(client_a_route_1)).Times(1);
181 controller_->StopSession(100); // Session 100 == client A/1
182 Mock::VerifyAndClearExpectations(client_a_.get());
183 ASSERT_EQ(2, controller_->GetClientCount())
184 << "Client should be closed but still exist after StopSession.";
185 // Clients in controller: [A/1 (closed, removal pending), B/2]
186 base::RunLoop().RunUntilIdle();
187 // Clients in controller: [B/2]
188 ASSERT_EQ(1, controller_->GetClientCount())
189 << "Client A/1 should be deleted by now.";
190 controller_->StopSession(200); // Session 200 does not exist anymore
191 // Clients in controller: [B/2]
192 ASSERT_EQ(1, controller_->GetClientCount())
193 << "Stopping non-existant session 200 should be a no-op.";
194 controller_->StopSession(256); // Session 256 never existed.
195 // Clients in controller: [B/2]
196 ASSERT_EQ(1, controller_->GetClientCount())
197 << "Stopping non-existant session 256 should be a no-op.";
198 ASSERT_EQ(static_cast<int>(kInvalidMediaCaptureSessionId),
199 controller_->RemoveClient(client_a_route_1, client_a_.get()))
200 << "Removing already-removed client A/1 should fail.";
201 // Clients in controller: [B/2]
202 ASSERT_EQ(1, controller_->GetClientCount())
203 << "Removing non-existant session 200 should be a no-op.";
204 ASSERT_EQ(400,
205 controller_->RemoveClient(client_b_route_2, client_b_.get()))
206 << "Removing client B/2 should return its session_id.";
207 // Clients in controller: []
208 ASSERT_EQ(0, controller_->GetClientCount())
209 << "Client count should return to zero after all clients are gone.";
212 // This test will connect and disconnect several clients while simulating an
213 // active capture device being started and generating frames. It runs on one
214 // thread and is intended to behave deterministically.
215 TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
216 media::VideoCaptureParams session_100;
217 session_100.requested_format = media::VideoCaptureFormat(
218 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
220 media::VideoCaptureParams session_200 = session_100;
222 media::VideoCaptureParams session_300 = session_100;
224 media::VideoCaptureParams session_1 = session_100;
226 gfx::Size capture_resolution(444, 200);
228 // The device format needn't match the VideoCaptureParams (the camera can do
229 // what it wants). Pick something random.
230 media::VideoCaptureFormat device_format(
231 gfx::Size(10, 10), 25, media::PIXEL_FORMAT_RGB24);
233 const VideoCaptureControllerID client_a_route_1(0xa1a1a1a1);
234 const VideoCaptureControllerID client_a_route_2(0xa2a2a2a2);
235 const VideoCaptureControllerID client_b_route_1(0xb1b1b1b1);
236 const VideoCaptureControllerID client_b_route_2(0xb2b2b2b2);
238 // Start with two clients.
239 controller_->AddClient(client_a_route_1,
240 client_a_.get(),
241 base::kNullProcessHandle,
242 100,
243 session_100);
244 controller_->AddClient(client_b_route_1,
245 client_b_.get(),
246 base::kNullProcessHandle,
247 300,
248 session_300);
249 controller_->AddClient(client_a_route_2,
250 client_a_.get(),
251 base::kNullProcessHandle,
252 200,
253 session_200);
254 ASSERT_EQ(3, controller_->GetClientCount());
256 // Now, simulate an incoming captured buffer from the capture device. As a
257 // side effect this will cause the first buffer to be shared with clients.
258 uint8 buffer_no = 1;
259 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer;
260 buffer =
261 device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
262 ASSERT_TRUE(buffer);
263 memset(buffer->data(), buffer_no++, buffer->size());
265 InSequence s;
266 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1)).Times(1);
267 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(1);
270 InSequence s;
271 EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1)).Times(1);
272 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(1);
275 InSequence s;
276 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2)).Times(1);
277 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(1);
279 device_->OnIncomingCapturedBuffer(buffer,
280 media::VideoFrame::I420,
281 capture_resolution,
282 base::Time(),
283 device_format.frame_rate);
284 buffer = NULL;
286 base::RunLoop().RunUntilIdle();
287 Mock::VerifyAndClearExpectations(client_a_.get());
288 Mock::VerifyAndClearExpectations(client_b_.get());
290 // Second buffer which ought to use the same shared memory buffer. In this
291 // case pretend that the Buffer pointer is held by the device for a long
292 // delay. This shouldn't affect anything.
293 buffer =
294 device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
295 ASSERT_TRUE(buffer);
296 memset(buffer->data(), buffer_no++, buffer->size());
297 device_->OnIncomingCapturedBuffer(buffer,
298 media::VideoFrame::I420,
299 capture_resolution,
300 base::Time(),
301 device_format.frame_rate);
302 buffer = NULL;
304 // The buffer should be delivered to the clients in any order.
305 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(1);
306 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(1);
307 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(1);
308 base::RunLoop().RunUntilIdle();
309 Mock::VerifyAndClearExpectations(client_a_.get());
310 Mock::VerifyAndClearExpectations(client_b_.get());
312 // Add a fourth client now that some buffers have come through.
313 controller_->AddClient(client_b_route_2,
314 client_b_.get(),
315 base::kNullProcessHandle,
317 session_1);
318 Mock::VerifyAndClearExpectations(client_b_.get());
320 // Third, fourth, and fifth buffers. Pretend they all arrive at the same time.
321 for (int i = 0; i < kPoolSize; i++) {
322 buffer = device_->ReserveOutputBuffer(media::VideoFrame::I420,
323 capture_resolution);
324 ASSERT_TRUE(buffer);
325 memset(buffer->data(), buffer_no++, buffer->size());
326 device_->OnIncomingCapturedBuffer(buffer,
327 media::VideoFrame::I420,
328 capture_resolution,
329 base::Time(),
330 device_format.frame_rate);
331 buffer = NULL;
333 // ReserveOutputBuffer ought to fail now, because the pool is depleted.
334 ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::I420,
335 capture_resolution));
337 // The new client needs to be told of 3 buffers; the old clients only 2.
338 EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_2)).Times(kPoolSize);
339 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(kPoolSize);
340 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1))
341 .Times(kPoolSize - 1);
342 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(kPoolSize);
343 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2))
344 .Times(kPoolSize - 1);
345 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(kPoolSize);
346 EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1))
347 .Times(kPoolSize - 1);
348 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(kPoolSize);
349 base::RunLoop().RunUntilIdle();
350 Mock::VerifyAndClearExpectations(client_a_.get());
351 Mock::VerifyAndClearExpectations(client_b_.get());
353 // Now test the interaction of client shutdown and buffer delivery.
354 // Kill A1 via renderer disconnect (synchronous).
355 controller_->RemoveClient(client_a_route_1, client_a_.get());
356 // Kill B1 via session close (posts a task to disconnect).
357 EXPECT_CALL(*client_b_, DoEnded(client_b_route_1)).Times(1);
358 controller_->StopSession(300);
359 // Queue up another buffer.
360 buffer =
361 device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
362 ASSERT_TRUE(buffer);
363 memset(buffer->data(), buffer_no++, buffer->size());
364 device_->OnIncomingCapturedBuffer(buffer,
365 media::VideoFrame::I420,
366 capture_resolution,
367 base::Time(),
368 device_format.frame_rate);
369 buffer = NULL;
370 buffer =
371 device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
373 // Kill A2 via session close (posts a task to disconnect, but A2 must not
374 // be sent either of these two buffers).
375 EXPECT_CALL(*client_a_, DoEnded(client_a_route_2)).Times(1);
376 controller_->StopSession(200);
378 ASSERT_TRUE(buffer);
379 memset(buffer->data(), buffer_no++, buffer->size());
380 device_->OnIncomingCapturedBuffer(buffer,
381 media::VideoFrame::I420,
382 capture_resolution,
383 base::Time(),
384 device_format.frame_rate);
385 buffer = NULL;
386 // B2 is the only client left, and is the only one that should
387 // get the buffer.
388 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(2);
389 base::RunLoop().RunUntilIdle();
390 Mock::VerifyAndClearExpectations(client_a_.get());
391 Mock::VerifyAndClearExpectations(client_b_.get());
394 // Exercises the OnError() codepath of VideoCaptureController, and tests the
395 // behavior of various operations after the error state has been signalled.
396 TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) {
397 media::VideoCaptureParams session_100;
398 session_100.requested_format = media::VideoCaptureFormat(
399 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
401 media::VideoCaptureParams session_200 = session_100;
403 const gfx::Size capture_resolution(320, 240);
405 const VideoCaptureControllerID route_id(0x99);
407 // Start with one client.
408 controller_->AddClient(
409 route_id, client_a_.get(), base::kNullProcessHandle, 100, session_100);
410 device_->OnError();
411 EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
412 base::RunLoop().RunUntilIdle();
413 Mock::VerifyAndClearExpectations(client_a_.get());
415 // Second client connects after the error state. It also should get told of
416 // the error.
417 EXPECT_CALL(*client_b_, DoError(route_id)).Times(1);
418 controller_->AddClient(
419 route_id, client_b_.get(), base::kNullProcessHandle, 200, session_200);
420 base::RunLoop().RunUntilIdle();
421 Mock::VerifyAndClearExpectations(client_b_.get());
423 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer =
424 device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
425 ASSERT_TRUE(buffer);
427 device_->OnIncomingCapturedBuffer(
428 buffer, media::VideoFrame::I420, capture_resolution, base::Time(), 30);
429 buffer = NULL;
431 base::RunLoop().RunUntilIdle();
434 // Exercises the OnError() codepath of VideoCaptureController, and tests the
435 // behavior of various operations after the error state has been signalled.
436 TEST_F(VideoCaptureControllerTest, ErrorAfterDeviceCreation) {
437 media::VideoCaptureParams session_100;
438 session_100.requested_format = media::VideoCaptureFormat(
439 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
441 media::VideoCaptureParams session_200 = session_100;
443 const VideoCaptureControllerID route_id(0x99);
445 // Start with one client.
446 controller_->AddClient(
447 route_id, client_a_.get(), base::kNullProcessHandle, 100, session_100);
448 media::VideoCaptureFormat device_format(
449 gfx::Size(10, 10), 25, media::PIXEL_FORMAT_ARGB);
451 // Start the device. Then, before the first buffer, signal an error and
452 // deliver the buffer. The error should be propagated to clients; the buffer
453 // should not be.
454 base::RunLoop().RunUntilIdle();
455 Mock::VerifyAndClearExpectations(client_a_.get());
457 const gfx::Size dims(320, 240);
458 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer =
459 device_->ReserveOutputBuffer(media::VideoFrame::I420, dims);
460 ASSERT_TRUE(buffer);
462 device_->OnError();
463 device_->OnIncomingCapturedBuffer(buffer,
464 media::VideoFrame::I420,
465 dims,
466 base::Time(),
467 device_format.frame_rate);
468 buffer = NULL;
470 EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
471 base::RunLoop().RunUntilIdle();
472 Mock::VerifyAndClearExpectations(client_a_.get());
474 // Second client connects after the error state. It also should get told of
475 // the error.
476 EXPECT_CALL(*client_b_, DoError(route_id)).Times(1);
477 controller_->AddClient(
478 route_id, client_b_.get(), base::kNullProcessHandle, 200, session_200);
479 Mock::VerifyAndClearExpectations(client_b_.get());
482 } // namespace content