15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Unit test for VideoCaptureController. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 10d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/bind_helpers.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 139ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/run_loop.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/media_stream_provider.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/video_capture_controller.h" 17d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/video_capture_manager.h" 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/common/gpu/client/gl_helper.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/media/media_stream_options.h" 21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "content/public/test/test_browser_thread_bundle.h" 22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "gpu/command_buffer/common/mailbox_holder.h" 23d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "media/base/video_util.h" 24d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "media/video/capture/video_capture_types.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_ANDROID) 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/renderer_host/test/no_transport_image_transport_factory_android.h" 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/compositor/test/no_transport_image_transport_factory.h" 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::InSequence; 35d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using ::testing::Mock; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockVideoCaptureControllerEventHandler 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public VideoCaptureControllerEventHandler { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 42d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) explicit MockVideoCaptureControllerEventHandler( 43d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) VideoCaptureController* controller) 44d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) : controller_(controller) {} 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~MockVideoCaptureControllerEventHandler() {} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 47d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // These mock methods are delegated to by our fake implementation of 48d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // VideoCaptureControllerEventHandler, to be used in EXPECT_CALL(). 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MOCK_METHOD1(DoBufferCreated, void(const VideoCaptureControllerID&)); 501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) MOCK_METHOD1(DoBufferDestroyed, void(const VideoCaptureControllerID&)); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MOCK_METHOD1(DoBufferReady, void(const VideoCaptureControllerID&)); 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MOCK_METHOD1(DoMailboxBufferReady, void(const VideoCaptureControllerID&)); 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD1(DoEnded, void(const VideoCaptureControllerID&)); 54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) MOCK_METHOD1(DoError, void(const VideoCaptureControllerID&)); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 56d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void OnError(const VideoCaptureControllerID& id) OVERRIDE { 57d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DoError(id); 58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnBufferCreated(const VideoCaptureControllerID& id, 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SharedMemoryHandle handle, 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int length, int buffer_id) OVERRIDE { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoBufferCreated(id); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) virtual void OnBufferDestroyed(const VideoCaptureControllerID& id, 651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int buffer_id) OVERRIDE { 661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DoBufferDestroyed(id); 671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnBufferReady(const VideoCaptureControllerID& id, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int buffer_id, 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const media::VideoCaptureFormat& format, 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const gfx::Rect& visible_rect, 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks timestamp) OVERRIDE { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoBufferReady(id); 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::MessageLoop::current()->PostTask( 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&VideoCaptureController::ReturnBuffer, 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Unretained(controller_), 78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) id, 79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) this, 80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer_id, 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 0)); 82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual void OnMailboxBufferReady(const VideoCaptureControllerID& id, 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int buffer_id, 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const gpu::MailboxHolder& mailbox_holder, 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const media::VideoCaptureFormat& format, 87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks timestamp) OVERRIDE { 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DoMailboxBufferReady(id); 89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::MessageLoop::current()->PostTask( 90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&VideoCaptureController::ReturnBuffer, 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Unretained(controller_), 93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) id, 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) this, 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer_id, 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mailbox_holder.sync_point)); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE { 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DoEnded(id); 100d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // OnEnded() must respond by (eventually) unregistering the client. 101d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::MessageLoop::current()->PostTask(FROM_HERE, 102d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Bind(base::IgnoreResult(&VideoCaptureController::RemoveClient), 103d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Unretained(controller_), id, this)); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 106d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) VideoCaptureController* controller_; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test class. 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VideoCaptureControllerTest : public testing::Test { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoCaptureControllerTest() {} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~VideoCaptureControllerTest() {} 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 116d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) static const int kPoolSize = 3; 117d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetUp() OVERRIDE { 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) controller_.reset(new VideoCaptureController(kPoolSize)); 120d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) device_ = controller_->NewDeviceClient().Pass(); 121d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) client_a_.reset(new MockVideoCaptureControllerEventHandler( 122d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) controller_.get())); 123d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) client_b_.reset(new MockVideoCaptureControllerEventHandler( 124d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) controller_.get())); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 127d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void TearDown() OVERRIDE { 128d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::RunLoop().RunUntilIdle(); 129d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<media::VideoFrame> WrapI420Buffer( 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const scoped_refptr<media::VideoCaptureDevice::Client::Buffer>& buffer, 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gfx::Size dimensions) { 134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return media::VideoFrame::WrapExternalPackedMemory( 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::VideoFrame::I420, 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dimensions, 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gfx::Rect(dimensions), 138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dimensions, 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) reinterpret_cast<uint8*>(buffer->data()), 140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::VideoFrame::AllocationSize(media::VideoFrame::I420, dimensions), 141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::SharedMemory::NULLHandle(), 142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeDelta(), 143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Closure()); 144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<media::VideoFrame> WrapMailboxBuffer( 147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const scoped_refptr<media::VideoCaptureDevice::Client::Buffer>& buffer, 148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<gpu::MailboxHolder> holder, 149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const media::VideoFrame::ReleaseMailboxCB& release_cb, 150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gfx::Size dimensions) { 151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return media::VideoFrame::WrapNativeTexture( 152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) holder.Pass(), 153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) release_cb, 154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dimensions, 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gfx::Rect(dimensions), 156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dimensions, 157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeDelta(), 158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::VideoFrame::ReadPixelsCB()); 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) TestBrowserThreadBundle bundle_; 162d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) scoped_ptr<MockVideoCaptureControllerEventHandler> client_a_; 163d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) scoped_ptr<MockVideoCaptureControllerEventHandler> client_b_; 164d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) scoped_ptr<VideoCaptureController> controller_; 16568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) scoped_ptr<media::VideoCaptureDevice::Client> device_; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(VideoCaptureControllerTest); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 171d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// A simple test of VideoCaptureController's ability to add, remove, and keep 172d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// track of clients. 173d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TEST_F(VideoCaptureControllerTest, AddAndRemoveClients) { 174d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) media::VideoCaptureParams session_100; 1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) session_100.requested_format = media::VideoCaptureFormat( 176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420); 177d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) media::VideoCaptureParams session_200 = session_100; 178d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 179d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) media::VideoCaptureParams session_300 = session_100; 180d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 181d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) media::VideoCaptureParams session_400 = session_100; 182d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 183d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Intentionally use the same route ID for two of the clients: the device_ids 184d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // are a per-VideoCaptureHost namespace, and can overlap across hosts. 185d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const VideoCaptureControllerID client_a_route_1(44); 186d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const VideoCaptureControllerID client_a_route_2(30); 187d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const VideoCaptureControllerID client_b_route_1(30); 188d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const VideoCaptureControllerID client_b_route_2(1); 189d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 190d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Clients in controller: [] 191d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ASSERT_EQ(0, controller_->GetClientCount()) 192d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "Client count should initially be zero."; 193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller_->AddClient(client_a_route_1, 194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) client_a_.get(), 195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::kNullProcessHandle, 196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 100, 197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) session_100); 198d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Clients in controller: [A/1] 199d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ASSERT_EQ(1, controller_->GetClientCount()) 200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << "Adding client A/1 should bump client count."; 201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller_->AddClient(client_a_route_2, 202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) client_a_.get(), 203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::kNullProcessHandle, 204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 200, 205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) session_200); 206d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Clients in controller: [A/1, A/2] 207d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ASSERT_EQ(2, controller_->GetClientCount()) 208d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "Adding client A/2 should bump client count."; 209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller_->AddClient(client_b_route_1, 210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) client_b_.get(), 211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::kNullProcessHandle, 212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 300, 213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) session_300); 214d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Clients in controller: [A/1, A/2, B/1] 215d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ASSERT_EQ(3, controller_->GetClientCount()) 216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "Adding client B/1 should bump client count."; 217d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ASSERT_EQ(200, 218d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) controller_->RemoveClient(client_a_route_2, client_a_.get())) 219d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "Removing client A/1 should return its session_id."; 220d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Clients in controller: [A/1, B/1] 221d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ASSERT_EQ(2, controller_->GetClientCount()); 222d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ASSERT_EQ(static_cast<int>(kInvalidMediaCaptureSessionId), 223d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) controller_->RemoveClient(client_a_route_2, client_a_.get())) 224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "Removing a nonexistant client should fail."; 225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Clients in controller: [A/1, B/1] 226d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ASSERT_EQ(2, controller_->GetClientCount()); 227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ASSERT_EQ(300, 228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) controller_->RemoveClient(client_b_route_1, client_b_.get())) 229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "Removing client B/1 should return its session_id."; 230d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Clients in controller: [A/1] 231d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ASSERT_EQ(1, controller_->GetClientCount()); 232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller_->AddClient(client_b_route_2, 233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) client_b_.get(), 234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::kNullProcessHandle, 235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 400, 236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) session_400); 237d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Clients in controller: [A/1, B/2] 238d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 239d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_CALL(*client_a_, DoEnded(client_a_route_1)).Times(1); 240d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) controller_->StopSession(100); // Session 100 == client A/1 241d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Mock::VerifyAndClearExpectations(client_a_.get()); 242d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ASSERT_EQ(2, controller_->GetClientCount()) 243d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "Client should be closed but still exist after StopSession."; 244d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Clients in controller: [A/1 (closed, removal pending), B/2] 245d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::RunLoop().RunUntilIdle(); 246d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Clients in controller: [B/2] 247d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ASSERT_EQ(1, controller_->GetClientCount()) 248d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "Client A/1 should be deleted by now."; 249d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) controller_->StopSession(200); // Session 200 does not exist anymore 250d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Clients in controller: [B/2] 251d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ASSERT_EQ(1, controller_->GetClientCount()) 252d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "Stopping non-existant session 200 should be a no-op."; 253d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) controller_->StopSession(256); // Session 256 never existed. 254d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Clients in controller: [B/2] 255d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ASSERT_EQ(1, controller_->GetClientCount()) 256d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "Stopping non-existant session 256 should be a no-op."; 257d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ASSERT_EQ(static_cast<int>(kInvalidMediaCaptureSessionId), 258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) controller_->RemoveClient(client_a_route_1, client_a_.get())) 259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "Removing already-removed client A/1 should fail."; 260d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Clients in controller: [B/2] 261d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ASSERT_EQ(1, controller_->GetClientCount()) 262d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "Removing non-existant session 200 should be a no-op."; 263d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ASSERT_EQ(400, 264d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) controller_->RemoveClient(client_b_route_2, client_b_.get())) 265d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "Removing client B/2 should return its session_id."; 266d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Clients in controller: [] 267d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ASSERT_EQ(0, controller_->GetClientCount()) 268d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "Client count should return to zero after all clients are gone."; 269d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 270d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void CacheSyncPoint(uint32* called_release_sync_point, 2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint32 release_sync_point) { 2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *called_release_sync_point = release_sync_point; 274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 276d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// This test will connect and disconnect several clients while simulating an 277d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// active capture device being started and generating frames. It runs on one 278d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// thread and is intended to behave deterministically. 279d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) { 2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// VideoCaptureController::ReturnBuffer() uses ImageTransportFactory. 2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_ANDROID) 2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ImageTransportFactoryAndroid::InitializeForUnitTests( 2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<ImageTransportFactoryAndroid>( 2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new NoTransportImageTransportFactoryAndroid)); 2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else 2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ImageTransportFactory::InitializeForUnitTests( 2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<ImageTransportFactory>(new NoTransportImageTransportFactory)); 2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 290d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) media::VideoCaptureParams session_100; 2911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) session_100.requested_format = media::VideoCaptureFormat( 292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420); 293d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 294d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) media::VideoCaptureParams session_200 = session_100; 295d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 296d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) media::VideoCaptureParams session_300 = session_100; 297d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 298d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) media::VideoCaptureParams session_1 = session_100; 299d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 3001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) gfx::Size capture_resolution(444, 200); 3011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 302d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // The device format needn't match the VideoCaptureParams (the camera can do 303f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // what it wants). Pick something random. 304f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) media::VideoCaptureFormat device_format( 305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gfx::Size(10, 10), 25, media::PIXEL_FORMAT_RGB24); 306d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 307d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const VideoCaptureControllerID client_a_route_1(0xa1a1a1a1); 308d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const VideoCaptureControllerID client_a_route_2(0xa2a2a2a2); 309d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const VideoCaptureControllerID client_b_route_1(0xb1b1b1b1); 310d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const VideoCaptureControllerID client_b_route_2(0xb2b2b2b2); 311d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 312d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Start with two clients. 313f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller_->AddClient(client_a_route_1, 314f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) client_a_.get(), 315f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::kNullProcessHandle, 316f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 100, 317f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) session_100); 318f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller_->AddClient(client_b_route_1, 319f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) client_b_.get(), 320f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::kNullProcessHandle, 321f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 300, 322f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) session_300); 323f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller_->AddClient(client_a_route_2, 324f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) client_a_.get(), 325f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::kNullProcessHandle, 326f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 200, 327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) session_200); 3281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ASSERT_EQ(3, controller_->GetClientCount()); 329d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Now, simulate an incoming captured buffer from the capture device. As a 331f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // side effect this will cause the first buffer to be shared with clients. 332f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) uint8 buffer_no = 1; 333f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer; 334f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) buffer = 335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution); 3361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_TRUE(buffer.get()); 337f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) memset(buffer->data(), buffer_no++, buffer->size()); 338d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) { 339d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) InSequence s; 3401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1)).Times(1); 3411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(1); 342d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 343d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) { 344d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) InSequence s; 3451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1)).Times(1); 3461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(1); 347d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 348d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) { 349d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) InSequence s; 3501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2)).Times(1); 3511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(1); 352d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 353a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_->OnIncomingCapturedVideoFrame( 354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer, 355a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::VideoCaptureFormat(capture_resolution, 356a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_format.frame_rate, 357a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::PIXEL_FORMAT_I420), 358a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) WrapI420Buffer(buffer, capture_resolution), 359a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks()); 360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) buffer = NULL; 361d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 362d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::RunLoop().RunUntilIdle(); 363d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Mock::VerifyAndClearExpectations(client_a_.get()); 364d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Mock::VerifyAndClearExpectations(client_b_.get()); 365d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Second buffer which ought to use the same shared memory buffer. In this 367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // case pretend that the Buffer pointer is held by the device for a long 368f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // delay. This shouldn't affect anything. 369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) buffer = 370f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution); 3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_TRUE(buffer.get()); 372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) memset(buffer->data(), buffer_no++, buffer->size()); 373a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_->OnIncomingCapturedVideoFrame( 374a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer, 375a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::VideoCaptureFormat(capture_resolution, 376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_format.frame_rate, 377a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::PIXEL_FORMAT_I420), 378a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) WrapI420Buffer(buffer, capture_resolution), 379a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks()); 380f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) buffer = NULL; 381d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 382d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // The buffer should be delivered to the clients in any order. 383d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(1); 384d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(1); 3851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(1); 386d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::RunLoop().RunUntilIdle(); 387d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Mock::VerifyAndClearExpectations(client_a_.get()); 388d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Mock::VerifyAndClearExpectations(client_b_.get()); 389d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Add a fourth client now that some buffers have come through. 391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller_->AddClient(client_b_route_2, 392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) client_b_.get(), 393f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::kNullProcessHandle, 394f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1, 395f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) session_1); 396d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Mock::VerifyAndClearExpectations(client_b_.get()); 397d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 398f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Third, fourth, and fifth buffers. Pretend they all arrive at the same time. 399d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (int i = 0; i < kPoolSize; i++) { 400f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) buffer = device_->ReserveOutputBuffer(media::VideoFrame::I420, 401f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) capture_resolution); 4021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_TRUE(buffer.get()); 403f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) memset(buffer->data(), buffer_no++, buffer->size()); 404a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_->OnIncomingCapturedVideoFrame( 405a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer, 406a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::VideoCaptureFormat(capture_resolution, 407a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_format.frame_rate, 408a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::PIXEL_FORMAT_I420), 409a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) WrapI420Buffer(buffer, capture_resolution), 410a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks()); 411f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) buffer = NULL; 412d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 413d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // ReserveOutputBuffer ought to fail now, because the pool is depleted. 414f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::I420, 4151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci capture_resolution).get()); 4161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 4171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // The new client needs to be told of 3 buffers; the old clients only 2. 4181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_2)).Times(kPoolSize); 4191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(kPoolSize); 4201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1)) 4211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) .Times(kPoolSize - 1); 422d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(kPoolSize); 4231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2)) 4241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) .Times(kPoolSize - 1); 425d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(kPoolSize); 4261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1)) 4271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) .Times(kPoolSize - 1); 428d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(kPoolSize); 429d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::RunLoop().RunUntilIdle(); 430d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Mock::VerifyAndClearExpectations(client_a_.get()); 431d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Mock::VerifyAndClearExpectations(client_b_.get()); 432d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 433f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Now test the interaction of client shutdown and buffer delivery. 434d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Kill A1 via renderer disconnect (synchronous). 435d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) controller_->RemoveClient(client_a_route_1, client_a_.get()); 436d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Kill B1 via session close (posts a task to disconnect). 437d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_CALL(*client_b_, DoEnded(client_b_route_1)).Times(1); 438d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) controller_->StopSession(300); 439f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Queue up another buffer. 440f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) buffer = 441f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution); 4421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_TRUE(buffer.get()); 443f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) memset(buffer->data(), buffer_no++, buffer->size()); 444a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_->OnIncomingCapturedVideoFrame( 445a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer, 446a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::VideoCaptureFormat(capture_resolution, 447a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_format.frame_rate, 448a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::PIXEL_FORMAT_I420), 449a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) WrapI420Buffer(buffer, capture_resolution), 450a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks()); 451f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) buffer = NULL; 452f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) buffer = 453f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution); 454d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) { 455d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Kill A2 via session close (posts a task to disconnect, but A2 must not 456f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // be sent either of these two buffers). 457d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_CALL(*client_a_, DoEnded(client_a_route_2)).Times(1); 458d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) controller_->StopSession(200); 459d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 4601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_TRUE(buffer.get()); 461f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) memset(buffer->data(), buffer_no++, buffer->size()); 462a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_->OnIncomingCapturedVideoFrame( 463a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer, 464a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::VideoCaptureFormat(capture_resolution, 465a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_format.frame_rate, 466a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::PIXEL_FORMAT_I420), 467a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) WrapI420Buffer(buffer, capture_resolution), 468a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks()); 469f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) buffer = NULL; 470d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // B2 is the only client left, and is the only one that should 471f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // get the buffer. 472d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(2); 473d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::RunLoop().RunUntilIdle(); 474d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Mock::VerifyAndClearExpectations(client_a_.get()); 475d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Mock::VerifyAndClearExpectations(client_b_.get()); 476a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 477a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Allocate all buffers from the buffer pool, half as SHM buffer and half as 478a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // mailbox buffers. Make sure of different counts though. 479a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int shm_buffers = kPoolSize / 2; 480a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int mailbox_buffers = kPoolSize - shm_buffers; 481a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (shm_buffers == mailbox_buffers) { 482a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) shm_buffers--; 483a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) mailbox_buffers++; 484a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 485a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 486a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (int i = 0; i < shm_buffers; ++i) { 487a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer = device_->ReserveOutputBuffer(media::VideoFrame::I420, 488a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) capture_resolution); 4891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_TRUE(buffer.get()); 490a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_->OnIncomingCapturedVideoFrame( 491a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer, 492a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::VideoCaptureFormat(capture_resolution, 493a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_format.frame_rate, 494a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::PIXEL_FORMAT_I420), 495a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) WrapI420Buffer(buffer, capture_resolution), 496a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks()); 497a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer = NULL; 498a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 499a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::vector<uint32> mailbox_syncpoints(mailbox_buffers); 5005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::vector<uint32> release_syncpoints(mailbox_buffers); 5015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_ANDROID) 5025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) GLHelper* gl_helper = 5035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ImageTransportFactoryAndroid::GetInstance()->GetGLHelper(); 5045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else 5055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper(); 5065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 507a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (int i = 0; i < mailbox_buffers; ++i) { 508a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer = device_->ReserveOutputBuffer(media::VideoFrame::NATIVE_TEXTURE, 509a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gfx::Size(0, 0)); 5101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_TRUE(buffer.get()); 5115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mailbox_syncpoints[i] = gl_helper->InsertSyncPoint(); 512a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_->OnIncomingCapturedVideoFrame( 513a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer, 514a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::VideoCaptureFormat(capture_resolution, 515a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_format.frame_rate, 516a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::PIXEL_FORMAT_TEXTURE), 5175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WrapMailboxBuffer(buffer, 5185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) make_scoped_ptr(new gpu::MailboxHolder( 5195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gpu::Mailbox(), 0, mailbox_syncpoints[i])), 5205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&CacheSyncPoint, &release_syncpoints[i]), 5215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) capture_resolution), 522a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks()); 523a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer = NULL; 524a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 525a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // ReserveOutputBuffers ought to fail now regardless of buffer format, because 526a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // the pool is depleted. 527a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::I420, 5281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci capture_resolution).get()); 529a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::NATIVE_TEXTURE, 5301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Size(0, 0)).get()); 531a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(shm_buffers); 532a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_CALL(*client_b_, DoMailboxBufferReady(client_b_route_2)) 533a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) .Times(mailbox_buffers); 534a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::RunLoop().RunUntilIdle(); 535a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (size_t i = 0; i < mailbox_syncpoints.size(); ++i) { 5365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // A new release sync point must be inserted when the video frame is 5375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // returned to the Browser process. 5385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // See: MockVideoCaptureControllerEventHandler::OnMailboxBufferReady() and 5395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // VideoCaptureController::ReturnBuffer() 5405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ASSERT_NE(mailbox_syncpoints[i], release_syncpoints[i]); 541a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 542a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Mock::VerifyAndClearExpectations(client_b_.get()); 5435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_ANDROID) 5455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ImageTransportFactoryAndroid::TerminateForUnitTests(); 5465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else 5475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ImageTransportFactory::Terminate(); 5485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 549d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 550d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 551d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Exercises the OnError() codepath of VideoCaptureController, and tests the 552d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// behavior of various operations after the error state has been signalled. 553d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) { 554d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) media::VideoCaptureParams session_100; 5551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) session_100.requested_format = media::VideoCaptureFormat( 556f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420); 557d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 558d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) media::VideoCaptureParams session_200 = session_100; 559f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 560f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const gfx::Size capture_resolution(320, 240); 561d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 562d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const VideoCaptureControllerID route_id(0x99); 563d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 564d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Start with one client. 565f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller_->AddClient( 566f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) route_id, client_a_.get(), base::kNullProcessHandle, 100, session_100); 5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_->OnError("Test Error"); 568d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_CALL(*client_a_, DoError(route_id)).Times(1); 569d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::RunLoop().RunUntilIdle(); 570d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Mock::VerifyAndClearExpectations(client_a_.get()); 571d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 572d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Second client connects after the error state. It also should get told of 573d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // the error. 574d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_CALL(*client_b_, DoError(route_id)).Times(1); 575f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller_->AddClient( 576f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) route_id, client_b_.get(), base::kNullProcessHandle, 200, session_200); 577d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::RunLoop().RunUntilIdle(); 578d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Mock::VerifyAndClearExpectations(client_b_.get()); 579d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 580f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer = 581f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution); 5821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_TRUE(buffer.get()); 583f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 584a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_->OnIncomingCapturedVideoFrame( 585a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer, 586a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::VideoCaptureFormat( 587a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) capture_resolution, 30, media::PIXEL_FORMAT_I420), 588a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) WrapI420Buffer(buffer, capture_resolution), 589a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks()); 590f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) buffer = NULL; 591d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 592d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::RunLoop().RunUntilIdle(); 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Exercises the OnError() codepath of VideoCaptureController, and tests the 596d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// behavior of various operations after the error state has been signalled. 597d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TEST_F(VideoCaptureControllerTest, ErrorAfterDeviceCreation) { 598d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) media::VideoCaptureParams session_100; 5991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) session_100.requested_format = media::VideoCaptureFormat( 600f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420); 601d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 602d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) media::VideoCaptureParams session_200 = session_100; 603d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 604d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const VideoCaptureControllerID route_id(0x99); 605d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 606d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Start with one client. 607f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller_->AddClient( 608f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) route_id, client_a_.get(), base::kNullProcessHandle, 100, session_100); 609f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) media::VideoCaptureFormat device_format( 610f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gfx::Size(10, 10), 25, media::PIXEL_FORMAT_ARGB); 611f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 612f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Start the device. Then, before the first buffer, signal an error and 613f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // deliver the buffer. The error should be propagated to clients; the buffer 614f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // should not be. 615d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::RunLoop().RunUntilIdle(); 616d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Mock::VerifyAndClearExpectations(client_a_.get()); 617d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 618f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const gfx::Size dims(320, 240); 619f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer = 620f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) device_->ReserveOutputBuffer(media::VideoFrame::I420, dims); 6211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_TRUE(buffer.get()); 622d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_->OnError("Test error"); 624a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_->OnIncomingCapturedVideoFrame( 625a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer, 626a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::VideoCaptureFormat( 627a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dims, device_format.frame_rate, media::PIXEL_FORMAT_I420), 628a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) WrapI420Buffer(buffer, dims), 629a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks()); 630f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) buffer = NULL; 631d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 632d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_CALL(*client_a_, DoError(route_id)).Times(1); 633d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::RunLoop().RunUntilIdle(); 634d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Mock::VerifyAndClearExpectations(client_a_.get()); 635d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 636d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Second client connects after the error state. It also should get told of 637d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // the error. 638d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_CALL(*client_b_, DoError(route_id)).Times(1); 639f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller_->AddClient( 640f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) route_id, client_b_.get(), base::kNullProcessHandle, 200, session_200); 641d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Mock::VerifyAndClearExpectations(client_b_.get()); 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 645