Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / renderer_host / media / video_capture_controller_unittest.cc
blobb20678fc3c7d8b94ac3b3abf7591a8a718a21c31
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 base::TimeTicks timestamp) OVERRIDE {
72 DoBufferReady(id);
73 base::MessageLoop::current()->PostTask(
74 FROM_HERE,
75 base::Bind(&VideoCaptureController::ReturnBuffer,
76 base::Unretained(controller_),
77 id,
78 this,
79 buffer_id,
80 0));
82 virtual void OnMailboxBufferReady(const VideoCaptureControllerID& id,
83 int buffer_id,
84 const gpu::MailboxHolder& mailbox_holder,
85 const media::VideoCaptureFormat& format,
86 base::TimeTicks timestamp) OVERRIDE {
87 DoMailboxBufferReady(id);
88 base::MessageLoop::current()->PostTask(
89 FROM_HERE,
90 base::Bind(&VideoCaptureController::ReturnBuffer,
91 base::Unretained(controller_),
92 id,
93 this,
94 buffer_id,
95 mailbox_holder.sync_point));
97 virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE {
98 DoEnded(id);
99 // OnEnded() must respond by (eventually) unregistering the client.
100 base::MessageLoop::current()->PostTask(FROM_HERE,
101 base::Bind(base::IgnoreResult(&VideoCaptureController::RemoveClient),
102 base::Unretained(controller_), id, this));
105 VideoCaptureController* controller_;
108 // Test class.
109 class VideoCaptureControllerTest : public testing::Test {
110 public:
111 VideoCaptureControllerTest() {}
112 virtual ~VideoCaptureControllerTest() {}
114 protected:
115 static const int kPoolSize = 3;
117 virtual void SetUp() OVERRIDE {
118 controller_.reset(new VideoCaptureController(kPoolSize));
119 device_ = controller_->NewDeviceClient().Pass();
120 client_a_.reset(new MockVideoCaptureControllerEventHandler(
121 controller_.get()));
122 client_b_.reset(new MockVideoCaptureControllerEventHandler(
123 controller_.get()));
126 virtual void TearDown() OVERRIDE {
127 base::RunLoop().RunUntilIdle();
130 scoped_refptr<media::VideoFrame> WrapI420Buffer(
131 const scoped_refptr<media::VideoCaptureDevice::Client::Buffer>& buffer,
132 gfx::Size dimensions) {
133 return media::VideoFrame::WrapExternalPackedMemory(
134 media::VideoFrame::I420,
135 dimensions,
136 gfx::Rect(dimensions),
137 dimensions,
138 reinterpret_cast<uint8*>(buffer->data()),
139 media::VideoFrame::AllocationSize(media::VideoFrame::I420, dimensions),
140 base::SharedMemory::NULLHandle(),
141 base::TimeDelta(),
142 base::Closure());
145 scoped_refptr<media::VideoFrame> WrapMailboxBuffer(
146 const scoped_refptr<media::VideoCaptureDevice::Client::Buffer>& buffer,
147 scoped_ptr<gpu::MailboxHolder> holder,
148 const media::VideoFrame::ReleaseMailboxCB& release_cb,
149 gfx::Size dimensions) {
150 return media::VideoFrame::WrapNativeTexture(
151 holder.Pass(),
152 release_cb,
153 dimensions,
154 gfx::Rect(dimensions),
155 dimensions,
156 base::TimeDelta(),
157 media::VideoFrame::ReadPixelsCB());
160 TestBrowserThreadBundle bundle_;
161 scoped_ptr<MockVideoCaptureControllerEventHandler> client_a_;
162 scoped_ptr<MockVideoCaptureControllerEventHandler> client_b_;
163 scoped_ptr<VideoCaptureController> controller_;
164 scoped_ptr<media::VideoCaptureDevice::Client> device_;
166 private:
167 DISALLOW_COPY_AND_ASSIGN(VideoCaptureControllerTest);
170 // A simple test of VideoCaptureController's ability to add, remove, and keep
171 // track of clients.
172 TEST_F(VideoCaptureControllerTest, AddAndRemoveClients) {
173 media::VideoCaptureParams session_100;
174 session_100.requested_format = media::VideoCaptureFormat(
175 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
176 media::VideoCaptureParams session_200 = session_100;
178 media::VideoCaptureParams session_300 = session_100;
180 media::VideoCaptureParams session_400 = session_100;
182 // Intentionally use the same route ID for two of the clients: the device_ids
183 // are a per-VideoCaptureHost namespace, and can overlap across hosts.
184 const VideoCaptureControllerID client_a_route_1(44);
185 const VideoCaptureControllerID client_a_route_2(30);
186 const VideoCaptureControllerID client_b_route_1(30);
187 const VideoCaptureControllerID client_b_route_2(1);
189 // Clients in controller: []
190 ASSERT_EQ(0, controller_->GetClientCount())
191 << "Client count should initially be zero.";
192 controller_->AddClient(client_a_route_1,
193 client_a_.get(),
194 base::kNullProcessHandle,
195 100,
196 session_100);
197 // Clients in controller: [A/1]
198 ASSERT_EQ(1, controller_->GetClientCount())
199 << "Adding client A/1 should bump client count.";
200 controller_->AddClient(client_a_route_2,
201 client_a_.get(),
202 base::kNullProcessHandle,
203 200,
204 session_200);
205 // Clients in controller: [A/1, A/2]
206 ASSERT_EQ(2, controller_->GetClientCount())
207 << "Adding client A/2 should bump client count.";
208 controller_->AddClient(client_b_route_1,
209 client_b_.get(),
210 base::kNullProcessHandle,
211 300,
212 session_300);
213 // Clients in controller: [A/1, A/2, B/1]
214 ASSERT_EQ(3, controller_->GetClientCount())
215 << "Adding client B/1 should bump client count.";
216 ASSERT_EQ(200,
217 controller_->RemoveClient(client_a_route_2, client_a_.get()))
218 << "Removing client A/1 should return its session_id.";
219 // Clients in controller: [A/1, B/1]
220 ASSERT_EQ(2, controller_->GetClientCount());
221 ASSERT_EQ(static_cast<int>(kInvalidMediaCaptureSessionId),
222 controller_->RemoveClient(client_a_route_2, client_a_.get()))
223 << "Removing a nonexistant client should fail.";
224 // Clients in controller: [A/1, B/1]
225 ASSERT_EQ(2, controller_->GetClientCount());
226 ASSERT_EQ(300,
227 controller_->RemoveClient(client_b_route_1, client_b_.get()))
228 << "Removing client B/1 should return its session_id.";
229 // Clients in controller: [A/1]
230 ASSERT_EQ(1, controller_->GetClientCount());
231 controller_->AddClient(client_b_route_2,
232 client_b_.get(),
233 base::kNullProcessHandle,
234 400,
235 session_400);
236 // Clients in controller: [A/1, B/2]
238 EXPECT_CALL(*client_a_, DoEnded(client_a_route_1)).Times(1);
239 controller_->StopSession(100); // Session 100 == client A/1
240 Mock::VerifyAndClearExpectations(client_a_.get());
241 ASSERT_EQ(2, controller_->GetClientCount())
242 << "Client should be closed but still exist after StopSession.";
243 // Clients in controller: [A/1 (closed, removal pending), B/2]
244 base::RunLoop().RunUntilIdle();
245 // Clients in controller: [B/2]
246 ASSERT_EQ(1, controller_->GetClientCount())
247 << "Client A/1 should be deleted by now.";
248 controller_->StopSession(200); // Session 200 does not exist anymore
249 // Clients in controller: [B/2]
250 ASSERT_EQ(1, controller_->GetClientCount())
251 << "Stopping non-existant session 200 should be a no-op.";
252 controller_->StopSession(256); // Session 256 never existed.
253 // Clients in controller: [B/2]
254 ASSERT_EQ(1, controller_->GetClientCount())
255 << "Stopping non-existant session 256 should be a no-op.";
256 ASSERT_EQ(static_cast<int>(kInvalidMediaCaptureSessionId),
257 controller_->RemoveClient(client_a_route_1, client_a_.get()))
258 << "Removing already-removed client A/1 should fail.";
259 // Clients in controller: [B/2]
260 ASSERT_EQ(1, controller_->GetClientCount())
261 << "Removing non-existant session 200 should be a no-op.";
262 ASSERT_EQ(400,
263 controller_->RemoveClient(client_b_route_2, client_b_.get()))
264 << "Removing client B/2 should return its session_id.";
265 // Clients in controller: []
266 ASSERT_EQ(0, controller_->GetClientCount())
267 << "Client count should return to zero after all clients are gone.";
270 static void CacheSyncPoint(uint32* called_release_sync_point,
271 uint32 release_sync_point) {
272 *called_release_sync_point = release_sync_point;
275 // This test will connect and disconnect several clients while simulating an
276 // active capture device being started and generating frames. It runs on one
277 // thread and is intended to behave deterministically.
278 TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
279 // VideoCaptureController::ReturnBuffer() uses ImageTransportFactory.
280 #if defined(OS_ANDROID)
281 ImageTransportFactoryAndroid::InitializeForUnitTests(
282 scoped_ptr<ImageTransportFactoryAndroid>(
283 new NoTransportImageTransportFactoryAndroid));
284 #else
285 ImageTransportFactory::InitializeForUnitTests(
286 scoped_ptr<ImageTransportFactory>(new NoTransportImageTransportFactory));
287 #endif
289 media::VideoCaptureParams session_100;
290 session_100.requested_format = media::VideoCaptureFormat(
291 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
293 media::VideoCaptureParams session_200 = session_100;
295 media::VideoCaptureParams session_300 = session_100;
297 media::VideoCaptureParams session_1 = session_100;
299 gfx::Size capture_resolution(444, 200);
301 // The device format needn't match the VideoCaptureParams (the camera can do
302 // what it wants). Pick something random.
303 media::VideoCaptureFormat device_format(
304 gfx::Size(10, 10), 25, media::PIXEL_FORMAT_RGB24);
306 const VideoCaptureControllerID client_a_route_1(0xa1a1a1a1);
307 const VideoCaptureControllerID client_a_route_2(0xa2a2a2a2);
308 const VideoCaptureControllerID client_b_route_1(0xb1b1b1b1);
309 const VideoCaptureControllerID client_b_route_2(0xb2b2b2b2);
311 // Start with two clients.
312 controller_->AddClient(client_a_route_1,
313 client_a_.get(),
314 base::kNullProcessHandle,
315 100,
316 session_100);
317 controller_->AddClient(client_b_route_1,
318 client_b_.get(),
319 base::kNullProcessHandle,
320 300,
321 session_300);
322 controller_->AddClient(client_a_route_2,
323 client_a_.get(),
324 base::kNullProcessHandle,
325 200,
326 session_200);
327 ASSERT_EQ(3, controller_->GetClientCount());
329 // Now, simulate an incoming captured buffer from the capture device. As a
330 // side effect this will cause the first buffer to be shared with clients.
331 uint8 buffer_no = 1;
332 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer;
333 buffer =
334 device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
335 ASSERT_TRUE(buffer.get());
336 memset(buffer->data(), buffer_no++, buffer->size());
338 InSequence s;
339 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1)).Times(1);
340 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(1);
343 InSequence s;
344 EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1)).Times(1);
345 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(1);
348 InSequence s;
349 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2)).Times(1);
350 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(1);
352 device_->OnIncomingCapturedVideoFrame(
353 buffer,
354 media::VideoCaptureFormat(capture_resolution,
355 device_format.frame_rate,
356 media::PIXEL_FORMAT_I420),
357 WrapI420Buffer(buffer, capture_resolution),
358 base::TimeTicks());
359 buffer = NULL;
361 base::RunLoop().RunUntilIdle();
362 Mock::VerifyAndClearExpectations(client_a_.get());
363 Mock::VerifyAndClearExpectations(client_b_.get());
365 // Second buffer which ought to use the same shared memory buffer. In this
366 // case pretend that the Buffer pointer is held by the device for a long
367 // delay. This shouldn't affect anything.
368 buffer =
369 device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
370 ASSERT_TRUE(buffer.get());
371 memset(buffer->data(), buffer_no++, buffer->size());
372 device_->OnIncomingCapturedVideoFrame(
373 buffer,
374 media::VideoCaptureFormat(capture_resolution,
375 device_format.frame_rate,
376 media::PIXEL_FORMAT_I420),
377 WrapI420Buffer(buffer, capture_resolution),
378 base::TimeTicks());
379 buffer = NULL;
381 // The buffer should be delivered to the clients in any order.
382 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(1);
383 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(1);
384 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(1);
385 base::RunLoop().RunUntilIdle();
386 Mock::VerifyAndClearExpectations(client_a_.get());
387 Mock::VerifyAndClearExpectations(client_b_.get());
389 // Add a fourth client now that some buffers have come through.
390 controller_->AddClient(client_b_route_2,
391 client_b_.get(),
392 base::kNullProcessHandle,
394 session_1);
395 Mock::VerifyAndClearExpectations(client_b_.get());
397 // Third, fourth, and fifth buffers. Pretend they all arrive at the same time.
398 for (int i = 0; i < kPoolSize; i++) {
399 buffer = device_->ReserveOutputBuffer(media::VideoFrame::I420,
400 capture_resolution);
401 ASSERT_TRUE(buffer.get());
402 memset(buffer->data(), buffer_no++, buffer->size());
403 device_->OnIncomingCapturedVideoFrame(
404 buffer,
405 media::VideoCaptureFormat(capture_resolution,
406 device_format.frame_rate,
407 media::PIXEL_FORMAT_I420),
408 WrapI420Buffer(buffer, capture_resolution),
409 base::TimeTicks());
410 buffer = NULL;
412 // ReserveOutputBuffer ought to fail now, because the pool is depleted.
413 ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::I420,
414 capture_resolution));
416 // The new client needs to be told of 3 buffers; the old clients only 2.
417 EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_2)).Times(kPoolSize);
418 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(kPoolSize);
419 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1))
420 .Times(kPoolSize - 1);
421 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(kPoolSize);
422 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2))
423 .Times(kPoolSize - 1);
424 EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(kPoolSize);
425 EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1))
426 .Times(kPoolSize - 1);
427 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(kPoolSize);
428 base::RunLoop().RunUntilIdle();
429 Mock::VerifyAndClearExpectations(client_a_.get());
430 Mock::VerifyAndClearExpectations(client_b_.get());
432 // Now test the interaction of client shutdown and buffer delivery.
433 // Kill A1 via renderer disconnect (synchronous).
434 controller_->RemoveClient(client_a_route_1, client_a_.get());
435 // Kill B1 via session close (posts a task to disconnect).
436 EXPECT_CALL(*client_b_, DoEnded(client_b_route_1)).Times(1);
437 controller_->StopSession(300);
438 // Queue up another buffer.
439 buffer =
440 device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
441 ASSERT_TRUE(buffer.get());
442 memset(buffer->data(), buffer_no++, buffer->size());
443 device_->OnIncomingCapturedVideoFrame(
444 buffer,
445 media::VideoCaptureFormat(capture_resolution,
446 device_format.frame_rate,
447 media::PIXEL_FORMAT_I420),
448 WrapI420Buffer(buffer, capture_resolution),
449 base::TimeTicks());
450 buffer = NULL;
451 buffer =
452 device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
454 // Kill A2 via session close (posts a task to disconnect, but A2 must not
455 // be sent either of these two buffers).
456 EXPECT_CALL(*client_a_, DoEnded(client_a_route_2)).Times(1);
457 controller_->StopSession(200);
459 ASSERT_TRUE(buffer.get());
460 memset(buffer->data(), buffer_no++, buffer->size());
461 device_->OnIncomingCapturedVideoFrame(
462 buffer,
463 media::VideoCaptureFormat(capture_resolution,
464 device_format.frame_rate,
465 media::PIXEL_FORMAT_I420),
466 WrapI420Buffer(buffer, capture_resolution),
467 base::TimeTicks());
468 buffer = NULL;
469 // B2 is the only client left, and is the only one that should
470 // get the buffer.
471 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(2);
472 base::RunLoop().RunUntilIdle();
473 Mock::VerifyAndClearExpectations(client_a_.get());
474 Mock::VerifyAndClearExpectations(client_b_.get());
476 // Allocate all buffers from the buffer pool, half as SHM buffer and half as
477 // mailbox buffers. Make sure of different counts though.
478 int shm_buffers = kPoolSize / 2;
479 int mailbox_buffers = kPoolSize - shm_buffers;
480 if (shm_buffers == mailbox_buffers) {
481 shm_buffers--;
482 mailbox_buffers++;
485 for (int i = 0; i < shm_buffers; ++i) {
486 buffer = device_->ReserveOutputBuffer(media::VideoFrame::I420,
487 capture_resolution);
488 ASSERT_TRUE(buffer.get());
489 device_->OnIncomingCapturedVideoFrame(
490 buffer,
491 media::VideoCaptureFormat(capture_resolution,
492 device_format.frame_rate,
493 media::PIXEL_FORMAT_I420),
494 WrapI420Buffer(buffer, capture_resolution),
495 base::TimeTicks());
496 buffer = NULL;
498 std::vector<uint32> mailbox_syncpoints(mailbox_buffers);
499 std::vector<uint32> release_syncpoints(mailbox_buffers);
500 #if defined(OS_ANDROID)
501 GLHelper* gl_helper =
502 ImageTransportFactoryAndroid::GetInstance()->GetGLHelper();
503 #else
504 GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
505 #endif
506 for (int i = 0; i < mailbox_buffers; ++i) {
507 buffer = device_->ReserveOutputBuffer(media::VideoFrame::NATIVE_TEXTURE,
508 gfx::Size(0, 0));
509 ASSERT_TRUE(buffer.get());
510 mailbox_syncpoints[i] = gl_helper->InsertSyncPoint();
511 device_->OnIncomingCapturedVideoFrame(
512 buffer,
513 media::VideoCaptureFormat(capture_resolution,
514 device_format.frame_rate,
515 media::PIXEL_FORMAT_TEXTURE),
516 WrapMailboxBuffer(buffer,
517 make_scoped_ptr(new gpu::MailboxHolder(
518 gpu::Mailbox(), 0, mailbox_syncpoints[i])),
519 base::Bind(&CacheSyncPoint, &release_syncpoints[i]),
520 capture_resolution),
521 base::TimeTicks());
522 buffer = NULL;
524 // ReserveOutputBuffers ought to fail now regardless of buffer format, because
525 // the pool is depleted.
526 ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::I420,
527 capture_resolution));
528 ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::NATIVE_TEXTURE,
529 gfx::Size(0, 0)));
530 EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(shm_buffers);
531 EXPECT_CALL(*client_b_, DoMailboxBufferReady(client_b_route_2))
532 .Times(mailbox_buffers);
533 base::RunLoop().RunUntilIdle();
534 for (size_t i = 0; i < mailbox_syncpoints.size(); ++i) {
535 // A new release sync point must be inserted when the video frame is
536 // returned to the Browser process.
537 // See: MockVideoCaptureControllerEventHandler::OnMailboxBufferReady() and
538 // VideoCaptureController::ReturnBuffer()
539 ASSERT_NE(mailbox_syncpoints[i], release_syncpoints[i]);
541 Mock::VerifyAndClearExpectations(client_b_.get());
543 #if defined(OS_ANDROID)
544 ImageTransportFactoryAndroid::TerminateForUnitTests();
545 #else
546 ImageTransportFactory::Terminate();
547 #endif
550 // Exercises the OnError() codepath of VideoCaptureController, and tests the
551 // behavior of various operations after the error state has been signalled.
552 TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) {
553 media::VideoCaptureParams session_100;
554 session_100.requested_format = media::VideoCaptureFormat(
555 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
557 media::VideoCaptureParams session_200 = session_100;
559 const gfx::Size capture_resolution(320, 240);
561 const VideoCaptureControllerID route_id(0x99);
563 // Start with one client.
564 controller_->AddClient(
565 route_id, client_a_.get(), base::kNullProcessHandle, 100, session_100);
566 device_->OnError("Test Error");
567 EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
568 base::RunLoop().RunUntilIdle();
569 Mock::VerifyAndClearExpectations(client_a_.get());
571 // Second client connects after the error state. It also should get told of
572 // the error.
573 EXPECT_CALL(*client_b_, DoError(route_id)).Times(1);
574 controller_->AddClient(
575 route_id, client_b_.get(), base::kNullProcessHandle, 200, session_200);
576 base::RunLoop().RunUntilIdle();
577 Mock::VerifyAndClearExpectations(client_b_.get());
579 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer =
580 device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
581 ASSERT_TRUE(buffer.get());
583 device_->OnIncomingCapturedVideoFrame(
584 buffer,
585 media::VideoCaptureFormat(
586 capture_resolution, 30, media::PIXEL_FORMAT_I420),
587 WrapI420Buffer(buffer, capture_resolution),
588 base::TimeTicks());
589 buffer = NULL;
591 base::RunLoop().RunUntilIdle();
594 // Exercises the OnError() codepath of VideoCaptureController, and tests the
595 // behavior of various operations after the error state has been signalled.
596 TEST_F(VideoCaptureControllerTest, ErrorAfterDeviceCreation) {
597 media::VideoCaptureParams session_100;
598 session_100.requested_format = media::VideoCaptureFormat(
599 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
601 media::VideoCaptureParams session_200 = session_100;
603 const VideoCaptureControllerID route_id(0x99);
605 // Start with one client.
606 controller_->AddClient(
607 route_id, client_a_.get(), base::kNullProcessHandle, 100, session_100);
608 media::VideoCaptureFormat device_format(
609 gfx::Size(10, 10), 25, media::PIXEL_FORMAT_ARGB);
611 // Start the device. Then, before the first buffer, signal an error and
612 // deliver the buffer. The error should be propagated to clients; the buffer
613 // should not be.
614 base::RunLoop().RunUntilIdle();
615 Mock::VerifyAndClearExpectations(client_a_.get());
617 const gfx::Size dims(320, 240);
618 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer =
619 device_->ReserveOutputBuffer(media::VideoFrame::I420, dims);
620 ASSERT_TRUE(buffer.get());
622 device_->OnError("Test error");
623 device_->OnIncomingCapturedVideoFrame(
624 buffer,
625 media::VideoCaptureFormat(
626 dims, device_format.frame_rate, media::PIXEL_FORMAT_I420),
627 WrapI420Buffer(buffer, dims),
628 base::TimeTicks());
629 buffer = NULL;
631 EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
632 base::RunLoop().RunUntilIdle();
633 Mock::VerifyAndClearExpectations(client_a_.get());
635 // Second client connects after the error state. It also should get told of
636 // the error.
637 EXPECT_CALL(*client_b_, DoError(route_id)).Times(1);
638 controller_->AddClient(
639 route_id, client_b_.get(), base::kNullProcessHandle, 200, session_200);
640 Mock::VerifyAndClearExpectations(client_b_.get());
643 } // namespace content