1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Unit test for VideoCaptureManager. 6 7 #include <string> 8 9 #include "base/bind.h" 10 #include "base/memory/ref_counted.h" 11 #include "base/memory/scoped_ptr.h" 12 #include "base/message_loop/message_loop.h" 13 #include "content/browser/browser_thread_impl.h" 14 #include "content/browser/renderer_host/media/media_stream_provider.h" 15 #include "content/browser/renderer_host/media/video_capture_manager.h" 16 #include "content/common/media/media_stream_options.h" 17 #include "media/video/capture/video_capture_device.h" 18 #include "testing/gmock/include/gmock/gmock.h" 19 #include "testing/gtest/include/gtest/gtest.h" 20 21 using ::testing::_; 22 using ::testing::AnyNumber; 23 using ::testing::InSequence; 24 using testing::SaveArg; 25 using ::testing::Return; 26 27 namespace content { 28 29 // Listener class used to track progress of VideoCaptureManager test. 30 class MockMediaStreamProviderListener : public MediaStreamProviderListener { 31 public: 32 MockMediaStreamProviderListener() {} 33 ~MockMediaStreamProviderListener() {} 34 35 MOCK_METHOD2(Opened, void(MediaStreamType, int)); 36 MOCK_METHOD2(Closed, void(MediaStreamType, int)); 37 MOCK_METHOD2(DevicesEnumerated, void(MediaStreamType, 38 const StreamDeviceInfoArray&)); 39 MOCK_METHOD3(Error, void(MediaStreamType, int, 40 MediaStreamProviderError)); 41 }; // class MockMediaStreamProviderListener 42 43 // Needed as an input argument to Start(). 44 class MockFrameObserver : public media::VideoCaptureDevice::EventHandler { 45 public: 46 virtual scoped_refptr<media::VideoFrame> ReserveOutputBuffer() OVERRIDE { 47 return NULL; 48 } 49 virtual void OnError() OVERRIDE {} 50 virtual void OnFrameInfo( 51 const media::VideoCaptureCapability& info) OVERRIDE {} 52 virtual void OnIncomingCapturedFrame(const uint8* data, 53 int length, 54 base::Time timestamp, 55 int rotation, 56 bool flip_vert, 57 bool flip_horiz) OVERRIDE {} 58 virtual void OnIncomingCapturedVideoFrame( 59 const scoped_refptr<media::VideoFrame>& frame, 60 base::Time timestamp) OVERRIDE {} 61 }; 62 63 // Test class 64 class VideoCaptureManagerTest : public testing::Test { 65 public: 66 VideoCaptureManagerTest() {} 67 virtual ~VideoCaptureManagerTest() {} 68 69 protected: 70 virtual void SetUp() OVERRIDE { 71 listener_.reset(new MockMediaStreamProviderListener()); 72 message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO)); 73 io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO, 74 message_loop_.get())); 75 vcm_ = new VideoCaptureManager(); 76 vcm_->UseFakeDevice(); 77 vcm_->Register(listener_.get(), message_loop_->message_loop_proxy().get()); 78 frame_observer_.reset(new MockFrameObserver()); 79 } 80 81 virtual void TearDown() OVERRIDE {} 82 83 scoped_refptr<VideoCaptureManager> vcm_; 84 scoped_ptr<MockMediaStreamProviderListener> listener_; 85 scoped_ptr<base::MessageLoop> message_loop_; 86 scoped_ptr<BrowserThreadImpl> io_thread_; 87 scoped_ptr<MockFrameObserver> frame_observer_; 88 89 private: 90 DISALLOW_COPY_AND_ASSIGN(VideoCaptureManagerTest); 91 }; 92 93 // Test cases 94 95 // Try to open, start, stop and close a device. 96 TEST_F(VideoCaptureManagerTest, CreateAndClose) { 97 StreamDeviceInfoArray devices; 98 99 InSequence s; 100 EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _)) 101 .Times(1).WillOnce(SaveArg<1>(&devices)); 102 EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1); 103 EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1); 104 105 vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE); 106 107 // Wait to get device callback. 108 message_loop_->RunUntilIdle(); 109 110 int video_session_id = vcm_->Open(devices.front()); 111 112 media::VideoCaptureParams capture_params; 113 capture_params.session_id = video_session_id; 114 capture_params.width = 320; 115 capture_params.height = 240; 116 capture_params.frame_per_second = 30; 117 vcm_->Start(capture_params, frame_observer_.get()); 118 119 vcm_->Stop(video_session_id, base::Closure()); 120 vcm_->Close(video_session_id); 121 122 // Wait to check callbacks before removing the listener. 123 message_loop_->RunUntilIdle(); 124 vcm_->Unregister(); 125 } 126 127 // Open the same device twice. 128 TEST_F(VideoCaptureManagerTest, OpenTwice) { 129 StreamDeviceInfoArray devices; 130 131 InSequence s; 132 EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _)) 133 .Times(1).WillOnce(SaveArg<1>(&devices)); 134 EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(2); 135 EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(2); 136 137 vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE); 138 139 // Wait to get device callback. 140 message_loop_->RunUntilIdle(); 141 142 int video_session_id_first = vcm_->Open(devices.front()); 143 144 // This should trigger an error callback with error code 145 // 'kDeviceAlreadyInUse'. 146 int video_session_id_second = vcm_->Open(devices.front()); 147 EXPECT_NE(video_session_id_first, video_session_id_second); 148 149 vcm_->Close(video_session_id_first); 150 vcm_->Close(video_session_id_second); 151 152 // Wait to check callbacks before removing the listener. 153 message_loop_->RunUntilIdle(); 154 vcm_->Unregister(); 155 } 156 157 // Open two different devices. 158 TEST_F(VideoCaptureManagerTest, OpenTwo) { 159 StreamDeviceInfoArray devices; 160 161 InSequence s; 162 EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _)) 163 .Times(1).WillOnce(SaveArg<1>(&devices)); 164 EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(2); 165 EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(2); 166 167 vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE); 168 169 // Wait to get device callback. 170 message_loop_->RunUntilIdle(); 171 172 StreamDeviceInfoArray::iterator it = devices.begin(); 173 174 int video_session_id_first = vcm_->Open(*it); 175 ++it; 176 int video_session_id_second = vcm_->Open(*it); 177 178 vcm_->Close(video_session_id_first); 179 vcm_->Close(video_session_id_second); 180 181 // Wait to check callbacks before removing the listener. 182 message_loop_->RunUntilIdle(); 183 vcm_->Unregister(); 184 } 185 186 // Try open a non-existing device. 187 TEST_F(VideoCaptureManagerTest, OpenNotExisting) { 188 StreamDeviceInfoArray devices; 189 190 InSequence s; 191 EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _)) 192 .Times(1).WillOnce(SaveArg<1>(&devices)); 193 EXPECT_CALL(*listener_, Error(MEDIA_DEVICE_VIDEO_CAPTURE, 194 _, kDeviceNotAvailable)) 195 .Times(1); 196 197 vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE); 198 199 // Wait to get device callback. 200 message_loop_->RunUntilIdle(); 201 202 MediaStreamType stream_type = MEDIA_DEVICE_VIDEO_CAPTURE; 203 std::string device_name("device_doesnt_exist"); 204 std::string device_id("id_doesnt_exist"); 205 StreamDeviceInfo dummy_device(stream_type, device_name, device_id, false); 206 207 // This should fail with error code 'kDeviceNotAvailable'. 208 vcm_->Open(dummy_device); 209 210 // Wait to check callbacks before removing the listener. 211 message_loop_->RunUntilIdle(); 212 vcm_->Unregister(); 213 } 214 215 // Start a device using "magic" id, i.e. call Start without calling Open. 216 TEST_F(VideoCaptureManagerTest, StartUsingId) { 217 InSequence s; 218 EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1); 219 EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1); 220 221 media::VideoCaptureParams capture_params; 222 capture_params.session_id = VideoCaptureManager::kStartOpenSessionId; 223 capture_params.width = 320; 224 capture_params.height = 240; 225 capture_params.frame_per_second = 30; 226 227 // Start shall trigger the Open callback. 228 vcm_->Start(capture_params, frame_observer_.get()); 229 230 // Stop shall trigger the Close callback 231 vcm_->Stop(VideoCaptureManager::kStartOpenSessionId, base::Closure()); 232 233 // Wait to check callbacks before removing the listener. 234 message_loop_->RunUntilIdle(); 235 vcm_->Unregister(); 236 } 237 238 // Open and start a device, close it before calling Stop. 239 TEST_F(VideoCaptureManagerTest, CloseWithoutStop) { 240 StreamDeviceInfoArray devices; 241 242 InSequence s; 243 EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _)) 244 .Times(1).WillOnce(SaveArg<1>(&devices)); 245 EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1); 246 EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1); 247 248 vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE); 249 250 // Wait to get device callback. 251 message_loop_->RunUntilIdle(); 252 253 int video_session_id = vcm_->Open(devices.front()); 254 255 media::VideoCaptureParams capture_params; 256 capture_params.session_id = video_session_id; 257 capture_params.width = 320; 258 capture_params.height = 240; 259 capture_params.frame_per_second = 30; 260 vcm_->Start(capture_params, frame_observer_.get()); 261 262 // Close will stop the running device, an assert will be triggered in 263 // VideoCaptureManager destructor otherwise. 264 vcm_->Close(video_session_id); 265 vcm_->Stop(video_session_id, base::Closure()); 266 267 // Wait to check callbacks before removing the listener 268 message_loop_->RunUntilIdle(); 269 vcm_->Unregister(); 270 } 271 272 } // namespace content 273