Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(74)

Side by Side Diff: content/renderer/media/video_capture_impl_manager_unittest.cc

Issue 2365223002: Video Capture: Allow suspension of individual devices. (Closed)
Patch Set: Style tweaks, per mcasas's comments. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <array>
6
5 #include "base/bind.h" 7 #include "base/bind.h"
6 #include "base/callback.h" 8 #include "base/callback.h"
7 #include "base/macros.h" 9 #include "base/macros.h"
10 #include "base/memory/ptr_util.h"
8 #include "base/memory/ref_counted.h" 11 #include "base/memory/ref_counted.h"
9 #include "base/message_loop/message_loop.h" 12 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h" 13 #include "base/run_loop.h"
11 #include "content/child/child_process.h" 14 #include "content/child/child_process.h"
15 #include "content/common/media/video_capture_messages.h"
12 #include "content/renderer/media/video_capture_impl.h" 16 #include "content/renderer/media/video_capture_impl.h"
13 #include "content/renderer/media/video_capture_impl_manager.h" 17 #include "content/renderer/media/video_capture_impl_manager.h"
14 #include "content/renderer/media/video_capture_message_filter.h" 18 #include "content/renderer/media/video_capture_message_filter.h"
15 #include "media/base/bind_to_current_loop.h" 19 #include "media/base/bind_to_current_loop.h"
16 #include "testing/gmock/include/gmock/gmock.h" 20 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h" 21 #include "testing/gtest/include/gtest/gtest.h"
18 22
19 using ::testing::_; 23 using ::testing::_;
20 using ::testing::DoAll; 24 using ::testing::DoAll;
21 using ::testing::SaveArg; 25 using ::testing::SaveArg;
22 using media::BindToCurrentLoop; 26 using media::BindToCurrentLoop;
23 27
24 namespace content { 28 namespace content {
25 29
26 ACTION_P(RunClosure, closure) { 30 ACTION_P(RunClosure, closure) {
27 closure.Run(); 31 closure.Run();
28 } 32 }
29 33
34 namespace {
35
36 // Callback interface to be implemented by
37 // VideoCaptureImplManagerTest. MockVideoCaptureImpl intercepts IPC messages and
38 // calls these methods to simulate what the VideoCaptureHost would do.
39 class PauseResumeCallback {
40 public:
41 PauseResumeCallback() {}
42 virtual ~PauseResumeCallback() {}
43
44 virtual void OnPaused(media::VideoCaptureSessionId session_id) = 0;
45 virtual void OnResumed(media::VideoCaptureSessionId session_id) = 0;
46 };
47
30 class MockVideoCaptureImpl : public VideoCaptureImpl { 48 class MockVideoCaptureImpl : public VideoCaptureImpl {
31 public: 49 public:
32 MockVideoCaptureImpl(media::VideoCaptureSessionId session_id, 50 MockVideoCaptureImpl(media::VideoCaptureSessionId session_id,
33 VideoCaptureMessageFilter* filter, 51 VideoCaptureMessageFilter* filter,
52 PauseResumeCallback* pause_callback,
34 base::Closure destruct_callback) 53 base::Closure destruct_callback)
35 : VideoCaptureImpl(session_id, filter), 54 : VideoCaptureImpl(session_id, filter),
36 destruct_callback_(destruct_callback) { 55 pause_callback_(pause_callback), destruct_callback_(destruct_callback) {
37 } 56 }
38 57
39 ~MockVideoCaptureImpl() override { destruct_callback_.Run(); } 58 ~MockVideoCaptureImpl() override { destruct_callback_.Run(); }
40 59
60 void Send(IPC::Message* message) override {
61 IPC_BEGIN_MESSAGE_MAP(MockVideoCaptureImpl, *message)
62 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Pause, DevicePauseCapture)
63 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Resume, DeviceResumeCapture)
64 default:
65 VideoCaptureImpl::Send(message);
66 return;
67 IPC_END_MESSAGE_MAP()
68 delete message;
69 }
70
41 private: 71 private:
72 void DevicePauseCapture(int device_id) {
73 pause_callback_->OnPaused(session_id());
74 }
75
76 void DeviceResumeCapture(int device_id,
77 media::VideoCaptureSessionId session_id,
78 const media::VideoCaptureParams& params) {
79 pause_callback_->OnResumed(session_id);
80 }
81
82 PauseResumeCallback* const pause_callback_;
42 base::Closure destruct_callback_; 83 base::Closure destruct_callback_;
43 84
44 DISALLOW_COPY_AND_ASSIGN(MockVideoCaptureImpl); 85 DISALLOW_COPY_AND_ASSIGN(MockVideoCaptureImpl);
45 }; 86 };
46 87
47 class MockVideoCaptureImplManager : public VideoCaptureImplManager { 88 class MockVideoCaptureImplManager : public VideoCaptureImplManager {
48 public: 89 public:
49 explicit MockVideoCaptureImplManager( 90 MockVideoCaptureImplManager(PauseResumeCallback* pause_callback,
50 base::Closure destruct_video_capture_callback) 91 base::Closure destruct_video_capture_callback)
51 : destruct_video_capture_callback_( 92 : pause_callback_(pause_callback),
93 destruct_video_capture_callback_(
52 destruct_video_capture_callback) {} 94 destruct_video_capture_callback) {}
53 ~MockVideoCaptureImplManager() override {} 95 ~MockVideoCaptureImplManager() override {}
54 96
55 protected: 97 protected:
56 VideoCaptureImpl* CreateVideoCaptureImplForTesting( 98 std::unique_ptr<VideoCaptureImpl> CreateVideoCaptureImplForTesting(
57 media::VideoCaptureSessionId id, 99 media::VideoCaptureSessionId id,
58 VideoCaptureMessageFilter* filter) const override { 100 VideoCaptureMessageFilter* filter) const override {
59 return new MockVideoCaptureImpl(id, 101 return base::MakeUnique<MockVideoCaptureImpl>(
60 filter, 102 id, filter, pause_callback_, destruct_video_capture_callback_);
61 destruct_video_capture_callback_);
62 } 103 }
63 104
64 private: 105 private:
106 PauseResumeCallback* const pause_callback_;
65 base::Closure destruct_video_capture_callback_; 107 base::Closure destruct_video_capture_callback_;
66 108
67 DISALLOW_COPY_AND_ASSIGN(MockVideoCaptureImplManager); 109 DISALLOW_COPY_AND_ASSIGN(MockVideoCaptureImplManager);
68 }; 110 };
69 111
70 class VideoCaptureImplManagerTest : public ::testing::Test { 112 } // namespace
113
114 class VideoCaptureImplManagerTest
115 : public ::testing::Test, public PauseResumeCallback {
71 public: 116 public:
72 VideoCaptureImplManagerTest() 117 VideoCaptureImplManagerTest()
73 : manager_(new MockVideoCaptureImplManager( 118 : manager_(new MockVideoCaptureImplManager(
74 BindToCurrentLoop(cleanup_run_loop_.QuitClosure()))) { 119 this, BindToCurrentLoop(cleanup_run_loop_.QuitClosure()))) {
75 params_.requested_format = media::VideoCaptureFormat( 120 params_.requested_format = media::VideoCaptureFormat(
76 gfx::Size(176, 144), 30, media::PIXEL_FORMAT_I420); 121 gfx::Size(176, 144), 30, media::PIXEL_FORMAT_I420);
77 child_process_.reset(new ChildProcess()); 122 child_process_.reset(new ChildProcess());
78 } 123 }
79 124
80 void FakeChannelSetup() { 125 void FakeChannelSetup() {
81 scoped_refptr<base::SingleThreadTaskRunner> task_runner = 126 scoped_refptr<base::SingleThreadTaskRunner> task_runner =
82 child_process_->io_task_runner(); 127 child_process_->io_task_runner();
83 if (!task_runner->BelongsToCurrentThread()) { 128 if (!task_runner->BelongsToCurrentThread()) {
84 task_runner->PostTask( 129 task_runner->PostTask(
85 FROM_HERE, base::Bind(&VideoCaptureImplManagerTest::FakeChannelSetup, 130 FROM_HERE, base::Bind(&VideoCaptureImplManagerTest::FakeChannelSetup,
86 base::Unretained(this))); 131 base::Unretained(this)));
87 return; 132 return;
88 } 133 }
89 manager_->video_capture_message_filter()->OnFilterAdded(NULL); 134 manager_->video_capture_message_filter()->OnFilterAdded(NULL);
90 } 135 }
91 136
92 protected: 137 protected:
138 static constexpr size_t kNumClients = 3;
139
140 std::array<base::Closure, kNumClients> StartCaptureForAllClients(
141 bool same_session_id) {
142 base::RunLoop run_loop;
143 base::Closure quit_closure = BindToCurrentLoop(run_loop.QuitClosure());
144 EXPECT_CALL(*this, OnStarted(_)).Times(kNumClients - 1)
145 .RetiresOnSaturation();
146 EXPECT_CALL(*this, OnStarted(_)).WillOnce(RunClosure(quit_closure))
147 .RetiresOnSaturation();
148 std::array<base::Closure, kNumClients> stop_callbacks;
149 for (size_t i = 0; i < kNumClients; ++i)
150 stop_callbacks[i] = StartCapture(
151 same_session_id ? 0 : static_cast<media::VideoCaptureSessionId>(i),
152 params_);
153 FakeChannelSetup();
154 run_loop.Run();
155 return stop_callbacks;
156 }
157
158 void StopCaptureForAllClients(
159 std::array<base::Closure, kNumClients>* stop_callbacks) {
160 base::RunLoop run_loop;
161 base::Closure quit_closure = BindToCurrentLoop(run_loop.QuitClosure());
162 EXPECT_CALL(*this, OnStopped(_)).Times(kNumClients - 1)
163 .RetiresOnSaturation();
164 EXPECT_CALL(*this, OnStopped(_)).WillOnce(RunClosure(quit_closure))
165 .RetiresOnSaturation();
166 for (size_t i = 0; i < kNumClients; ++i)
167 (*stop_callbacks)[i].Run();
168 run_loop.Run();
169 }
170
93 MOCK_METHOD2(OnFrameReady, 171 MOCK_METHOD2(OnFrameReady,
94 void(const scoped_refptr<media::VideoFrame>&, 172 void(const scoped_refptr<media::VideoFrame>&,
95 base::TimeTicks estimated_capture_time)); 173 base::TimeTicks estimated_capture_time));
96 MOCK_METHOD0(OnStarted, void()); 174 MOCK_METHOD1(OnStarted, void(media::VideoCaptureSessionId id));
97 MOCK_METHOD0(OnStopped, void()); 175 MOCK_METHOD1(OnStopped, void(media::VideoCaptureSessionId id));
176 MOCK_METHOD1(OnPaused, void(media::VideoCaptureSessionId id));
177 MOCK_METHOD1(OnResumed, void(media::VideoCaptureSessionId id));
98 178
99 void OnStateUpdate(VideoCaptureState state) { 179 void OnStateUpdate(media::VideoCaptureSessionId id, VideoCaptureState state) {
100 switch (state) { 180 switch (state) {
101 case VIDEO_CAPTURE_STATE_STARTED: 181 case VIDEO_CAPTURE_STATE_STARTED:
102 OnStarted(); 182 OnStarted(id);
103 break; 183 break;
104 case VIDEO_CAPTURE_STATE_STOPPED: 184 case VIDEO_CAPTURE_STATE_STOPPED:
105 OnStopped(); 185 OnStopped(id);
106 break; 186 break;
107 default: 187 default:
108 NOTREACHED(); 188 NOTREACHED();
109 } 189 }
110 } 190 }
111 191
112 base::Closure StartCapture(const media::VideoCaptureParams& params) { 192 base::Closure StartCapture(media::VideoCaptureSessionId id,
193 const media::VideoCaptureParams& params) {
113 return manager_->StartCapture( 194 return manager_->StartCapture(
114 0, params, base::Bind(&VideoCaptureImplManagerTest::OnStateUpdate, 195 id, params, base::Bind(&VideoCaptureImplManagerTest::OnStateUpdate,
115 base::Unretained(this)), 196 base::Unretained(this), id),
116 base::Bind(&VideoCaptureImplManagerTest::OnFrameReady, 197 base::Bind(&VideoCaptureImplManagerTest::OnFrameReady,
117 base::Unretained(this))); 198 base::Unretained(this)));
118 } 199 }
119 200
120 base::MessageLoop message_loop_; 201 base::MessageLoop message_loop_;
121 std::unique_ptr<ChildProcess> child_process_; 202 std::unique_ptr<ChildProcess> child_process_;
122 media::VideoCaptureParams params_; 203 media::VideoCaptureParams params_;
123 base::RunLoop cleanup_run_loop_; 204 base::RunLoop cleanup_run_loop_;
124 std::unique_ptr<MockVideoCaptureImplManager> manager_; 205 std::unique_ptr<MockVideoCaptureImplManager> manager_;
125 206
126 private: 207 private:
127 DISALLOW_COPY_AND_ASSIGN(VideoCaptureImplManagerTest); 208 DISALLOW_COPY_AND_ASSIGN(VideoCaptureImplManagerTest);
128 }; 209 };
129 210
130 // Multiple clients with the same session id. There is only one 211 // Multiple clients with the same session id. There is only one
131 // media::VideoCapture object. 212 // media::VideoCapture object.
132 TEST_F(VideoCaptureImplManagerTest, MultipleClients) { 213 TEST_F(VideoCaptureImplManagerTest, MultipleClients) {
133 base::Closure release_cb1 = manager_->UseDevice(0); 214 std::array<base::Closure, kNumClients> release_callbacks;
134 base::Closure release_cb2 = manager_->UseDevice(0); 215 for (size_t i = 0; i < kNumClients; ++i)
135 base::Closure stop_cb1, stop_cb2; 216 release_callbacks[i] = manager_->UseDevice(0);
136 { 217 std::array<base::Closure, kNumClients> stop_callbacks =
137 base::RunLoop run_loop; 218 StartCaptureForAllClients(true);
138 base::Closure quit_closure = BindToCurrentLoop(run_loop.QuitClosure()); 219 StopCaptureForAllClients(&stop_callbacks);
139 EXPECT_CALL(*this, OnStarted()).WillOnce(RunClosure(quit_closure)); 220 for (size_t i = 0; i < kNumClients; ++i)
140 EXPECT_CALL(*this, OnStarted()).RetiresOnSaturation(); 221 release_callbacks[i].Run();
141 stop_cb1 = StartCapture(params_);
142 stop_cb2 = StartCapture(params_);
143 FakeChannelSetup();
144 run_loop.Run();
145 }
146
147 {
148 base::RunLoop run_loop;
149 base::Closure quit_closure = BindToCurrentLoop(run_loop.QuitClosure());
150 EXPECT_CALL(*this, OnStopped()).WillOnce(RunClosure(quit_closure));
151 EXPECT_CALL(*this, OnStopped()).RetiresOnSaturation();
152 stop_cb1.Run();
153 stop_cb2.Run();
154 run_loop.Run();
155 }
156
157 release_cb1.Run();
158 release_cb2.Run();
159 cleanup_run_loop_.Run(); 222 cleanup_run_loop_.Run();
160 } 223 }
161 224
162 TEST_F(VideoCaptureImplManagerTest, NoLeak) { 225 TEST_F(VideoCaptureImplManagerTest, NoLeak) {
163 manager_->UseDevice(0).Reset(); 226 manager_->UseDevice(0).Reset();
164 manager_.reset(); 227 manager_.reset();
165 cleanup_run_loop_.Run(); 228 cleanup_run_loop_.Run();
166 } 229 }
167 230
231 TEST_F(VideoCaptureImplManagerTest, SuspendAndResumeSessions) {
232 std::array<base::Closure, kNumClients> release_callbacks;
233 for (size_t i = 0; i < kNumClients; ++i) {
234 release_callbacks[i] =
235 manager_->UseDevice(static_cast<media::VideoCaptureSessionId>(i));
236 }
237 std::array<base::Closure, kNumClients> stop_callbacks =
238 StartCaptureForAllClients(false);
239
240 // Call SuspendDevices(true) to suspend all clients, and expect all to be
241 // paused.
242 {
243 base::RunLoop run_loop;
244 base::Closure quit_closure = BindToCurrentLoop(run_loop.QuitClosure());
245 EXPECT_CALL(*this, OnPaused(0)).Times(1).RetiresOnSaturation();
246 EXPECT_CALL(*this, OnPaused(1)).Times(1).RetiresOnSaturation();
247 EXPECT_CALL(*this, OnPaused(2)).WillOnce(RunClosure(quit_closure))
248 .RetiresOnSaturation();
249 manager_->SuspendDevices(true);
250 run_loop.Run();
251 }
252
253 // Call SuspendDevices(false) and expect all to be resumed.
254 {
255 base::RunLoop run_loop;
256 base::Closure quit_closure = BindToCurrentLoop(run_loop.QuitClosure());
257 EXPECT_CALL(*this, OnResumed(0)).Times(1).RetiresOnSaturation();
258 EXPECT_CALL(*this, OnResumed(1)).Times(1).RetiresOnSaturation();
259 EXPECT_CALL(*this, OnResumed(2)).WillOnce(RunClosure(quit_closure))
260 .RetiresOnSaturation();
261 manager_->SuspendDevices(false);
262 run_loop.Run();
263 }
264
265 // Suspend just the first client and expect just the first client to be
266 // paused.
267 {
268 base::RunLoop run_loop;
269 base::Closure quit_closure = BindToCurrentLoop(run_loop.QuitClosure());
270 EXPECT_CALL(*this, OnPaused(0)).WillOnce(RunClosure(quit_closure))
271 .RetiresOnSaturation();
272 manager_->Suspend(0);
273 run_loop.Run();
274 }
275
276 // Now call SuspendDevices(true) again, and expect just the second and third
277 // clients to be paused.
278 {
279 base::RunLoop run_loop;
280 base::Closure quit_closure = BindToCurrentLoop(run_loop.QuitClosure());
281 EXPECT_CALL(*this, OnPaused(1)).Times(1).RetiresOnSaturation();
282 EXPECT_CALL(*this, OnPaused(2)).WillOnce(RunClosure(quit_closure))
283 .RetiresOnSaturation();
284 manager_->SuspendDevices(true);
285 run_loop.Run();
286 }
287
288 // Resume just the first client, but it should not resume because all devices
289 // are supposed to be suspended.
290 {
291 manager_->Resume(0);
292 base::RunLoop().RunUntilIdle();
293 }
294
295 // Now, call SuspendDevices(false) and expect all to be resumed.
296 {
297 base::RunLoop run_loop;
298 base::Closure quit_closure = BindToCurrentLoop(run_loop.QuitClosure());
299 EXPECT_CALL(*this, OnResumed(0)).Times(1).RetiresOnSaturation();
300 EXPECT_CALL(*this, OnResumed(1)).Times(1).RetiresOnSaturation();
301 EXPECT_CALL(*this, OnResumed(2)).WillOnce(RunClosure(quit_closure))
302 .RetiresOnSaturation();
303 manager_->SuspendDevices(false);
304 run_loop.Run();
305 }
306
307 StopCaptureForAllClients(&stop_callbacks);
308 for (size_t i = 0; i < kNumClients; ++i)
309 release_callbacks[i].Run();
310 cleanup_run_loop_.Run();
311 }
312
168 } // namespace content 313 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/media/video_capture_impl_manager.cc ('k') | media/base/video_capturer_source.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698