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.
9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "content/child/child_process.h"
14 #include "content/renderer/media/media_stream_video_source.h"
15 #include "content/renderer/media/media_stream_video_track.h"
16 #include "content/renderer/media/mock_media_constraint_factory.h"
17 #include "content/renderer/media/mock_media_stream_video_sink.h"
18 #include "content/renderer/media/mock_media_stream_video_source.h"
19 #include "media/base/video_frame.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "third_party/WebKit/public/web/WebHeap.h"
24 using ::testing::DoAll;
25 using ::testing::SaveArg;
29 ACTION_P(RunClosure, closure) {
33 class MediaStreamVideoSourceTest
34 : public ::testing::Test {
36 MediaStreamVideoSourceTest()
37 : child_process_(new ChildProcess()),
38 number_of_successful_constraints_applied_(0),
39 number_of_failed_constraints_applied_(0),
40 result_(MEDIA_DEVICE_OK),
42 mock_source_(new MockMediaStreamVideoSource(true)) {
43 media::VideoCaptureFormats formats;
44 formats.push_back(media::VideoCaptureFormat(
45 gfx::Size(1280, 720), 30, media::PIXEL_FORMAT_I420));
46 formats.push_back(media::VideoCaptureFormat(
47 gfx::Size(640, 480), 30, media::PIXEL_FORMAT_I420));
48 formats.push_back(media::VideoCaptureFormat(
49 gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420));
50 formats.push_back(media::VideoCaptureFormat(
51 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420));
52 mock_source_->SetSupportedFormats(formats);
53 webkit_source_.initialize(base::UTF8ToUTF16("dummy_source_id"),
54 blink::WebMediaStreamSource::TypeVideo,
55 base::UTF8ToUTF16("dummy_source_name"));
56 webkit_source_.setExtraData(mock_source_);
59 virtual void TearDown() {
60 webkit_source_.reset();
61 blink::WebHeap::collectAllGarbageForTesting();
65 // Create a track that's associated with |webkit_source_|.
66 blink::WebMediaStreamTrack CreateTrack(
67 const std::string& id,
68 const blink::WebMediaConstraints& constraints) {
70 return MediaStreamVideoTrack::CreateVideoTrack(
71 mock_source_, constraints,
73 &MediaStreamVideoSourceTest::OnConstraintsApplied,
74 base::Unretained(this)),
78 blink::WebMediaStreamTrack CreateTrackAndStartSource(
79 const blink::WebMediaConstraints& constraints,
82 int expected_frame_rate) {
83 blink::WebMediaStreamTrack track = CreateTrack("123", constraints);
85 mock_source_->CompleteGetSupportedFormats();
86 const media::VideoCaptureFormat& format = mock_source()->start_format();
87 EXPECT_EQ(expected_width, format.frame_size.width());
88 EXPECT_EQ(expected_height, format.frame_size.height());
89 EXPECT_EQ(expected_frame_rate, format.frame_rate);
91 EXPECT_EQ(0, NumberOfSuccessConstraintsCallbacks());
92 mock_source_->StartMockedSource();
93 // Once the source has started successfully we expect that the
94 // ConstraintsCallback in MediaStreamSource::AddTrack completes.
95 EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
99 int NumberOfSuccessConstraintsCallbacks() const {
100 return number_of_successful_constraints_applied_;
103 int NumberOfFailedConstraintsCallbacks() const {
104 return number_of_failed_constraints_applied_;
107 content::MediaStreamRequestResult error_type() const { return result_; }
108 blink::WebString error_name() const { return result_name_; }
110 MockMediaStreamVideoSource* mock_source() { return mock_source_; }
112 // Test that the source crops/scales to the requested width and
113 // height even though the camera delivers a larger frame.
114 void TestSourceCropFrame(int capture_width,
116 const blink::WebMediaConstraints& constraints,
118 int expected_height) {
119 // Expect the source to start capture with the supported resolution.
120 blink::WebMediaStreamTrack track =
121 CreateTrackAndStartSource(constraints, capture_width, capture_height,
124 MockMediaStreamVideoSink sink;
125 MediaStreamVideoSink::AddToVideoTrack(
126 &sink, sink.GetDeliverFrameCB(), track);
127 DeliverVideoFrameAndWaitForRenderer(capture_width, capture_height, &sink);
128 EXPECT_EQ(1, sink.number_of_frames());
130 // Expect the delivered frame to be cropped.
131 EXPECT_EQ(expected_height, sink.frame_size().height());
132 EXPECT_EQ(expected_width, sink.frame_size().width());
133 MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
136 void DeliverVideoFrameAndWaitForRenderer(int width, int height,
137 MockMediaStreamVideoSink* sink) {
138 base::RunLoop run_loop;
139 base::Closure quit_closure = run_loop.QuitClosure();
140 EXPECT_CALL(*sink, OnVideoFrame()).WillOnce(
141 RunClosure(quit_closure));
142 scoped_refptr<media::VideoFrame> frame =
143 media::VideoFrame::CreateBlackFrame(gfx::Size(width, height));
144 mock_source()->DeliverVideoFrame(frame);
148 void DeliverVideoFrameAndWaitForTwoRenderers(
151 MockMediaStreamVideoSink* sink1,
152 MockMediaStreamVideoSink* sink2) {
153 base::RunLoop run_loop;
154 base::Closure quit_closure = run_loop.QuitClosure();
155 EXPECT_CALL(*sink1, OnVideoFrame());
156 EXPECT_CALL(*sink2, OnVideoFrame()).WillOnce(
157 RunClosure(quit_closure));
158 scoped_refptr<media::VideoFrame> frame =
159 media::VideoFrame::CreateBlackFrame(gfx::Size(width, height));
160 mock_source()->DeliverVideoFrame(frame);
164 void TestTwoTracksWithDifferentConstraints(
165 const blink::WebMediaConstraints& constraints1,
166 const blink::WebMediaConstraints& constraints2,
170 int expected_height1,
172 int expected_height2) {
173 blink::WebMediaStreamTrack track1 =
174 CreateTrackAndStartSource(constraints1, capture_width, capture_height,
175 MediaStreamVideoSource::kDefaultFrameRate);
177 blink::WebMediaStreamTrack track2 =
178 CreateTrack("dummy", constraints2);
180 MockMediaStreamVideoSink sink1;
181 MediaStreamVideoSink::AddToVideoTrack(&sink1, sink1.GetDeliverFrameCB(),
183 EXPECT_EQ(0, sink1.number_of_frames());
185 MockMediaStreamVideoSink sink2;
186 MediaStreamVideoSink::AddToVideoTrack(&sink2, sink2.GetDeliverFrameCB(),
188 EXPECT_EQ(0, sink2.number_of_frames());
190 DeliverVideoFrameAndWaitForTwoRenderers(capture_width,
195 EXPECT_EQ(1, sink1.number_of_frames());
196 EXPECT_EQ(expected_width1, sink1.frame_size().width());
197 EXPECT_EQ(expected_height1, sink1.frame_size().height());
199 EXPECT_EQ(1, sink2.number_of_frames());
200 EXPECT_EQ(expected_width2, sink2.frame_size().width());
201 EXPECT_EQ(expected_height2, sink2.frame_size().height());
203 MediaStreamVideoSink::RemoveFromVideoTrack(&sink1, track1);
204 MediaStreamVideoSink::RemoveFromVideoTrack(&sink2, track2);
207 void SetSourceSupportedFormats(const media::VideoCaptureFormats& formats) {
208 mock_source_->SetSupportedFormats(formats);
211 void ReleaseTrackAndSourceOnAddTrackCallback(
212 const blink::WebMediaStreamTrack& track_to_release) {
213 track_to_release_ = track_to_release;
217 void OnConstraintsApplied(MediaStreamSource* source,
218 MediaStreamRequestResult result,
219 const blink::WebString& result_name) {
220 ASSERT_EQ(source, webkit_source_.extraData());
222 if (result == MEDIA_DEVICE_OK) {
223 ++number_of_successful_constraints_applied_;
226 result_name_ = result_name;
227 ++number_of_failed_constraints_applied_;
230 if (!track_to_release_.isNull()) {
232 webkit_source_.reset();
233 track_to_release_.reset();
236 base::MessageLoopForUI message_loop_;
237 scoped_ptr<ChildProcess> child_process_;
238 blink::WebMediaStreamTrack track_to_release_;
239 int number_of_successful_constraints_applied_;
240 int number_of_failed_constraints_applied_;
241 content::MediaStreamRequestResult result_;
242 blink::WebString result_name_;
243 blink::WebMediaStreamSource webkit_source_;
244 // |mock_source_| is owned by |webkit_source_|.
245 MockMediaStreamVideoSource* mock_source_;
248 TEST_F(MediaStreamVideoSourceTest, AddTrackAndStartSource) {
249 blink::WebMediaConstraints constraints;
250 constraints.initialize();
251 blink::WebMediaStreamTrack track = CreateTrack("123", constraints);
252 mock_source()->CompleteGetSupportedFormats();
253 mock_source()->StartMockedSource();
254 EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
257 TEST_F(MediaStreamVideoSourceTest, AddTwoTracksBeforeSourceStarts) {
258 blink::WebMediaConstraints constraints;
259 constraints.initialize();
260 blink::WebMediaStreamTrack track1 = CreateTrack("123", constraints);
261 mock_source()->CompleteGetSupportedFormats();
262 blink::WebMediaStreamTrack track2 = CreateTrack("123", constraints);
263 EXPECT_EQ(0, NumberOfSuccessConstraintsCallbacks());
264 mock_source()->StartMockedSource();
265 EXPECT_EQ(2, NumberOfSuccessConstraintsCallbacks());
268 TEST_F(MediaStreamVideoSourceTest, AddTrackAfterSourceStarts) {
269 blink::WebMediaConstraints constraints;
270 constraints.initialize();
271 blink::WebMediaStreamTrack track1 = CreateTrack("123", constraints);
272 mock_source()->CompleteGetSupportedFormats();
273 mock_source()->StartMockedSource();
274 EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
275 blink::WebMediaStreamTrack track2 = CreateTrack("123", constraints);
276 EXPECT_EQ(2, NumberOfSuccessConstraintsCallbacks());
279 TEST_F(MediaStreamVideoSourceTest, AddTrackAndFailToStartSource) {
280 blink::WebMediaConstraints constraints;
281 constraints.initialize();
282 blink::WebMediaStreamTrack track = CreateTrack("123", constraints);
283 mock_source()->CompleteGetSupportedFormats();
284 mock_source()->FailToStartMockedSource();
285 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
288 TEST_F(MediaStreamVideoSourceTest, AddTwoTracksBeforeGetSupportedFormats) {
289 blink::WebMediaConstraints constraints;
290 constraints.initialize();
291 blink::WebMediaStreamTrack track1 = CreateTrack("123", constraints);
292 blink::WebMediaStreamTrack track2 = CreateTrack("123", constraints);
293 mock_source()->CompleteGetSupportedFormats();
294 mock_source()->StartMockedSource();
295 EXPECT_EQ(2, NumberOfSuccessConstraintsCallbacks());
298 // Test that the capture output is CIF if we set max constraints to CIF.
299 // and the capture device support CIF.
300 TEST_F(MediaStreamVideoSourceTest, MandatoryConstraintCif5Fps) {
301 MockMediaConstraintFactory factory;
302 factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 352);
303 factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 288);
304 factory.AddMandatory(MediaStreamVideoSource::kMaxFrameRate, 5);
306 CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), 352, 288, 5);
309 // Test that the capture output is 720P if the camera support it and the
310 // optional constraint is set to 720P.
311 TEST_F(MediaStreamVideoSourceTest, MandatoryMinVgaOptional720P) {
312 MockMediaConstraintFactory factory;
313 factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 640);
314 factory.AddMandatory(MediaStreamVideoSource::kMinHeight, 480);
315 factory.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
316 factory.AddOptional(MediaStreamVideoSource::kMinAspectRatio,
319 CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), 1280, 720, 30);
322 // Test that the capture output have aspect ratio 4:3 if a mandatory constraint
323 // require it even if an optional constraint request a higher resolution
324 // that don't have this aspect ratio.
325 TEST_F(MediaStreamVideoSourceTest, MandatoryAspectRatio4To3) {
326 MockMediaConstraintFactory factory;
327 factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 640);
328 factory.AddMandatory(MediaStreamVideoSource::kMinHeight, 480);
329 factory.AddMandatory(MediaStreamVideoSource::kMaxAspectRatio,
331 factory.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
333 TestSourceCropFrame(1280, 720,
334 factory.CreateWebMediaConstraints(), 960, 720);
337 // Test that AddTrack succeeds if the mandatory min aspect ratio it set to 2.
338 TEST_F(MediaStreamVideoSourceTest, MandatoryAspectRatio2) {
339 MockMediaConstraintFactory factory;
340 factory.AddMandatory(MediaStreamVideoSource::kMinAspectRatio, 2);
342 TestSourceCropFrame(MediaStreamVideoSource::kDefaultWidth,
343 MediaStreamVideoSource::kDefaultHeight,
344 factory.CreateWebMediaConstraints(), 640, 320);
347 TEST_F(MediaStreamVideoSourceTest, MinAspectRatioLargerThanMaxAspectRatio) {
348 MockMediaConstraintFactory factory;
349 factory.AddMandatory(MediaStreamVideoSource::kMinAspectRatio, 2);
350 factory.AddMandatory(MediaStreamVideoSource::kMaxAspectRatio, 1);
351 blink::WebMediaStreamTrack track = CreateTrack(
352 "123", factory.CreateWebMediaConstraints());
353 mock_source()->CompleteGetSupportedFormats();
354 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
357 TEST_F(MediaStreamVideoSourceTest, MaxAspectRatioZero) {
358 MockMediaConstraintFactory factory;
359 factory.AddOptional(MediaStreamVideoSource::kMaxAspectRatio, 0);
360 blink::WebMediaStreamTrack track = CreateTrack(
361 "123", factory.CreateWebMediaConstraints());
362 mock_source()->CompleteGetSupportedFormats();
363 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
366 TEST_F(MediaStreamVideoSourceTest, MinWidthLargerThanMaxWidth) {
367 MockMediaConstraintFactory factory;
368 factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 640);
369 factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 320);
370 blink::WebMediaStreamTrack track = CreateTrack(
371 "123", factory.CreateWebMediaConstraints());
372 mock_source()->CompleteGetSupportedFormats();
373 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
376 TEST_F(MediaStreamVideoSourceTest, MinHeightLargerThanMaxHeight) {
377 MockMediaConstraintFactory factory;
378 factory.AddMandatory(MediaStreamVideoSource::kMinHeight, 480);
379 factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 360);
380 blink::WebMediaStreamTrack track = CreateTrack(
381 "123", factory.CreateWebMediaConstraints());
382 mock_source()->CompleteGetSupportedFormats();
383 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
386 TEST_F(MediaStreamVideoSourceTest, MinFrameRateLargerThanMaxFrameRate) {
387 MockMediaConstraintFactory factory;
388 factory.AddMandatory(MediaStreamVideoSource::kMinFrameRate, 25);
389 factory.AddMandatory(MediaStreamVideoSource::kMaxFrameRate, 15);
390 blink::WebMediaStreamTrack track = CreateTrack(
391 "123", factory.CreateWebMediaConstraints());
392 mock_source()->CompleteGetSupportedFormats();
393 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
396 // Test that its safe to release the last reference of a blink track and the
397 // source during the callback if adding a track succeeds.
398 TEST_F(MediaStreamVideoSourceTest, ReleaseTrackAndSourceOnSuccessCallBack) {
399 MockMediaConstraintFactory factory;
401 blink::WebMediaStreamTrack track =
402 CreateTrack("123", factory.CreateWebMediaConstraints());
403 ReleaseTrackAndSourceOnAddTrackCallback(track);
405 mock_source()->CompleteGetSupportedFormats();
406 mock_source()->StartMockedSource();
407 EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
410 // Test that its safe to release the last reference of a blink track and the
411 // source during the callback if adding a track fails.
412 TEST_F(MediaStreamVideoSourceTest, ReleaseTrackAndSourceOnFailureCallBack) {
413 MockMediaConstraintFactory factory;
414 factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 99999);
416 blink::WebMediaStreamTrack track =
417 CreateTrack("123", factory.CreateWebMediaConstraints());
418 ReleaseTrackAndSourceOnAddTrackCallback(track);
420 mock_source()->CompleteGetSupportedFormats();
421 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
424 // Test that the source ignores an optional aspect ratio that is higher than
426 TEST_F(MediaStreamVideoSourceTest, OptionalAspectRatioTooHigh) {
427 MockMediaConstraintFactory factory;
428 factory.AddOptional(MediaStreamVideoSource::kMinAspectRatio, 2);
429 blink::WebMediaStreamTrack track = CreateTrack(
430 "123", factory.CreateWebMediaConstraints());
431 mock_source()->CompleteGetSupportedFormats();
433 const media::VideoCaptureFormat& format = mock_source()->start_format();
434 double aspect_ratio =
435 static_cast<double>(format.frame_size.width()) /
436 format.frame_size.height();
437 EXPECT_LT(aspect_ratio, 2);
440 // Test that the source starts video with the default resolution if the
441 // that is the only supported.
442 TEST_F(MediaStreamVideoSourceTest, DefaultCapability) {
443 media::VideoCaptureFormats formats;
444 formats.push_back(media::VideoCaptureFormat(
445 gfx::Size(MediaStreamVideoSource::kDefaultWidth,
446 MediaStreamVideoSource::kDefaultHeight),
447 MediaStreamVideoSource::kDefaultFrameRate,
448 media::PIXEL_FORMAT_I420));
449 mock_source()->SetSupportedFormats(formats);
451 blink::WebMediaConstraints constraints;
452 constraints.initialize();
453 CreateTrackAndStartSource(constraints,
454 MediaStreamVideoSource::kDefaultWidth,
455 MediaStreamVideoSource::kDefaultHeight,
459 TEST_F(MediaStreamVideoSourceTest, InvalidMandatoryConstraint) {
460 MockMediaConstraintFactory factory;
461 factory.AddMandatory("weird key", 640);
462 blink::WebMediaStreamTrack track = CreateTrack(
463 "123", factory.CreateWebMediaConstraints());
464 mock_source()->CompleteGetSupportedFormats();
465 EXPECT_EQ(MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED, error_type());
466 EXPECT_EQ("weird key", error_name());
467 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
470 // Test that the source ignores an unknown optional constraint.
471 TEST_F(MediaStreamVideoSourceTest, InvalidOptionalConstraint) {
472 MockMediaConstraintFactory factory;
473 factory.AddOptional("weird key", 640);
475 CreateTrackAndStartSource(factory.CreateWebMediaConstraints(),
476 MediaStreamVideoSource::kDefaultWidth,
477 MediaStreamVideoSource::kDefaultHeight,
481 // Tests that the source starts video with the max width and height set by
482 // constraints for screencast.
483 TEST_F(MediaStreamVideoSourceTest, ScreencastResolutionWithConstraint) {
484 media::VideoCaptureFormats formats;
485 formats.push_back(media::VideoCaptureFormat(
486 gfx::Size(480, 270), 30, media::PIXEL_FORMAT_I420));
487 mock_source()->SetSupportedFormats(formats);
488 MockMediaConstraintFactory factory;
489 factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 480);
490 factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 270);
492 blink::WebMediaStreamTrack track = CreateTrackAndStartSource(
493 factory.CreateWebMediaConstraints(), 480, 270, 30);
494 EXPECT_EQ(480, mock_source()->max_requested_height());
495 EXPECT_EQ(270, mock_source()->max_requested_width());
498 // Test that optional constraints are applied in order.
499 TEST_F(MediaStreamVideoSourceTest, OptionalConstraints) {
500 MockMediaConstraintFactory factory;
501 // Min width of 2056 pixels can not be fulfilled.
502 factory.AddOptional(MediaStreamVideoSource::kMinWidth, 2056);
503 factory.AddOptional(MediaStreamVideoSource::kMinWidth, 641);
504 // Since min width is set to 641 pixels, max width 640 can not be fulfilled.
505 factory.AddOptional(MediaStreamVideoSource::kMaxWidth, 640);
506 CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), 1280, 720, 30);
509 // Test that the source crops to the requested max width and
510 // height even though the camera delivers a larger frame.
511 TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrameOptional640360) {
512 MockMediaConstraintFactory factory;
513 factory.AddOptional(MediaStreamVideoSource::kMaxWidth, 640);
514 factory.AddOptional(MediaStreamVideoSource::kMaxHeight, 360);
515 TestSourceCropFrame(640, 480, factory.CreateWebMediaConstraints(), 640, 360);
518 TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrameMandatory640360) {
519 MockMediaConstraintFactory factory;
520 factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 640);
521 factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 360);
522 TestSourceCropFrame(640, 480, factory.CreateWebMediaConstraints(), 640, 360);
525 TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrameMandatory732489) {
526 MockMediaConstraintFactory factory;
527 factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 732);
528 factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 489);
529 factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 732);
530 factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 489);
531 TestSourceCropFrame(1280, 720, factory.CreateWebMediaConstraints(), 732, 489);
534 // Test that the source crops to the requested max width and
535 // height even though the requested frame has odd size.
536 TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrame637359) {
537 MockMediaConstraintFactory factory;
538 factory.AddOptional(MediaStreamVideoSource::kMaxWidth, 637);
539 factory.AddOptional(MediaStreamVideoSource::kMaxHeight, 359);
540 TestSourceCropFrame(640, 480, factory.CreateWebMediaConstraints(), 637, 359);
543 TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrame320320) {
544 MockMediaConstraintFactory factory;
545 factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 320);
546 factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 320);
547 factory.AddMandatory(MediaStreamVideoSource::kMinHeight, 320);
548 factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 320);
549 TestSourceCropFrame(640, 480, factory.CreateWebMediaConstraints(), 320, 320);
552 TEST_F(MediaStreamVideoSourceTest, DeliverSmallerSizeWhenTooLargeMax) {
553 MockMediaConstraintFactory factory;
554 factory.AddOptional(MediaStreamVideoSource::kMaxWidth, 1920);
555 factory.AddOptional(MediaStreamVideoSource::kMaxHeight, 1080);
556 factory.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
557 factory.AddOptional(MediaStreamVideoSource::kMinHeight, 720);
558 TestSourceCropFrame(1280, 720, factory.CreateWebMediaConstraints(),
562 TEST_F(MediaStreamVideoSourceTest, TwoTracksWithVGAAndWVGA) {
563 MockMediaConstraintFactory factory1;
564 factory1.AddOptional(MediaStreamVideoSource::kMaxWidth, 640);
565 factory1.AddOptional(MediaStreamVideoSource::kMaxHeight, 480);
567 MockMediaConstraintFactory factory2;
568 factory2.AddOptional(MediaStreamVideoSource::kMaxHeight, 360);
570 TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
571 factory2.CreateWebMediaConstraints(),
577 TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndWVGA) {
578 MockMediaConstraintFactory factory1;
579 factory1.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
580 factory1.AddOptional(MediaStreamVideoSource::kMinHeight, 720);
583 MockMediaConstraintFactory factory2;
584 factory2.AddMandatory(MediaStreamVideoSource::kMaxWidth, 640);
585 factory2.AddMandatory(MediaStreamVideoSource::kMaxHeight, 360);
587 TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
588 factory2.CreateWebMediaConstraints(),
594 TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndW700H700) {
595 MockMediaConstraintFactory factory1;
596 factory1.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
597 factory1.AddOptional(MediaStreamVideoSource::kMinHeight, 720);
599 MockMediaConstraintFactory factory2;
600 factory2.AddMandatory(MediaStreamVideoSource::kMaxWidth, 700);
601 factory2.AddMandatory(MediaStreamVideoSource::kMaxHeight, 700);
603 TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
604 factory2.CreateWebMediaConstraints(),
610 TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndMaxAspectRatio4To3) {
611 MockMediaConstraintFactory factory1;
612 factory1.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
613 factory1.AddOptional(MediaStreamVideoSource::kMinHeight, 720);
615 MockMediaConstraintFactory factory2;
616 factory2.AddMandatory(MediaStreamVideoSource::kMaxAspectRatio, 640.0 / 480);
618 TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
619 factory2.CreateWebMediaConstraints(),
625 TEST_F(MediaStreamVideoSourceTest, TwoTracksWithVgaAndMinAspectRatio) {
626 MockMediaConstraintFactory factory1;
627 factory1.AddOptional(MediaStreamVideoSource::kMaxWidth, 640);
628 factory1.AddOptional(MediaStreamVideoSource::kMaxHeight, 480);
630 MockMediaConstraintFactory factory2;
631 factory2.AddMandatory(MediaStreamVideoSource::kMinAspectRatio, 640.0 / 360);
633 TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
634 factory2.CreateWebMediaConstraints(),
640 TEST_F(MediaStreamVideoSourceTest,
641 TwoTracksWithSecondTrackFrameRateHigherThanFirst) {
642 MockMediaConstraintFactory factory1;
643 factory1.AddMandatory(MediaStreamVideoSource::kMinFrameRate, 15);
644 factory1.AddMandatory(MediaStreamVideoSource::kMaxFrameRate, 15);
646 blink::WebMediaStreamTrack track1 =
647 CreateTrackAndStartSource(factory1.CreateWebMediaConstraints(),
648 MediaStreamVideoSource::kDefaultWidth,
649 MediaStreamVideoSource::kDefaultHeight,
652 MockMediaConstraintFactory factory2;
653 factory2.AddMandatory(MediaStreamVideoSource::kMinFrameRate, 30);
654 blink::WebMediaStreamTrack track2 = CreateTrack(
655 "123", factory2.CreateWebMediaConstraints());
656 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
659 // Test that a source can change the frame resolution on the fly and that
660 // tracks sinks get the new frame size unless constraints force the frame to be
662 TEST_F(MediaStreamVideoSourceTest, SourceChangeFrameSize) {
663 MockMediaConstraintFactory factory;
664 factory.AddOptional(MediaStreamVideoSource::kMaxWidth, 800);
665 factory.AddOptional(MediaStreamVideoSource::kMaxHeight, 700);
667 // Expect the source to start capture with the supported resolution.
668 blink::WebMediaStreamTrack track =
669 CreateTrackAndStartSource(factory.CreateWebMediaConstraints(),
672 MockMediaStreamVideoSink sink;
673 MediaStreamVideoSink::AddToVideoTrack(
674 &sink, sink.GetDeliverFrameCB(), track);
675 EXPECT_EQ(0, sink.number_of_frames());
676 DeliverVideoFrameAndWaitForRenderer(320, 240, &sink);
677 EXPECT_EQ(1, sink.number_of_frames());
678 // Expect the delivered frame to be passed unchanged since its smaller than
680 EXPECT_EQ(320, sink.frame_size().width());
681 EXPECT_EQ(240, sink.frame_size().height());
683 DeliverVideoFrameAndWaitForRenderer(640, 480, &sink);
684 EXPECT_EQ(2, sink.number_of_frames());
685 // Expect the delivered frame to be passed unchanged since its smaller than
687 EXPECT_EQ(640, sink.frame_size().width());
688 EXPECT_EQ(480, sink.frame_size().height());
690 DeliverVideoFrameAndWaitForRenderer(1280, 720, &sink);
692 EXPECT_EQ(3, sink.number_of_frames());
693 // Expect a frame to be cropped since its larger than max requested.
694 EXPECT_EQ(800, sink.frame_size().width());
695 EXPECT_EQ(700, sink.frame_size().height());
697 MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
700 TEST_F(MediaStreamVideoSourceTest, IsConstraintSupported) {
701 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
702 MediaStreamVideoSource::kMaxFrameRate));
703 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
704 MediaStreamVideoSource::kMinFrameRate));
705 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
706 MediaStreamVideoSource::kMaxWidth));
707 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
708 MediaStreamVideoSource::kMinWidth));
709 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
710 MediaStreamVideoSource::kMaxHeight));
711 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
712 MediaStreamVideoSource::kMinHeight));
713 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
714 MediaStreamVideoSource::kMaxAspectRatio));
715 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
716 MediaStreamVideoSource::kMinAspectRatio));
718 EXPECT_FALSE(MediaStreamVideoSource::IsConstraintSupported(
719 "something unsupported"));
722 // Test that the constraint negotiation can handle 0.0 fps as frame rate.
723 TEST_F(MediaStreamVideoSourceTest, Use0FpsSupportedFormat) {
724 media::VideoCaptureFormats formats;
725 formats.push_back(media::VideoCaptureFormat(
726 gfx::Size(640, 480), 0.0f, media::PIXEL_FORMAT_I420));
727 formats.push_back(media::VideoCaptureFormat(
728 gfx::Size(320, 240), 0.0f, media::PIXEL_FORMAT_I420));
729 mock_source()->SetSupportedFormats(formats);
731 blink::WebMediaConstraints constraints;
732 constraints.initialize();
733 blink::WebMediaStreamTrack track = CreateTrack("123", constraints);
734 mock_source()->CompleteGetSupportedFormats();
735 mock_source()->StartMockedSource();
736 EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
738 MockMediaStreamVideoSink sink;
739 MediaStreamVideoSink::AddToVideoTrack(
740 &sink, sink.GetDeliverFrameCB(), track);
741 EXPECT_EQ(0, sink.number_of_frames());
742 DeliverVideoFrameAndWaitForRenderer(320, 240, &sink);
743 EXPECT_EQ(1, sink.number_of_frames());
744 // Expect the delivered frame to be passed unchanged since its smaller than
746 EXPECT_EQ(320, sink.frame_size().width());
747 EXPECT_EQ(240, sink.frame_size().height());
748 MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
751 // Test that a source producing no frames change the source readyState to muted.
752 // that in a reasonable time frame the muted state turns to false.
753 TEST_F(MediaStreamVideoSourceTest, MutedSource) {
754 // Setup the source for support a frame rate of 2000fps in order to test
755 // the muted event faster. This is since the frame monitoring uses
756 // PostDelayedTask that is dependent on the source frame rate.
757 media::VideoCaptureFormats formats;
758 formats.push_back(media::VideoCaptureFormat(
759 gfx::Size(640, 480), 2000, media::PIXEL_FORMAT_I420));
760 SetSourceSupportedFormats(formats);
762 MockMediaConstraintFactory factory;
763 blink::WebMediaStreamTrack track =
764 CreateTrackAndStartSource(factory.CreateWebMediaConstraints(),
766 MockMediaStreamVideoSink sink;
767 MediaStreamVideoSink::AddToVideoTrack(&sink, sink.GetDeliverFrameCB(), track);
768 EXPECT_EQ(track.source().readyState(),
769 blink::WebMediaStreamSource::ReadyStateLive);
771 base::RunLoop run_loop;
772 base::Closure quit_closure = run_loop.QuitClosure();
773 bool muted_state = false;
774 EXPECT_CALL(*mock_source(), DoSetMutedState(_))
775 .WillOnce(DoAll(SaveArg<0>(&muted_state), RunClosure(quit_closure)));
777 EXPECT_EQ(muted_state, true);
779 EXPECT_EQ(track.source().readyState(),
780 blink::WebMediaStreamSource::ReadyStateMuted);
782 base::RunLoop run_loop2;
783 base::Closure quit_closure2 = run_loop2.QuitClosure();
784 EXPECT_CALL(*mock_source(), DoSetMutedState(_))
785 .WillOnce(DoAll(SaveArg<0>(&muted_state), RunClosure(quit_closure2)));
786 DeliverVideoFrameAndWaitForRenderer(640, 480, &sink);
789 EXPECT_EQ(muted_state, false);
790 EXPECT_EQ(track.source().readyState(),
791 blink::WebMediaStreamSource::ReadyStateLive);
793 MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
796 } // namespace content