Clean up check for dependency_info.
[chromium-blink-merge.git] / content / browser / renderer_host / media / video_capture_controller_unittest.cc
blobe376b90ee3cfcd8dd5176a043652dc57d01d1c2a
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/location.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/run_loop.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/thread_task_runner_handle.h"
17 #include "content/browser/renderer_host/media/media_stream_provider.h"
18 #include "content/browser/renderer_host/media/video_capture_controller.h"
19 #include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
20 #include "content/browser/renderer_host/media/video_capture_manager.h"
21 #include "content/common/gpu/client/gl_helper.h"
22 #include "content/common/media/media_stream_options.h"
23 #include "content/public/test/test_browser_thread_bundle.h"
24 #include "gpu/command_buffer/common/mailbox_holder.h"
25 #include "media/base/video_capture_types.h"
26 #include "media/base/video_frame_metadata.h"
27 #include "media/base/video_util.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
31 #if !defined(OS_ANDROID)
32 #include "content/browser/compositor/test/no_transport_image_transport_factory.h"
33 #endif
35 using ::testing::_;
36 using ::testing::InSequence;
37 using ::testing::Mock;
38 using ::testing::SaveArg;
40 namespace content {
42 class MockVideoCaptureControllerEventHandler
43 : public VideoCaptureControllerEventHandler {
44 public:
45 explicit MockVideoCaptureControllerEventHandler(
46 VideoCaptureController* controller)
47 : controller_(controller),
48 resource_utilization_(-1.0) {}
49 ~MockVideoCaptureControllerEventHandler() override {}
51 // These mock methods are delegated to by our fake implementation of
52 // VideoCaptureControllerEventHandler, to be used in EXPECT_CALL().
53 MOCK_METHOD1(DoBufferCreated, void(VideoCaptureControllerID));
54 MOCK_METHOD1(DoBufferCreated2, void(VideoCaptureControllerID));
55 MOCK_METHOD1(DoBufferDestroyed, void(VideoCaptureControllerID));
56 MOCK_METHOD2(DoI420BufferReady,
57 void(VideoCaptureControllerID, const gfx::Size&));
58 MOCK_METHOD2(DoTextureBufferReady,
59 void(VideoCaptureControllerID, const gfx::Size&));
60 MOCK_METHOD1(DoEnded, void(VideoCaptureControllerID));
61 MOCK_METHOD1(DoError, void(VideoCaptureControllerID));
63 void OnError(VideoCaptureControllerID id) override {
64 DoError(id);
66 void OnBufferCreated(VideoCaptureControllerID id,
67 base::SharedMemoryHandle handle,
68 int length, int buffer_id) override {
69 DoBufferCreated(id);
71 void OnBufferCreated2(
72 VideoCaptureControllerID id,
73 const std::vector<gfx::GpuMemoryBufferHandle>& handles,
74 const gfx::Size& size,
75 int buffer_id) override {
76 DoBufferCreated2(id);
78 void OnBufferDestroyed(VideoCaptureControllerID id, int buffer_id) override {
79 DoBufferDestroyed(id);
81 void OnBufferReady(VideoCaptureControllerID id,
82 int buffer_id,
83 const scoped_refptr<media::VideoFrame>& frame,
84 const base::TimeTicks& timestamp) override {
85 if (!frame->HasTextures()) {
86 EXPECT_EQ(frame->format(), media::PIXEL_FORMAT_I420);
87 DoI420BufferReady(id, frame->coded_size());
88 base::ThreadTaskRunnerHandle::Get()->PostTask(
89 FROM_HERE, base::Bind(&VideoCaptureController::ReturnBuffer,
90 base::Unretained(controller_), id, this,
91 buffer_id, 0, resource_utilization_));
92 } else {
93 EXPECT_EQ(frame->format(), media::PIXEL_FORMAT_ARGB);
94 DoTextureBufferReady(id, frame->coded_size());
95 base::ThreadTaskRunnerHandle::Get()->PostTask(
96 FROM_HERE, base::Bind(&VideoCaptureController::ReturnBuffer,
97 base::Unretained(controller_), id, this,
98 buffer_id, frame->mailbox_holder(0).sync_point,
99 resource_utilization_));
102 void OnEnded(VideoCaptureControllerID id) override {
103 DoEnded(id);
104 // OnEnded() must respond by (eventually) unregistering the client.
105 base::ThreadTaskRunnerHandle::Get()->PostTask(
106 FROM_HERE,
107 base::Bind(base::IgnoreResult(&VideoCaptureController::RemoveClient),
108 base::Unretained(controller_), id, this));
111 VideoCaptureController* controller_;
112 double resource_utilization_;
115 // Test class.
116 class VideoCaptureControllerTest : public testing::Test {
117 public:
118 VideoCaptureControllerTest() {}
119 ~VideoCaptureControllerTest() override {}
121 protected:
122 static const int kPoolSize = 3;
124 void SetUp() override {
125 controller_.reset(new VideoCaptureController(kPoolSize));
126 device_ = controller_->NewDeviceClient(
127 base::ThreadTaskRunnerHandle::Get());
128 client_a_.reset(new MockVideoCaptureControllerEventHandler(
129 controller_.get()));
130 client_b_.reset(new MockVideoCaptureControllerEventHandler(
131 controller_.get()));
134 void TearDown() override { base::RunLoop().RunUntilIdle(); }
136 scoped_refptr<media::VideoFrame> WrapI420Buffer(gfx::Size dimensions,
137 uint8* data) {
138 return media::VideoFrame::WrapExternalData(
139 media::PIXEL_FORMAT_I420, dimensions, gfx::Rect(dimensions), dimensions,
140 data,
141 media::VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420, dimensions),
142 base::TimeDelta());
145 scoped_refptr<media::VideoFrame> WrapMailboxBuffer(
146 const gpu::MailboxHolder& holder,
147 const media::VideoFrame::ReleaseMailboxCB& release_cb,
148 gfx::Size dimensions) {
149 return media::VideoFrame::WrapNativeTexture(
150 media::PIXEL_FORMAT_ARGB, holder, release_cb, dimensions,
151 gfx::Rect(dimensions), dimensions, base::TimeDelta());
154 TestBrowserThreadBundle bundle_;
155 scoped_ptr<MockVideoCaptureControllerEventHandler> client_a_;
156 scoped_ptr<MockVideoCaptureControllerEventHandler> client_b_;
157 scoped_ptr<VideoCaptureController> controller_;
158 scoped_ptr<media::VideoCaptureDevice::Client> device_;
160 private:
161 DISALLOW_COPY_AND_ASSIGN(VideoCaptureControllerTest);
164 // A simple test of VideoCaptureController's ability to add, remove, and keep
165 // track of clients.
166 TEST_F(VideoCaptureControllerTest, AddAndRemoveClients) {
167 media::VideoCaptureParams session_100;
168 session_100.requested_format = media::VideoCaptureFormat(
169 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
170 media::VideoCaptureParams session_200 = session_100;
172 media::VideoCaptureParams session_300 = session_100;
174 media::VideoCaptureParams session_400 = session_100;
176 // Intentionally use the same route ID for two of the clients: the device_ids
177 // are a per-VideoCaptureHost namespace, and can overlap across hosts.
178 const VideoCaptureControllerID client_a_route_1(44);
179 const VideoCaptureControllerID client_a_route_2(30);
180 const VideoCaptureControllerID client_b_route_1(30);
181 const VideoCaptureControllerID client_b_route_2(1);
183 // Clients in controller: []
184 ASSERT_EQ(0, controller_->GetClientCount())
185 << "Client count should initially be zero.";
186 controller_->AddClient(client_a_route_1,
187 client_a_.get(),
188 base::kNullProcessHandle,
189 100,
190 session_100);
191 // Clients in controller: [A/1]
192 ASSERT_EQ(1, controller_->GetClientCount())
193 << "Adding client A/1 should bump client count.";
194 controller_->AddClient(client_a_route_2,
195 client_a_.get(),
196 base::kNullProcessHandle,
197 200,
198 session_200);
199 // Clients in controller: [A/1, A/2]
200 ASSERT_EQ(2, controller_->GetClientCount())
201 << "Adding client A/2 should bump client count.";
202 controller_->AddClient(client_b_route_1,
203 client_b_.get(),
204 base::kNullProcessHandle,
205 300,
206 session_300);
207 // Clients in controller: [A/1, A/2, B/1]
208 ASSERT_EQ(3, controller_->GetClientCount())
209 << "Adding client B/1 should bump client count.";
210 ASSERT_EQ(200,
211 controller_->RemoveClient(client_a_route_2, client_a_.get()))
212 << "Removing client A/1 should return its session_id.";
213 // Clients in controller: [A/1, B/1]
214 ASSERT_EQ(2, controller_->GetClientCount());
215 ASSERT_EQ(static_cast<int>(kInvalidMediaCaptureSessionId),
216 controller_->RemoveClient(client_a_route_2, client_a_.get()))
217 << "Removing a nonexistant client should fail.";
218 // Clients in controller: [A/1, B/1]
219 ASSERT_EQ(2, controller_->GetClientCount());
220 ASSERT_EQ(300,
221 controller_->RemoveClient(client_b_route_1, client_b_.get()))
222 << "Removing client B/1 should return its session_id.";
223 // Clients in controller: [A/1]
224 ASSERT_EQ(1, controller_->GetClientCount());
225 controller_->AddClient(client_b_route_2,
226 client_b_.get(),
227 base::kNullProcessHandle,
228 400,
229 session_400);
230 // Clients in controller: [A/1, B/2]
232 EXPECT_CALL(*client_a_, DoEnded(client_a_route_1)).Times(1);
233 controller_->StopSession(100); // Session 100 == client A/1
234 Mock::VerifyAndClearExpectations(client_a_.get());
235 ASSERT_EQ(2, controller_->GetClientCount())
236 << "Client should be closed but still exist after StopSession.";
237 // Clients in controller: [A/1 (closed, removal pending), B/2]
238 base::RunLoop().RunUntilIdle();
239 // Clients in controller: [B/2]
240 ASSERT_EQ(1, controller_->GetClientCount())
241 << "Client A/1 should be deleted by now.";
242 controller_->StopSession(200); // Session 200 does not exist anymore
243 // Clients in controller: [B/2]
244 ASSERT_EQ(1, controller_->GetClientCount())
245 << "Stopping non-existant session 200 should be a no-op.";
246 controller_->StopSession(256); // Session 256 never existed.
247 // Clients in controller: [B/2]
248 ASSERT_EQ(1, controller_->GetClientCount())
249 << "Stopping non-existant session 256 should be a no-op.";
250 ASSERT_EQ(static_cast<int>(kInvalidMediaCaptureSessionId),
251 controller_->RemoveClient(client_a_route_1, client_a_.get()))
252 << "Removing already-removed client A/1 should fail.";
253 // Clients in controller: [B/2]
254 ASSERT_EQ(1, controller_->GetClientCount())
255 << "Removing non-existant session 200 should be a no-op.";
256 ASSERT_EQ(400,
257 controller_->RemoveClient(client_b_route_2, client_b_.get()))
258 << "Removing client B/2 should return its session_id.";
259 // Clients in controller: []
260 ASSERT_EQ(0, controller_->GetClientCount())
261 << "Client count should return to zero after all clients are gone.";
264 static void CacheSyncPoint(uint32* called_release_sync_point,
265 uint32 release_sync_point) {
266 *called_release_sync_point = release_sync_point;
269 // This test will connect and disconnect several clients while simulating an
270 // active capture device being started and generating frames. It runs on one
271 // thread and is intended to behave deterministically.
272 TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
273 // VideoCaptureController::ReturnBuffer() uses ImageTransportFactory.
274 #if !defined(OS_ANDROID)
275 ImageTransportFactory::InitializeForUnitTests(
276 scoped_ptr<ImageTransportFactory>(new NoTransportImageTransportFactory));
277 #endif
279 media::VideoCaptureParams session_100;
280 session_100.requested_format = media::VideoCaptureFormat(
281 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
283 media::VideoCaptureParams session_200 = session_100;
285 media::VideoCaptureParams session_300 = session_100;
287 media::VideoCaptureParams session_1 = session_100;
289 const gfx::Size capture_resolution(444, 200);
291 // The device format needn't match the VideoCaptureParams (the camera can do
292 // what it wants). Pick something random.
293 media::VideoCaptureFormat device_format(
294 gfx::Size(10, 10), 25, media::PIXEL_FORMAT_RGB24);
296 const VideoCaptureControllerID client_a_route_1(0xa1a1a1a1);
297 const VideoCaptureControllerID client_a_route_2(0xa2a2a2a2);
298 const VideoCaptureControllerID client_b_route_1(0xb1b1b1b1);
299 const VideoCaptureControllerID client_b_route_2(0xb2b2b2b2);
301 // Start with two clients.
302 controller_->AddClient(client_a_route_1,
303 client_a_.get(),
304 base::kNullProcessHandle,
305 100,
306 session_100);
307 controller_->AddClient(client_b_route_1,
308 client_b_.get(),
309 base::kNullProcessHandle,
310 300,
311 session_300);
312 controller_->AddClient(client_a_route_2,
313 client_a_.get(),
314 base::kNullProcessHandle,
315 200,
316 session_200);
317 ASSERT_EQ(3, controller_->GetClientCount());
319 // Now, simulate an incoming captured buffer from the capture device. As a
320 // side effect this will cause the first buffer to be shared with clients.
321 uint8 buffer_no = 1;
322 ASSERT_EQ(0.0, device_->GetBufferPoolUtilization());
323 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer(
324 device_->ReserveOutputBuffer(capture_resolution,
325 media::PIXEL_FORMAT_I420,
326 media::PIXEL_STORAGE_CPU));
327 ASSERT_TRUE(buffer.get());
328 ASSERT_EQ(1.0 / kPoolSize, device_->GetBufferPoolUtilization());
329 memset(buffer->data(), buffer_no++, buffer->mapped_size());
331 InSequence s;
332 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1)).Times(1);
333 EXPECT_CALL(*client_a_,
334 DoI420BufferReady(client_a_route_1, capture_resolution))
335 .Times(1);
338 InSequence s;
339 EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1)).Times(1);
340 EXPECT_CALL(*client_b_,
341 DoI420BufferReady(client_b_route_1, capture_resolution))
342 .Times(1);
345 InSequence s;
346 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2)).Times(1);
347 EXPECT_CALL(*client_a_,
348 DoI420BufferReady(client_a_route_2, capture_resolution))
349 .Times(1);
351 scoped_refptr<media::VideoFrame> video_frame =
352 WrapI420Buffer(capture_resolution, static_cast<uint8*>(buffer->data()));
353 ASSERT_FALSE(video_frame->metadata()->HasKey(
354 media::VideoFrameMetadata::RESOURCE_UTILIZATION));
355 client_a_->resource_utilization_ = 0.5;
356 client_b_->resource_utilization_ = -1.0;
357 device_->OnIncomingCapturedVideoFrame(buffer.Pass(), video_frame,
358 base::TimeTicks());
360 base::RunLoop().RunUntilIdle();
361 Mock::VerifyAndClearExpectations(client_a_.get());
362 Mock::VerifyAndClearExpectations(client_b_.get());
363 // Expect VideoCaptureController set the metadata in |video_frame| to hold a
364 // resource utilization of 0.5 (the largest of all reported values).
365 double resource_utilization_in_metadata = -1.0;
366 ASSERT_TRUE(video_frame->metadata()->GetDouble(
367 media::VideoFrameMetadata::RESOURCE_UTILIZATION,
368 &resource_utilization_in_metadata));
369 ASSERT_EQ(0.5, resource_utilization_in_metadata);
371 // Second buffer which ought to use the same shared memory buffer. In this
372 // case pretend that the Buffer pointer is held by the device for a long
373 // delay. This shouldn't affect anything.
374 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer2 =
375 device_->ReserveOutputBuffer(capture_resolution,
376 media::PIXEL_FORMAT_I420,
377 media::PIXEL_STORAGE_CPU);
378 ASSERT_TRUE(buffer2.get());
379 memset(buffer2->data(), buffer_no++, buffer2->mapped_size());
380 video_frame =
381 WrapI420Buffer(capture_resolution, static_cast<uint8*>(buffer2->data()));
382 ASSERT_FALSE(video_frame->metadata()->HasKey(
383 media::VideoFrameMetadata::RESOURCE_UTILIZATION));
384 client_a_->resource_utilization_ = 0.5;
385 client_b_->resource_utilization_ = 3.14;
386 device_->OnIncomingCapturedVideoFrame(buffer2.Pass(), video_frame,
387 base::TimeTicks());
389 // The buffer should be delivered to the clients in any order.
390 EXPECT_CALL(*client_a_,
391 DoI420BufferReady(client_a_route_1, capture_resolution))
392 .Times(1);
393 EXPECT_CALL(*client_b_,
394 DoI420BufferReady(client_b_route_1, capture_resolution))
395 .Times(1);
396 EXPECT_CALL(*client_a_,
397 DoI420BufferReady(client_a_route_2, capture_resolution))
398 .Times(1);
399 base::RunLoop().RunUntilIdle();
400 Mock::VerifyAndClearExpectations(client_a_.get());
401 Mock::VerifyAndClearExpectations(client_b_.get());
402 // Expect VideoCaptureController set the metadata in |video_frame| to hold a
403 // resource utilization of 3.14 (the largest of all reported values).
404 resource_utilization_in_metadata = -1.0;
405 ASSERT_TRUE(video_frame->metadata()->GetDouble(
406 media::VideoFrameMetadata::RESOURCE_UTILIZATION,
407 &resource_utilization_in_metadata));
408 ASSERT_EQ(3.14, resource_utilization_in_metadata);
410 // Add a fourth client now that some buffers have come through.
411 controller_->AddClient(client_b_route_2,
412 client_b_.get(),
413 base::kNullProcessHandle,
415 session_1);
416 Mock::VerifyAndClearExpectations(client_b_.get());
418 // Third, fourth, and fifth buffers. Pretend they all arrive at the same time.
419 for (int i = 0; i < kPoolSize; i++) {
420 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer =
421 device_->ReserveOutputBuffer(capture_resolution,
422 media::PIXEL_FORMAT_I420,
423 media::PIXEL_STORAGE_CPU);
424 ASSERT_TRUE(buffer.get());
425 memset(buffer->data(), buffer_no++, buffer->mapped_size());
426 video_frame =
427 WrapI420Buffer(capture_resolution, static_cast<uint8*>(buffer->data()));
428 device_->OnIncomingCapturedVideoFrame(buffer.Pass(), video_frame,
429 base::TimeTicks());
431 // ReserveOutputBuffer ought to fail now, because the pool is depleted.
432 ASSERT_FALSE(
433 device_->ReserveOutputBuffer(capture_resolution,
434 media::PIXEL_FORMAT_I420,
435 media::PIXEL_STORAGE_CPU).get());
437 // The new client needs to be told of 3 buffers; the old clients only 2.
438 EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_2)).Times(kPoolSize);
439 EXPECT_CALL(*client_b_,
440 DoI420BufferReady(client_b_route_2, capture_resolution))
441 .Times(kPoolSize);
442 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1))
443 .Times(kPoolSize - 1);
444 EXPECT_CALL(*client_a_,
445 DoI420BufferReady(client_a_route_1, capture_resolution))
446 .Times(kPoolSize);
447 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2))
448 .Times(kPoolSize - 1);
449 EXPECT_CALL(*client_a_,
450 DoI420BufferReady(client_a_route_2, capture_resolution))
451 .Times(kPoolSize);
452 EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1))
453 .Times(kPoolSize - 1);
454 EXPECT_CALL(*client_b_,
455 DoI420BufferReady(client_b_route_1, capture_resolution))
456 .Times(kPoolSize);
457 base::RunLoop().RunUntilIdle();
458 Mock::VerifyAndClearExpectations(client_a_.get());
459 Mock::VerifyAndClearExpectations(client_b_.get());
461 // Now test the interaction of client shutdown and buffer delivery.
462 // Kill A1 via renderer disconnect (synchronous).
463 controller_->RemoveClient(client_a_route_1, client_a_.get());
464 // Kill B1 via session close (posts a task to disconnect).
465 EXPECT_CALL(*client_b_, DoEnded(client_b_route_1)).Times(1);
466 controller_->StopSession(300);
467 // Queue up another buffer.
468 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer3 =
469 device_->ReserveOutputBuffer(capture_resolution,
470 media::PIXEL_FORMAT_I420,
471 media::PIXEL_STORAGE_CPU);
472 ASSERT_TRUE(buffer3.get());
473 memset(buffer3->data(), buffer_no++, buffer3->mapped_size());
474 video_frame =
475 WrapI420Buffer(capture_resolution, static_cast<uint8*>(buffer3->data()));
476 device_->OnIncomingCapturedVideoFrame(buffer3.Pass(), video_frame,
477 base::TimeTicks());
479 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer4 =
480 device_->ReserveOutputBuffer(capture_resolution,
481 media::PIXEL_FORMAT_I420,
482 media::PIXEL_STORAGE_CPU);
484 // Kill A2 via session close (posts a task to disconnect, but A2 must not
485 // be sent either of these two buffers).
486 EXPECT_CALL(*client_a_, DoEnded(client_a_route_2)).Times(1);
487 controller_->StopSession(200);
489 ASSERT_TRUE(buffer4.get());
490 memset(buffer4->data(), buffer_no++, buffer4->mapped_size());
491 video_frame =
492 WrapI420Buffer(capture_resolution, static_cast<uint8*>(buffer4->data()));
493 device_->OnIncomingCapturedVideoFrame(buffer4.Pass(), video_frame,
494 base::TimeTicks());
495 // B2 is the only client left, and is the only one that should
496 // get the buffer.
497 EXPECT_CALL(*client_b_,
498 DoI420BufferReady(client_b_route_2, capture_resolution))
499 .Times(2);
500 base::RunLoop().RunUntilIdle();
501 Mock::VerifyAndClearExpectations(client_a_.get());
502 Mock::VerifyAndClearExpectations(client_b_.get());
504 // Allocate all buffers from the buffer pool, half as SHM buffer and half as
505 // mailbox buffers. Make sure of different counts though.
506 #if defined(OS_ANDROID)
507 int mailbox_buffers = 0;
508 #else
509 int mailbox_buffers = kPoolSize / 2;
510 #endif
511 int shm_buffers = kPoolSize - mailbox_buffers;
512 if (shm_buffers == mailbox_buffers) {
513 shm_buffers--;
514 mailbox_buffers++;
517 for (int i = 0; i < shm_buffers; ++i) {
518 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer =
519 device_->ReserveOutputBuffer(capture_resolution,
520 media::PIXEL_FORMAT_I420,
521 media::PIXEL_STORAGE_CPU);
522 ASSERT_TRUE(buffer.get());
523 video_frame =
524 WrapI420Buffer(capture_resolution, static_cast<uint8*>(buffer->data()));
525 device_->OnIncomingCapturedVideoFrame(buffer.Pass(), video_frame,
526 base::TimeTicks());
528 std::vector<uint32> mailbox_syncpoints(mailbox_buffers);
529 std::vector<uint32> release_syncpoints(mailbox_buffers);
530 for (int i = 0; i < mailbox_buffers; ++i) {
531 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer =
532 device_->ReserveOutputBuffer(capture_resolution,
533 media::PIXEL_FORMAT_ARGB,
534 media::PIXEL_STORAGE_TEXTURE);
535 ASSERT_TRUE(buffer.get());
536 #if !defined(OS_ANDROID)
537 mailbox_syncpoints[i] =
538 ImageTransportFactory::GetInstance()->GetGLHelper()->InsertSyncPoint();
539 #endif
540 device_->OnIncomingCapturedVideoFrame(
541 buffer.Pass(),
542 WrapMailboxBuffer(gpu::MailboxHolder(gpu::Mailbox::Generate(), 0,
543 mailbox_syncpoints[i]),
544 base::Bind(&CacheSyncPoint, &release_syncpoints[i]),
545 capture_resolution),
546 base::TimeTicks());
548 // ReserveOutputBuffers ought to fail now regardless of buffer format, because
549 // the pool is depleted.
550 ASSERT_FALSE(
551 device_->ReserveOutputBuffer(capture_resolution,
552 media::PIXEL_FORMAT_I420,
553 media::PIXEL_STORAGE_CPU).get());
554 ASSERT_FALSE(
555 device_->ReserveOutputBuffer(capture_resolution,
556 media::PIXEL_FORMAT_ARGB,
557 media::PIXEL_STORAGE_TEXTURE).get());
558 EXPECT_CALL(*client_b_,
559 DoI420BufferReady(client_b_route_2, capture_resolution))
560 .Times(shm_buffers);
561 EXPECT_CALL(*client_b_,
562 DoTextureBufferReady(client_b_route_2, capture_resolution))
563 .Times(mailbox_buffers);
564 #if !defined(OS_ANDROID)
565 EXPECT_CALL(*client_b_, DoBufferDestroyed(client_b_route_2));
566 #endif
567 base::RunLoop().RunUntilIdle();
568 for (size_t i = 0; i < mailbox_syncpoints.size(); ++i) {
569 // A new release sync point must be inserted when the video frame is
570 // returned to the Browser process.
571 // See: MockVideoCaptureControllerEventHandler::OnMailboxBufferReady() and
572 // VideoCaptureController::ReturnBuffer()
573 ASSERT_NE(mailbox_syncpoints[i], release_syncpoints[i]);
575 Mock::VerifyAndClearExpectations(client_b_.get());
577 #if !defined(OS_ANDROID)
578 ImageTransportFactory::Terminate();
579 #endif
582 // Exercises the OnError() codepath of VideoCaptureController, and tests the
583 // behavior of various operations after the error state has been signalled.
584 TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) {
585 media::VideoCaptureParams session_100;
586 session_100.requested_format = media::VideoCaptureFormat(
587 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
589 media::VideoCaptureParams session_200 = session_100;
591 const gfx::Size capture_resolution(320, 240);
593 const VideoCaptureControllerID route_id(0x99);
595 // Start with one client.
596 controller_->AddClient(
597 route_id, client_a_.get(), base::kNullProcessHandle, 100, session_100);
598 device_->OnError("Test Error");
599 EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
600 base::RunLoop().RunUntilIdle();
601 Mock::VerifyAndClearExpectations(client_a_.get());
603 // Second client connects after the error state. It also should get told of
604 // the error.
605 EXPECT_CALL(*client_b_, DoError(route_id)).Times(1);
606 controller_->AddClient(
607 route_id, client_b_.get(), base::kNullProcessHandle, 200, session_200);
608 base::RunLoop().RunUntilIdle();
609 Mock::VerifyAndClearExpectations(client_b_.get());
611 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer(
612 device_->ReserveOutputBuffer(capture_resolution,
613 media::PIXEL_FORMAT_I420,
614 media::PIXEL_STORAGE_CPU));
615 ASSERT_TRUE(buffer.get());
616 scoped_refptr<media::VideoFrame> video_frame =
617 WrapI420Buffer(capture_resolution, static_cast<uint8*>(buffer->data()));
618 device_->OnIncomingCapturedVideoFrame(buffer.Pass(), video_frame,
619 base::TimeTicks());
621 base::RunLoop().RunUntilIdle();
624 // Exercises the OnError() codepath of VideoCaptureController, and tests the
625 // behavior of various operations after the error state has been signalled.
626 TEST_F(VideoCaptureControllerTest, ErrorAfterDeviceCreation) {
627 media::VideoCaptureParams session_100;
628 session_100.requested_format = media::VideoCaptureFormat(
629 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
631 media::VideoCaptureParams session_200 = session_100;
633 const VideoCaptureControllerID route_id(0x99);
635 // Start with one client.
636 controller_->AddClient(
637 route_id, client_a_.get(), base::kNullProcessHandle, 100, session_100);
638 media::VideoCaptureFormat device_format(
639 gfx::Size(10, 10), 25, media::PIXEL_FORMAT_ARGB);
641 // Start the device. Then, before the first buffer, signal an error and
642 // deliver the buffer. The error should be propagated to clients; the buffer
643 // should not be.
644 base::RunLoop().RunUntilIdle();
645 Mock::VerifyAndClearExpectations(client_a_.get());
647 const gfx::Size dims(320, 240);
648 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer(
649 device_->ReserveOutputBuffer(dims, media::PIXEL_FORMAT_I420,
650 media::PIXEL_STORAGE_CPU));
651 ASSERT_TRUE(buffer.get());
653 scoped_refptr<media::VideoFrame> video_frame =
654 WrapI420Buffer(dims, static_cast<uint8*>(buffer->data()));
655 device_->OnError("Test Error");
656 device_->OnIncomingCapturedVideoFrame(buffer.Pass(), video_frame,
657 base::TimeTicks());
659 EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
660 base::RunLoop().RunUntilIdle();
661 Mock::VerifyAndClearExpectations(client_a_.get());
663 // Second client connects after the error state. It also should get told of
664 // the error.
665 EXPECT_CALL(*client_b_, DoError(route_id)).Times(1);
666 controller_->AddClient(
667 route_id, client_b_.get(), base::kNullProcessHandle, 200, session_200);
668 Mock::VerifyAndClearExpectations(client_b_.get());
671 } // namespace content