Revert 268405 "Make sure that ScratchBuffer::Allocate() always r..."
[chromium-blink-merge.git] / content / browser / renderer_host / media / video_capture_controller_unittest.cc
blobf650397de7bfc0c59890c91a0ce7997e9caa29ec
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 "gpu/command_buffer/common/mailbox_holder.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(DoMailboxBufferReady, void(const VideoCaptureControllerID&));
46 MOCK_METHOD1(DoEnded, void(const VideoCaptureControllerID&));
47 MOCK_METHOD1(DoError, void(const VideoCaptureControllerID&));
49 virtual void OnError(const VideoCaptureControllerID& id) OVERRIDE {
50 DoError(id);
52 virtual void OnBufferCreated(const VideoCaptureControllerID& id,
53 base::SharedMemoryHandle handle,
54 int length, int buffer_id) OVERRIDE {
55 DoBufferCreated(id);
57 virtual void OnBufferDestroyed(const VideoCaptureControllerID& id,
58 int buffer_id) OVERRIDE {
59 DoBufferDestroyed(id);
61 virtual void OnBufferReady(const VideoCaptureControllerID& id,
62 int buffer_id,
63 const media::VideoCaptureFormat& format,
64 base::TimeTicks timestamp) OVERRIDE {
65 DoBufferReady(id);
66 base::MessageLoop::current()->PostTask(
67 FROM_HERE,
68 base::Bind(&VideoCaptureController::ReturnBuffer,
69 base::Unretained(controller_),
70 id,
71 this,
72 buffer_id,
73 std::vector<uint32>()));
75 virtual void OnMailboxBufferReady(const VideoCaptureControllerID& id,
76 int buffer_id,
77 const gpu::MailboxHolder& mailbox_holder,
78 const media::VideoCaptureFormat& format,
79 base::TimeTicks timestamp) OVERRIDE {
80 DoMailboxBufferReady(id);
81 // Use a very different syncpoint value when returning a new syncpoint.
82 std::vector<uint32> release_sync_points;
83 release_sync_points.push_back(~mailbox_holder.sync_point);
84 base::MessageLoop::current()->PostTask(
85 FROM_HERE,
86 base::Bind(&VideoCaptureController::ReturnBuffer,
87 base::Unretained(controller_),
88 id,
89 this,
90 buffer_id,
91 release_sync_points));
93 virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE {
94 DoEnded(id);
95 // OnEnded() must respond by (eventually) unregistering the client.
96 base::MessageLoop::current()->PostTask(FROM_HERE,
97 base::Bind(base::IgnoreResult(&VideoCaptureController::RemoveClient),
98 base::Unretained(controller_), id, this));
101 VideoCaptureController* controller_;
104 // Test class.
105 class VideoCaptureControllerTest : public testing::Test {
106 public:
107 VideoCaptureControllerTest() {}
108 virtual ~VideoCaptureControllerTest() {}
110 protected:
111 static const int kPoolSize = 3;
113 virtual void SetUp() OVERRIDE {
114 controller_.reset(new VideoCaptureController());
115 device_ = controller_->NewDeviceClient().Pass();
116 client_a_.reset(new MockVideoCaptureControllerEventHandler(
117 controller_.get()));
118 client_b_.reset(new MockVideoCaptureControllerEventHandler(
119 controller_.get()));
122 virtual void TearDown() OVERRIDE {
123 base::RunLoop().RunUntilIdle();
126 scoped_refptr<media::VideoFrame> WrapI420Buffer(
127 const scoped_refptr<media::VideoCaptureDevice::Client::Buffer>& buffer,
128 gfx::Size dimensions) {
129 return media::VideoFrame::WrapExternalPackedMemory(
130 media::VideoFrame::I420,
131 dimensions,
132 gfx::Rect(dimensions),
133 dimensions,
134 reinterpret_cast<uint8*>(buffer->data()),
135 media::VideoFrame::AllocationSize(media::VideoFrame::I420, dimensions),
136 base::SharedMemory::NULLHandle(),
137 base::TimeDelta(),
138 base::Closure());
141 scoped_refptr<media::VideoFrame> WrapMailboxBuffer(
142 const scoped_refptr<media::VideoCaptureDevice::Client::Buffer>& buffer,
143 scoped_ptr<gpu::MailboxHolder> holder,
144 const media::VideoFrame::ReleaseMailboxCB& release_cb,
145 gfx::Size dimensions) {
146 return media::VideoFrame::WrapNativeTexture(
147 holder.Pass(),
148 release_cb,
149 dimensions,
150 gfx::Rect(dimensions),
151 dimensions,
152 base::TimeDelta(),
153 media::VideoFrame::ReadPixelsCB());
156 TestBrowserThreadBundle bundle_;
157 scoped_ptr<MockVideoCaptureControllerEventHandler> client_a_;
158 scoped_ptr<MockVideoCaptureControllerEventHandler> client_b_;
159 scoped_ptr<VideoCaptureController> controller_;
160 scoped_ptr<media::VideoCaptureDevice::Client> device_;
162 private:
163 DISALLOW_COPY_AND_ASSIGN(VideoCaptureControllerTest);
166 // A simple test of VideoCaptureController's ability to add, remove, and keep
167 // track of clients.
168 TEST_F(VideoCaptureControllerTest, AddAndRemoveClients) {
169 media::VideoCaptureParams session_100;
170 session_100.requested_format = media::VideoCaptureFormat(
171 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
172 media::VideoCaptureParams session_200 = session_100;
174 media::VideoCaptureParams session_300 = session_100;
176 media::VideoCaptureParams session_400 = session_100;
178 // Intentionally use the same route ID for two of the clients: the device_ids
179 // are a per-VideoCaptureHost namespace, and can overlap across hosts.
180 const VideoCaptureControllerID client_a_route_1(44);
181 const VideoCaptureControllerID client_a_route_2(30);
182 const VideoCaptureControllerID client_b_route_1(30);
183 const VideoCaptureControllerID client_b_route_2(1);
185 // Clients in controller: []
186 ASSERT_EQ(0, controller_->GetClientCount())
187 << "Client count should initially be zero.";
188 controller_->AddClient(client_a_route_1,
189 client_a_.get(),
190 base::kNullProcessHandle,
191 100,
192 session_100);
193 // Clients in controller: [A/1]
194 ASSERT_EQ(1, controller_->GetClientCount())
195 << "Adding client A/1 should bump client count.";
196 controller_->AddClient(client_a_route_2,
197 client_a_.get(),
198 base::kNullProcessHandle,
199 200,
200 session_200);
201 // Clients in controller: [A/1, A/2]
202 ASSERT_EQ(2, controller_->GetClientCount())
203 << "Adding client A/2 should bump client count.";
204 controller_->AddClient(client_b_route_1,
205 client_b_.get(),
206 base::kNullProcessHandle,
207 300,
208 session_300);
209 // Clients in controller: [A/1, A/2, B/1]
210 ASSERT_EQ(3, controller_->GetClientCount())
211 << "Adding client B/1 should bump client count.";
212 ASSERT_EQ(200,
213 controller_->RemoveClient(client_a_route_2, client_a_.get()))
214 << "Removing client A/1 should return its session_id.";
215 // Clients in controller: [A/1, B/1]
216 ASSERT_EQ(2, controller_->GetClientCount());
217 ASSERT_EQ(static_cast<int>(kInvalidMediaCaptureSessionId),
218 controller_->RemoveClient(client_a_route_2, client_a_.get()))
219 << "Removing a nonexistant client should fail.";
220 // Clients in controller: [A/1, B/1]
221 ASSERT_EQ(2, controller_->GetClientCount());
222 ASSERT_EQ(300,
223 controller_->RemoveClient(client_b_route_1, client_b_.get()))
224 << "Removing client B/1 should return its session_id.";
225 // Clients in controller: [A/1]
226 ASSERT_EQ(1, controller_->GetClientCount());
227 controller_->AddClient(client_b_route_2,
228 client_b_.get(),
229 base::kNullProcessHandle,
230 400,
231 session_400);
232 // Clients in controller: [A/1, B/2]
234 EXPECT_CALL(*client_a_, DoEnded(client_a_route_1)).Times(1);
235 controller_->StopSession(100); // Session 100 == client A/1
236 Mock::VerifyAndClearExpectations(client_a_.get());
237 ASSERT_EQ(2, controller_->GetClientCount())
238 << "Client should be closed but still exist after StopSession.";
239 // Clients in controller: [A/1 (closed, removal pending), B/2]
240 base::RunLoop().RunUntilIdle();
241 // Clients in controller: [B/2]
242 ASSERT_EQ(1, controller_->GetClientCount())
243 << "Client A/1 should be deleted by now.";
244 controller_->StopSession(200); // Session 200 does not exist anymore
245 // Clients in controller: [B/2]
246 ASSERT_EQ(1, controller_->GetClientCount())
247 << "Stopping non-existant session 200 should be a no-op.";
248 controller_->StopSession(256); // Session 256 never existed.
249 // Clients in controller: [B/2]
250 ASSERT_EQ(1, controller_->GetClientCount())
251 << "Stopping non-existant session 256 should be a no-op.";
252 ASSERT_EQ(static_cast<int>(kInvalidMediaCaptureSessionId),
253 controller_->RemoveClient(client_a_route_1, client_a_.get()))
254 << "Removing already-removed client A/1 should fail.";
255 // Clients in controller: [B/2]
256 ASSERT_EQ(1, controller_->GetClientCount())
257 << "Removing non-existant session 200 should be a no-op.";
258 ASSERT_EQ(400,
259 controller_->RemoveClient(client_b_route_2, client_b_.get()))
260 << "Removing client B/2 should return its session_id.";
261 // Clients in controller: []
262 ASSERT_EQ(0, controller_->GetClientCount())
263 << "Client count should return to zero after all clients are gone.";
266 static void CacheSyncPoint(std::vector<uint32>* called_release_sync_points,
267 const std::vector<uint32>& release_sync_points) {
268 DCHECK(called_release_sync_points->empty());
269 called_release_sync_points->assign(release_sync_points.begin(),
270 release_sync_points.end());
273 // This test will connect and disconnect several clients while simulating an
274 // active capture device being started and generating frames. It runs on one
275 // thread and is intended to behave deterministically.
276 TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
277 media::VideoCaptureParams session_100;
278 session_100.requested_format = media::VideoCaptureFormat(
279 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
281 media::VideoCaptureParams session_200 = session_100;
283 media::VideoCaptureParams session_300 = session_100;
285 media::VideoCaptureParams session_1 = session_100;
287 gfx::Size capture_resolution(444, 200);
289 // The device format needn't match the VideoCaptureParams (the camera can do
290 // what it wants). Pick something random.
291 media::VideoCaptureFormat device_format(
292 gfx::Size(10, 10), 25, media::PIXEL_FORMAT_RGB24);
294 const VideoCaptureControllerID client_a_route_1(0xa1a1a1a1);
295 const VideoCaptureControllerID client_a_route_2(0xa2a2a2a2);
296 const VideoCaptureControllerID client_b_route_1(0xb1b1b1b1);
297 const VideoCaptureControllerID client_b_route_2(0xb2b2b2b2);
299 // Start with two clients.
300 controller_->AddClient(client_a_route_1,
301 client_a_.get(),
302 base::kNullProcessHandle,
303 100,
304 session_100);
305 controller_->AddClient(client_b_route_1,
306 client_b_.get(),
307 base::kNullProcessHandle,
308 300,
309 session_300);
310 controller_->AddClient(client_a_route_2,
311 client_a_.get(),
312 base::kNullProcessHandle,
313 200,
314 session_200);
315 ASSERT_EQ(3, controller_->GetClientCount());
317 // Now, simulate an incoming captured buffer from the capture device. As a
318 // side effect this will cause the first buffer to be shared with clients.
319 uint8 buffer_no = 1;
320 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer;
321 buffer =
322 device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
323 ASSERT_TRUE(buffer);
324 memset(buffer->data(), buffer_no++, buffer->size());
326 InSequence s;
327 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1)).Times(1);
328 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(1);
331 InSequence s;
332 EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1)).Times(1);
333 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(1);
336 InSequence s;
337 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2)).Times(1);
338 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(1);
340 device_->OnIncomingCapturedVideoFrame(
341 buffer,
342 media::VideoCaptureFormat(capture_resolution,
343 device_format.frame_rate,
344 media::PIXEL_FORMAT_I420),
345 WrapI420Buffer(buffer, capture_resolution),
346 base::TimeTicks());
347 buffer = NULL;
349 base::RunLoop().RunUntilIdle();
350 Mock::VerifyAndClearExpectations(client_a_.get());
351 Mock::VerifyAndClearExpectations(client_b_.get());
353 // Second buffer which ought to use the same shared memory buffer. In this
354 // case pretend that the Buffer pointer is held by the device for a long
355 // delay. This shouldn't affect anything.
356 buffer =
357 device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
358 ASSERT_TRUE(buffer);
359 memset(buffer->data(), buffer_no++, buffer->size());
360 device_->OnIncomingCapturedVideoFrame(
361 buffer,
362 media::VideoCaptureFormat(capture_resolution,
363 device_format.frame_rate,
364 media::PIXEL_FORMAT_I420),
365 WrapI420Buffer(buffer, capture_resolution),
366 base::TimeTicks());
367 buffer = NULL;
369 // The buffer should be delivered to the clients in any order.
370 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(1);
371 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(1);
372 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(1);
373 base::RunLoop().RunUntilIdle();
374 Mock::VerifyAndClearExpectations(client_a_.get());
375 Mock::VerifyAndClearExpectations(client_b_.get());
377 // Add a fourth client now that some buffers have come through.
378 controller_->AddClient(client_b_route_2,
379 client_b_.get(),
380 base::kNullProcessHandle,
382 session_1);
383 Mock::VerifyAndClearExpectations(client_b_.get());
385 // Third, fourth, and fifth buffers. Pretend they all arrive at the same time.
386 for (int i = 0; i < kPoolSize; i++) {
387 buffer = device_->ReserveOutputBuffer(media::VideoFrame::I420,
388 capture_resolution);
389 ASSERT_TRUE(buffer);
390 memset(buffer->data(), buffer_no++, buffer->size());
391 device_->OnIncomingCapturedVideoFrame(
392 buffer,
393 media::VideoCaptureFormat(capture_resolution,
394 device_format.frame_rate,
395 media::PIXEL_FORMAT_I420),
396 WrapI420Buffer(buffer, capture_resolution),
397 base::TimeTicks());
398 buffer = NULL;
400 // ReserveOutputBuffer ought to fail now, because the pool is depleted.
401 ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::I420,
402 capture_resolution));
404 // The new client needs to be told of 3 buffers; the old clients only 2.
405 EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_2)).Times(kPoolSize);
406 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(kPoolSize);
407 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1))
408 .Times(kPoolSize - 1);
409 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(kPoolSize);
410 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2))
411 .Times(kPoolSize - 1);
412 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(kPoolSize);
413 EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1))
414 .Times(kPoolSize - 1);
415 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(kPoolSize);
416 base::RunLoop().RunUntilIdle();
417 Mock::VerifyAndClearExpectations(client_a_.get());
418 Mock::VerifyAndClearExpectations(client_b_.get());
420 // Now test the interaction of client shutdown and buffer delivery.
421 // Kill A1 via renderer disconnect (synchronous).
422 controller_->RemoveClient(client_a_route_1, client_a_.get());
423 // Kill B1 via session close (posts a task to disconnect).
424 EXPECT_CALL(*client_b_, DoEnded(client_b_route_1)).Times(1);
425 controller_->StopSession(300);
426 // Queue up another buffer.
427 buffer =
428 device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
429 ASSERT_TRUE(buffer);
430 memset(buffer->data(), buffer_no++, buffer->size());
431 device_->OnIncomingCapturedVideoFrame(
432 buffer,
433 media::VideoCaptureFormat(capture_resolution,
434 device_format.frame_rate,
435 media::PIXEL_FORMAT_I420),
436 WrapI420Buffer(buffer, capture_resolution),
437 base::TimeTicks());
438 buffer = NULL;
439 buffer =
440 device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
442 // Kill A2 via session close (posts a task to disconnect, but A2 must not
443 // be sent either of these two buffers).
444 EXPECT_CALL(*client_a_, DoEnded(client_a_route_2)).Times(1);
445 controller_->StopSession(200);
447 ASSERT_TRUE(buffer);
448 memset(buffer->data(), buffer_no++, buffer->size());
449 device_->OnIncomingCapturedVideoFrame(
450 buffer,
451 media::VideoCaptureFormat(capture_resolution,
452 device_format.frame_rate,
453 media::PIXEL_FORMAT_I420),
454 WrapI420Buffer(buffer, capture_resolution),
455 base::TimeTicks());
456 buffer = NULL;
457 // B2 is the only client left, and is the only one that should
458 // get the buffer.
459 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(2);
460 base::RunLoop().RunUntilIdle();
461 Mock::VerifyAndClearExpectations(client_a_.get());
462 Mock::VerifyAndClearExpectations(client_b_.get());
464 // Allocate all buffers from the buffer pool, half as SHM buffer and half as
465 // mailbox buffers. Make sure of different counts though.
466 int shm_buffers = kPoolSize / 2;
467 int mailbox_buffers = kPoolSize - shm_buffers;
468 if (shm_buffers == mailbox_buffers) {
469 shm_buffers--;
470 mailbox_buffers++;
473 for (int i = 0; i < shm_buffers; ++i) {
474 buffer = device_->ReserveOutputBuffer(media::VideoFrame::I420,
475 capture_resolution);
476 ASSERT_TRUE(buffer);
477 device_->OnIncomingCapturedVideoFrame(
478 buffer,
479 media::VideoCaptureFormat(capture_resolution,
480 device_format.frame_rate,
481 media::PIXEL_FORMAT_I420),
482 WrapI420Buffer(buffer, capture_resolution),
483 base::TimeTicks());
484 buffer = NULL;
486 std::vector<uint32> mailbox_syncpoints(mailbox_buffers);
487 std::vector<std::vector<uint32> > release_syncpoint_vectors(mailbox_buffers);
488 for (int i = 0; i < mailbox_buffers; ++i) {
489 buffer = device_->ReserveOutputBuffer(media::VideoFrame::NATIVE_TEXTURE,
490 gfx::Size(0, 0));
491 ASSERT_TRUE(buffer);
492 mailbox_syncpoints[i] = i;
493 device_->OnIncomingCapturedVideoFrame(
494 buffer,
495 media::VideoCaptureFormat(capture_resolution,
496 device_format.frame_rate,
497 media::PIXEL_FORMAT_TEXTURE),
498 WrapMailboxBuffer(
499 buffer,
500 make_scoped_ptr(new gpu::MailboxHolder(
501 gpu::Mailbox(), 0, mailbox_syncpoints[i])),
502 base::Bind(&CacheSyncPoint, &release_syncpoint_vectors[i]),
503 capture_resolution),
504 base::TimeTicks());
505 buffer = NULL;
507 // ReserveOutputBuffers ought to fail now regardless of buffer format, because
508 // the pool is depleted.
509 ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::I420,
510 capture_resolution));
511 ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::NATIVE_TEXTURE,
512 gfx::Size(0, 0)));
513 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(shm_buffers);
514 EXPECT_CALL(*client_b_, DoMailboxBufferReady(client_b_route_2))
515 .Times(mailbox_buffers);
516 base::RunLoop().RunUntilIdle();
517 for (size_t i = 0; i < mailbox_syncpoints.size(); ++i) {
518 // See: MockVideoCaptureControllerEventHandler::OnMailboxBufferReady()
519 ASSERT_EQ(1u, release_syncpoint_vectors[i].size());
520 ASSERT_EQ(mailbox_syncpoints[i], ~release_syncpoint_vectors[i][0]);
522 Mock::VerifyAndClearExpectations(client_b_.get());
525 // Exercises the OnError() codepath of VideoCaptureController, and tests the
526 // behavior of various operations after the error state has been signalled.
527 TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) {
528 media::VideoCaptureParams session_100;
529 session_100.requested_format = media::VideoCaptureFormat(
530 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
532 media::VideoCaptureParams session_200 = session_100;
534 const gfx::Size capture_resolution(320, 240);
536 const VideoCaptureControllerID route_id(0x99);
538 // Start with one client.
539 controller_->AddClient(
540 route_id, client_a_.get(), base::kNullProcessHandle, 100, session_100);
541 device_->OnError("Test Error");
542 EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
543 base::RunLoop().RunUntilIdle();
544 Mock::VerifyAndClearExpectations(client_a_.get());
546 // Second client connects after the error state. It also should get told of
547 // the error.
548 EXPECT_CALL(*client_b_, DoError(route_id)).Times(1);
549 controller_->AddClient(
550 route_id, client_b_.get(), base::kNullProcessHandle, 200, session_200);
551 base::RunLoop().RunUntilIdle();
552 Mock::VerifyAndClearExpectations(client_b_.get());
554 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer =
555 device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
556 ASSERT_TRUE(buffer);
558 device_->OnIncomingCapturedVideoFrame(
559 buffer,
560 media::VideoCaptureFormat(
561 capture_resolution, 30, media::PIXEL_FORMAT_I420),
562 WrapI420Buffer(buffer, capture_resolution),
563 base::TimeTicks());
564 buffer = NULL;
566 base::RunLoop().RunUntilIdle();
569 // Exercises the OnError() codepath of VideoCaptureController, and tests the
570 // behavior of various operations after the error state has been signalled.
571 TEST_F(VideoCaptureControllerTest, ErrorAfterDeviceCreation) {
572 media::VideoCaptureParams session_100;
573 session_100.requested_format = media::VideoCaptureFormat(
574 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
576 media::VideoCaptureParams session_200 = session_100;
578 const VideoCaptureControllerID route_id(0x99);
580 // Start with one client.
581 controller_->AddClient(
582 route_id, client_a_.get(), base::kNullProcessHandle, 100, session_100);
583 media::VideoCaptureFormat device_format(
584 gfx::Size(10, 10), 25, media::PIXEL_FORMAT_ARGB);
586 // Start the device. Then, before the first buffer, signal an error and
587 // deliver the buffer. The error should be propagated to clients; the buffer
588 // should not be.
589 base::RunLoop().RunUntilIdle();
590 Mock::VerifyAndClearExpectations(client_a_.get());
592 const gfx::Size dims(320, 240);
593 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer =
594 device_->ReserveOutputBuffer(media::VideoFrame::I420, dims);
595 ASSERT_TRUE(buffer);
597 device_->OnError("Test error");
598 device_->OnIncomingCapturedVideoFrame(
599 buffer,
600 media::VideoCaptureFormat(
601 dims, device_format.frame_rate, media::PIXEL_FORMAT_I420),
602 WrapI420Buffer(buffer, dims),
603 base::TimeTicks());
604 buffer = NULL;
606 EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
607 base::RunLoop().RunUntilIdle();
608 Mock::VerifyAndClearExpectations(client_a_.get());
610 // Second client connects after the error state. It also should get told of
611 // the error.
612 EXPECT_CALL(*client_b_, DoError(route_id)).Times(1);
613 controller_->AddClient(
614 route_id, client_b_.get(), base::kNullProcessHandle, 200, session_200);
615 Mock::VerifyAndClearExpectations(client_b_.get());
618 } // namespace content