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"
23 using ::testing::DoAll
;
24 using ::testing::SaveArg
;
28 ACTION_P(RunClosure
, closure
) {
32 class MediaStreamVideoSourceTest
33 : public ::testing::Test
{
35 MediaStreamVideoSourceTest()
36 : child_process_(new ChildProcess()),
37 number_of_successful_constraints_applied_(0),
38 number_of_failed_constraints_applied_(0),
39 result_(MEDIA_DEVICE_OK
),
41 mock_source_(new MockMediaStreamVideoSource(true)) {
42 media::VideoCaptureFormats formats
;
43 formats
.push_back(media::VideoCaptureFormat(
44 gfx::Size(1280, 720), 30, media::PIXEL_FORMAT_I420
));
45 formats
.push_back(media::VideoCaptureFormat(
46 gfx::Size(640, 480), 30, media::PIXEL_FORMAT_I420
));
47 formats
.push_back(media::VideoCaptureFormat(
48 gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420
));
49 formats
.push_back(media::VideoCaptureFormat(
50 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420
));
51 mock_source_
->SetSupportedFormats(formats
);
52 webkit_source_
.initialize(base::UTF8ToUTF16("dummy_source_id"),
53 blink::WebMediaStreamSource::TypeVideo
,
54 base::UTF8ToUTF16("dummy_source_name"));
55 webkit_source_
.setExtraData(mock_source_
);
59 // Create a track that's associated with |webkit_source_|.
60 blink::WebMediaStreamTrack
CreateTrack(
61 const std::string
& id
,
62 const blink::WebMediaConstraints
& constraints
) {
64 return MediaStreamVideoTrack::CreateVideoTrack(
65 mock_source_
, constraints
,
67 &MediaStreamVideoSourceTest::OnConstraintsApplied
,
68 base::Unretained(this)),
72 blink::WebMediaStreamTrack
CreateTrackAndStartSource(
73 const blink::WebMediaConstraints
& constraints
,
76 int expected_frame_rate
) {
77 blink::WebMediaStreamTrack track
= CreateTrack("123", constraints
);
79 mock_source_
->CompleteGetSupportedFormats();
80 const media::VideoCaptureParams
& format
= mock_source()->start_params();
81 EXPECT_EQ(expected_width
, format
.requested_format
.frame_size
.width());
82 EXPECT_EQ(expected_height
, format
.requested_format
.frame_size
.height());
83 EXPECT_EQ(expected_frame_rate
, format
.requested_format
.frame_rate
);
85 EXPECT_EQ(0, NumberOfSuccessConstraintsCallbacks());
86 mock_source_
->StartMockedSource();
87 // Once the source has started successfully we expect that the
88 // ConstraintsCallback in MediaStreamSource::AddTrack completes.
89 EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
93 int NumberOfSuccessConstraintsCallbacks() const {
94 return number_of_successful_constraints_applied_
;
97 int NumberOfFailedConstraintsCallbacks() const {
98 return number_of_failed_constraints_applied_
;
101 content::MediaStreamRequestResult
error_type() const { return result_
; }
102 blink::WebString
error_name() const { return result_name_
; }
104 MockMediaStreamVideoSource
* mock_source() { return mock_source_
; }
106 // Test that the source crops/scales to the requested width and
107 // height even though the camera delivers a larger frame.
108 void TestSourceCropFrame(int capture_width
,
110 const blink::WebMediaConstraints
& constraints
,
112 int expected_height
) {
113 // Expect the source to start capture with the supported resolution.
114 blink::WebMediaStreamTrack track
=
115 CreateTrackAndStartSource(constraints
, capture_width
, capture_height
,
118 MockMediaStreamVideoSink sink
;
119 MediaStreamVideoSink::AddToVideoTrack(
120 &sink
, sink
.GetDeliverFrameCB(), track
);
121 DeliverVideoFrameAndWaitForRenderer(capture_width
, capture_height
, &sink
);
122 EXPECT_EQ(1, sink
.number_of_frames());
124 // Expect the delivered frame to be cropped.
125 EXPECT_EQ(expected_height
, sink
.frame_size().height());
126 EXPECT_EQ(expected_width
, sink
.frame_size().width());
127 MediaStreamVideoSink::RemoveFromVideoTrack(&sink
, track
);
130 void DeliverVideoFrameAndWaitForRenderer(int width
, int height
,
131 MockMediaStreamVideoSink
* sink
) {
132 base::RunLoop run_loop
;
133 base::Closure quit_closure
= run_loop
.QuitClosure();
134 EXPECT_CALL(*sink
, OnVideoFrame()).WillOnce(
135 RunClosure(quit_closure
));
136 scoped_refptr
<media::VideoFrame
> frame
=
137 media::VideoFrame::CreateBlackFrame(gfx::Size(width
, height
));
138 mock_source()->DeliverVideoFrame(frame
);
142 void DeliverVideoFrameAndWaitForTwoRenderers(
145 MockMediaStreamVideoSink
* sink1
,
146 MockMediaStreamVideoSink
* sink2
) {
147 base::RunLoop run_loop
;
148 base::Closure quit_closure
= run_loop
.QuitClosure();
149 EXPECT_CALL(*sink1
, OnVideoFrame());
150 EXPECT_CALL(*sink2
, OnVideoFrame()).WillOnce(
151 RunClosure(quit_closure
));
152 scoped_refptr
<media::VideoFrame
> frame
=
153 media::VideoFrame::CreateBlackFrame(gfx::Size(width
, height
));
154 mock_source()->DeliverVideoFrame(frame
);
158 void TestTwoTracksWithDifferentConstraints(
159 const blink::WebMediaConstraints
& constraints1
,
160 const blink::WebMediaConstraints
& constraints2
,
164 int expected_height1
,
166 int expected_height2
) {
167 blink::WebMediaStreamTrack track1
=
168 CreateTrackAndStartSource(constraints1
, capture_width
, capture_height
,
169 MediaStreamVideoSource::kDefaultFrameRate
);
171 blink::WebMediaStreamTrack track2
=
172 CreateTrack("dummy", constraints2
);
174 MockMediaStreamVideoSink sink1
;
175 MediaStreamVideoSink::AddToVideoTrack(&sink1
, sink1
.GetDeliverFrameCB(),
177 EXPECT_EQ(0, sink1
.number_of_frames());
179 MockMediaStreamVideoSink sink2
;
180 MediaStreamVideoSink::AddToVideoTrack(&sink2
, sink2
.GetDeliverFrameCB(),
182 EXPECT_EQ(0, sink2
.number_of_frames());
184 DeliverVideoFrameAndWaitForTwoRenderers(capture_width
,
189 EXPECT_EQ(1, sink1
.number_of_frames());
190 EXPECT_EQ(expected_width1
, sink1
.frame_size().width());
191 EXPECT_EQ(expected_height1
, sink1
.frame_size().height());
193 EXPECT_EQ(1, sink2
.number_of_frames());
194 EXPECT_EQ(expected_width2
, sink2
.frame_size().width());
195 EXPECT_EQ(expected_height2
, sink2
.frame_size().height());
197 MediaStreamVideoSink::RemoveFromVideoTrack(&sink1
, track1
);
198 MediaStreamVideoSink::RemoveFromVideoTrack(&sink2
, track2
);
201 void ReleaseTrackAndSourceOnAddTrackCallback(
202 const blink::WebMediaStreamTrack
& track_to_release
) {
203 track_to_release_
= track_to_release
;
207 void OnConstraintsApplied(MediaStreamSource
* source
,
208 MediaStreamRequestResult result
,
209 const blink::WebString
& result_name
) {
210 ASSERT_EQ(source
, webkit_source_
.extraData());
212 if (result
== MEDIA_DEVICE_OK
) {
213 ++number_of_successful_constraints_applied_
;
216 result_name_
= result_name
;
217 ++number_of_failed_constraints_applied_
;
220 if (!track_to_release_
.isNull()) {
222 webkit_source_
.reset();
223 track_to_release_
.reset();
226 base::MessageLoopForUI message_loop_
;
227 scoped_ptr
<ChildProcess
> child_process_
;
228 blink::WebMediaStreamTrack track_to_release_
;
229 int number_of_successful_constraints_applied_
;
230 int number_of_failed_constraints_applied_
;
231 content::MediaStreamRequestResult result_
;
232 blink::WebString result_name_
;
233 blink::WebMediaStreamSource webkit_source_
;
234 // |mock_source_| is owned by |webkit_source_|.
235 MockMediaStreamVideoSource
* mock_source_
;
238 TEST_F(MediaStreamVideoSourceTest
, AddTrackAndStartSource
) {
239 blink::WebMediaConstraints constraints
;
240 constraints
.initialize();
241 blink::WebMediaStreamTrack track
= CreateTrack("123", constraints
);
242 mock_source()->CompleteGetSupportedFormats();
243 mock_source()->StartMockedSource();
244 EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
247 TEST_F(MediaStreamVideoSourceTest
, AddTwoTracksBeforeSourceStarts
) {
248 blink::WebMediaConstraints constraints
;
249 constraints
.initialize();
250 blink::WebMediaStreamTrack track1
= CreateTrack("123", constraints
);
251 mock_source()->CompleteGetSupportedFormats();
252 blink::WebMediaStreamTrack track2
= CreateTrack("123", constraints
);
253 EXPECT_EQ(0, NumberOfSuccessConstraintsCallbacks());
254 mock_source()->StartMockedSource();
255 EXPECT_EQ(2, NumberOfSuccessConstraintsCallbacks());
258 TEST_F(MediaStreamVideoSourceTest
, AddTrackAfterSourceStarts
) {
259 blink::WebMediaConstraints constraints
;
260 constraints
.initialize();
261 blink::WebMediaStreamTrack track1
= CreateTrack("123", constraints
);
262 mock_source()->CompleteGetSupportedFormats();
263 mock_source()->StartMockedSource();
264 EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
265 blink::WebMediaStreamTrack track2
= CreateTrack("123", constraints
);
266 EXPECT_EQ(2, NumberOfSuccessConstraintsCallbacks());
269 TEST_F(MediaStreamVideoSourceTest
, AddTrackAndFailToStartSource
) {
270 blink::WebMediaConstraints constraints
;
271 constraints
.initialize();
272 blink::WebMediaStreamTrack track
= CreateTrack("123", constraints
);
273 mock_source()->CompleteGetSupportedFormats();
274 mock_source()->FailToStartMockedSource();
275 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
278 TEST_F(MediaStreamVideoSourceTest
, AddTwoTracksBeforeGetSupportedFormats
) {
279 blink::WebMediaConstraints constraints
;
280 constraints
.initialize();
281 blink::WebMediaStreamTrack track1
= CreateTrack("123", constraints
);
282 blink::WebMediaStreamTrack track2
= CreateTrack("123", constraints
);
283 mock_source()->CompleteGetSupportedFormats();
284 mock_source()->StartMockedSource();
285 EXPECT_EQ(2, NumberOfSuccessConstraintsCallbacks());
288 // Test that the capture output is CIF if we set max constraints to CIF.
289 // and the capture device support CIF.
290 TEST_F(MediaStreamVideoSourceTest
, MandatoryConstraintCif5Fps
) {
291 MockMediaConstraintFactory factory
;
292 factory
.AddMandatory(MediaStreamVideoSource::kMaxWidth
, 352);
293 factory
.AddMandatory(MediaStreamVideoSource::kMaxHeight
, 288);
294 factory
.AddMandatory(MediaStreamVideoSource::kMaxFrameRate
, 5);
296 CreateTrackAndStartSource(factory
.CreateWebMediaConstraints(), 352, 288, 5);
299 // Test that the capture output is 720P if the camera support it and the
300 // optional constraint is set to 720P.
301 TEST_F(MediaStreamVideoSourceTest
, MandatoryMinVgaOptional720P
) {
302 MockMediaConstraintFactory factory
;
303 factory
.AddMandatory(MediaStreamVideoSource::kMinWidth
, 640);
304 factory
.AddMandatory(MediaStreamVideoSource::kMinHeight
, 480);
305 factory
.AddOptional(MediaStreamVideoSource::kMinWidth
, 1280);
306 factory
.AddOptional(MediaStreamVideoSource::kMinAspectRatio
,
309 CreateTrackAndStartSource(factory
.CreateWebMediaConstraints(), 1280, 720, 30);
312 // Test that the capture output have aspect ratio 4:3 if a mandatory constraint
313 // require it even if an optional constraint request a higher resolution
314 // that don't have this aspect ratio.
315 TEST_F(MediaStreamVideoSourceTest
, MandatoryAspectRatio4To3
) {
316 MockMediaConstraintFactory factory
;
317 factory
.AddMandatory(MediaStreamVideoSource::kMinWidth
, 640);
318 factory
.AddMandatory(MediaStreamVideoSource::kMinHeight
, 480);
319 factory
.AddMandatory(MediaStreamVideoSource::kMaxAspectRatio
,
321 factory
.AddOptional(MediaStreamVideoSource::kMinWidth
, 1280);
323 TestSourceCropFrame(1280, 720,
324 factory
.CreateWebMediaConstraints(), 960, 720);
327 // Test that AddTrack succeeds if the mandatory min aspect ratio it set to 2.
328 TEST_F(MediaStreamVideoSourceTest
, MandatoryAspectRatio2
) {
329 MockMediaConstraintFactory factory
;
330 factory
.AddMandatory(MediaStreamVideoSource::kMinAspectRatio
, 2);
332 TestSourceCropFrame(MediaStreamVideoSource::kDefaultWidth
,
333 MediaStreamVideoSource::kDefaultHeight
,
334 factory
.CreateWebMediaConstraints(), 640, 320);
337 TEST_F(MediaStreamVideoSourceTest
, MinAspectRatioLargerThanMaxAspectRatio
) {
338 MockMediaConstraintFactory factory
;
339 factory
.AddMandatory(MediaStreamVideoSource::kMinAspectRatio
, 2);
340 factory
.AddMandatory(MediaStreamVideoSource::kMaxAspectRatio
, 1);
341 blink::WebMediaStreamTrack track
= CreateTrack(
342 "123", factory
.CreateWebMediaConstraints());
343 mock_source()->CompleteGetSupportedFormats();
344 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
347 TEST_F(MediaStreamVideoSourceTest
, MaxAspectRatioZero
) {
348 MockMediaConstraintFactory factory
;
349 factory
.AddOptional(MediaStreamVideoSource::kMaxAspectRatio
, 0);
350 blink::WebMediaStreamTrack track
= CreateTrack(
351 "123", factory
.CreateWebMediaConstraints());
352 mock_source()->CompleteGetSupportedFormats();
353 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
356 TEST_F(MediaStreamVideoSourceTest
, MinWidthLargerThanMaxWidth
) {
357 MockMediaConstraintFactory factory
;
358 factory
.AddMandatory(MediaStreamVideoSource::kMinWidth
, 640);
359 factory
.AddMandatory(MediaStreamVideoSource::kMaxWidth
, 320);
360 blink::WebMediaStreamTrack track
= CreateTrack(
361 "123", factory
.CreateWebMediaConstraints());
362 mock_source()->CompleteGetSupportedFormats();
363 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
366 TEST_F(MediaStreamVideoSourceTest
, MinHeightLargerThanMaxHeight
) {
367 MockMediaConstraintFactory factory
;
368 factory
.AddMandatory(MediaStreamVideoSource::kMinHeight
, 480);
369 factory
.AddMandatory(MediaStreamVideoSource::kMaxHeight
, 360);
370 blink::WebMediaStreamTrack track
= CreateTrack(
371 "123", factory
.CreateWebMediaConstraints());
372 mock_source()->CompleteGetSupportedFormats();
373 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
376 TEST_F(MediaStreamVideoSourceTest
, MinFrameRateLargerThanMaxFrameRate
) {
377 MockMediaConstraintFactory factory
;
378 factory
.AddMandatory(MediaStreamVideoSource::kMinFrameRate
, 25);
379 factory
.AddMandatory(MediaStreamVideoSource::kMaxFrameRate
, 15);
380 blink::WebMediaStreamTrack track
= CreateTrack(
381 "123", factory
.CreateWebMediaConstraints());
382 mock_source()->CompleteGetSupportedFormats();
383 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
386 // Test that its safe to release the last reference of a blink track and the
387 // source during the callback if adding a track succeeds.
388 TEST_F(MediaStreamVideoSourceTest
, ReleaseTrackAndSourceOnSuccessCallBack
) {
389 MockMediaConstraintFactory factory
;
391 blink::WebMediaStreamTrack track
=
392 CreateTrack("123", factory
.CreateWebMediaConstraints());
393 ReleaseTrackAndSourceOnAddTrackCallback(track
);
395 mock_source()->CompleteGetSupportedFormats();
396 mock_source()->StartMockedSource();
397 EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
400 // Test that its safe to release the last reference of a blink track and the
401 // source during the callback if adding a track fails.
402 TEST_F(MediaStreamVideoSourceTest
, ReleaseTrackAndSourceOnFailureCallBack
) {
403 MockMediaConstraintFactory factory
;
404 factory
.AddMandatory(MediaStreamVideoSource::kMinWidth
, 99999);
406 blink::WebMediaStreamTrack track
=
407 CreateTrack("123", factory
.CreateWebMediaConstraints());
408 ReleaseTrackAndSourceOnAddTrackCallback(track
);
410 mock_source()->CompleteGetSupportedFormats();
411 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
414 // Test that the source ignores an optional aspect ratio that is higher than
416 TEST_F(MediaStreamVideoSourceTest
, OptionalAspectRatioTooHigh
) {
417 MockMediaConstraintFactory factory
;
418 factory
.AddOptional(MediaStreamVideoSource::kMinAspectRatio
, 2);
419 blink::WebMediaStreamTrack track
= CreateTrack(
420 "123", factory
.CreateWebMediaConstraints());
421 mock_source()->CompleteGetSupportedFormats();
423 const media::VideoCaptureParams
& params
= mock_source()->start_params();
424 double aspect_ratio
=
425 static_cast<double>(params
.requested_format
.frame_size
.width()) /
426 params
.requested_format
.frame_size
.height();
427 EXPECT_LT(aspect_ratio
, 2);
430 // Test that the source starts video with the default resolution if the
431 // that is the only supported.
432 TEST_F(MediaStreamVideoSourceTest
, DefaultCapability
) {
433 media::VideoCaptureFormats formats
;
434 formats
.push_back(media::VideoCaptureFormat(
435 gfx::Size(MediaStreamVideoSource::kDefaultWidth
,
436 MediaStreamVideoSource::kDefaultHeight
),
437 MediaStreamVideoSource::kDefaultFrameRate
,
438 media::PIXEL_FORMAT_I420
));
439 mock_source()->SetSupportedFormats(formats
);
441 blink::WebMediaConstraints constraints
;
442 constraints
.initialize();
443 CreateTrackAndStartSource(constraints
,
444 MediaStreamVideoSource::kDefaultWidth
,
445 MediaStreamVideoSource::kDefaultHeight
,
449 TEST_F(MediaStreamVideoSourceTest
, InvalidMandatoryConstraint
) {
450 MockMediaConstraintFactory factory
;
451 factory
.AddMandatory("weird key", 640);
452 blink::WebMediaStreamTrack track
= CreateTrack(
453 "123", factory
.CreateWebMediaConstraints());
454 mock_source()->CompleteGetSupportedFormats();
455 EXPECT_EQ(MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED
, error_type());
456 EXPECT_EQ("weird key", error_name());
457 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
460 // Test that the source ignores an unknown optional constraint.
461 TEST_F(MediaStreamVideoSourceTest
, InvalidOptionalConstraint
) {
462 MockMediaConstraintFactory factory
;
463 factory
.AddOptional("weird key", 640);
465 CreateTrackAndStartSource(factory
.CreateWebMediaConstraints(),
466 MediaStreamVideoSource::kDefaultWidth
,
467 MediaStreamVideoSource::kDefaultHeight
,
471 // Tests that the source starts video with the max width and height set by
472 // constraints for screencast.
473 TEST_F(MediaStreamVideoSourceTest
, ScreencastResolutionWithConstraint
) {
474 media::VideoCaptureFormats formats
;
475 formats
.push_back(media::VideoCaptureFormat(
476 gfx::Size(480, 270), 30, media::PIXEL_FORMAT_I420
));
477 mock_source()->SetSupportedFormats(formats
);
478 MockMediaConstraintFactory factory
;
479 factory
.AddMandatory(MediaStreamVideoSource::kMaxWidth
, 480);
480 factory
.AddMandatory(MediaStreamVideoSource::kMaxHeight
, 270);
482 blink::WebMediaStreamTrack track
= CreateTrackAndStartSource(
483 factory
.CreateWebMediaConstraints(), 480, 270, 30);
484 EXPECT_EQ(480, mock_source()->max_requested_height());
485 EXPECT_EQ(270, mock_source()->max_requested_width());
488 // Test that optional constraints are applied in order.
489 TEST_F(MediaStreamVideoSourceTest
, OptionalConstraints
) {
490 MockMediaConstraintFactory factory
;
491 // Min width of 2056 pixels can not be fulfilled.
492 factory
.AddOptional(MediaStreamVideoSource::kMinWidth
, 2056);
493 factory
.AddOptional(MediaStreamVideoSource::kMinWidth
, 641);
494 // Since min width is set to 641 pixels, max width 640 can not be fulfilled.
495 factory
.AddOptional(MediaStreamVideoSource::kMaxWidth
, 640);
496 CreateTrackAndStartSource(factory
.CreateWebMediaConstraints(), 1280, 720, 30);
499 // Test that the source crops to the requested max width and
500 // height even though the camera delivers a larger frame.
501 TEST_F(MediaStreamVideoSourceTest
, DeliverCroppedVideoFrameOptional640360
) {
502 MockMediaConstraintFactory factory
;
503 factory
.AddOptional(MediaStreamVideoSource::kMaxWidth
, 640);
504 factory
.AddOptional(MediaStreamVideoSource::kMaxHeight
, 360);
505 TestSourceCropFrame(640, 480, factory
.CreateWebMediaConstraints(), 640, 360);
508 TEST_F(MediaStreamVideoSourceTest
, DeliverCroppedVideoFrameMandatory640360
) {
509 MockMediaConstraintFactory factory
;
510 factory
.AddMandatory(MediaStreamVideoSource::kMaxWidth
, 640);
511 factory
.AddMandatory(MediaStreamVideoSource::kMaxHeight
, 360);
512 TestSourceCropFrame(640, 480, factory
.CreateWebMediaConstraints(), 640, 360);
515 TEST_F(MediaStreamVideoSourceTest
, DeliverCroppedVideoFrameMandatory732489
) {
516 MockMediaConstraintFactory factory
;
517 factory
.AddMandatory(MediaStreamVideoSource::kMaxWidth
, 732);
518 factory
.AddMandatory(MediaStreamVideoSource::kMaxHeight
, 489);
519 factory
.AddMandatory(MediaStreamVideoSource::kMinWidth
, 732);
520 factory
.AddMandatory(MediaStreamVideoSource::kMinWidth
, 489);
521 TestSourceCropFrame(1280, 720, factory
.CreateWebMediaConstraints(), 732, 489);
524 // Test that the source crops to the requested max width and
525 // height even though the requested frame has odd size.
526 TEST_F(MediaStreamVideoSourceTest
, DeliverCroppedVideoFrame637359
) {
527 MockMediaConstraintFactory factory
;
528 factory
.AddOptional(MediaStreamVideoSource::kMaxWidth
, 637);
529 factory
.AddOptional(MediaStreamVideoSource::kMaxHeight
, 359);
530 TestSourceCropFrame(640, 480, factory
.CreateWebMediaConstraints(), 637, 359);
533 TEST_F(MediaStreamVideoSourceTest
, DeliverCroppedVideoFrame320320
) {
534 MockMediaConstraintFactory factory
;
535 factory
.AddMandatory(MediaStreamVideoSource::kMaxWidth
, 320);
536 factory
.AddMandatory(MediaStreamVideoSource::kMaxHeight
, 320);
537 factory
.AddMandatory(MediaStreamVideoSource::kMinHeight
, 320);
538 factory
.AddMandatory(MediaStreamVideoSource::kMinWidth
, 320);
539 TestSourceCropFrame(640, 480, factory
.CreateWebMediaConstraints(), 320, 320);
542 TEST_F(MediaStreamVideoSourceTest
, DeliverSmallerSizeWhenTooLargeMax
) {
543 MockMediaConstraintFactory factory
;
544 factory
.AddOptional(MediaStreamVideoSource::kMaxWidth
, 1920);
545 factory
.AddOptional(MediaStreamVideoSource::kMaxHeight
, 1080);
546 factory
.AddOptional(MediaStreamVideoSource::kMinWidth
, 1280);
547 factory
.AddOptional(MediaStreamVideoSource::kMinHeight
, 720);
548 TestSourceCropFrame(1280, 720, factory
.CreateWebMediaConstraints(),
552 TEST_F(MediaStreamVideoSourceTest
, TwoTracksWithVGAAndWVGA
) {
553 MockMediaConstraintFactory factory1
;
554 factory1
.AddOptional(MediaStreamVideoSource::kMaxWidth
, 640);
555 factory1
.AddOptional(MediaStreamVideoSource::kMaxHeight
, 480);
557 MockMediaConstraintFactory factory2
;
558 factory2
.AddOptional(MediaStreamVideoSource::kMaxHeight
, 360);
560 TestTwoTracksWithDifferentConstraints(factory1
.CreateWebMediaConstraints(),
561 factory2
.CreateWebMediaConstraints(),
567 TEST_F(MediaStreamVideoSourceTest
, TwoTracksWith720AndWVGA
) {
568 MockMediaConstraintFactory factory1
;
569 factory1
.AddOptional(MediaStreamVideoSource::kMinWidth
, 1280);
570 factory1
.AddOptional(MediaStreamVideoSource::kMinHeight
, 720);
573 MockMediaConstraintFactory factory2
;
574 factory2
.AddMandatory(MediaStreamVideoSource::kMaxWidth
, 640);
575 factory2
.AddMandatory(MediaStreamVideoSource::kMaxHeight
, 360);
577 TestTwoTracksWithDifferentConstraints(factory1
.CreateWebMediaConstraints(),
578 factory2
.CreateWebMediaConstraints(),
584 TEST_F(MediaStreamVideoSourceTest
, TwoTracksWith720AndW700H700
) {
585 MockMediaConstraintFactory factory1
;
586 factory1
.AddOptional(MediaStreamVideoSource::kMinWidth
, 1280);
587 factory1
.AddOptional(MediaStreamVideoSource::kMinHeight
, 720);
589 MockMediaConstraintFactory factory2
;
590 factory2
.AddMandatory(MediaStreamVideoSource::kMaxWidth
, 700);
591 factory2
.AddMandatory(MediaStreamVideoSource::kMaxHeight
, 700);
593 TestTwoTracksWithDifferentConstraints(factory1
.CreateWebMediaConstraints(),
594 factory2
.CreateWebMediaConstraints(),
600 TEST_F(MediaStreamVideoSourceTest
, TwoTracksWith720AndMaxAspectRatio4To3
) {
601 MockMediaConstraintFactory factory1
;
602 factory1
.AddOptional(MediaStreamVideoSource::kMinWidth
, 1280);
603 factory1
.AddOptional(MediaStreamVideoSource::kMinHeight
, 720);
605 MockMediaConstraintFactory factory2
;
606 factory2
.AddMandatory(MediaStreamVideoSource::kMaxAspectRatio
, 640.0 / 480);
608 TestTwoTracksWithDifferentConstraints(factory1
.CreateWebMediaConstraints(),
609 factory2
.CreateWebMediaConstraints(),
615 TEST_F(MediaStreamVideoSourceTest
, TwoTracksWithVgaAndMinAspectRatio
) {
616 MockMediaConstraintFactory factory1
;
617 factory1
.AddOptional(MediaStreamVideoSource::kMaxWidth
, 640);
618 factory1
.AddOptional(MediaStreamVideoSource::kMaxHeight
, 480);
620 MockMediaConstraintFactory factory2
;
621 factory2
.AddMandatory(MediaStreamVideoSource::kMinAspectRatio
, 640.0 / 360);
623 TestTwoTracksWithDifferentConstraints(factory1
.CreateWebMediaConstraints(),
624 factory2
.CreateWebMediaConstraints(),
630 TEST_F(MediaStreamVideoSourceTest
,
631 TwoTracksWithSecondTrackFrameRateHigherThanFirst
) {
632 MockMediaConstraintFactory factory1
;
633 factory1
.AddMandatory(MediaStreamVideoSource::kMinFrameRate
, 15);
634 factory1
.AddMandatory(MediaStreamVideoSource::kMaxFrameRate
, 15);
636 blink::WebMediaStreamTrack track1
=
637 CreateTrackAndStartSource(factory1
.CreateWebMediaConstraints(),
638 MediaStreamVideoSource::kDefaultWidth
,
639 MediaStreamVideoSource::kDefaultHeight
,
642 MockMediaConstraintFactory factory2
;
643 factory2
.AddMandatory(MediaStreamVideoSource::kMinFrameRate
, 30);
644 blink::WebMediaStreamTrack track2
= CreateTrack(
645 "123", factory2
.CreateWebMediaConstraints());
646 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
649 // Test that a source can change the frame resolution on the fly and that
650 // tracks sinks get the new frame size unless constraints force the frame to be
652 TEST_F(MediaStreamVideoSourceTest
, SourceChangeFrameSize
) {
653 MockMediaConstraintFactory factory
;
654 factory
.AddOptional(MediaStreamVideoSource::kMaxWidth
, 800);
655 factory
.AddOptional(MediaStreamVideoSource::kMaxHeight
, 700);
657 // Expect the source to start capture with the supported resolution.
658 blink::WebMediaStreamTrack track
=
659 CreateTrackAndStartSource(factory
.CreateWebMediaConstraints(),
662 MockMediaStreamVideoSink sink
;
663 MediaStreamVideoSink::AddToVideoTrack(
664 &sink
, sink
.GetDeliverFrameCB(), track
);
665 EXPECT_EQ(0, sink
.number_of_frames());
666 DeliverVideoFrameAndWaitForRenderer(320, 240, &sink
);
667 EXPECT_EQ(1, sink
.number_of_frames());
668 // Expect the delivered frame to be passed unchanged since its smaller than
670 EXPECT_EQ(320, sink
.frame_size().width());
671 EXPECT_EQ(240, sink
.frame_size().height());
673 DeliverVideoFrameAndWaitForRenderer(640, 480, &sink
);
674 EXPECT_EQ(2, sink
.number_of_frames());
675 // Expect the delivered frame to be passed unchanged since its smaller than
677 EXPECT_EQ(640, sink
.frame_size().width());
678 EXPECT_EQ(480, sink
.frame_size().height());
680 DeliverVideoFrameAndWaitForRenderer(1280, 720, &sink
);
682 EXPECT_EQ(3, sink
.number_of_frames());
683 // Expect a frame to be cropped since its larger than max requested.
684 EXPECT_EQ(800, sink
.frame_size().width());
685 EXPECT_EQ(700, sink
.frame_size().height());
687 MediaStreamVideoSink::RemoveFromVideoTrack(&sink
, track
);
690 TEST_F(MediaStreamVideoSourceTest
, IsConstraintSupported
) {
691 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
692 MediaStreamVideoSource::kMaxFrameRate
));
693 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
694 MediaStreamVideoSource::kMinFrameRate
));
695 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
696 MediaStreamVideoSource::kMaxWidth
));
697 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
698 MediaStreamVideoSource::kMinWidth
));
699 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
700 MediaStreamVideoSource::kMaxHeight
));
701 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
702 MediaStreamVideoSource::kMinHeight
));
703 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
704 MediaStreamVideoSource::kMaxAspectRatio
));
705 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
706 MediaStreamVideoSource::kMinAspectRatio
));
708 EXPECT_FALSE(MediaStreamVideoSource::IsConstraintSupported(
709 "something unsupported"));
712 // Test that the constraint negotiation can handle 0.0 fps as frame rate.
713 TEST_F(MediaStreamVideoSourceTest
, Use0FpsSupportedFormat
) {
714 media::VideoCaptureFormats formats
;
715 formats
.push_back(media::VideoCaptureFormat(
716 gfx::Size(640, 480), 0.0f
, media::PIXEL_FORMAT_I420
));
717 formats
.push_back(media::VideoCaptureFormat(
718 gfx::Size(320, 240), 0.0f
, media::PIXEL_FORMAT_I420
));
719 mock_source()->SetSupportedFormats(formats
);
721 blink::WebMediaConstraints constraints
;
722 constraints
.initialize();
723 blink::WebMediaStreamTrack track
= CreateTrack("123", constraints
);
724 mock_source()->CompleteGetSupportedFormats();
725 mock_source()->StartMockedSource();
726 EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
728 MockMediaStreamVideoSink sink
;
729 MediaStreamVideoSink::AddToVideoTrack(
730 &sink
, sink
.GetDeliverFrameCB(), track
);
731 EXPECT_EQ(0, sink
.number_of_frames());
732 DeliverVideoFrameAndWaitForRenderer(320, 240, &sink
);
733 EXPECT_EQ(1, sink
.number_of_frames());
734 // Expect the delivered frame to be passed unchanged since its smaller than
736 EXPECT_EQ(320, sink
.frame_size().width());
737 EXPECT_EQ(240, sink
.frame_size().height());
738 MediaStreamVideoSink::RemoveFromVideoTrack(&sink
, track
);
741 // Test that a source producing no frames calls back the MSVCS to tell so, and
742 // this in turn tells the Track attached. Then start passing frames, and check
743 // that in a reasonable time frame the muted state turns to false.
744 TEST_F(MediaStreamVideoSourceTest
, MutedSource
) {
745 MockMediaConstraintFactory factory
;
746 blink::WebMediaStreamTrack track
=
747 CreateTrackAndStartSource(factory
.CreateWebMediaConstraints(),
750 MockMediaStreamVideoSink sink
;
751 MediaStreamVideoSink::AddToVideoTrack(&sink
, sink
.GetDeliverFrameCB(), track
);
752 EXPECT_EQ(MediaStreamTrack::GetTrack(track
)->GetMutedState(), false);
754 base::RunLoop run_loop
;
755 base::Closure quit_closure
= run_loop
.QuitClosure();
756 bool muted_state
= false;
757 EXPECT_CALL(*mock_source(), DoSetMutedState(_
))
758 .WillOnce(DoAll(SaveArg
<0>(&muted_state
), RunClosure(quit_closure
)));
760 EXPECT_EQ(muted_state
, true);
761 // TODO(mcasas): When added, check |track|'s (WebMediaStreamTrack) Muted
762 // attribute, should be true. In the meantime, check the MediaStreamTrack's.
763 EXPECT_EQ(MediaStreamTrack::GetTrack(track
)->GetMutedState(), true);
765 EXPECT_CALL(*mock_source(), DoSetMutedState(_
))
766 .WillOnce(DoAll(SaveArg
<0>(&muted_state
), RunClosure(quit_closure
)));
767 // Mock frame delivery happens asynchronously, not according to the configured
768 // frame rate, potentially many frames can pass before the muted state is
769 // flipped. |kMaxFrameCount| is used as a reasonable high bound of this value.
770 const int kMaxFrameCount
= 10000;
772 while (muted_state
!= false || ++i
> kMaxFrameCount
)
773 DeliverVideoFrameAndWaitForRenderer(640, 480, &sink
);
774 EXPECT_EQ(muted_state
, false);
775 EXPECT_LT(i
, kMaxFrameCount
);
776 EXPECT_EQ(MediaStreamTrack::GetTrack(track
)->GetMutedState(), false);
778 MediaStreamVideoSink::RemoveFromVideoTrack(&sink
, track
);
781 // Test that a source producing no frames calls back the MSVCS to tell so, and
782 // this in turn tells all the Tracks attached.
783 TEST_F(MediaStreamVideoSourceTest
, MutedSourceWithTwoTracks
) {
784 MockMediaConstraintFactory factory1
;
785 blink::WebMediaStreamTrack track1
=
786 CreateTrackAndStartSource(factory1
.CreateWebMediaConstraints(),
787 MediaStreamVideoSource::kDefaultWidth
,
788 MediaStreamVideoSource::kDefaultHeight
,
791 MockMediaConstraintFactory factory2
;
792 factory2
.AddMandatory(MediaStreamVideoSource::kMaxFrameRate
, 15);
793 blink::WebMediaStreamTrack track2
= CreateTrack(
794 "123", factory2
.CreateWebMediaConstraints());
795 EXPECT_EQ(0, NumberOfFailedConstraintsCallbacks());
797 MockMediaStreamVideoSink sink1
;
798 MediaStreamVideoSink::AddToVideoTrack(&sink1
, sink1
.GetDeliverFrameCB(),
800 EXPECT_EQ(MediaStreamTrack::GetTrack(track1
)->GetMutedState(), false);
802 MockMediaStreamVideoSink sink2
;
803 MediaStreamVideoSink::AddToVideoTrack(&sink2
, sink2
.GetDeliverFrameCB(),
805 EXPECT_EQ(MediaStreamTrack::GetTrack(track2
)->GetMutedState(), false);
807 base::RunLoop run_loop
;
808 base::Closure quit_closure
= run_loop
.QuitClosure();
809 bool muted_state
= false;
810 EXPECT_CALL(*mock_source(), DoSetMutedState(_
))
811 .WillOnce(DoAll(SaveArg
<0>(&muted_state
), RunClosure(quit_closure
)));
813 EXPECT_EQ(muted_state
, true);
815 // TODO(mcasas): When added, check |track|'s (WebMediaStreamTrack) Muted
816 // attribute, should be true. In the meantime, check the MediaStreamTrack's.
817 EXPECT_EQ(MediaStreamTrack::GetTrack(track1
)->GetMutedState(), true);
818 EXPECT_EQ(MediaStreamTrack::GetTrack(track2
)->GetMutedState(), true);
820 MediaStreamVideoSink::RemoveFromVideoTrack(&sink1
, track1
);
821 MediaStreamVideoSink::RemoveFromVideoTrack(&sink2
, track2
);
824 } // namespace content