OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2012 The WebRTC project authors. All Rights Reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include <string> | |
12 #include <vector> | |
13 | |
14 #include "webrtc/api/remotevideocapturer.h" | |
15 #include "webrtc/api/test/fakeconstraints.h" | |
16 #include "webrtc/api/videosource.h" | |
17 #include "webrtc/base/gunit.h" | |
18 #include "webrtc/media/base/fakemediaengine.h" | |
19 #include "webrtc/media/base/fakevideocapturer.h" | |
20 #include "webrtc/media/base/fakevideorenderer.h" | |
21 #include "webrtc/media/engine/webrtcvideoframe.h" | |
22 | |
23 using webrtc::FakeConstraints; | |
24 using webrtc::VideoSource; | |
25 using webrtc::MediaConstraintsInterface; | |
26 using webrtc::MediaSourceInterface; | |
27 using webrtc::ObserverInterface; | |
28 using webrtc::VideoSourceInterface; | |
29 | |
30 namespace { | |
31 | |
32 // Max wait time for a test. | |
33 const int kMaxWaitMs = 100; | |
34 | |
35 } // anonymous namespace | |
36 | |
37 | |
38 // TestVideoCapturer extends cricket::FakeVideoCapturer so it can be used for | |
39 // testing without known camera formats. | |
40 // It keeps its own lists of cricket::VideoFormats for the unit tests in this | |
41 // file. | |
42 class TestVideoCapturer : public cricket::FakeVideoCapturer { | |
43 public: | |
44 TestVideoCapturer(bool is_screencast) | |
45 : FakeVideoCapturer(is_screencast), | |
46 test_without_formats_(false) { | |
47 std::vector<cricket::VideoFormat> formats; | |
48 formats.push_back(cricket::VideoFormat(1280, 720, | |
49 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); | |
50 formats.push_back(cricket::VideoFormat(640, 480, | |
51 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); | |
52 formats.push_back(cricket::VideoFormat(640, 400, | |
53 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); | |
54 formats.push_back(cricket::VideoFormat(320, 240, | |
55 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); | |
56 formats.push_back(cricket::VideoFormat(352, 288, | |
57 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); | |
58 ResetSupportedFormats(formats); | |
59 } | |
60 | |
61 // This function is used for resetting the supported capture formats and | |
62 // simulating a cricket::VideoCapturer implementation that don't support | |
63 // capture format enumeration. This is used to simulate the current | |
64 // Chrome implementation. | |
65 void TestWithoutCameraFormats() { | |
66 test_without_formats_ = true; | |
67 std::vector<cricket::VideoFormat> formats; | |
68 ResetSupportedFormats(formats); | |
69 } | |
70 | |
71 virtual cricket::CaptureState Start( | |
72 const cricket::VideoFormat& capture_format) { | |
73 if (test_without_formats_) { | |
74 std::vector<cricket::VideoFormat> formats; | |
75 formats.push_back(capture_format); | |
76 ResetSupportedFormats(formats); | |
77 } | |
78 return FakeVideoCapturer::Start(capture_format); | |
79 } | |
80 | |
81 virtual bool GetBestCaptureFormat(const cricket::VideoFormat& desired, | |
82 cricket::VideoFormat* best_format) { | |
83 if (test_without_formats_) { | |
84 *best_format = desired; | |
85 return true; | |
86 } | |
87 return FakeVideoCapturer::GetBestCaptureFormat(desired, | |
88 best_format); | |
89 } | |
90 | |
91 private: | |
92 bool test_without_formats_; | |
93 }; | |
94 | |
95 class StateObserver : public ObserverInterface { | |
96 public: | |
97 explicit StateObserver(VideoSourceInterface* source) | |
98 : state_(source->state()), | |
99 source_(source) { | |
100 } | |
101 virtual void OnChanged() { | |
102 state_ = source_->state(); | |
103 } | |
104 MediaSourceInterface::SourceState state() const { return state_; } | |
105 | |
106 private: | |
107 MediaSourceInterface::SourceState state_; | |
108 rtc::scoped_refptr<VideoSourceInterface> source_; | |
109 }; | |
110 | |
111 class VideoSourceTest : public testing::Test { | |
112 protected: | |
113 VideoSourceTest() { | |
114 InitCapturer(false); | |
115 } | |
116 void InitCapturer(bool is_screencast) { | |
117 capturer_cleanup_ = rtc::scoped_ptr<TestVideoCapturer>( | |
118 new TestVideoCapturer(is_screencast)); | |
119 capturer_ = capturer_cleanup_.get(); | |
120 } | |
121 | |
122 void InitScreencast() { InitCapturer(true); } | |
123 | |
124 void CreateVideoSource() { | |
125 CreateVideoSource(NULL); | |
126 } | |
127 | |
128 void CreateVideoSource( | |
129 const webrtc::MediaConstraintsInterface* constraints) { | |
130 // VideoSource take ownership of |capturer_| | |
131 source_ = | |
132 VideoSource::Create(rtc::Thread::Current(), capturer_cleanup_.release(), | |
133 constraints, false); | |
134 | |
135 ASSERT_TRUE(source_.get() != NULL); | |
136 EXPECT_EQ(capturer_, source_->GetVideoCapturer()); | |
137 | |
138 state_observer_.reset(new StateObserver(source_)); | |
139 source_->RegisterObserver(state_observer_.get()); | |
140 source_->AddOrUpdateSink(&renderer_, rtc::VideoSinkWants()); | |
141 } | |
142 | |
143 rtc::scoped_ptr<TestVideoCapturer> capturer_cleanup_; | |
144 TestVideoCapturer* capturer_; | |
145 cricket::FakeVideoRenderer renderer_; | |
146 rtc::scoped_ptr<StateObserver> state_observer_; | |
147 rtc::scoped_refptr<VideoSource> source_; | |
148 }; | |
149 | |
150 | |
151 // Test that a VideoSource transition to kLive state when the capture | |
152 // device have started and kEnded if it is stopped. | |
153 // It also test that an output can receive video frames. | |
154 TEST_F(VideoSourceTest, CapturerStartStop) { | |
155 // Initialize without constraints. | |
156 CreateVideoSource(); | |
157 EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(), | |
158 kMaxWaitMs); | |
159 | |
160 ASSERT_TRUE(capturer_->CaptureFrame()); | |
161 EXPECT_EQ(1, renderer_.num_rendered_frames()); | |
162 | |
163 capturer_->Stop(); | |
164 EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(), | |
165 kMaxWaitMs); | |
166 } | |
167 | |
168 // Test that a VideoSource can be stopped and restarted. | |
169 TEST_F(VideoSourceTest, StopRestart) { | |
170 // Initialize without constraints. | |
171 CreateVideoSource(); | |
172 EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(), | |
173 kMaxWaitMs); | |
174 | |
175 ASSERT_TRUE(capturer_->CaptureFrame()); | |
176 EXPECT_EQ(1, renderer_.num_rendered_frames()); | |
177 | |
178 source_->Stop(); | |
179 EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(), | |
180 kMaxWaitMs); | |
181 | |
182 source_->Restart(); | |
183 EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(), | |
184 kMaxWaitMs); | |
185 | |
186 ASSERT_TRUE(capturer_->CaptureFrame()); | |
187 EXPECT_EQ(2, renderer_.num_rendered_frames()); | |
188 | |
189 source_->Stop(); | |
190 } | |
191 | |
192 // Test start stop with a remote VideoSource - the video source that has a | |
193 // RemoteVideoCapturer and takes video frames from FrameInput. | |
194 TEST_F(VideoSourceTest, StartStopRemote) { | |
195 source_ = VideoSource::Create(rtc::Thread::Current(), | |
196 new webrtc::RemoteVideoCapturer(), NULL, true); | |
197 | |
198 ASSERT_TRUE(source_.get() != NULL); | |
199 EXPECT_TRUE(NULL != source_->GetVideoCapturer()); | |
200 | |
201 state_observer_.reset(new StateObserver(source_)); | |
202 source_->RegisterObserver(state_observer_.get()); | |
203 source_->AddOrUpdateSink(&renderer_, rtc::VideoSinkWants()); | |
204 | |
205 EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(), | |
206 kMaxWaitMs); | |
207 | |
208 source_->GetVideoCapturer()->Stop(); | |
209 EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(), | |
210 kMaxWaitMs); | |
211 } | |
212 | |
213 // Test that a VideoSource transition to kEnded if the capture device | |
214 // fails. | |
215 TEST_F(VideoSourceTest, CameraFailed) { | |
216 CreateVideoSource(); | |
217 EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(), | |
218 kMaxWaitMs); | |
219 | |
220 capturer_->SignalStateChange(capturer_, cricket::CS_FAILED); | |
221 EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(), | |
222 kMaxWaitMs); | |
223 } | |
224 | |
225 // Test that the capture output is CIF if we set max constraints to CIF. | |
226 // and the capture device support CIF. | |
227 TEST_F(VideoSourceTest, MandatoryConstraintCif5Fps) { | |
228 FakeConstraints constraints; | |
229 constraints.AddMandatory(MediaConstraintsInterface::kMaxWidth, 352); | |
230 constraints.AddMandatory(MediaConstraintsInterface::kMaxHeight, 288); | |
231 constraints.AddMandatory(MediaConstraintsInterface::kMaxFrameRate, 5); | |
232 | |
233 CreateVideoSource(&constraints); | |
234 EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(), | |
235 kMaxWaitMs); | |
236 const cricket::VideoFormat* format = capturer_->GetCaptureFormat(); | |
237 ASSERT_TRUE(format != NULL); | |
238 EXPECT_EQ(352, format->width); | |
239 EXPECT_EQ(288, format->height); | |
240 EXPECT_EQ(30, format->framerate()); | |
241 } | |
242 | |
243 // Test that the capture output is 720P if the camera support it and the | |
244 // optional constraint is set to 720P. | |
245 TEST_F(VideoSourceTest, MandatoryMinVgaOptional720P) { | |
246 FakeConstraints constraints; | |
247 constraints.AddMandatory(MediaConstraintsInterface::kMinWidth, 640); | |
248 constraints.AddMandatory(MediaConstraintsInterface::kMinHeight, 480); | |
249 constraints.AddOptional(MediaConstraintsInterface::kMinWidth, 1280); | |
250 constraints.AddOptional(MediaConstraintsInterface::kMinAspectRatio, | |
251 1280.0 / 720); | |
252 | |
253 CreateVideoSource(&constraints); | |
254 EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(), | |
255 kMaxWaitMs); | |
256 const cricket::VideoFormat* format = capturer_->GetCaptureFormat(); | |
257 ASSERT_TRUE(format != NULL); | |
258 EXPECT_EQ(1280, format->width); | |
259 EXPECT_EQ(720, format->height); | |
260 EXPECT_EQ(30, format->framerate()); | |
261 } | |
262 | |
263 // Test that the capture output have aspect ratio 4:3 if a mandatory constraint | |
264 // require it even if an optional constraint request a higher resolution | |
265 // that don't have this aspect ratio. | |
266 TEST_F(VideoSourceTest, MandatoryAspectRatio4To3) { | |
267 FakeConstraints constraints; | |
268 constraints.AddMandatory(MediaConstraintsInterface::kMinWidth, 640); | |
269 constraints.AddMandatory(MediaConstraintsInterface::kMinHeight, 480); | |
270 constraints.AddMandatory(MediaConstraintsInterface::kMaxAspectRatio, | |
271 640.0 / 480); | |
272 constraints.AddOptional(MediaConstraintsInterface::kMinWidth, 1280); | |
273 | |
274 CreateVideoSource(&constraints); | |
275 EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(), | |
276 kMaxWaitMs); | |
277 const cricket::VideoFormat* format = capturer_->GetCaptureFormat(); | |
278 ASSERT_TRUE(format != NULL); | |
279 EXPECT_EQ(640, format->width); | |
280 EXPECT_EQ(480, format->height); | |
281 EXPECT_EQ(30, format->framerate()); | |
282 } | |
283 | |
284 | |
285 // Test that the source state transition to kEnded if the mandatory aspect ratio | |
286 // is set higher than supported. | |
287 TEST_F(VideoSourceTest, MandatoryAspectRatioTooHigh) { | |
288 FakeConstraints constraints; | |
289 constraints.AddMandatory(MediaConstraintsInterface::kMinAspectRatio, 2); | |
290 CreateVideoSource(&constraints); | |
291 EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(), | |
292 kMaxWaitMs); | |
293 } | |
294 | |
295 // Test that the source ignores an optional aspect ratio that is higher than | |
296 // supported. | |
297 TEST_F(VideoSourceTest, OptionalAspectRatioTooHigh) { | |
298 FakeConstraints constraints; | |
299 constraints.AddOptional(MediaConstraintsInterface::kMinAspectRatio, 2); | |
300 CreateVideoSource(&constraints); | |
301 EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(), | |
302 kMaxWaitMs); | |
303 const cricket::VideoFormat* format = capturer_->GetCaptureFormat(); | |
304 ASSERT_TRUE(format != NULL); | |
305 double aspect_ratio = static_cast<double>(format->width) / format->height; | |
306 EXPECT_LT(aspect_ratio, 2); | |
307 } | |
308 | |
309 // Test that the source starts video with the default resolution if the | |
310 // camera doesn't support capability enumeration and there are no constraints. | |
311 TEST_F(VideoSourceTest, NoCameraCapability) { | |
312 capturer_->TestWithoutCameraFormats(); | |
313 | |
314 CreateVideoSource(); | |
315 EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(), | |
316 kMaxWaitMs); | |
317 const cricket::VideoFormat* format = capturer_->GetCaptureFormat(); | |
318 ASSERT_TRUE(format != NULL); | |
319 EXPECT_EQ(640, format->width); | |
320 EXPECT_EQ(480, format->height); | |
321 EXPECT_EQ(30, format->framerate()); | |
322 } | |
323 | |
324 // Test that the source can start the video and get the requested aspect ratio | |
325 // if the camera doesn't support capability enumeration and the aspect ratio is | |
326 // set. | |
327 TEST_F(VideoSourceTest, NoCameraCapability16To9Ratio) { | |
328 capturer_->TestWithoutCameraFormats(); | |
329 | |
330 FakeConstraints constraints; | |
331 double requested_aspect_ratio = 640.0 / 360; | |
332 constraints.AddMandatory(MediaConstraintsInterface::kMinWidth, 640); | |
333 constraints.AddMandatory(MediaConstraintsInterface::kMinAspectRatio, | |
334 requested_aspect_ratio); | |
335 | |
336 CreateVideoSource(&constraints); | |
337 EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(), | |
338 kMaxWaitMs); | |
339 const cricket::VideoFormat* format = capturer_->GetCaptureFormat(); | |
340 double aspect_ratio = static_cast<double>(format->width) / format->height; | |
341 EXPECT_LE(requested_aspect_ratio, aspect_ratio); | |
342 } | |
343 | |
344 // Test that the source state transitions to kEnded if an unknown mandatory | |
345 // constraint is found. | |
346 TEST_F(VideoSourceTest, InvalidMandatoryConstraint) { | |
347 FakeConstraints constraints; | |
348 constraints.AddMandatory("weird key", 640); | |
349 | |
350 CreateVideoSource(&constraints); | |
351 EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(), | |
352 kMaxWaitMs); | |
353 } | |
354 | |
355 // Test that the source ignores an unknown optional constraint. | |
356 TEST_F(VideoSourceTest, InvalidOptionalConstraint) { | |
357 FakeConstraints constraints; | |
358 constraints.AddOptional("weird key", 640); | |
359 | |
360 CreateVideoSource(&constraints); | |
361 EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(), | |
362 kMaxWaitMs); | |
363 } | |
364 | |
365 TEST_F(VideoSourceTest, SetValidOptionValues) { | |
366 FakeConstraints constraints; | |
367 constraints.AddMandatory(MediaConstraintsInterface::kNoiseReduction, "false"); | |
368 | |
369 CreateVideoSource(&constraints); | |
370 | |
371 EXPECT_EQ(rtc::Optional<bool>(false), | |
372 source_->options()->video_noise_reduction); | |
373 } | |
374 | |
375 TEST_F(VideoSourceTest, OptionNotSet) { | |
376 FakeConstraints constraints; | |
377 CreateVideoSource(&constraints); | |
378 EXPECT_EQ(rtc::Optional<bool>(), source_->options()->video_noise_reduction); | |
379 } | |
380 | |
381 TEST_F(VideoSourceTest, MandatoryOptionOverridesOptional) { | |
382 FakeConstraints constraints; | |
383 constraints.AddMandatory( | |
384 MediaConstraintsInterface::kNoiseReduction, true); | |
385 constraints.AddOptional( | |
386 MediaConstraintsInterface::kNoiseReduction, false); | |
387 | |
388 CreateVideoSource(&constraints); | |
389 | |
390 EXPECT_EQ(rtc::Optional<bool>(true), | |
391 source_->options()->video_noise_reduction); | |
392 } | |
393 | |
394 TEST_F(VideoSourceTest, InvalidOptionKeyOptional) { | |
395 FakeConstraints constraints; | |
396 constraints.AddOptional( | |
397 MediaConstraintsInterface::kNoiseReduction, false); | |
398 constraints.AddOptional("invalidKey", false); | |
399 | |
400 CreateVideoSource(&constraints); | |
401 | |
402 EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(), | |
403 kMaxWaitMs); | |
404 EXPECT_EQ(rtc::Optional<bool>(false), | |
405 source_->options()->video_noise_reduction); | |
406 } | |
407 | |
408 TEST_F(VideoSourceTest, InvalidOptionKeyMandatory) { | |
409 FakeConstraints constraints; | |
410 constraints.AddMandatory( | |
411 MediaConstraintsInterface::kNoiseReduction, false); | |
412 constraints.AddMandatory("invalidKey", false); | |
413 | |
414 CreateVideoSource(&constraints); | |
415 | |
416 EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(), | |
417 kMaxWaitMs); | |
418 EXPECT_EQ(rtc::Optional<bool>(), source_->options()->video_noise_reduction); | |
419 } | |
420 | |
421 TEST_F(VideoSourceTest, InvalidOptionValueOptional) { | |
422 FakeConstraints constraints; | |
423 constraints.AddOptional( | |
424 MediaConstraintsInterface::kNoiseReduction, "not a boolean"); | |
425 | |
426 CreateVideoSource(&constraints); | |
427 | |
428 EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(), | |
429 kMaxWaitMs); | |
430 EXPECT_EQ(rtc::Optional<bool>(), source_->options()->video_noise_reduction); | |
431 } | |
432 | |
433 TEST_F(VideoSourceTest, InvalidOptionValueMandatory) { | |
434 FakeConstraints constraints; | |
435 // Optional constraints should be ignored if the mandatory constraints fail. | |
436 constraints.AddOptional( | |
437 MediaConstraintsInterface::kNoiseReduction, "false"); | |
438 // Values are case-sensitive and must be all lower-case. | |
439 constraints.AddMandatory( | |
440 MediaConstraintsInterface::kNoiseReduction, "True"); | |
441 | |
442 CreateVideoSource(&constraints); | |
443 | |
444 EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(), | |
445 kMaxWaitMs); | |
446 EXPECT_EQ(rtc::Optional<bool>(), source_->options()->video_noise_reduction); | |
447 } | |
448 | |
449 TEST_F(VideoSourceTest, MixedOptionsAndConstraints) { | |
450 FakeConstraints constraints; | |
451 constraints.AddMandatory(MediaConstraintsInterface::kMaxWidth, 352); | |
452 constraints.AddMandatory(MediaConstraintsInterface::kMaxHeight, 288); | |
453 constraints.AddOptional(MediaConstraintsInterface::kMaxFrameRate, 5); | |
454 | |
455 constraints.AddMandatory( | |
456 MediaConstraintsInterface::kNoiseReduction, false); | |
457 constraints.AddOptional( | |
458 MediaConstraintsInterface::kNoiseReduction, true); | |
459 | |
460 CreateVideoSource(&constraints); | |
461 EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(), | |
462 kMaxWaitMs); | |
463 const cricket::VideoFormat* format = capturer_->GetCaptureFormat(); | |
464 ASSERT_TRUE(format != NULL); | |
465 EXPECT_EQ(352, format->width); | |
466 EXPECT_EQ(288, format->height); | |
467 EXPECT_EQ(30, format->framerate()); | |
468 | |
469 EXPECT_EQ(rtc::Optional<bool>(false), | |
470 source_->options()->video_noise_reduction); | |
471 } | |
472 | |
473 // Tests that the source starts video with the default resolution for | |
474 // screencast if no constraint is set. | |
475 TEST_F(VideoSourceTest, ScreencastResolutionNoConstraint) { | |
476 InitScreencast(); | |
477 capturer_->TestWithoutCameraFormats(); | |
478 | |
479 CreateVideoSource(); | |
480 EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(), | |
481 kMaxWaitMs); | |
482 const cricket::VideoFormat* format = capturer_->GetCaptureFormat(); | |
483 ASSERT_TRUE(format != NULL); | |
484 EXPECT_EQ(640, format->width); | |
485 EXPECT_EQ(480, format->height); | |
486 EXPECT_EQ(30, format->framerate()); | |
487 } | |
488 | |
489 // Tests that the source starts video with the max width and height set by | |
490 // constraints for screencast. | |
491 TEST_F(VideoSourceTest, ScreencastResolutionWithConstraint) { | |
492 FakeConstraints constraints; | |
493 constraints.AddMandatory(MediaConstraintsInterface::kMaxWidth, 480); | |
494 constraints.AddMandatory(MediaConstraintsInterface::kMaxHeight, 270); | |
495 | |
496 InitScreencast(); | |
497 capturer_->TestWithoutCameraFormats(); | |
498 | |
499 CreateVideoSource(&constraints); | |
500 EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(), | |
501 kMaxWaitMs); | |
502 const cricket::VideoFormat* format = capturer_->GetCaptureFormat(); | |
503 ASSERT_TRUE(format != NULL); | |
504 EXPECT_EQ(480, format->width); | |
505 EXPECT_EQ(270, format->height); | |
506 EXPECT_EQ(30, format->framerate()); | |
507 } | |
508 | |
509 TEST_F(VideoSourceTest, MandatorySubOneFpsConstraints) { | |
510 FakeConstraints constraints; | |
511 constraints.AddMandatory(MediaConstraintsInterface::kMaxFrameRate, 0.5); | |
512 | |
513 CreateVideoSource(&constraints); | |
514 EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(), | |
515 kMaxWaitMs); | |
516 ASSERT_TRUE(capturer_->GetCaptureFormat() == NULL); | |
517 } | |
518 | |
519 TEST_F(VideoSourceTest, OptionalSubOneFpsConstraints) { | |
520 FakeConstraints constraints; | |
521 constraints.AddOptional(MediaConstraintsInterface::kMaxFrameRate, 0.5); | |
522 | |
523 CreateVideoSource(&constraints); | |
524 EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(), | |
525 kMaxWaitMs); | |
526 const cricket::VideoFormat* format = capturer_->GetCaptureFormat(); | |
527 ASSERT_TRUE(format != NULL); | |
528 EXPECT_EQ(30, format->framerate()); | |
529 } | |
OLD | NEW |