Add ICU message format support
[chromium-blink-merge.git] / content / browser / renderer_host / media / video_capture_controller_unittest.cc
blob97065a108c0ed4a080a90194da97f161af7e23d4
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(DoBufferDestroyed, void(VideoCaptureControllerID));
55 MOCK_METHOD2(DoI420BufferReady,
56 void(VideoCaptureControllerID, const gfx::Size&));
57 MOCK_METHOD2(DoTextureBufferReady,
58 void(VideoCaptureControllerID, const gfx::Size&));
59 MOCK_METHOD1(DoEnded, void(VideoCaptureControllerID));
60 MOCK_METHOD1(DoError, void(VideoCaptureControllerID));
62 void OnError(VideoCaptureControllerID id) override {
63 DoError(id);
65 void OnBufferCreated(VideoCaptureControllerID id,
66 base::SharedMemoryHandle handle,
67 int length, int buffer_id) override {
68 DoBufferCreated(id);
70 void OnBufferDestroyed(VideoCaptureControllerID id, int buffer_id) override {
71 DoBufferDestroyed(id);
73 void OnBufferReady(VideoCaptureControllerID id,
74 int buffer_id,
75 const scoped_refptr<media::VideoFrame>& frame,
76 const base::TimeTicks& timestamp) override {
77 if (!frame->HasTextures()) {
78 EXPECT_EQ(frame->format(), media::PIXEL_FORMAT_I420);
79 DoI420BufferReady(id, frame->coded_size());
80 base::ThreadTaskRunnerHandle::Get()->PostTask(
81 FROM_HERE, base::Bind(&VideoCaptureController::ReturnBuffer,
82 base::Unretained(controller_), id, this,
83 buffer_id, 0, resource_utilization_));
84 } else {
85 EXPECT_EQ(frame->format(), media::PIXEL_FORMAT_ARGB);
86 DoTextureBufferReady(id, frame->coded_size());
87 base::ThreadTaskRunnerHandle::Get()->PostTask(
88 FROM_HERE, base::Bind(&VideoCaptureController::ReturnBuffer,
89 base::Unretained(controller_), id, this,
90 buffer_id, frame->mailbox_holder(0).sync_point,
91 resource_utilization_));
94 void OnEnded(VideoCaptureControllerID id) override {
95 DoEnded(id);
96 // OnEnded() must respond by (eventually) unregistering the client.
97 base::ThreadTaskRunnerHandle::Get()->PostTask(
98 FROM_HERE,
99 base::Bind(base::IgnoreResult(&VideoCaptureController::RemoveClient),
100 base::Unretained(controller_), id, this));
103 VideoCaptureController* controller_;
104 double resource_utilization_;
107 // Test class.
108 class VideoCaptureControllerTest : public testing::Test {
109 public:
110 VideoCaptureControllerTest() {}
111 ~VideoCaptureControllerTest() override {}
113 protected:
114 static const int kPoolSize = 3;
116 void SetUp() override {
117 controller_.reset(new VideoCaptureController(kPoolSize));
118 device_ = controller_->NewDeviceClient(
119 base::ThreadTaskRunnerHandle::Get());
120 client_a_.reset(new MockVideoCaptureControllerEventHandler(
121 controller_.get()));
122 client_b_.reset(new MockVideoCaptureControllerEventHandler(
123 controller_.get()));
126 void TearDown() override { base::RunLoop().RunUntilIdle(); }
128 scoped_refptr<media::VideoFrame> WrapI420Buffer(gfx::Size dimensions,
129 uint8* data) {
130 return media::VideoFrame::WrapExternalData(
131 media::PIXEL_FORMAT_I420, dimensions, gfx::Rect(dimensions), dimensions,
132 data,
133 media::VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420, dimensions),
134 base::TimeDelta());
137 scoped_refptr<media::VideoFrame> WrapMailboxBuffer(
138 const gpu::MailboxHolder& holder,
139 const media::VideoFrame::ReleaseMailboxCB& release_cb,
140 gfx::Size dimensions) {
141 return media::VideoFrame::WrapNativeTexture(
142 media::PIXEL_FORMAT_ARGB, holder, release_cb, dimensions,
143 gfx::Rect(dimensions), dimensions, base::TimeDelta());
146 TestBrowserThreadBundle bundle_;
147 scoped_ptr<MockVideoCaptureControllerEventHandler> client_a_;
148 scoped_ptr<MockVideoCaptureControllerEventHandler> client_b_;
149 scoped_ptr<VideoCaptureController> controller_;
150 scoped_ptr<media::VideoCaptureDevice::Client> device_;
152 private:
153 DISALLOW_COPY_AND_ASSIGN(VideoCaptureControllerTest);
156 // A simple test of VideoCaptureController's ability to add, remove, and keep
157 // track of clients.
158 TEST_F(VideoCaptureControllerTest, AddAndRemoveClients) {
159 media::VideoCaptureParams session_100;
160 session_100.requested_format = media::VideoCaptureFormat(
161 gfx::Size(320, 240), 30, media::VIDEO_CAPTURE_PIXEL_FORMAT_I420);
162 media::VideoCaptureParams session_200 = session_100;
164 media::VideoCaptureParams session_300 = session_100;
166 media::VideoCaptureParams session_400 = session_100;
168 // Intentionally use the same route ID for two of the clients: the device_ids
169 // are a per-VideoCaptureHost namespace, and can overlap across hosts.
170 const VideoCaptureControllerID client_a_route_1(44);
171 const VideoCaptureControllerID client_a_route_2(30);
172 const VideoCaptureControllerID client_b_route_1(30);
173 const VideoCaptureControllerID client_b_route_2(1);
175 // Clients in controller: []
176 ASSERT_EQ(0, controller_->GetClientCount())
177 << "Client count should initially be zero.";
178 controller_->AddClient(client_a_route_1,
179 client_a_.get(),
180 base::kNullProcessHandle,
181 100,
182 session_100);
183 // Clients in controller: [A/1]
184 ASSERT_EQ(1, controller_->GetClientCount())
185 << "Adding client A/1 should bump client count.";
186 controller_->AddClient(client_a_route_2,
187 client_a_.get(),
188 base::kNullProcessHandle,
189 200,
190 session_200);
191 // Clients in controller: [A/1, A/2]
192 ASSERT_EQ(2, controller_->GetClientCount())
193 << "Adding client A/2 should bump client count.";
194 controller_->AddClient(client_b_route_1,
195 client_b_.get(),
196 base::kNullProcessHandle,
197 300,
198 session_300);
199 // Clients in controller: [A/1, A/2, B/1]
200 ASSERT_EQ(3, controller_->GetClientCount())
201 << "Adding client B/1 should bump client count.";
202 ASSERT_EQ(200,
203 controller_->RemoveClient(client_a_route_2, client_a_.get()))
204 << "Removing client A/1 should return its session_id.";
205 // Clients in controller: [A/1, B/1]
206 ASSERT_EQ(2, controller_->GetClientCount());
207 ASSERT_EQ(static_cast<int>(kInvalidMediaCaptureSessionId),
208 controller_->RemoveClient(client_a_route_2, client_a_.get()))
209 << "Removing a nonexistant client should fail.";
210 // Clients in controller: [A/1, B/1]
211 ASSERT_EQ(2, controller_->GetClientCount());
212 ASSERT_EQ(300,
213 controller_->RemoveClient(client_b_route_1, client_b_.get()))
214 << "Removing client B/1 should return its session_id.";
215 // Clients in controller: [A/1]
216 ASSERT_EQ(1, controller_->GetClientCount());
217 controller_->AddClient(client_b_route_2,
218 client_b_.get(),
219 base::kNullProcessHandle,
220 400,
221 session_400);
222 // Clients in controller: [A/1, B/2]
224 EXPECT_CALL(*client_a_, DoEnded(client_a_route_1)).Times(1);
225 controller_->StopSession(100); // Session 100 == client A/1
226 Mock::VerifyAndClearExpectations(client_a_.get());
227 ASSERT_EQ(2, controller_->GetClientCount())
228 << "Client should be closed but still exist after StopSession.";
229 // Clients in controller: [A/1 (closed, removal pending), B/2]
230 base::RunLoop().RunUntilIdle();
231 // Clients in controller: [B/2]
232 ASSERT_EQ(1, controller_->GetClientCount())
233 << "Client A/1 should be deleted by now.";
234 controller_->StopSession(200); // Session 200 does not exist anymore
235 // Clients in controller: [B/2]
236 ASSERT_EQ(1, controller_->GetClientCount())
237 << "Stopping non-existant session 200 should be a no-op.";
238 controller_->StopSession(256); // Session 256 never existed.
239 // Clients in controller: [B/2]
240 ASSERT_EQ(1, controller_->GetClientCount())
241 << "Stopping non-existant session 256 should be a no-op.";
242 ASSERT_EQ(static_cast<int>(kInvalidMediaCaptureSessionId),
243 controller_->RemoveClient(client_a_route_1, client_a_.get()))
244 << "Removing already-removed client A/1 should fail.";
245 // Clients in controller: [B/2]
246 ASSERT_EQ(1, controller_->GetClientCount())
247 << "Removing non-existant session 200 should be a no-op.";
248 ASSERT_EQ(400,
249 controller_->RemoveClient(client_b_route_2, client_b_.get()))
250 << "Removing client B/2 should return its session_id.";
251 // Clients in controller: []
252 ASSERT_EQ(0, controller_->GetClientCount())
253 << "Client count should return to zero after all clients are gone.";
256 static void CacheSyncPoint(uint32* called_release_sync_point,
257 uint32 release_sync_point) {
258 *called_release_sync_point = release_sync_point;
261 // This test will connect and disconnect several clients while simulating an
262 // active capture device being started and generating frames. It runs on one
263 // thread and is intended to behave deterministically.
264 TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
265 // VideoCaptureController::ReturnBuffer() uses ImageTransportFactory.
266 #if !defined(OS_ANDROID)
267 ImageTransportFactory::InitializeForUnitTests(
268 scoped_ptr<ImageTransportFactory>(new NoTransportImageTransportFactory));
269 #endif
271 media::VideoCaptureParams session_100;
272 session_100.requested_format = media::VideoCaptureFormat(
273 gfx::Size(320, 240), 30, media::VIDEO_CAPTURE_PIXEL_FORMAT_I420);
275 media::VideoCaptureParams session_200 = session_100;
277 media::VideoCaptureParams session_300 = session_100;
279 media::VideoCaptureParams session_1 = session_100;
281 const gfx::Size capture_resolution(444, 200);
283 // The device format needn't match the VideoCaptureParams (the camera can do
284 // what it wants). Pick something random.
285 media::VideoCaptureFormat device_format(
286 gfx::Size(10, 10), 25, media::VIDEO_CAPTURE_PIXEL_FORMAT_RGB24);
288 const VideoCaptureControllerID client_a_route_1(0xa1a1a1a1);
289 const VideoCaptureControllerID client_a_route_2(0xa2a2a2a2);
290 const VideoCaptureControllerID client_b_route_1(0xb1b1b1b1);
291 const VideoCaptureControllerID client_b_route_2(0xb2b2b2b2);
293 // Start with two clients.
294 controller_->AddClient(client_a_route_1,
295 client_a_.get(),
296 base::kNullProcessHandle,
297 100,
298 session_100);
299 controller_->AddClient(client_b_route_1,
300 client_b_.get(),
301 base::kNullProcessHandle,
302 300,
303 session_300);
304 controller_->AddClient(client_a_route_2,
305 client_a_.get(),
306 base::kNullProcessHandle,
307 200,
308 session_200);
309 ASSERT_EQ(3, controller_->GetClientCount());
311 // Now, simulate an incoming captured buffer from the capture device. As a
312 // side effect this will cause the first buffer to be shared with clients.
313 uint8 buffer_no = 1;
314 ASSERT_EQ(0.0, device_->GetBufferPoolUtilization());
315 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer(
316 device_->ReserveOutputBuffer(capture_resolution,
317 media::VIDEO_CAPTURE_PIXEL_FORMAT_I420,
318 media::PIXEL_STORAGE_CPU));
319 ASSERT_TRUE(buffer.get());
320 ASSERT_EQ(1.0 / kPoolSize, device_->GetBufferPoolUtilization());
321 memset(buffer->data(), buffer_no++, buffer->size());
323 InSequence s;
324 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1)).Times(1);
325 EXPECT_CALL(*client_a_,
326 DoI420BufferReady(client_a_route_1, capture_resolution))
327 .Times(1);
330 InSequence s;
331 EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1)).Times(1);
332 EXPECT_CALL(*client_b_,
333 DoI420BufferReady(client_b_route_1, capture_resolution))
334 .Times(1);
337 InSequence s;
338 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2)).Times(1);
339 EXPECT_CALL(*client_a_,
340 DoI420BufferReady(client_a_route_2, capture_resolution))
341 .Times(1);
343 scoped_refptr<media::VideoFrame> video_frame =
344 WrapI420Buffer(capture_resolution, static_cast<uint8*>(buffer->data()));
345 ASSERT_FALSE(video_frame->metadata()->HasKey(
346 media::VideoFrameMetadata::RESOURCE_UTILIZATION));
347 client_a_->resource_utilization_ = 0.5;
348 client_b_->resource_utilization_ = -1.0;
349 device_->OnIncomingCapturedVideoFrame(buffer.Pass(), video_frame,
350 base::TimeTicks());
352 base::RunLoop().RunUntilIdle();
353 Mock::VerifyAndClearExpectations(client_a_.get());
354 Mock::VerifyAndClearExpectations(client_b_.get());
355 // Expect VideoCaptureController set the metadata in |video_frame| to hold a
356 // resource utilization of 0.5 (the largest of all reported values).
357 double resource_utilization_in_metadata = -1.0;
358 ASSERT_TRUE(video_frame->metadata()->GetDouble(
359 media::VideoFrameMetadata::RESOURCE_UTILIZATION,
360 &resource_utilization_in_metadata));
361 ASSERT_EQ(0.5, resource_utilization_in_metadata);
363 // Second buffer which ought to use the same shared memory buffer. In this
364 // case pretend that the Buffer pointer is held by the device for a long
365 // delay. This shouldn't affect anything.
366 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer2 =
367 device_->ReserveOutputBuffer(capture_resolution,
368 media::VIDEO_CAPTURE_PIXEL_FORMAT_I420,
369 media::PIXEL_STORAGE_CPU);
370 ASSERT_TRUE(buffer2.get());
371 memset(buffer2->data(), buffer_no++, buffer2->size());
372 video_frame =
373 WrapI420Buffer(capture_resolution, static_cast<uint8*>(buffer2->data()));
374 ASSERT_FALSE(video_frame->metadata()->HasKey(
375 media::VideoFrameMetadata::RESOURCE_UTILIZATION));
376 client_a_->resource_utilization_ = 0.5;
377 client_b_->resource_utilization_ = 3.14;
378 device_->OnIncomingCapturedVideoFrame(buffer2.Pass(), video_frame,
379 base::TimeTicks());
381 // The buffer should be delivered to the clients in any order.
382 EXPECT_CALL(*client_a_,
383 DoI420BufferReady(client_a_route_1, capture_resolution))
384 .Times(1);
385 EXPECT_CALL(*client_b_,
386 DoI420BufferReady(client_b_route_1, capture_resolution))
387 .Times(1);
388 EXPECT_CALL(*client_a_,
389 DoI420BufferReady(client_a_route_2, capture_resolution))
390 .Times(1);
391 base::RunLoop().RunUntilIdle();
392 Mock::VerifyAndClearExpectations(client_a_.get());
393 Mock::VerifyAndClearExpectations(client_b_.get());
394 // Expect VideoCaptureController set the metadata in |video_frame| to hold a
395 // resource utilization of 3.14 (the largest of all reported values).
396 resource_utilization_in_metadata = -1.0;
397 ASSERT_TRUE(video_frame->metadata()->GetDouble(
398 media::VideoFrameMetadata::RESOURCE_UTILIZATION,
399 &resource_utilization_in_metadata));
400 ASSERT_EQ(3.14, resource_utilization_in_metadata);
402 // Add a fourth client now that some buffers have come through.
403 controller_->AddClient(client_b_route_2,
404 client_b_.get(),
405 base::kNullProcessHandle,
407 session_1);
408 Mock::VerifyAndClearExpectations(client_b_.get());
410 // Third, fourth, and fifth buffers. Pretend they all arrive at the same time.
411 for (int i = 0; i < kPoolSize; i++) {
412 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer =
413 device_->ReserveOutputBuffer(capture_resolution,
414 media::VIDEO_CAPTURE_PIXEL_FORMAT_I420,
415 media::PIXEL_STORAGE_CPU);
416 ASSERT_TRUE(buffer.get());
417 memset(buffer->data(), buffer_no++, buffer->size());
418 video_frame =
419 WrapI420Buffer(capture_resolution, static_cast<uint8*>(buffer->data()));
420 device_->OnIncomingCapturedVideoFrame(buffer.Pass(), video_frame,
421 base::TimeTicks());
423 // ReserveOutputBuffer ought to fail now, because the pool is depleted.
424 ASSERT_FALSE(
425 device_->ReserveOutputBuffer(capture_resolution,
426 media::VIDEO_CAPTURE_PIXEL_FORMAT_I420,
427 media::PIXEL_STORAGE_CPU).get());
429 // The new client needs to be told of 3 buffers; the old clients only 2.
430 EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_2)).Times(kPoolSize);
431 EXPECT_CALL(*client_b_,
432 DoI420BufferReady(client_b_route_2, capture_resolution))
433 .Times(kPoolSize);
434 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1))
435 .Times(kPoolSize - 1);
436 EXPECT_CALL(*client_a_,
437 DoI420BufferReady(client_a_route_1, capture_resolution))
438 .Times(kPoolSize);
439 EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2))
440 .Times(kPoolSize - 1);
441 EXPECT_CALL(*client_a_,
442 DoI420BufferReady(client_a_route_2, capture_resolution))
443 .Times(kPoolSize);
444 EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1))
445 .Times(kPoolSize - 1);
446 EXPECT_CALL(*client_b_,
447 DoI420BufferReady(client_b_route_1, capture_resolution))
448 .Times(kPoolSize);
449 base::RunLoop().RunUntilIdle();
450 Mock::VerifyAndClearExpectations(client_a_.get());
451 Mock::VerifyAndClearExpectations(client_b_.get());
453 // Now test the interaction of client shutdown and buffer delivery.
454 // Kill A1 via renderer disconnect (synchronous).
455 controller_->RemoveClient(client_a_route_1, client_a_.get());
456 // Kill B1 via session close (posts a task to disconnect).
457 EXPECT_CALL(*client_b_, DoEnded(client_b_route_1)).Times(1);
458 controller_->StopSession(300);
459 // Queue up another buffer.
460 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer3 =
461 device_->ReserveOutputBuffer(capture_resolution,
462 media::VIDEO_CAPTURE_PIXEL_FORMAT_I420,
463 media::PIXEL_STORAGE_CPU);
464 ASSERT_TRUE(buffer3.get());
465 memset(buffer3->data(), buffer_no++, buffer3->size());
466 video_frame =
467 WrapI420Buffer(capture_resolution, static_cast<uint8*>(buffer3->data()));
468 device_->OnIncomingCapturedVideoFrame(buffer3.Pass(), video_frame,
469 base::TimeTicks());
471 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer4 =
472 device_->ReserveOutputBuffer(capture_resolution,
473 media::VIDEO_CAPTURE_PIXEL_FORMAT_I420,
474 media::PIXEL_STORAGE_CPU);
476 // Kill A2 via session close (posts a task to disconnect, but A2 must not
477 // be sent either of these two buffers).
478 EXPECT_CALL(*client_a_, DoEnded(client_a_route_2)).Times(1);
479 controller_->StopSession(200);
481 ASSERT_TRUE(buffer4.get());
482 memset(buffer4->data(), buffer_no++, buffer4->size());
483 video_frame =
484 WrapI420Buffer(capture_resolution, static_cast<uint8*>(buffer4->data()));
485 device_->OnIncomingCapturedVideoFrame(buffer4.Pass(), video_frame,
486 base::TimeTicks());
487 // B2 is the only client left, and is the only one that should
488 // get the buffer.
489 EXPECT_CALL(*client_b_,
490 DoI420BufferReady(client_b_route_2, capture_resolution))
491 .Times(2);
492 base::RunLoop().RunUntilIdle();
493 Mock::VerifyAndClearExpectations(client_a_.get());
494 Mock::VerifyAndClearExpectations(client_b_.get());
496 // Allocate all buffers from the buffer pool, half as SHM buffer and half as
497 // mailbox buffers. Make sure of different counts though.
498 #if defined(OS_ANDROID)
499 int mailbox_buffers = 0;
500 #else
501 int mailbox_buffers = kPoolSize / 2;
502 #endif
503 int shm_buffers = kPoolSize - mailbox_buffers;
504 if (shm_buffers == mailbox_buffers) {
505 shm_buffers--;
506 mailbox_buffers++;
509 for (int i = 0; i < shm_buffers; ++i) {
510 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer =
511 device_->ReserveOutputBuffer(capture_resolution,
512 media::VIDEO_CAPTURE_PIXEL_FORMAT_I420,
513 media::PIXEL_STORAGE_CPU);
514 ASSERT_TRUE(buffer.get());
515 video_frame =
516 WrapI420Buffer(capture_resolution, static_cast<uint8*>(buffer->data()));
517 device_->OnIncomingCapturedVideoFrame(buffer.Pass(), video_frame,
518 base::TimeTicks());
520 std::vector<uint32> mailbox_syncpoints(mailbox_buffers);
521 std::vector<uint32> release_syncpoints(mailbox_buffers);
522 for (int i = 0; i < mailbox_buffers; ++i) {
523 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer =
524 device_->ReserveOutputBuffer(capture_resolution,
525 media::VIDEO_CAPTURE_PIXEL_FORMAT_ARGB,
526 media::PIXEL_STORAGE_TEXTURE);
527 ASSERT_TRUE(buffer.get());
528 #if !defined(OS_ANDROID)
529 mailbox_syncpoints[i] =
530 ImageTransportFactory::GetInstance()->GetGLHelper()->InsertSyncPoint();
531 #endif
532 device_->OnIncomingCapturedVideoFrame(
533 buffer.Pass(),
534 WrapMailboxBuffer(gpu::MailboxHolder(gpu::Mailbox::Generate(), 0,
535 mailbox_syncpoints[i]),
536 base::Bind(&CacheSyncPoint, &release_syncpoints[i]),
537 capture_resolution),
538 base::TimeTicks());
540 // ReserveOutputBuffers ought to fail now regardless of buffer format, because
541 // the pool is depleted.
542 ASSERT_FALSE(
543 device_->ReserveOutputBuffer(capture_resolution,
544 media::VIDEO_CAPTURE_PIXEL_FORMAT_I420,
545 media::PIXEL_STORAGE_CPU).get());
546 ASSERT_FALSE(
547 device_->ReserveOutputBuffer(capture_resolution,
548 media::VIDEO_CAPTURE_PIXEL_FORMAT_ARGB,
549 media::PIXEL_STORAGE_TEXTURE).get());
550 EXPECT_CALL(*client_b_,
551 DoI420BufferReady(client_b_route_2, capture_resolution))
552 .Times(shm_buffers);
553 EXPECT_CALL(*client_b_,
554 DoTextureBufferReady(client_b_route_2, capture_resolution))
555 .Times(mailbox_buffers);
556 #if !defined(OS_ANDROID)
557 EXPECT_CALL(*client_b_, DoBufferDestroyed(client_b_route_2));
558 #endif
559 base::RunLoop().RunUntilIdle();
560 for (size_t i = 0; i < mailbox_syncpoints.size(); ++i) {
561 // A new release sync point must be inserted when the video frame is
562 // returned to the Browser process.
563 // See: MockVideoCaptureControllerEventHandler::OnMailboxBufferReady() and
564 // VideoCaptureController::ReturnBuffer()
565 ASSERT_NE(mailbox_syncpoints[i], release_syncpoints[i]);
567 Mock::VerifyAndClearExpectations(client_b_.get());
569 #if !defined(OS_ANDROID)
570 ImageTransportFactory::Terminate();
571 #endif
574 // Exercises the OnError() codepath of VideoCaptureController, and tests the
575 // behavior of various operations after the error state has been signalled.
576 TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) {
577 media::VideoCaptureParams session_100;
578 session_100.requested_format = media::VideoCaptureFormat(
579 gfx::Size(320, 240), 30, media::VIDEO_CAPTURE_PIXEL_FORMAT_I420);
581 media::VideoCaptureParams session_200 = session_100;
583 const gfx::Size capture_resolution(320, 240);
585 const VideoCaptureControllerID route_id(0x99);
587 // Start with one client.
588 controller_->AddClient(
589 route_id, client_a_.get(), base::kNullProcessHandle, 100, session_100);
590 device_->OnError("Test Error");
591 EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
592 base::RunLoop().RunUntilIdle();
593 Mock::VerifyAndClearExpectations(client_a_.get());
595 // Second client connects after the error state. It also should get told of
596 // the error.
597 EXPECT_CALL(*client_b_, DoError(route_id)).Times(1);
598 controller_->AddClient(
599 route_id, client_b_.get(), base::kNullProcessHandle, 200, session_200);
600 base::RunLoop().RunUntilIdle();
601 Mock::VerifyAndClearExpectations(client_b_.get());
603 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer(
604 device_->ReserveOutputBuffer(capture_resolution,
605 media::VIDEO_CAPTURE_PIXEL_FORMAT_I420,
606 media::PIXEL_STORAGE_CPU));
607 ASSERT_TRUE(buffer.get());
608 scoped_refptr<media::VideoFrame> video_frame =
609 WrapI420Buffer(capture_resolution, static_cast<uint8*>(buffer->data()));
610 device_->OnIncomingCapturedVideoFrame(buffer.Pass(), video_frame,
611 base::TimeTicks());
613 base::RunLoop().RunUntilIdle();
616 // Exercises the OnError() codepath of VideoCaptureController, and tests the
617 // behavior of various operations after the error state has been signalled.
618 TEST_F(VideoCaptureControllerTest, ErrorAfterDeviceCreation) {
619 media::VideoCaptureParams session_100;
620 session_100.requested_format = media::VideoCaptureFormat(
621 gfx::Size(320, 240), 30, media::VIDEO_CAPTURE_PIXEL_FORMAT_I420);
623 media::VideoCaptureParams session_200 = session_100;
625 const VideoCaptureControllerID route_id(0x99);
627 // Start with one client.
628 controller_->AddClient(
629 route_id, client_a_.get(), base::kNullProcessHandle, 100, session_100);
630 media::VideoCaptureFormat device_format(
631 gfx::Size(10, 10), 25, media::VIDEO_CAPTURE_PIXEL_FORMAT_ARGB);
633 // Start the device. Then, before the first buffer, signal an error and
634 // deliver the buffer. The error should be propagated to clients; the buffer
635 // should not be.
636 base::RunLoop().RunUntilIdle();
637 Mock::VerifyAndClearExpectations(client_a_.get());
639 const gfx::Size dims(320, 240);
640 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer(
641 device_->ReserveOutputBuffer(dims, media::VIDEO_CAPTURE_PIXEL_FORMAT_I420,
642 media::PIXEL_STORAGE_CPU));
643 ASSERT_TRUE(buffer.get());
645 scoped_refptr<media::VideoFrame> video_frame =
646 WrapI420Buffer(dims, static_cast<uint8*>(buffer->data()));
647 device_->OnError("Test Error");
648 device_->OnIncomingCapturedVideoFrame(buffer.Pass(), video_frame,
649 base::TimeTicks());
651 EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
652 base::RunLoop().RunUntilIdle();
653 Mock::VerifyAndClearExpectations(client_a_.get());
655 // Second client connects after the error state. It also should get told of
656 // the error.
657 EXPECT_CALL(*client_b_, DoError(route_id)).Times(1);
658 controller_->AddClient(
659 route_id, client_b_.get(), base::kNullProcessHandle, 200, session_200);
660 Mock::VerifyAndClearExpectations(client_b_.get());
663 } // namespace content