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