1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/bind.h" 6#include "base/memory/scoped_ptr.h" 7#include "base/run_loop.h" 8#include "base/test/test_timeouts.h" 9#include "base/threading/thread.h" 10#include "media/video/capture/fake_video_capture_device.h" 11#include "media/video/capture/fake_video_capture_device_factory.h" 12#include "media/video/capture/video_capture_device.h" 13#include "media/video/capture/video_capture_types.h" 14#include "testing/gmock/include/gmock/gmock.h" 15#include "testing/gtest/include/gtest/gtest.h" 16 17using ::testing::_; 18using ::testing::SaveArg; 19 20namespace media { 21 22class MockClient : public media::VideoCaptureDevice::Client { 23 public: 24 MOCK_METHOD2(ReserveOutputBuffer, 25 scoped_refptr<Buffer>(media::VideoFrame::Format format, 26 const gfx::Size& dimensions)); 27 MOCK_METHOD0(OnErr, void()); 28 29 explicit MockClient(base::Callback<void(const VideoCaptureFormat&)> frame_cb) 30 : main_thread_(base::MessageLoopProxy::current()), frame_cb_(frame_cb) {} 31 32 virtual void OnError(const std::string& error_message) OVERRIDE { 33 OnErr(); 34 } 35 36 virtual void OnIncomingCapturedData(const uint8* data, 37 int length, 38 const VideoCaptureFormat& format, 39 int rotation, 40 base::TimeTicks timestamp) OVERRIDE { 41 main_thread_->PostTask(FROM_HERE, base::Bind(frame_cb_, format)); 42 } 43 44 virtual void OnIncomingCapturedVideoFrame( 45 const scoped_refptr<Buffer>& buffer, 46 const media::VideoCaptureFormat& buffer_format, 47 const scoped_refptr<media::VideoFrame>& frame, 48 base::TimeTicks timestamp) OVERRIDE { 49 NOTREACHED(); 50 } 51 52 private: 53 scoped_refptr<base::SingleThreadTaskRunner> main_thread_; 54 base::Callback<void(const VideoCaptureFormat&)> frame_cb_; 55}; 56 57class DeviceEnumerationListener : 58 public base::RefCounted<DeviceEnumerationListener> { 59 public: 60 MOCK_METHOD1(OnEnumeratedDevicesCallbackPtr, 61 void(media::VideoCaptureDevice::Names* names)); 62 // GMock doesn't support move-only arguments, so we use this forward method. 63 void OnEnumeratedDevicesCallback( 64 scoped_ptr<media::VideoCaptureDevice::Names> names) { 65 OnEnumeratedDevicesCallbackPtr(names.release()); 66 } 67 68 private: 69 friend class base::RefCounted<DeviceEnumerationListener>; 70 virtual ~DeviceEnumerationListener() {} 71}; 72 73class FakeVideoCaptureDeviceTest : public testing::Test { 74 protected: 75 typedef media::VideoCaptureDevice::Client Client; 76 77 FakeVideoCaptureDeviceTest() 78 : loop_(new base::MessageLoop()), 79 client_(new MockClient( 80 base::Bind(&FakeVideoCaptureDeviceTest::OnFrameCaptured, 81 base::Unretained(this)))), 82 video_capture_device_factory_(new FakeVideoCaptureDeviceFactory()) { 83 device_enumeration_listener_ = new DeviceEnumerationListener(); 84 } 85 86 virtual void SetUp() { 87 } 88 89 void OnFrameCaptured(const VideoCaptureFormat& format) { 90 last_format_ = format; 91 run_loop_->QuitClosure().Run(); 92 } 93 94 void WaitForCapturedFrame() { 95 run_loop_.reset(new base::RunLoop()); 96 run_loop_->Run(); 97 } 98 99 scoped_ptr<media::VideoCaptureDevice::Names> EnumerateDevices() { 100 media::VideoCaptureDevice::Names* names; 101 EXPECT_CALL(*device_enumeration_listener_.get(), 102 OnEnumeratedDevicesCallbackPtr(_)).WillOnce(SaveArg<0>(&names)); 103 104 video_capture_device_factory_->EnumerateDeviceNames( 105 base::Bind(&DeviceEnumerationListener::OnEnumeratedDevicesCallback, 106 device_enumeration_listener_)); 107 base::MessageLoop::current()->RunUntilIdle(); 108 return scoped_ptr<media::VideoCaptureDevice::Names>(names); 109 } 110 111 const VideoCaptureFormat& last_format() const { return last_format_; } 112 113 VideoCaptureDevice::Names names_; 114 scoped_ptr<base::MessageLoop> loop_; 115 scoped_ptr<base::RunLoop> run_loop_; 116 scoped_ptr<MockClient> client_; 117 scoped_refptr<DeviceEnumerationListener> device_enumeration_listener_; 118 VideoCaptureFormat last_format_; 119 scoped_ptr<VideoCaptureDeviceFactory> video_capture_device_factory_; 120}; 121 122TEST_F(FakeVideoCaptureDeviceTest, Capture) { 123 scoped_ptr<media::VideoCaptureDevice::Names> names(EnumerateDevices()); 124 125 ASSERT_GT(static_cast<int>(names->size()), 0); 126 127 scoped_ptr<VideoCaptureDevice> device( 128 video_capture_device_factory_->Create(names->front())); 129 ASSERT_TRUE(device); 130 131 EXPECT_CALL(*client_, OnErr()).Times(0); 132 133 VideoCaptureParams capture_params; 134 capture_params.requested_format.frame_size.SetSize(640, 480); 135 capture_params.requested_format.frame_rate = 30; 136 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; 137 device->AllocateAndStart(capture_params, client_.PassAs<Client>()); 138 WaitForCapturedFrame(); 139 EXPECT_EQ(last_format().frame_size.width(), 640); 140 EXPECT_EQ(last_format().frame_size.height(), 480); 141 EXPECT_EQ(last_format().frame_rate, 30); 142 device->StopAndDeAllocate(); 143} 144 145TEST_F(FakeVideoCaptureDeviceTest, GetDeviceSupportedFormats) { 146 scoped_ptr<VideoCaptureDevice::Names> names(EnumerateDevices()); 147 148 VideoCaptureFormats supported_formats; 149 VideoCaptureDevice::Names::iterator names_iterator; 150 151 for (names_iterator = names->begin(); names_iterator != names->end(); 152 ++names_iterator) { 153 video_capture_device_factory_->GetDeviceSupportedFormats( 154 *names_iterator, &supported_formats); 155 EXPECT_EQ(supported_formats.size(), 3u); 156 EXPECT_EQ(supported_formats[0].frame_size.width(), 320); 157 EXPECT_EQ(supported_formats[0].frame_size.height(), 240); 158 EXPECT_EQ(supported_formats[0].pixel_format, media::PIXEL_FORMAT_I420); 159 EXPECT_GE(supported_formats[0].frame_rate, 20); 160 EXPECT_EQ(supported_formats[1].frame_size.width(), 640); 161 EXPECT_EQ(supported_formats[1].frame_size.height(), 480); 162 EXPECT_EQ(supported_formats[1].pixel_format, media::PIXEL_FORMAT_I420); 163 EXPECT_GE(supported_formats[1].frame_rate, 20); 164 EXPECT_EQ(supported_formats[2].frame_size.width(), 1280); 165 EXPECT_EQ(supported_formats[2].frame_size.height(), 720); 166 EXPECT_EQ(supported_formats[2].pixel_format, media::PIXEL_FORMAT_I420); 167 EXPECT_GE(supported_formats[2].frame_rate, 20); 168 } 169} 170 171// Disabled, http://crbug.com/407061 . 172TEST_F(FakeVideoCaptureDeviceTest, DISABLED_CaptureVariableResolution) { 173 scoped_ptr<VideoCaptureDevice::Names> names(EnumerateDevices()); 174 175 VideoCaptureParams capture_params; 176 capture_params.requested_format.frame_size.SetSize(640, 480); 177 capture_params.requested_format.frame_rate = 30; 178 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; 179 capture_params.resolution_change_policy = 180 RESOLUTION_POLICY_DYNAMIC_WITHIN_LIMIT; 181 182 ASSERT_GT(static_cast<int>(names->size()), 0); 183 184 scoped_ptr<VideoCaptureDevice> device( 185 video_capture_device_factory_->Create(names->front())); 186 ASSERT_TRUE(device); 187 188 // Configure the FakeVideoCaptureDevice to use all its formats as roster. 189 VideoCaptureFormats formats; 190 video_capture_device_factory_->GetDeviceSupportedFormats(names->front(), 191 &formats); 192 static_cast<FakeVideoCaptureDevice*>(device.get())-> 193 PopulateVariableFormatsRoster(formats); 194 195 EXPECT_CALL(*client_, OnErr()) 196 .Times(0); 197 int action_count = 200; 198 199 device->AllocateAndStart(capture_params, client_.PassAs<Client>()); 200 201 // We set TimeWait to 200 action timeouts and this should be enough for at 202 // least action_count/kFakeCaptureCapabilityChangePeriod calls. 203 for (int i = 0; i < action_count; ++i) { 204 WaitForCapturedFrame(); 205 } 206 device->StopAndDeAllocate(); 207} 208 209}; // namespace media 210