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)#include <map> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/command_line.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h" 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/files/scoped_file.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 139ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/run_loop.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/browser_thread_impl.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/media_stream_manager.h" 194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/browser/renderer_host/media/media_stream_requester.h" 204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/browser/renderer_host/media/media_stream_ui_proxy.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/video_capture_host.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/video_capture_manager.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/media/video_capture_messages.h" 245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/public/common/content_switches.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/mock_resource_context.h" 26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/test/test_browser_context.h" 27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/test/test_browser_thread_bundle.h" 28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/test/test_content_browser_client.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_manager.h" 30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "media/base/media_switches.h" 31424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "media/base/video_frame.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/video/capture/video_capture_types.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::_; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::AtLeast; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::AnyNumber; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::DoAll; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::InSequence; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Mock; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Return; 444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using ::testing::SaveArg; 454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using ::testing::StrictMock; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Id used to identify the capture session between renderer and 50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// video_capture_host. This is an arbitrary value. 51d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)static const int kDeviceId = 555; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Define to enable test where video is dumped to file. 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// #define DUMP_VIDEO 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Define to use a real video capture device. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// #define TEST_REAL_CAPTURE_DEVICE 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Simple class used for dumping video to a file. This can be used for 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// verifying the output. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DumpVideo { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DumpVideo() : expected_size_(0) {} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StartDump(int width, int height) { 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath file_name = base::FilePath(base::StringPrintf( 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FILE_PATH_LITERAL("dump_w%d_h%d.yuv"), width, height)); 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) file_.reset(base::OpenFile(file_name, "wb")); 68424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) expected_size_ = media::VideoFrame::AllocationSize( 69424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) media::VideoFrame::I420, gfx::Size(width, height)); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void NewVideoFrame(const void* buffer) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (file_.get() != NULL) { 73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_EQ(1U, fwrite(buffer, expected_size_, 1, file_.get())); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::ScopedFILE file_; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int expected_size_; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class MockMediaStreamRequester : public MediaStreamRequester { 834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public: 844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) MockMediaStreamRequester() {} 854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual ~MockMediaStreamRequester() {} 864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // MediaStreamRequester implementation. 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MOCK_METHOD5(StreamGenerated, 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void(int render_view_id, 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int page_request_id, 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& label, 924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const StreamDeviceInfoArray& audio_devices, 934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const StreamDeviceInfoArray& video_devices)); 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MOCK_METHOD3(StreamGenerationFailed, 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void(int render_view_id, 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int page_request_id, 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) content::MediaStreamRequestResult result)); 98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) MOCK_METHOD3(DeviceStopped, void(int render_view_id, 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& label, 100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const StreamDeviceInfo& device)); 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MOCK_METHOD4(DevicesEnumerated, void(int render_view_id, 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int page_request_id, 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& label, 1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const StreamDeviceInfoArray& devices)); 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MOCK_METHOD4(DeviceOpened, void(int render_view_id, 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int page_request_id, 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& label, 1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const StreamDeviceInfo& device_info)); 1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private: 1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MockMediaStreamRequester); 1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}; 1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockVideoCaptureHost : public VideoCaptureHost { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockVideoCaptureHost(MediaStreamManager* manager) 117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : VideoCaptureHost(manager), 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return_buffers_(false), 119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch dump_video_(false) {} 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A list of mock methods. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MOCK_METHOD4(OnNewBufferCreated, 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void(int device_id, 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::SharedMemoryHandle handle, 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int length, 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int buffer_id)); 1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) MOCK_METHOD2(OnBufferFreed, 1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) void(int device_id, int buffer_id)); 1291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) MOCK_METHOD4(OnBufferFilled, 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void(int device_id, 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int buffer_id, 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const media::VideoCaptureFormat& format, 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks timestamp)); 134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MOCK_METHOD5(OnMailboxBufferFilled, 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void(int device_id, 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int buffer_id, 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const gpu::MailboxHolder& mailbox_holder, 138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const media::VideoCaptureFormat& format, 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks timestamp)); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MOCK_METHOD2(OnStateChanged, void(int device_id, VideoCaptureState state)); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use class DumpVideo to write I420 video to file. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetDumpVideo(bool enable) { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dump_video_ = enable; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) void SetReturnReceivedDibs(bool enable) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return_buffers_ = enable; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return Dibs we currently have received. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ReturnReceivedDibs(int device_id) { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int handle = GetReceivedDib(); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (handle) { 1555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this->OnReceiveEmptyBuffer(device_id, handle, std::vector<uint32>()); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handle = GetReceivedDib(); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int GetReceivedDib() { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (filled_dib_.empty()) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<int, base::SharedMemory*>::iterator it = filled_dib_.begin(); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int h = it->first; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete it->second; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filled_dib_.erase(it); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return h; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~MockVideoCaptureHost() { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLDeleteContainerPairSecondPointers(filled_dib_.begin(), 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filled_dib_.end()); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This method is used to dispatch IPC messages to the renderer. We intercept 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // these messages here and dispatch to our mock methods to verify the 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // conversation between this object and the renderer. 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool Send(IPC::Message* message) OVERRIDE { 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(message); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In this method we dispatch the messages to the according handlers as if 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we are the renderer. 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool handled = true; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_BEGIN_MESSAGE_MAP(MockVideoCaptureHost, *message) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_HANDLER(VideoCaptureMsg_NewBuffer, OnNewBufferCreatedDispatch) 1881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) IPC_MESSAGE_HANDLER(VideoCaptureMsg_FreeBuffer, OnBufferFreedDispatch) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_HANDLER(VideoCaptureMsg_BufferReady, OnBufferFilledDispatch) 190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) IPC_MESSAGE_HANDLER(VideoCaptureMsg_MailboxBufferReady, 191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OnMailboxBufferFilledDispatch) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_HANDLER(VideoCaptureMsg_StateChanged, OnStateChangedDispatch) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_UNHANDLED(handled = false) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_END_MESSAGE_MAP() 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(handled); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete message; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These handler methods do minimal things and delegate to the mock methods. 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnNewBufferCreatedDispatch(int device_id, 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SharedMemoryHandle handle, 204424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) uint32 length, 205424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) int buffer_id) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnNewBufferCreated(device_id, handle, length, buffer_id); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SharedMemory* dib = new base::SharedMemory(handle, false); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dib->Map(length); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filled_dib_[buffer_id] = dib; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) void OnBufferFreedDispatch(int device_id, int buffer_id) { 2131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) OnBufferFreed(device_id, buffer_id); 2141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::map<int, base::SharedMemory*>::iterator it = 2161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) filled_dib_.find(buffer_id); 2171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ASSERT_TRUE(it != filled_dib_.end()); 2181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) delete it->second; 2191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) filled_dib_.erase(it); 2201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 2211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) void OnBufferFilledDispatch(int device_id, 2231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int buffer_id, 224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const media::VideoCaptureFormat& frame_format, 225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks timestamp) { 2261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::SharedMemory* dib = filled_dib_[buffer_id]; 2271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ASSERT_TRUE(dib != NULL); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dump_video_) { 2291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!format_.IsValid()) { 230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) dumper_.StartDump(frame_format.frame_size.width(), 231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) frame_format.frame_size.height()); 2321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) format_ = frame_format; 2331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_EQ(format_.frame_size.width(), frame_format.frame_size.width()) 235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) << "Dump format does not handle variable resolution."; 236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_EQ(format_.frame_size.height(), frame_format.frame_size.height()) 2371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) << "Dump format does not handle variable resolution."; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dumper_.NewVideoFrame(dib->memory()); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OnBufferFilled(device_id, buffer_id, frame_format, timestamp); 242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (return_buffers_) { 2435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu VideoCaptureHost::OnReceiveEmptyBuffer( 2445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu device_id, buffer_id, std::vector<uint32>()); 245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void OnMailboxBufferFilledDispatch(int device_id, 249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int buffer_id, 250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const gpu::MailboxHolder& mailbox_holder, 251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const media::VideoCaptureFormat& format, 252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks timestamp) { 253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OnMailboxBufferFilled( 254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_id, buffer_id, mailbox_holder, format, timestamp); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (return_buffers_) { 256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) VideoCaptureHost::OnReceiveEmptyBuffer( 2575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu device_id, buffer_id, std::vector<uint32>()); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnStateChangedDispatch(int device_id, VideoCaptureState state) { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnStateChanged(device_id, state); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<int, base::SharedMemory*> filled_dib_; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool return_buffers_; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool dump_video_; 2681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) media::VideoCaptureFormat format_; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DumpVideo dumper_; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochACTION_P2(ExitMessageLoop, message_loop, quit_closure) { 273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch message_loop->PostTask(FROM_HERE, quit_closure); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// This is an integration test of VideoCaptureHost in conjunction with 2774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// MediaStreamManager, VideoCaptureManager, VideoCaptureController, and 2784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// VideoCaptureDevice. 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VideoCaptureHostTest : public testing::Test { 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch VideoCaptureHostTest() 282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), 2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) message_loop_(base::MessageLoopProxy::current()), 2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) opened_session_id_(kInvalidMediaCaptureSessionId) {} 2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual void SetUp() OVERRIDE { 287a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SetBrowserClientForTesting(&browser_client_); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create our own MediaStreamManager. 289a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) audio_manager_.reset(media::AudioManager::CreateForTesting()); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef TEST_REAL_CAPTURE_DEVICE 2915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::CommandLine::ForCurrentProcess()->AppendSwitch( 2925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu switches::kUseFakeDeviceForMediaStream); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get())); 2954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) media_stream_manager_->UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy>()); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Create a Host and connect it to a simulated IPC channel. 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_ = new MockVideoCaptureHost(media_stream_manager_.get()); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->OnChannelConnected(base::GetCurrentProcId()); 3004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) OpenSession(); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual void TearDown() OVERRIDE { 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verifies and removes the expectations on host_ and 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returns true iff successful. 307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Mock::VerifyAndClearExpectations(host_.get()); 3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_EQ(0u, host_->entries_.size()); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) CloseSession(); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Simulate closing the IPC sender. 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->OnChannelClosing(); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release the reference to the mock object. The object will be destructed 316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // on the current message loop. 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_ = NULL; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) void OpenSession() { 3214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const int render_process_id = 1; 3224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const int render_view_id = 1; 3234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const int page_request_id = 1; 324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const GURL security_origin("http://test.com"); 3254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ASSERT_TRUE(opened_device_label_.empty()); 3274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Enumerate video devices. 3294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StreamDeviceInfoArray devices; 3304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) { 3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::RunLoop run_loop; 3324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string label = media_stream_manager_->EnumerateDevices( 3334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &stream_requester_, 3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) render_process_id, 3354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) render_view_id, 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), 3374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) page_request_id, 3384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) MEDIA_DEVICE_VIDEO_CAPTURE, 33946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) security_origin, 34046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) true); 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(stream_requester_, DevicesEnumerated(render_view_id, 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) page_request_id, 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) label, 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) _)) 3454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) .Times(1).WillOnce( 3464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DoAll(ExitMessageLoop(message_loop_, run_loop.QuitClosure()), 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SaveArg<3>(&devices))); 3484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) run_loop.Run(); 3494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Mock::VerifyAndClearExpectations(&stream_requester_); 3504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) media_stream_manager_->CancelRequest(label); 3514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 3524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ASSERT_FALSE(devices.empty()); 3534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ASSERT_EQ(StreamDeviceInfo::kNoId, devices[0].session_id); 3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Open the first device. 3564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) { 3574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::RunLoop run_loop; 3584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StreamDeviceInfo opened_device; 3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) media_stream_manager_->OpenDevice( 3604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &stream_requester_, 3614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) render_process_id, 3624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) render_view_id, 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), 3644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) page_request_id, 3654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) devices[0].device.id, 3664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) MEDIA_DEVICE_VIDEO_CAPTURE, 3674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) security_origin); 3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(stream_requester_, DeviceOpened(render_view_id, 3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) page_request_id, 3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) _, 3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) _)) 3724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) .Times(1).WillOnce( 3734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DoAll(ExitMessageLoop(message_loop_, run_loop.QuitClosure()), 3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SaveArg<2>(&opened_device_label_), 3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SaveArg<3>(&opened_device))); 3764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) run_loop.Run(); 3774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Mock::VerifyAndClearExpectations(&stream_requester_); 3784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ASSERT_NE(StreamDeviceInfo::kNoId, opened_device.session_id); 3794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) opened_session_id_ = opened_device.session_id; 3804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 3814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 3824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) void CloseSession() { 3844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (opened_device_label_.empty()) 3854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 3868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) media_stream_manager_->CancelRequest(opened_device_label_); 3874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) opened_device_label_.clear(); 3884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) opened_session_id_ = kInvalidMediaCaptureSessionId; 3894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 3904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch protected: 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StartCapture() { 3934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*host_, OnNewBufferCreated(kDeviceId, _, _, _)) 394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) .Times(AnyNumber()).WillRepeatedly(Return()); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::RunLoop run_loop; 3971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*host_, OnBufferFilled(kDeviceId, _, _, _)) 398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch .Times(AnyNumber()).WillOnce(ExitMessageLoop( 399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch message_loop_, run_loop.QuitClosure())); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::VideoCaptureParams params; 4021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) params.requested_format = media::VideoCaptureFormat( 403f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420); 404f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) host_->OnStartCapture(kDeviceId, opened_session_id_, params); 405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch run_loop.Run(); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 408d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) void StartStopCapture() { 409d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Quickly start and then stop capture, without giving much chance for 410d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // asynchronous start operations to complete. 411d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) InSequence s; 412d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::RunLoop run_loop; 4134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*host_, OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED)); 414d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) media::VideoCaptureParams params; 4151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) params.requested_format = media::VideoCaptureFormat( 416f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420); 417f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) host_->OnStartCapture(kDeviceId, opened_session_id_, params); 418d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) host_->OnStopCapture(kDeviceId); 419d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) run_loop.RunUntilIdle(); 420d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 421d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DUMP_VIDEO 423d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) void CaptureAndDumpVideo(int width, int height, int frame_rate) { 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InSequence s; 4251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*host_.get(), OnNewBufferCreated(kDeviceId, _, _, _)) 4261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) .Times(AnyNumber()).WillRepeatedly(Return()); 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::RunLoop run_loop; 4291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*host_, OnBufferFilled(kDeviceId, _, _, _)) 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .Times(AnyNumber()) 431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch .WillOnce(ExitMessageLoop(message_loop_, run_loop.QuitClosure())); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::VideoCaptureParams params; 434f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) params.requested_format = 435f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) media::VideoCaptureFormat(gfx::Size(width, height), frame_rate); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->SetDumpVideo(true); 437f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) host_->OnStartCapture(kDeviceId, opened_session_id_, params); 438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch run_loop.Run(); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StopCapture() { 443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::RunLoop run_loop; 4444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*host_, OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED)) 445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch .WillOnce(ExitMessageLoop(message_loop_, run_loop.QuitClosure())); 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->OnStopCapture(kDeviceId); 4481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) host_->SetReturnReceivedDibs(true); 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->ReturnReceivedDibs(kDeviceId); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch run_loop.Run(); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) host_->SetReturnReceivedDibs(false); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Expect the VideoCaptureDevice has been stopped 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0u, host_->entries_.size()); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void NotifyPacketReady() { 459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::RunLoop run_loop; 4601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*host_, OnBufferFilled(kDeviceId, _, _, _)) 461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch .Times(AnyNumber()).WillOnce(ExitMessageLoop( 462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch message_loop_, run_loop.QuitClosure())) 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .RetiresOnSaturation(); 464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch run_loop.Run(); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ReturnReceivedPackets() { 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->ReturnReceivedDibs(kDeviceId); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SimulateError() { 4724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Expect a change state to error state sent through IPC. 4734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*host_, OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_ERROR)) 4744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) .Times(1); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoCaptureControllerID id(kDeviceId); 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->OnError(id); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait for the error callback. 478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::RunLoop().RunUntilIdle(); 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<MockVideoCaptureHost> host_; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 4844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StrictMock<MockMediaStreamRequester> stream_requester_; 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<media::AudioManager> audio_manager_; 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<MediaStreamManager> media_stream_manager_; 487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::TestBrowserThreadBundle thread_bundle_; 488a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) content::TestBrowserContext browser_context_; 489a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) content::TestContentBrowserClient browser_client_; 490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_refptr<base::MessageLoopProxy> message_loop_; 4914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int opened_session_id_; 4924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string opened_device_label_; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(VideoCaptureHostTest); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(VideoCaptureHostTest, CloseSessionWithoutStopping) { 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartCapture(); 4994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 5004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // When the session is closed via the stream without stopping capture, the 5014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // ENDED event is sent. 5024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*host_, OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_ENDED)) 5034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) .Times(1); 5044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) CloseSession(); 5054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::RunLoop().RunUntilIdle(); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(VideoCaptureHostTest, StopWhileStartPending) { 509d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) StartStopCapture(); 510d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 511d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VideoCaptureHostTest, StartCapturePlayStop) { 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartCapture(); 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyPacketReady(); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyPacketReady(); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReturnReceivedPackets(); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopCapture(); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VideoCaptureHostTest, StartCaptureErrorStop) { 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartCapture(); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateError(); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopCapture(); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VideoCaptureHostTest, StartCaptureError) { 5274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*host_, OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED)) 5284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) .Times(0); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartCapture(); 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyPacketReady(); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateError(); 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200)); 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DUMP_VIDEO 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VideoCaptureHostTest, CaptureAndDumpVideoVga) { 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CaptureAndDumpVideo(640, 480, 30); 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VideoCaptureHostTest, CaptureAndDump720P) { 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CaptureAndDumpVideo(1280, 720, 30); 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 545