[blink-in-js] Migrate resources required for blink-in-js to grd - part 2
[chromium-blink-merge.git] / content / browser / renderer_host / media / video_capture_controller_unittest.cc
blob6a9f4b749e803a05d7f7d9f31ed0b163610578cd
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/gpu/client/gl_helper.h"
20 #include "content/common/media/media_stream_options.h"
21 #include "content/public/test/test_browser_thread_bundle.h"
22 #include "gpu/command_buffer/common/mailbox_holder.h"
23 #include "media/base/video_util.h"
24 #include "media/video/capture/video_capture_types.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
28 #if defined(OS_ANDROID)
29 #include "content/browser/renderer_host/test/no_transport_image_transport_factory_android.h"
30 #else
31 #include "content/browser/compositor/test/no_transport_image_transport_factory.h"
32 #endif
34 using ::testing::InSequence;
35 using ::testing::Mock;
37 namespace content {
39 class MockVideoCaptureControllerEventHandler
40 : public VideoCaptureControllerEventHandler {
41 public:
42 explicit MockVideoCaptureControllerEventHandler(
43 VideoCaptureController* controller)
44 : controller_(controller) {}
45 virtual ~MockVideoCaptureControllerEventHandler() {}
47 // These mock methods are delegated to by our fake implementation of
48 // VideoCaptureControllerEventHandler, to be used in EXPECT_CALL().
49 MOCK_METHOD1(DoBufferCreated, void(const VideoCaptureControllerID&));
50 MOCK_METHOD1(DoBufferDestroyed, void(const VideoCaptureControllerID&));
51 MOCK_METHOD1(DoBufferReady, void(const VideoCaptureControllerID&));
52 MOCK_METHOD1(DoMailboxBufferReady, void(const VideoCaptureControllerID&));
53 MOCK_METHOD1(DoEnded, void(const VideoCaptureControllerID&));
54 MOCK_METHOD1(DoError, void(const VideoCaptureControllerID&));
56 virtual void OnError(const VideoCaptureControllerID& id) OVERRIDE {
57 DoError(id);
59 virtual void OnBufferCreated(const VideoCaptureControllerID& id,
60 base::SharedMemoryHandle handle,
61 int length, int buffer_id) OVERRIDE {
62 DoBufferCreated(id);
64 virtual void OnBufferDestroyed(const VideoCaptureControllerID& id,
65 int buffer_id) OVERRIDE {
66 DoBufferDestroyed(id);
68 virtual void OnBufferReady(const VideoCaptureControllerID& id,
69 int buffer_id,
70 const media::VideoCaptureFormat& format,
71 const gfx::Rect& visible_rect,
72 base::TimeTicks timestamp) OVERRIDE {
73 DoBufferReady(id);
74 base::MessageLoop::current()->PostTask(
75 FROM_HERE,
76 base::Bind(&VideoCaptureController::ReturnBuffer,
77 base::Unretained(controller_),
78 id,
79 this,
80 buffer_id,
81 0));
83 virtual void OnMailboxBufferReady(const VideoCaptureControllerID& id,
84 int buffer_id,
85 const gpu::MailboxHolder& mailbox_holder,
86 const media::VideoCaptureFormat& format,
87 base::TimeTicks timestamp) OVERRIDE {
88 DoMailboxBufferReady(id);
89 base::MessageLoop::current()->PostTask(
90 FROM_HERE,
91 base::Bind(&VideoCaptureController::ReturnBuffer,
92 base::Unretained(controller_),
93 id,
94 this,
95 buffer_id,
96 mailbox_holder.sync_point));
98 virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE {
99 DoEnded(id);
100 // OnEnded() must respond by (eventually) unregistering the client.
101 base::MessageLoop::current()->PostTask(FROM_HERE,
102 base::Bind(base::IgnoreResult(&VideoCaptureController::RemoveClient),
103 base::Unretained(controller_), id, this));
106 VideoCaptureController* controller_;
109 // Test class.
110 class VideoCaptureControllerTest : public testing::Test {
111 public:
112 VideoCaptureControllerTest() {}
113 virtual ~VideoCaptureControllerTest() {}
115 protected:
116 static const int kPoolSize = 3;
118 virtual void SetUp() OVERRIDE {
119 controller_.reset(new VideoCaptureController(kPoolSize));
120 device_ = controller_->NewDeviceClient().Pass();
121 client_a_.reset(new MockVideoCaptureControllerEventHandler(
122 controller_.get()));
123 client_b_.reset(new MockVideoCaptureControllerEventHandler(
124 controller_.get()));
127 virtual void TearDown() OVERRIDE {
128 base::RunLoop().RunUntilIdle();
131 scoped_refptr<media::VideoFrame> WrapI420Buffer(
132 const scoped_refptr<media::VideoCaptureDevice::Client::Buffer>& buffer,
133 gfx::Size dimensions) {
134 return media::VideoFrame::WrapExternalPackedMemory(
135 media::VideoFrame::I420,
136 dimensions,
137 gfx::Rect(dimensions),
138 dimensions,
139 reinterpret_cast<uint8*>(buffer->data()),
140 media::VideoFrame::AllocationSize(media::VideoFrame::I420, dimensions),
141 base::SharedMemory::NULLHandle(),
142 base::TimeDelta(),
143 base::Closure());
146 scoped_refptr<media::VideoFrame> WrapMailboxBuffer(
147 const scoped_refptr<media::VideoCaptureDevice::Client::Buffer>& buffer,
148 scoped_ptr<gpu::MailboxHolder> holder,
149 const media::VideoFrame::ReleaseMailboxCB& release_cb,
150 gfx::Size dimensions) {
151 return media::VideoFrame::WrapNativeTexture(
152 holder.Pass(),
153 release_cb,
154 dimensions,
155 gfx::Rect(dimensions),
156 dimensions,
157 base::TimeDelta(),
158 media::VideoFrame::ReadPixelsCB());
161 TestBrowserThreadBundle bundle_;
162 scoped_ptr<MockVideoCaptureControllerEventHandler> client_a_;
163 scoped_ptr<MockVideoCaptureControllerEventHandler> client_b_;
164 scoped_ptr<VideoCaptureController> controller_;
165 scoped_ptr<media::VideoCaptureDevice::Client> device_;
167 private:
168 DISALLOW_COPY_AND_ASSIGN(VideoCaptureControllerTest);
171 // A simple test of VideoCaptureController's ability to add, remove, and keep
172 // track of clients.
173 TEST_F(VideoCaptureControllerTest, AddAndRemoveClients) {
174 media::VideoCaptureParams session_100;
175 session_100.requested_format = media::VideoCaptureFormat(
176 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
177 media::VideoCaptureParams session_200 = session_100;
179 media::VideoCaptureParams session_300 = session_100;
181 media::VideoCaptureParams session_400 = session_100;
183 // Intentionally use the same route ID for two of the clients: the device_ids
184 // are a per-VideoCaptureHost namespace, and can overlap across hosts.
185 const VideoCaptureControllerID client_a_route_1(44);
186 const VideoCaptureControllerID client_a_route_2(30);
187 const VideoCaptureControllerID client_b_route_1(30);
188 const VideoCaptureControllerID client_b_route_2(1);
190 // Clients in controller: []
191 ASSERT_EQ(0, controller_->GetClientCount())
192 << "Client count should initially be zero.";
193 controller_->AddClient(client_a_route_1,
194 client_a_.get(),
195 base::kNullProcessHandle,
196 100,
197 session_100);
198 // Clients in controller: [A/1]
199 ASSERT_EQ(1, controller_->GetClientCount())
200 << "Adding client A/1 should bump client count.";
201 controller_->AddClient(client_a_route_2,
202 client_a_.get(),
203 base::kNullProcessHandle,
204 200,
205 session_200);
206 // Clients in controller: [A/1, A/2]
207 ASSERT_EQ(2, controller_->GetClientCount())
208 << "Adding client A/2 should bump client count.";
209 controller_->AddClient(client_b_route_1,
210 client_b_.get(),
211 base::kNullProcessHandle,
212 300,
213 session_300);
214 // Clients in controller: [A/1, A/2, B/1]
215 ASSERT_EQ(3, controller_->GetClientCount())
216 << "Adding client B/1 should bump client count.";
217 ASSERT_EQ(200,
218 controller_->RemoveClient(client_a_route_2, client_a_.get()))
219 << "Removing client A/1 should return its session_id.";
220 // Clients in controller: [A/1, B/1]
221 ASSERT_EQ(2, controller_->GetClientCount());
222 ASSERT_EQ(static_cast<int>(kInvalidMediaCaptureSessionId),
223 controller_->RemoveClient(client_a_route_2, client_a_.get()))
224 << "Removing a nonexistant client should fail.";
225 // Clients in controller: [A/1, B/1]
226 ASSERT_EQ(2, controller_->GetClientCount());
227 ASSERT_EQ(300,
228 controller_->RemoveClient(client_b_route_1, client_b_.get()))
229 << "Removing client B/1 should return its session_id.";
230 // Clients in controller: [A/1]
231 ASSERT_EQ(1, controller_->GetClientCount());
232 controller_->AddClient(client_b_route_2,
233 client_b_.get(),
234 base::kNullProcessHandle,
235 400,
236 session_400);
237 // Clients in controller: [A/1, B/2]
239 EXPECT_CALL(*client_a_, DoEnded(client_a_route_1)).Times(1);
240 controller_->StopSession(100); // Session 100 == client A/1
241 Mock::VerifyAndClearExpectations(client_a_.get());
242 ASSERT_EQ(2, controller_->GetClientCount())
243 << "Client should be closed but still exist after StopSession.";
244 // Clients in controller: [A/1 (closed, removal pending), B/2]
245 base::RunLoop().RunUntilIdle();
246 // Clients in controller: [B/2]
247 ASSERT_EQ(1, controller_->GetClientCount())
248 << "Client A/1 should be deleted by now.";
249 controller_->StopSession(200); // Session 200 does not exist anymore
250 // Clients in controller: [B/2]
251 ASSERT_EQ(1, controller_->GetClientCount())
252 << "Stopping non-existant session 200 should be a no-op.";
253 controller_->StopSession(256); // Session 256 never existed.
254 // Clients in controller: [B/2]
255 ASSERT_EQ(1, controller_->GetClientCount())
256 << "Stopping non-existant session 256 should be a no-op.";
257 ASSERT_EQ(static_cast<int>(kInvalidMediaCaptureSessionId),
258 controller_->RemoveClient(client_a_route_1, client_a_.get()))
259 << "Removing already-removed client A/1 should fail.";
260 // Clients in controller: [B/2]
261 ASSERT_EQ(1, controller_->GetClientCount())
262 << "Removing non-existant session 200 should be a no-op.";
263 ASSERT_EQ(400,
264 controller_->RemoveClient(client_b_route_2, client_b_.get()))
265 << "Removing client B/2 should return its session_id.";
266 // Clients in controller: []
267 ASSERT_EQ(0, controller_->GetClientCount())
268 << "Client count should return to zero after all clients are gone.";
271 static void CacheSyncPoint(uint32* called_release_sync_point,
272 uint32 release_sync_point) {
273 *called_release_sync_point = release_sync_point;
276 // This test will connect and disconnect several clients while simulating an
277 // active capture device being started and generating frames. It runs on one
278 // thread and is intended to behave deterministically.
279 TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
280 // VideoCaptureController::ReturnBuffer() uses ImageTransportFactory.
281 #if defined(OS_ANDROID)
282 ImageTransportFactoryAndroid::InitializeForUnitTests(
283 scoped_ptr<ImageTransportFactoryAndroid>(
284 new NoTransportImageTransportFactoryAndroid));
285 #else
286 ImageTransportFactory::InitializeForUnitTests(
287 scoped_ptr<ImageTransportFactory>(new NoTransportImageTransportFactory));
288 #endif
290 media::VideoCaptureParams session_100;
291 session_100.requested_format = media::VideoCaptureFormat(
292 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
294 media::VideoCaptureParams session_200 = session_100;
296 media::VideoCaptureParams session_300 = session_100;
298 media::VideoCaptureParams session_1 = session_100;
300 gfx::Size capture_resolution(444, 200);
302 // The device format needn't match the VideoCaptureParams (the camera can do
303 // what it wants). Pick something random.
304 media::VideoCaptureFormat device_format(
305 gfx::Size(10, 10), 25, media::PIXEL_FORMAT_RGB24);
307 const VideoCaptureControllerID client_a_route_1(0xa1a1a1a1);
308 const VideoCaptureControllerID client_a_route_2(0xa2a2a2a2);
309 const VideoCaptureControllerID client_b_route_1(0xb1b1b1b1);
310 const VideoCaptureControllerID client_b_route_2(0xb2b2b2b2);
312 // Start with two clients.
313 controller_->AddClient(client_a_route_1,
314 client_a_.get(),
315 base::kNullProcessHandle,
316 100,
317 session_100);
318 controller_->AddClient(client_b_route_1,
319 client_b_.get(),
320 base::kNullProcessHandle,
321 300,
322 session_300);
323 controller_->AddClient(client_a_route_2,
324 client_a_.get(),
325 base::kNullProcessHandle,
326 200,
327 session_200);
328 ASSERT_EQ(3, controller_->GetClientCount());
330 // Now, simulate an incoming captured buffer from the capture device. As a
331 // side effect this will cause the first buffer to be shared with clients.
332 uint8 buffer_no = 1;
333 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer;
334 buffer =
335 device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
336 ASSERT_TRUE(buffer.get());
337 memset(buffer->data(), buffer_no++, buffer->size());
339 InSequence s;
340 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1)).Times(1);
341 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(1);
344 InSequence s;
345 EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1)).Times(1);
346 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(1);
349 InSequence s;
350 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2)).Times(1);
351 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(1);
353 device_->OnIncomingCapturedVideoFrame(
354 buffer,
355 media::VideoCaptureFormat(capture_resolution,
356 device_format.frame_rate,
357 media::PIXEL_FORMAT_I420),
358 WrapI420Buffer(buffer, capture_resolution),
359 base::TimeTicks());
360 buffer = NULL;
362 base::RunLoop().RunUntilIdle();
363 Mock::VerifyAndClearExpectations(client_a_.get());
364 Mock::VerifyAndClearExpectations(client_b_.get());
366 // Second buffer which ought to use the same shared memory buffer. In this
367 // case pretend that the Buffer pointer is held by the device for a long
368 // delay. This shouldn't affect anything.
369 buffer =
370 device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
371 ASSERT_TRUE(buffer.get());
372 memset(buffer->data(), buffer_no++, buffer->size());
373 device_->OnIncomingCapturedVideoFrame(
374 buffer,
375 media::VideoCaptureFormat(capture_resolution,
376 device_format.frame_rate,
377 media::PIXEL_FORMAT_I420),
378 WrapI420Buffer(buffer, capture_resolution),
379 base::TimeTicks());
380 buffer = NULL;
382 // The buffer should be delivered to the clients in any order.
383 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(1);
384 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(1);
385 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(1);
386 base::RunLoop().RunUntilIdle();
387 Mock::VerifyAndClearExpectations(client_a_.get());
388 Mock::VerifyAndClearExpectations(client_b_.get());
390 // Add a fourth client now that some buffers have come through.
391 controller_->AddClient(client_b_route_2,
392 client_b_.get(),
393 base::kNullProcessHandle,
395 session_1);
396 Mock::VerifyAndClearExpectations(client_b_.get());
398 // Third, fourth, and fifth buffers. Pretend they all arrive at the same time.
399 for (int i = 0; i < kPoolSize; i++) {
400 buffer = device_->ReserveOutputBuffer(media::VideoFrame::I420,
401 capture_resolution);
402 ASSERT_TRUE(buffer.get());
403 memset(buffer->data(), buffer_no++, buffer->size());
404 device_->OnIncomingCapturedVideoFrame(
405 buffer,
406 media::VideoCaptureFormat(capture_resolution,
407 device_format.frame_rate,
408 media::PIXEL_FORMAT_I420),
409 WrapI420Buffer(buffer, capture_resolution),
410 base::TimeTicks());
411 buffer = NULL;
413 // ReserveOutputBuffer ought to fail now, because the pool is depleted.
414 ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::I420,
415 capture_resolution).get());
417 // The new client needs to be told of 3 buffers; the old clients only 2.
418 EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_2)).Times(kPoolSize);
419 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(kPoolSize);
420 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1))
421 .Times(kPoolSize - 1);
422 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(kPoolSize);
423 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2))
424 .Times(kPoolSize - 1);
425 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(kPoolSize);
426 EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1))
427 .Times(kPoolSize - 1);
428 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(kPoolSize);
429 base::RunLoop().RunUntilIdle();
430 Mock::VerifyAndClearExpectations(client_a_.get());
431 Mock::VerifyAndClearExpectations(client_b_.get());
433 // Now test the interaction of client shutdown and buffer delivery.
434 // Kill A1 via renderer disconnect (synchronous).
435 controller_->RemoveClient(client_a_route_1, client_a_.get());
436 // Kill B1 via session close (posts a task to disconnect).
437 EXPECT_CALL(*client_b_, DoEnded(client_b_route_1)).Times(1);
438 controller_->StopSession(300);
439 // Queue up another buffer.
440 buffer =
441 device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
442 ASSERT_TRUE(buffer.get());
443 memset(buffer->data(), buffer_no++, buffer->size());
444 device_->OnIncomingCapturedVideoFrame(
445 buffer,
446 media::VideoCaptureFormat(capture_resolution,
447 device_format.frame_rate,
448 media::PIXEL_FORMAT_I420),
449 WrapI420Buffer(buffer, capture_resolution),
450 base::TimeTicks());
451 buffer = NULL;
452 buffer =
453 device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
455 // Kill A2 via session close (posts a task to disconnect, but A2 must not
456 // be sent either of these two buffers).
457 EXPECT_CALL(*client_a_, DoEnded(client_a_route_2)).Times(1);
458 controller_->StopSession(200);
460 ASSERT_TRUE(buffer.get());
461 memset(buffer->data(), buffer_no++, buffer->size());
462 device_->OnIncomingCapturedVideoFrame(
463 buffer,
464 media::VideoCaptureFormat(capture_resolution,
465 device_format.frame_rate,
466 media::PIXEL_FORMAT_I420),
467 WrapI420Buffer(buffer, capture_resolution),
468 base::TimeTicks());
469 buffer = NULL;
470 // B2 is the only client left, and is the only one that should
471 // get the buffer.
472 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(2);
473 base::RunLoop().RunUntilIdle();
474 Mock::VerifyAndClearExpectations(client_a_.get());
475 Mock::VerifyAndClearExpectations(client_b_.get());
477 // Allocate all buffers from the buffer pool, half as SHM buffer and half as
478 // mailbox buffers. Make sure of different counts though.
479 int shm_buffers = kPoolSize / 2;
480 int mailbox_buffers = kPoolSize - shm_buffers;
481 if (shm_buffers == mailbox_buffers) {
482 shm_buffers--;
483 mailbox_buffers++;
486 for (int i = 0; i < shm_buffers; ++i) {
487 buffer = device_->ReserveOutputBuffer(media::VideoFrame::I420,
488 capture_resolution);
489 ASSERT_TRUE(buffer.get());
490 device_->OnIncomingCapturedVideoFrame(
491 buffer,
492 media::VideoCaptureFormat(capture_resolution,
493 device_format.frame_rate,
494 media::PIXEL_FORMAT_I420),
495 WrapI420Buffer(buffer, capture_resolution),
496 base::TimeTicks());
497 buffer = NULL;
499 std::vector<uint32> mailbox_syncpoints(mailbox_buffers);
500 std::vector<uint32> release_syncpoints(mailbox_buffers);
501 #if defined(OS_ANDROID)
502 GLHelper* gl_helper =
503 ImageTransportFactoryAndroid::GetInstance()->GetGLHelper();
504 #else
505 GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
506 #endif
507 for (int i = 0; i < mailbox_buffers; ++i) {
508 buffer = device_->ReserveOutputBuffer(media::VideoFrame::NATIVE_TEXTURE,
509 gfx::Size(0, 0));
510 ASSERT_TRUE(buffer.get());
511 mailbox_syncpoints[i] = gl_helper->InsertSyncPoint();
512 device_->OnIncomingCapturedVideoFrame(
513 buffer,
514 media::VideoCaptureFormat(capture_resolution,
515 device_format.frame_rate,
516 media::PIXEL_FORMAT_TEXTURE),
517 WrapMailboxBuffer(buffer,
518 make_scoped_ptr(new gpu::MailboxHolder(
519 gpu::Mailbox(), 0, mailbox_syncpoints[i])),
520 base::Bind(&CacheSyncPoint, &release_syncpoints[i]),
521 capture_resolution),
522 base::TimeTicks());
523 buffer = NULL;
525 // ReserveOutputBuffers ought to fail now regardless of buffer format, because
526 // the pool is depleted.
527 ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::I420,
528 capture_resolution).get());
529 ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::NATIVE_TEXTURE,
530 gfx::Size(0, 0)).get());
531 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(shm_buffers);
532 EXPECT_CALL(*client_b_, DoMailboxBufferReady(client_b_route_2))
533 .Times(mailbox_buffers);
534 base::RunLoop().RunUntilIdle();
535 for (size_t i = 0; i < mailbox_syncpoints.size(); ++i) {
536 // A new release sync point must be inserted when the video frame is
537 // returned to the Browser process.
538 // See: MockVideoCaptureControllerEventHandler::OnMailboxBufferReady() and
539 // VideoCaptureController::ReturnBuffer()
540 ASSERT_NE(mailbox_syncpoints[i], release_syncpoints[i]);
542 Mock::VerifyAndClearExpectations(client_b_.get());
544 #if defined(OS_ANDROID)
545 ImageTransportFactoryAndroid::TerminateForUnitTests();
546 #else
547 ImageTransportFactory::Terminate();
548 #endif
551 // Exercises the OnError() codepath of VideoCaptureController, and tests the
552 // behavior of various operations after the error state has been signalled.
553 TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) {
554 media::VideoCaptureParams session_100;
555 session_100.requested_format = media::VideoCaptureFormat(
556 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
558 media::VideoCaptureParams session_200 = session_100;
560 const gfx::Size capture_resolution(320, 240);
562 const VideoCaptureControllerID route_id(0x99);
564 // Start with one client.
565 controller_->AddClient(
566 route_id, client_a_.get(), base::kNullProcessHandle, 100, session_100);
567 device_->OnError("Test Error");
568 EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
569 base::RunLoop().RunUntilIdle();
570 Mock::VerifyAndClearExpectations(client_a_.get());
572 // Second client connects after the error state. It also should get told of
573 // the error.
574 EXPECT_CALL(*client_b_, DoError(route_id)).Times(1);
575 controller_->AddClient(
576 route_id, client_b_.get(), base::kNullProcessHandle, 200, session_200);
577 base::RunLoop().RunUntilIdle();
578 Mock::VerifyAndClearExpectations(client_b_.get());
580 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer =
581 device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
582 ASSERT_TRUE(buffer.get());
584 device_->OnIncomingCapturedVideoFrame(
585 buffer,
586 media::VideoCaptureFormat(
587 capture_resolution, 30, media::PIXEL_FORMAT_I420),
588 WrapI420Buffer(buffer, capture_resolution),
589 base::TimeTicks());
590 buffer = NULL;
592 base::RunLoop().RunUntilIdle();
595 // Exercises the OnError() codepath of VideoCaptureController, and tests the
596 // behavior of various operations after the error state has been signalled.
597 TEST_F(VideoCaptureControllerTest, ErrorAfterDeviceCreation) {
598 media::VideoCaptureParams session_100;
599 session_100.requested_format = media::VideoCaptureFormat(
600 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
602 media::VideoCaptureParams session_200 = session_100;
604 const VideoCaptureControllerID route_id(0x99);
606 // Start with one client.
607 controller_->AddClient(
608 route_id, client_a_.get(), base::kNullProcessHandle, 100, session_100);
609 media::VideoCaptureFormat device_format(
610 gfx::Size(10, 10), 25, media::PIXEL_FORMAT_ARGB);
612 // Start the device. Then, before the first buffer, signal an error and
613 // deliver the buffer. The error should be propagated to clients; the buffer
614 // should not be.
615 base::RunLoop().RunUntilIdle();
616 Mock::VerifyAndClearExpectations(client_a_.get());
618 const gfx::Size dims(320, 240);
619 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer =
620 device_->ReserveOutputBuffer(media::VideoFrame::I420, dims);
621 ASSERT_TRUE(buffer.get());
623 device_->OnError("Test error");
624 device_->OnIncomingCapturedVideoFrame(
625 buffer,
626 media::VideoCaptureFormat(
627 dims, device_format.frame_rate, media::PIXEL_FORMAT_I420),
628 WrapI420Buffer(buffer, dims),
629 base::TimeTicks());
630 buffer = NULL;
632 EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
633 base::RunLoop().RunUntilIdle();
634 Mock::VerifyAndClearExpectations(client_a_.get());
636 // Second client connects after the error state. It also should get told of
637 // the error.
638 EXPECT_CALL(*client_b_, DoError(route_id)).Times(1);
639 controller_->AddClient(
640 route_id, client_b_.get(), base::kNullProcessHandle, 200, session_200);
641 Mock::VerifyAndClearExpectations(client_b_.get());
644 } // namespace content