1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/message_loop/message_loop.h" 6 #include "content/child/child_process.h" 7 #include "content/common/media/video_capture_messages.h" 8 #include "content/renderer/media/video_capture_impl.h" 9 #include "media/base/bind_to_current_loop.h" 10 #include "testing/gmock/include/gmock/gmock.h" 11 #include "testing/gtest/include/gtest/gtest.h" 12 13 using ::testing::_; 14 using ::testing::AtLeast; 15 using ::testing::InvokeWithoutArgs; 16 using ::testing::Return; 17 using ::testing::SaveArg; 18 19 namespace content { 20 21 class MockVideoCaptureMessageFilter : public VideoCaptureMessageFilter { 22 public: 23 MockVideoCaptureMessageFilter() : VideoCaptureMessageFilter() {} 24 25 // Filter implementation. 26 MOCK_METHOD1(Send, bool(IPC::Message* message)); 27 28 protected: 29 virtual ~MockVideoCaptureMessageFilter() {} 30 31 private: 32 DISALLOW_COPY_AND_ASSIGN(MockVideoCaptureMessageFilter); 33 }; 34 35 class VideoCaptureImplTest : public ::testing::Test { 36 public: 37 class MockVideoCaptureImpl : public VideoCaptureImpl { 38 public: 39 MockVideoCaptureImpl(const media::VideoCaptureSessionId id, 40 VideoCaptureMessageFilter* filter) 41 : VideoCaptureImpl(id, filter) { 42 } 43 virtual ~MockVideoCaptureImpl() {} 44 45 // Override Send() to mimic device to send events. 46 virtual void Send(IPC::Message* message) OVERRIDE { 47 CHECK(message); 48 49 // In this method, messages are sent to the according handlers as if 50 // we are the device. 51 bool handled = true; 52 IPC_BEGIN_MESSAGE_MAP(MockVideoCaptureImpl, *message) 53 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Start, DeviceStartCapture) 54 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Pause, DevicePauseCapture) 55 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Stop, DeviceStopCapture) 56 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_BufferReady, 57 DeviceReceiveEmptyBuffer) 58 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_GetDeviceSupportedFormats, 59 DeviceGetSupportedFormats) 60 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_GetDeviceFormatsInUse, 61 DeviceGetFormatsInUse) 62 IPC_MESSAGE_UNHANDLED(handled = false) 63 IPC_END_MESSAGE_MAP() 64 EXPECT_TRUE(handled); 65 delete message; 66 } 67 68 void DeviceStartCapture(int device_id, 69 media::VideoCaptureSessionId session_id, 70 const media::VideoCaptureParams& params) { 71 OnStateChanged(VIDEO_CAPTURE_STATE_STARTED); 72 capture_params_ = params; 73 } 74 75 void DevicePauseCapture(int device_id) {} 76 77 void DeviceStopCapture(int device_id) { 78 OnStateChanged(VIDEO_CAPTURE_STATE_STOPPED); 79 } 80 81 void DeviceReceiveEmptyBuffer(int device_id, 82 int buffer_id, 83 uint32 sync_point) {} 84 85 void DeviceGetSupportedFormats(int device_id, 86 media::VideoCaptureSessionId session_id) { 87 // When the mock message filter receives a request for the device 88 // supported formats, replies immediately with an empty format list. 89 OnDeviceSupportedFormatsEnumerated( 90 media::VideoCaptureFormats()); 91 } 92 93 void DeviceGetFormatsInUse(int device_id, 94 media::VideoCaptureSessionId session_id) { 95 OnDeviceFormatsInUseReceived(media::VideoCaptureFormats()); 96 } 97 98 void ReceiveStateChangeMessage(VideoCaptureState state) { 99 OnStateChanged(state); 100 } 101 102 const media::VideoCaptureParams& capture_params() const { 103 return capture_params_; 104 } 105 106 private: 107 media::VideoCaptureParams capture_params_; 108 }; 109 110 VideoCaptureImplTest() { 111 params_small_.requested_format = media::VideoCaptureFormat( 112 gfx::Size(176, 144), 30, media::PIXEL_FORMAT_I420); 113 114 params_large_.requested_format = media::VideoCaptureFormat( 115 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420); 116 117 child_process_.reset(new ChildProcess()); 118 119 message_filter_ = new MockVideoCaptureMessageFilter; 120 session_id_ = 1; 121 122 video_capture_impl_.reset(new MockVideoCaptureImpl( 123 session_id_, message_filter_.get())); 124 125 video_capture_impl_->device_id_ = 2; 126 } 127 128 virtual ~VideoCaptureImplTest() { 129 } 130 131 protected: 132 MOCK_METHOD3(OnFrameReady, 133 void(const scoped_refptr<media::VideoFrame>&, 134 const media::VideoCaptureFormat&, 135 const base::TimeTicks&)); 136 MOCK_METHOD1(OnStateUpdate, void(VideoCaptureState)); 137 MOCK_METHOD1(OnDeviceFormatsInUse, 138 void(const media::VideoCaptureFormats&)); 139 MOCK_METHOD1(OnDeviceSupportedFormats, 140 void(const media::VideoCaptureFormats&)); 141 142 void Init() { 143 video_capture_impl_->Init(); 144 } 145 146 void StartCapture(int client_id, 147 const media::VideoCaptureParams& params) { 148 video_capture_impl_->StartCapture( 149 client_id, params, 150 base::Bind(&VideoCaptureImplTest::OnStateUpdate, 151 base::Unretained(this)), 152 base::Bind(&VideoCaptureImplTest::OnFrameReady, 153 base::Unretained(this))); 154 } 155 156 void StopCapture(int client_id) { 157 video_capture_impl_->StopCapture(client_id); 158 } 159 160 void DeInit() { 161 video_capture_impl_->DeInit(); 162 } 163 164 void GetDeviceSupportedFormats() { 165 const base::Callback<void(const media::VideoCaptureFormats&)> 166 callback = base::Bind( 167 &VideoCaptureImplTest::OnDeviceSupportedFormats, 168 base::Unretained(this)); 169 video_capture_impl_->GetDeviceSupportedFormats(callback); 170 } 171 172 void GetDeviceFormatsInUse() { 173 const base::Callback<void(const media::VideoCaptureFormats&)> 174 callback = base::Bind( 175 &VideoCaptureImplTest::OnDeviceFormatsInUse, 176 base::Unretained(this)); 177 video_capture_impl_->GetDeviceFormatsInUse(callback); 178 } 179 180 base::MessageLoop message_loop_; 181 scoped_ptr<ChildProcess> child_process_; 182 scoped_refptr<MockVideoCaptureMessageFilter> message_filter_; 183 media::VideoCaptureSessionId session_id_; 184 scoped_ptr<MockVideoCaptureImpl> video_capture_impl_; 185 media::VideoCaptureParams params_small_; 186 media::VideoCaptureParams params_large_; 187 188 private: 189 DISALLOW_COPY_AND_ASSIGN(VideoCaptureImplTest); 190 }; 191 192 TEST_F(VideoCaptureImplTest, Simple) { 193 // Execute SetCapture() and StopCapture() for one client. 194 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED)); 195 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STOPPED)); 196 197 Init(); 198 StartCapture(0, params_small_); 199 StopCapture(0); 200 DeInit(); 201 } 202 203 TEST_F(VideoCaptureImplTest, TwoClientsInSequence) { 204 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED)).Times(2); 205 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STOPPED)).Times(2); 206 207 Init(); 208 StartCapture(0, params_small_); 209 StopCapture(0); 210 StartCapture(1, params_small_); 211 StopCapture(1); 212 DeInit(); 213 } 214 215 TEST_F(VideoCaptureImplTest, LargeAndSmall) { 216 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED)).Times(2); 217 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STOPPED)).Times(2); 218 219 Init(); 220 StartCapture(0, params_large_); 221 StopCapture(0); 222 StartCapture(1, params_small_); 223 StopCapture(1); 224 DeInit(); 225 } 226 227 TEST_F(VideoCaptureImplTest, SmallAndLarge) { 228 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED)).Times(2); 229 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STOPPED)).Times(2); 230 231 Init(); 232 StartCapture(0, params_small_); 233 StopCapture(0); 234 StartCapture(1, params_large_); 235 StopCapture(1); 236 DeInit(); 237 } 238 239 // Check that a request to GetDeviceSupportedFormats() ends up eventually in the 240 // provided callback. 241 TEST_F(VideoCaptureImplTest, GetDeviceFormats) { 242 EXPECT_CALL(*this, OnDeviceSupportedFormats(_)); 243 244 Init(); 245 GetDeviceSupportedFormats(); 246 DeInit(); 247 } 248 249 // Check that two requests to GetDeviceSupportedFormats() end up eventually 250 // calling the provided callbacks. 251 TEST_F(VideoCaptureImplTest, TwoClientsGetDeviceFormats) { 252 EXPECT_CALL(*this, OnDeviceSupportedFormats(_)).Times(2); 253 254 Init(); 255 GetDeviceSupportedFormats(); 256 GetDeviceSupportedFormats(); 257 DeInit(); 258 } 259 260 // Check that a request to GetDeviceFormatsInUse() ends up eventually in the 261 // provided callback. 262 TEST_F(VideoCaptureImplTest, GetDeviceFormatsInUse) { 263 EXPECT_CALL(*this, OnDeviceFormatsInUse(_)); 264 265 Init(); 266 GetDeviceFormatsInUse(); 267 DeInit(); 268 } 269 270 TEST_F(VideoCaptureImplTest, AlreadyStarted) { 271 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED)).Times(2); 272 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STOPPED)).Times(2); 273 274 Init(); 275 StartCapture(0, params_small_); 276 StartCapture(1, params_large_); 277 StopCapture(0); 278 StopCapture(1); 279 DeInit(); 280 DCHECK(video_capture_impl_->capture_params().requested_format 281 .frame_size == 282 params_small_.requested_format.frame_size); 283 } 284 285 TEST_F(VideoCaptureImplTest, EndedBeforeStop) { 286 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED)); 287 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STOPPED)); 288 289 Init(); 290 StartCapture(0, params_small_); 291 292 // Receive state change message from browser. 293 video_capture_impl_->ReceiveStateChangeMessage(VIDEO_CAPTURE_STATE_ENDED); 294 295 StopCapture(0); 296 DeInit(); 297 } 298 299 TEST_F(VideoCaptureImplTest, ErrorBeforeStop) { 300 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED)); 301 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_ERROR)); 302 303 Init(); 304 StartCapture(0, params_small_); 305 306 // Receive state change message from browser. 307 video_capture_impl_->ReceiveStateChangeMessage(VIDEO_CAPTURE_STATE_ERROR); 308 309 StopCapture(0); 310 DeInit(); 311 } 312 313 } // namespace content 314