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
: 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 false /* remote */, true /* readonly */);
56 webkit_source_
.setExtraData(mock_source_
);
59 void TearDown() override
{
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
,
72 base::Bind(&MediaStreamVideoSourceTest::OnConstraintsApplied
,
73 base::Unretained(this)),
77 blink::WebMediaStreamTrack
CreateTrackAndStartSource(
78 const blink::WebMediaConstraints
& constraints
,
81 int expected_frame_rate
) {
82 blink::WebMediaStreamTrack track
= CreateTrack("123", constraints
);
84 mock_source_
->CompleteGetSupportedFormats();
85 const media::VideoCaptureFormat
& format
= mock_source()->start_format();
86 EXPECT_EQ(expected_width
, format
.frame_size
.width());
87 EXPECT_EQ(expected_height
, format
.frame_size
.height());
88 EXPECT_EQ(expected_frame_rate
, format
.frame_rate
);
90 EXPECT_EQ(0, NumberOfSuccessConstraintsCallbacks());
91 mock_source_
->StartMockedSource();
92 // Once the source has started successfully we expect that the
93 // ConstraintsCallback in MediaStreamSource::AddTrack completes.
94 EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
98 int NumberOfSuccessConstraintsCallbacks() const {
99 return number_of_successful_constraints_applied_
;
102 int NumberOfFailedConstraintsCallbacks() const {
103 return number_of_failed_constraints_applied_
;
106 content::MediaStreamRequestResult
error_type() const { return result_
; }
107 blink::WebString
error_name() const { return result_name_
; }
109 MockMediaStreamVideoSource
* mock_source() { return mock_source_
; }
111 // Test that the source crops/scales to the requested width and
112 // height even though the camera delivers a larger frame.
113 void TestSourceCropFrame(int capture_width
,
115 const blink::WebMediaConstraints
& constraints
,
117 int expected_height
) {
118 // Expect the source to start capture with the supported resolution.
119 blink::WebMediaStreamTrack track
=
120 CreateTrackAndStartSource(constraints
, capture_width
, capture_height
,
123 MockMediaStreamVideoSink sink
;
124 MediaStreamVideoSink::AddToVideoTrack(
125 &sink
, sink
.GetDeliverFrameCB(), track
);
126 DeliverVideoFrameAndWaitForRenderer(capture_width
, capture_height
, &sink
);
127 EXPECT_EQ(1, sink
.number_of_frames());
129 // Expect the delivered frame to be cropped.
130 EXPECT_EQ(expected_height
, sink
.frame_size().height());
131 EXPECT_EQ(expected_width
, sink
.frame_size().width());
132 MediaStreamVideoSink::RemoveFromVideoTrack(&sink
, track
);
135 void DeliverVideoFrameAndWaitForRenderer(int width
, int height
,
136 MockMediaStreamVideoSink
* sink
) {
137 base::RunLoop run_loop
;
138 base::Closure quit_closure
= run_loop
.QuitClosure();
139 EXPECT_CALL(*sink
, OnVideoFrame()).WillOnce(
140 RunClosure(quit_closure
));
141 scoped_refptr
<media::VideoFrame
> frame
=
142 media::VideoFrame::CreateBlackFrame(gfx::Size(width
, height
));
143 mock_source()->DeliverVideoFrame(frame
);
147 void DeliverVideoFrameAndWaitForTwoRenderers(
150 MockMediaStreamVideoSink
* sink1
,
151 MockMediaStreamVideoSink
* sink2
) {
152 base::RunLoop run_loop
;
153 base::Closure quit_closure
= run_loop
.QuitClosure();
154 EXPECT_CALL(*sink1
, OnVideoFrame());
155 EXPECT_CALL(*sink2
, OnVideoFrame()).WillOnce(
156 RunClosure(quit_closure
));
157 scoped_refptr
<media::VideoFrame
> frame
=
158 media::VideoFrame::CreateBlackFrame(gfx::Size(width
, height
));
159 mock_source()->DeliverVideoFrame(frame
);
163 void TestTwoTracksWithDifferentConstraints(
164 const blink::WebMediaConstraints
& constraints1
,
165 const blink::WebMediaConstraints
& constraints2
,
169 int expected_height1
,
171 int expected_height2
) {
172 blink::WebMediaStreamTrack track1
=
173 CreateTrackAndStartSource(constraints1
, capture_width
, capture_height
,
174 MediaStreamVideoSource::kDefaultFrameRate
);
176 blink::WebMediaStreamTrack track2
= CreateTrack("dummy", constraints2
);
178 MockMediaStreamVideoSink sink1
;
179 MediaStreamVideoSink::AddToVideoTrack(&sink1
, sink1
.GetDeliverFrameCB(),
181 EXPECT_EQ(0, sink1
.number_of_frames());
183 MockMediaStreamVideoSink sink2
;
184 MediaStreamVideoSink::AddToVideoTrack(&sink2
, sink2
.GetDeliverFrameCB(),
186 EXPECT_EQ(0, sink2
.number_of_frames());
188 DeliverVideoFrameAndWaitForTwoRenderers(capture_width
,
193 EXPECT_EQ(1, sink1
.number_of_frames());
194 EXPECT_EQ(expected_width1
, sink1
.frame_size().width());
195 EXPECT_EQ(expected_height1
, sink1
.frame_size().height());
197 EXPECT_EQ(1, sink2
.number_of_frames());
198 EXPECT_EQ(expected_width2
, sink2
.frame_size().width());
199 EXPECT_EQ(expected_height2
, sink2
.frame_size().height());
201 MediaStreamVideoSink::RemoveFromVideoTrack(&sink1
, track1
);
202 MediaStreamVideoSink::RemoveFromVideoTrack(&sink2
, track2
);
205 void SetSourceSupportedFormats(const media::VideoCaptureFormats
& formats
) {
206 mock_source_
->SetSupportedFormats(formats
);
209 void ReleaseTrackAndSourceOnAddTrackCallback(
210 const blink::WebMediaStreamTrack
& track_to_release
) {
211 track_to_release_
= track_to_release
;
215 void OnConstraintsApplied(MediaStreamSource
* source
,
216 MediaStreamRequestResult result
,
217 const blink::WebString
& result_name
) {
218 ASSERT_EQ(source
, webkit_source_
.extraData());
220 if (result
== MEDIA_DEVICE_OK
) {
221 ++number_of_successful_constraints_applied_
;
224 result_name_
= result_name
;
225 ++number_of_failed_constraints_applied_
;
228 if (!track_to_release_
.isNull()) {
230 webkit_source_
.reset();
231 track_to_release_
.reset();
234 const base::MessageLoopForUI message_loop_
;
235 const scoped_ptr
<ChildProcess
> child_process_
;
236 blink::WebMediaStreamTrack track_to_release_
;
237 int number_of_successful_constraints_applied_
;
238 int number_of_failed_constraints_applied_
;
239 content::MediaStreamRequestResult result_
;
240 blink::WebString result_name_
;
241 blink::WebMediaStreamSource webkit_source_
;
242 // |mock_source_| is owned by |webkit_source_|.
243 MockMediaStreamVideoSource
* mock_source_
;
246 TEST_F(MediaStreamVideoSourceTest
, AddTrackAndStartSource
) {
247 blink::WebMediaConstraints constraints
;
248 constraints
.initialize();
249 blink::WebMediaStreamTrack track
= CreateTrack("123", constraints
);
250 mock_source()->CompleteGetSupportedFormats();
251 mock_source()->StartMockedSource();
252 EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
255 TEST_F(MediaStreamVideoSourceTest
, AddTwoTracksBeforeSourceStarts
) {
256 blink::WebMediaConstraints constraints
;
257 constraints
.initialize();
258 blink::WebMediaStreamTrack track1
= CreateTrack("123", constraints
);
259 mock_source()->CompleteGetSupportedFormats();
260 blink::WebMediaStreamTrack track2
= CreateTrack("123", constraints
);
261 EXPECT_EQ(0, NumberOfSuccessConstraintsCallbacks());
262 mock_source()->StartMockedSource();
263 EXPECT_EQ(2, NumberOfSuccessConstraintsCallbacks());
266 TEST_F(MediaStreamVideoSourceTest
, AddTrackAfterSourceStarts
) {
267 blink::WebMediaConstraints constraints
;
268 constraints
.initialize();
269 blink::WebMediaStreamTrack track1
= CreateTrack("123", constraints
);
270 mock_source()->CompleteGetSupportedFormats();
271 mock_source()->StartMockedSource();
272 EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
273 blink::WebMediaStreamTrack track2
= CreateTrack("123", constraints
);
274 EXPECT_EQ(2, NumberOfSuccessConstraintsCallbacks());
277 TEST_F(MediaStreamVideoSourceTest
, AddTrackAndFailToStartSource
) {
278 blink::WebMediaConstraints constraints
;
279 constraints
.initialize();
280 blink::WebMediaStreamTrack track
= CreateTrack("123", constraints
);
281 mock_source()->CompleteGetSupportedFormats();
282 mock_source()->FailToStartMockedSource();
283 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
286 TEST_F(MediaStreamVideoSourceTest
, AddTwoTracksBeforeGetSupportedFormats
) {
287 blink::WebMediaConstraints constraints
;
288 constraints
.initialize();
289 blink::WebMediaStreamTrack track1
= CreateTrack("123", constraints
);
290 blink::WebMediaStreamTrack track2
= CreateTrack("123", constraints
);
291 mock_source()->CompleteGetSupportedFormats();
292 mock_source()->StartMockedSource();
293 EXPECT_EQ(2, NumberOfSuccessConstraintsCallbacks());
296 // Test that the capture output is CIF if we set max constraints to CIF.
297 // and the capture device support CIF.
298 TEST_F(MediaStreamVideoSourceTest
, MandatoryConstraintCif5Fps
) {
299 MockMediaConstraintFactory factory
;
300 factory
.AddMandatory(MediaStreamVideoSource::kMaxWidth
, 352);
301 factory
.AddMandatory(MediaStreamVideoSource::kMaxHeight
, 288);
302 factory
.AddMandatory(MediaStreamVideoSource::kMaxFrameRate
, 5);
304 CreateTrackAndStartSource(factory
.CreateWebMediaConstraints(), 352, 288, 5);
307 // Test that the capture output is 720P if the camera support it and the
308 // optional constraint is set to 720P.
309 TEST_F(MediaStreamVideoSourceTest
, MandatoryMinVgaOptional720P
) {
310 MockMediaConstraintFactory factory
;
311 factory
.AddMandatory(MediaStreamVideoSource::kMinWidth
, 640);
312 factory
.AddMandatory(MediaStreamVideoSource::kMinHeight
, 480);
313 factory
.AddOptional(MediaStreamVideoSource::kMinWidth
, 1280);
314 factory
.AddOptional(MediaStreamVideoSource::kMinAspectRatio
, 1280.0 / 720);
316 CreateTrackAndStartSource(factory
.CreateWebMediaConstraints(), 1280, 720, 30);
319 // Test that the capture output have aspect ratio 4:3 if a mandatory constraint
320 // require it even if an optional constraint request a higher resolution
321 // that don't have this aspect ratio.
322 TEST_F(MediaStreamVideoSourceTest
, MandatoryAspectRatio4To3
) {
323 MockMediaConstraintFactory factory
;
324 factory
.AddMandatory(MediaStreamVideoSource::kMinWidth
, 640);
325 factory
.AddMandatory(MediaStreamVideoSource::kMinHeight
, 480);
326 factory
.AddMandatory(MediaStreamVideoSource::kMaxAspectRatio
, 640.0 / 480);
327 factory
.AddOptional(MediaStreamVideoSource::kMinWidth
, 1280);
329 TestSourceCropFrame(1280, 720,
330 factory
.CreateWebMediaConstraints(), 960, 720);
333 // Test that AddTrack succeeds if the mandatory min aspect ratio it set to 2.
334 TEST_F(MediaStreamVideoSourceTest
, MandatoryAspectRatio2
) {
335 MockMediaConstraintFactory factory
;
336 factory
.AddMandatory(MediaStreamVideoSource::kMinAspectRatio
, 2);
338 TestSourceCropFrame(MediaStreamVideoSource::kDefaultWidth
,
339 MediaStreamVideoSource::kDefaultHeight
,
340 factory
.CreateWebMediaConstraints(), 640, 320);
343 TEST_F(MediaStreamVideoSourceTest
, MinAspectRatioLargerThanMaxAspectRatio
) {
344 MockMediaConstraintFactory factory
;
345 factory
.AddMandatory(MediaStreamVideoSource::kMinAspectRatio
, 2);
346 factory
.AddMandatory(MediaStreamVideoSource::kMaxAspectRatio
, 1);
347 blink::WebMediaStreamTrack track
= CreateTrack(
348 "123", factory
.CreateWebMediaConstraints());
349 mock_source()->CompleteGetSupportedFormats();
350 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
353 TEST_F(MediaStreamVideoSourceTest
, MaxAspectRatioZero
) {
354 MockMediaConstraintFactory factory
;
355 factory
.AddOptional(MediaStreamVideoSource::kMaxAspectRatio
, 0);
356 blink::WebMediaStreamTrack track
= CreateTrack(
357 "123", factory
.CreateWebMediaConstraints());
358 mock_source()->CompleteGetSupportedFormats();
359 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
362 TEST_F(MediaStreamVideoSourceTest
, MinWidthLargerThanMaxWidth
) {
363 MockMediaConstraintFactory factory
;
364 factory
.AddMandatory(MediaStreamVideoSource::kMinWidth
, 640);
365 factory
.AddMandatory(MediaStreamVideoSource::kMaxWidth
, 320);
366 blink::WebMediaStreamTrack track
= CreateTrack(
367 "123", factory
.CreateWebMediaConstraints());
368 mock_source()->CompleteGetSupportedFormats();
369 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
372 TEST_F(MediaStreamVideoSourceTest
, MinHeightLargerThanMaxHeight
) {
373 MockMediaConstraintFactory factory
;
374 factory
.AddMandatory(MediaStreamVideoSource::kMinHeight
, 480);
375 factory
.AddMandatory(MediaStreamVideoSource::kMaxHeight
, 360);
376 blink::WebMediaStreamTrack track
= CreateTrack(
377 "123", factory
.CreateWebMediaConstraints());
378 mock_source()->CompleteGetSupportedFormats();
379 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
382 TEST_F(MediaStreamVideoSourceTest
, MinFrameRateLargerThanMaxFrameRate
) {
383 MockMediaConstraintFactory factory
;
384 factory
.AddMandatory(MediaStreamVideoSource::kMinFrameRate
, 25);
385 factory
.AddMandatory(MediaStreamVideoSource::kMaxFrameRate
, 15);
386 blink::WebMediaStreamTrack track
= CreateTrack(
387 "123", factory
.CreateWebMediaConstraints());
388 mock_source()->CompleteGetSupportedFormats();
389 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
392 // Test that its safe to release the last reference of a blink track and the
393 // source during the callback if adding a track succeeds.
394 TEST_F(MediaStreamVideoSourceTest
, ReleaseTrackAndSourceOnSuccessCallBack
) {
395 MockMediaConstraintFactory factory
;
397 blink::WebMediaStreamTrack track
=
398 CreateTrack("123", factory
.CreateWebMediaConstraints());
399 ReleaseTrackAndSourceOnAddTrackCallback(track
);
401 mock_source()->CompleteGetSupportedFormats();
402 mock_source()->StartMockedSource();
403 EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
406 // Test that its safe to release the last reference of a blink track and the
407 // source during the callback if adding a track fails.
408 TEST_F(MediaStreamVideoSourceTest
, ReleaseTrackAndSourceOnFailureCallBack
) {
409 MockMediaConstraintFactory factory
;
410 factory
.AddMandatory(MediaStreamVideoSource::kMinWidth
, 99999);
412 blink::WebMediaStreamTrack track
=
413 CreateTrack("123", factory
.CreateWebMediaConstraints());
414 ReleaseTrackAndSourceOnAddTrackCallback(track
);
416 mock_source()->CompleteGetSupportedFormats();
417 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
420 // Test that the source ignores an optional aspect ratio that is higher than
422 TEST_F(MediaStreamVideoSourceTest
, OptionalAspectRatioTooHigh
) {
423 MockMediaConstraintFactory factory
;
424 factory
.AddOptional(MediaStreamVideoSource::kMinAspectRatio
, 2);
425 blink::WebMediaStreamTrack track
= CreateTrack(
426 "123", factory
.CreateWebMediaConstraints());
427 mock_source()->CompleteGetSupportedFormats();
429 const media::VideoCaptureFormat
& format
= mock_source()->start_format();
430 const double aspect_ratio
= static_cast<double>(format
.frame_size
.width()) /
431 format
.frame_size
.height();
432 EXPECT_LT(aspect_ratio
, 2);
435 // Test that the source starts video with the default resolution if the
436 // that is the only supported.
437 TEST_F(MediaStreamVideoSourceTest
, DefaultCapability
) {
438 media::VideoCaptureFormats formats
;
439 formats
.push_back(media::VideoCaptureFormat(
440 gfx::Size(MediaStreamVideoSource::kDefaultWidth
,
441 MediaStreamVideoSource::kDefaultHeight
),
442 MediaStreamVideoSource::kDefaultFrameRate
,
443 media::PIXEL_FORMAT_I420
));
444 mock_source()->SetSupportedFormats(formats
);
446 blink::WebMediaConstraints constraints
;
447 constraints
.initialize();
448 CreateTrackAndStartSource(constraints
,
449 MediaStreamVideoSource::kDefaultWidth
,
450 MediaStreamVideoSource::kDefaultHeight
,
454 TEST_F(MediaStreamVideoSourceTest
, InvalidMandatoryConstraint
) {
455 MockMediaConstraintFactory factory
;
456 factory
.AddMandatory("weird key", 640);
457 blink::WebMediaStreamTrack track
= CreateTrack(
458 "123", factory
.CreateWebMediaConstraints());
459 mock_source()->CompleteGetSupportedFormats();
460 EXPECT_EQ(MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED
, error_type());
461 EXPECT_EQ("weird key", error_name());
462 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
465 // Test that the source ignores an unknown optional constraint.
466 TEST_F(MediaStreamVideoSourceTest
, InvalidOptionalConstraint
) {
467 MockMediaConstraintFactory factory
;
468 factory
.AddOptional("weird key", 640);
470 CreateTrackAndStartSource(factory
.CreateWebMediaConstraints(),
471 MediaStreamVideoSource::kDefaultWidth
,
472 MediaStreamVideoSource::kDefaultHeight
,
476 // Tests that the source starts video with the max width and height set by
477 // constraints for screencast.
478 TEST_F(MediaStreamVideoSourceTest
, ScreencastResolutionWithConstraint
) {
479 media::VideoCaptureFormats formats
;
480 formats
.push_back(media::VideoCaptureFormat(
481 gfx::Size(480, 270), 30, media::PIXEL_FORMAT_I420
));
482 mock_source()->SetSupportedFormats(formats
);
483 MockMediaConstraintFactory factory
;
484 factory
.AddMandatory(MediaStreamVideoSource::kMaxWidth
, 480);
485 factory
.AddMandatory(MediaStreamVideoSource::kMaxHeight
, 270);
487 blink::WebMediaStreamTrack track
= CreateTrackAndStartSource(
488 factory
.CreateWebMediaConstraints(), 480, 270, 30);
489 EXPECT_EQ(480, mock_source()->max_requested_height());
490 EXPECT_EQ(270, mock_source()->max_requested_width());
493 // Test that optional constraints are applied in order.
494 TEST_F(MediaStreamVideoSourceTest
, OptionalConstraints
) {
495 MockMediaConstraintFactory factory
;
496 // Min width of 2056 pixels can not be fulfilled.
497 factory
.AddOptional(MediaStreamVideoSource::kMinWidth
, 2056);
498 factory
.AddOptional(MediaStreamVideoSource::kMinWidth
, 641);
499 // Since min width is set to 641 pixels, max width 640 can not be fulfilled.
500 factory
.AddOptional(MediaStreamVideoSource::kMaxWidth
, 640);
501 CreateTrackAndStartSource(factory
.CreateWebMediaConstraints(), 1280, 720, 30);
504 // Test that the source crops to the requested max width and
505 // height even though the camera delivers a larger frame.
506 TEST_F(MediaStreamVideoSourceTest
, DeliverCroppedVideoFrameOptional640360
) {
507 MockMediaConstraintFactory factory
;
508 factory
.AddOptional(MediaStreamVideoSource::kMaxWidth
, 640);
509 factory
.AddOptional(MediaStreamVideoSource::kMaxHeight
, 360);
510 TestSourceCropFrame(640, 480, factory
.CreateWebMediaConstraints(), 640, 360);
513 TEST_F(MediaStreamVideoSourceTest
, DeliverCroppedVideoFrameMandatory640360
) {
514 MockMediaConstraintFactory factory
;
515 factory
.AddMandatory(MediaStreamVideoSource::kMaxWidth
, 640);
516 factory
.AddMandatory(MediaStreamVideoSource::kMaxHeight
, 360);
517 TestSourceCropFrame(640, 480, factory
.CreateWebMediaConstraints(), 640, 360);
520 TEST_F(MediaStreamVideoSourceTest
, DeliverCroppedVideoFrameMandatory732489
) {
521 MockMediaConstraintFactory factory
;
522 factory
.AddMandatory(MediaStreamVideoSource::kMaxWidth
, 732);
523 factory
.AddMandatory(MediaStreamVideoSource::kMaxHeight
, 489);
524 factory
.AddMandatory(MediaStreamVideoSource::kMinWidth
, 732);
525 factory
.AddMandatory(MediaStreamVideoSource::kMinWidth
, 489);
526 TestSourceCropFrame(1280, 720, factory
.CreateWebMediaConstraints(), 732, 489);
529 // Test that the source crops to the requested max width and
530 // height even though the requested frame has odd size.
531 TEST_F(MediaStreamVideoSourceTest
, DeliverCroppedVideoFrame637359
) {
532 MockMediaConstraintFactory factory
;
533 factory
.AddOptional(MediaStreamVideoSource::kMaxWidth
, 637);
534 factory
.AddOptional(MediaStreamVideoSource::kMaxHeight
, 359);
535 TestSourceCropFrame(640, 480, factory
.CreateWebMediaConstraints(), 637, 359);
538 TEST_F(MediaStreamVideoSourceTest
, DeliverCroppedVideoFrame320320
) {
539 MockMediaConstraintFactory factory
;
540 factory
.AddMandatory(MediaStreamVideoSource::kMaxWidth
, 320);
541 factory
.AddMandatory(MediaStreamVideoSource::kMaxHeight
, 320);
542 factory
.AddMandatory(MediaStreamVideoSource::kMinHeight
, 320);
543 factory
.AddMandatory(MediaStreamVideoSource::kMinWidth
, 320);
544 TestSourceCropFrame(640, 480, factory
.CreateWebMediaConstraints(), 320, 320);
547 TEST_F(MediaStreamVideoSourceTest
, DeliverSmallerSizeWhenTooLargeMax
) {
548 MockMediaConstraintFactory factory
;
549 factory
.AddOptional(MediaStreamVideoSource::kMaxWidth
, 1920);
550 factory
.AddOptional(MediaStreamVideoSource::kMaxHeight
, 1080);
551 factory
.AddOptional(MediaStreamVideoSource::kMinWidth
, 1280);
552 factory
.AddOptional(MediaStreamVideoSource::kMinHeight
, 720);
553 TestSourceCropFrame(1280, 720, factory
.CreateWebMediaConstraints(),
557 TEST_F(MediaStreamVideoSourceTest
, TwoTracksWithVGAAndWVGA
) {
558 MockMediaConstraintFactory factory1
;
559 factory1
.AddOptional(MediaStreamVideoSource::kMaxWidth
, 640);
560 factory1
.AddOptional(MediaStreamVideoSource::kMaxHeight
, 480);
562 MockMediaConstraintFactory factory2
;
563 factory2
.AddOptional(MediaStreamVideoSource::kMaxHeight
, 360);
565 TestTwoTracksWithDifferentConstraints(factory1
.CreateWebMediaConstraints(),
566 factory2
.CreateWebMediaConstraints(),
572 TEST_F(MediaStreamVideoSourceTest
, TwoTracksWith720AndWVGA
) {
573 MockMediaConstraintFactory factory1
;
574 factory1
.AddOptional(MediaStreamVideoSource::kMinWidth
, 1280);
575 factory1
.AddOptional(MediaStreamVideoSource::kMinHeight
, 720);
578 MockMediaConstraintFactory factory2
;
579 factory2
.AddMandatory(MediaStreamVideoSource::kMaxWidth
, 640);
580 factory2
.AddMandatory(MediaStreamVideoSource::kMaxHeight
, 360);
582 TestTwoTracksWithDifferentConstraints(factory1
.CreateWebMediaConstraints(),
583 factory2
.CreateWebMediaConstraints(),
589 TEST_F(MediaStreamVideoSourceTest
, TwoTracksWith720AndW700H700
) {
590 MockMediaConstraintFactory factory1
;
591 factory1
.AddOptional(MediaStreamVideoSource::kMinWidth
, 1280);
592 factory1
.AddOptional(MediaStreamVideoSource::kMinHeight
, 720);
594 MockMediaConstraintFactory factory2
;
595 factory2
.AddMandatory(MediaStreamVideoSource::kMaxWidth
, 700);
596 factory2
.AddMandatory(MediaStreamVideoSource::kMaxHeight
, 700);
598 TestTwoTracksWithDifferentConstraints(factory1
.CreateWebMediaConstraints(),
599 factory2
.CreateWebMediaConstraints(),
605 TEST_F(MediaStreamVideoSourceTest
, TwoTracksWith720AndMaxAspectRatio4To3
) {
606 MockMediaConstraintFactory factory1
;
607 factory1
.AddOptional(MediaStreamVideoSource::kMinWidth
, 1280);
608 factory1
.AddOptional(MediaStreamVideoSource::kMinHeight
, 720);
610 MockMediaConstraintFactory factory2
;
611 factory2
.AddMandatory(MediaStreamVideoSource::kMaxAspectRatio
, 640.0 / 480);
613 TestTwoTracksWithDifferentConstraints(factory1
.CreateWebMediaConstraints(),
614 factory2
.CreateWebMediaConstraints(),
620 TEST_F(MediaStreamVideoSourceTest
, TwoTracksWithVgaAndMinAspectRatio
) {
621 MockMediaConstraintFactory factory1
;
622 factory1
.AddOptional(MediaStreamVideoSource::kMaxWidth
, 640);
623 factory1
.AddOptional(MediaStreamVideoSource::kMaxHeight
, 480);
625 MockMediaConstraintFactory factory2
;
626 factory2
.AddMandatory(MediaStreamVideoSource::kMinAspectRatio
, 640.0 / 360);
628 TestTwoTracksWithDifferentConstraints(factory1
.CreateWebMediaConstraints(),
629 factory2
.CreateWebMediaConstraints(),
635 TEST_F(MediaStreamVideoSourceTest
,
636 TwoTracksWithSecondTrackFrameRateHigherThanFirst
) {
637 MockMediaConstraintFactory factory1
;
638 factory1
.AddMandatory(MediaStreamVideoSource::kMinFrameRate
, 15);
639 factory1
.AddMandatory(MediaStreamVideoSource::kMaxFrameRate
, 15);
641 blink::WebMediaStreamTrack track1
=
642 CreateTrackAndStartSource(factory1
.CreateWebMediaConstraints(),
643 MediaStreamVideoSource::kDefaultWidth
,
644 MediaStreamVideoSource::kDefaultHeight
,
647 MockMediaConstraintFactory factory2
;
648 factory2
.AddMandatory(MediaStreamVideoSource::kMinFrameRate
, 30);
649 blink::WebMediaStreamTrack track2
= CreateTrack(
650 "123", factory2
.CreateWebMediaConstraints());
651 EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
654 // Test that a source can change the frame resolution on the fly and that
655 // tracks sinks get the new frame size unless constraints force the frame to be
657 TEST_F(MediaStreamVideoSourceTest
, SourceChangeFrameSize
) {
658 MockMediaConstraintFactory factory
;
659 factory
.AddOptional(MediaStreamVideoSource::kMaxWidth
, 800);
660 factory
.AddOptional(MediaStreamVideoSource::kMaxHeight
, 700);
662 // Expect the source to start capture with the supported resolution.
663 blink::WebMediaStreamTrack track
=
664 CreateTrackAndStartSource(factory
.CreateWebMediaConstraints(),
667 MockMediaStreamVideoSink sink
;
668 MediaStreamVideoSink::AddToVideoTrack(
669 &sink
, sink
.GetDeliverFrameCB(), track
);
670 EXPECT_EQ(0, sink
.number_of_frames());
671 DeliverVideoFrameAndWaitForRenderer(320, 240, &sink
);
672 EXPECT_EQ(1, sink
.number_of_frames());
673 // Expect the delivered frame to be passed unchanged since its smaller than
675 EXPECT_EQ(320, sink
.frame_size().width());
676 EXPECT_EQ(240, sink
.frame_size().height());
678 DeliverVideoFrameAndWaitForRenderer(640, 480, &sink
);
679 EXPECT_EQ(2, sink
.number_of_frames());
680 // Expect the delivered frame to be passed unchanged since its smaller than
682 EXPECT_EQ(640, sink
.frame_size().width());
683 EXPECT_EQ(480, sink
.frame_size().height());
685 DeliverVideoFrameAndWaitForRenderer(1280, 720, &sink
);
687 EXPECT_EQ(3, sink
.number_of_frames());
688 // Expect a frame to be cropped since its larger than max requested.
689 EXPECT_EQ(800, sink
.frame_size().width());
690 EXPECT_EQ(700, sink
.frame_size().height());
692 MediaStreamVideoSink::RemoveFromVideoTrack(&sink
, track
);
695 TEST_F(MediaStreamVideoSourceTest
, IsConstraintSupported
) {
696 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
697 MediaStreamVideoSource::kMaxFrameRate
));
698 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
699 MediaStreamVideoSource::kMinFrameRate
));
700 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
701 MediaStreamVideoSource::kMaxWidth
));
702 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
703 MediaStreamVideoSource::kMinWidth
));
704 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
705 MediaStreamVideoSource::kMaxHeight
));
706 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
707 MediaStreamVideoSource::kMinHeight
));
708 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
709 MediaStreamVideoSource::kMaxAspectRatio
));
710 EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
711 MediaStreamVideoSource::kMinAspectRatio
));
713 EXPECT_FALSE(MediaStreamVideoSource::IsConstraintSupported(
714 "something unsupported"));
717 // Test that the constraint negotiation can handle 0.0 fps as frame rate.
718 TEST_F(MediaStreamVideoSourceTest
, Use0FpsSupportedFormat
) {
719 media::VideoCaptureFormats formats
;
720 formats
.push_back(media::VideoCaptureFormat(
721 gfx::Size(640, 480), 0.0f
, media::PIXEL_FORMAT_I420
));
722 formats
.push_back(media::VideoCaptureFormat(
723 gfx::Size(320, 240), 0.0f
, media::PIXEL_FORMAT_I420
));
724 mock_source()->SetSupportedFormats(formats
);
726 blink::WebMediaConstraints constraints
;
727 constraints
.initialize();
728 blink::WebMediaStreamTrack track
= CreateTrack("123", constraints
);
729 mock_source()->CompleteGetSupportedFormats();
730 mock_source()->StartMockedSource();
731 EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
733 MockMediaStreamVideoSink sink
;
734 MediaStreamVideoSink::AddToVideoTrack(
735 &sink
, sink
.GetDeliverFrameCB(), track
);
736 EXPECT_EQ(0, sink
.number_of_frames());
737 DeliverVideoFrameAndWaitForRenderer(320, 240, &sink
);
738 EXPECT_EQ(1, sink
.number_of_frames());
739 // Expect the delivered frame to be passed unchanged since its smaller than
741 EXPECT_EQ(320, sink
.frame_size().width());
742 EXPECT_EQ(240, sink
.frame_size().height());
743 MediaStreamVideoSink::RemoveFromVideoTrack(&sink
, track
);
746 // Test that a source producing no frames change the source readyState to muted.
747 // that in a reasonable time frame the muted state turns to false.
748 TEST_F(MediaStreamVideoSourceTest
, MutedSource
) {
749 // Setup the source for support a frame rate of 2000fps in order to test
750 // the muted event faster. This is since the frame monitoring uses
751 // PostDelayedTask that is dependent on the source frame rate.
752 media::VideoCaptureFormats formats
;
753 formats
.push_back(media::VideoCaptureFormat(
754 gfx::Size(640, 480), 2000, media::PIXEL_FORMAT_I420
));
755 SetSourceSupportedFormats(formats
);
757 MockMediaConstraintFactory factory
;
758 blink::WebMediaStreamTrack track
=
759 CreateTrackAndStartSource(factory
.CreateWebMediaConstraints(),
761 MockMediaStreamVideoSink sink
;
762 MediaStreamVideoSink::AddToVideoTrack(&sink
, sink
.GetDeliverFrameCB(), track
);
763 EXPECT_EQ(track
.source().readyState(),
764 blink::WebMediaStreamSource::ReadyStateLive
);
766 base::RunLoop run_loop
;
767 base::Closure quit_closure
= run_loop
.QuitClosure();
768 bool muted_state
= false;
769 EXPECT_CALL(*mock_source(), DoSetMutedState(_
))
770 .WillOnce(DoAll(SaveArg
<0>(&muted_state
), RunClosure(quit_closure
)));
772 EXPECT_EQ(muted_state
, true);
774 EXPECT_EQ(track
.source().readyState(),
775 blink::WebMediaStreamSource::ReadyStateMuted
);
777 base::RunLoop run_loop2
;
778 base::Closure quit_closure2
= run_loop2
.QuitClosure();
779 EXPECT_CALL(*mock_source(), DoSetMutedState(_
))
780 .WillOnce(DoAll(SaveArg
<0>(&muted_state
), RunClosure(quit_closure2
)));
781 DeliverVideoFrameAndWaitForRenderer(640, 480, &sink
);
784 EXPECT_EQ(muted_state
, false);
785 EXPECT_EQ(track
.source().readyState(),
786 blink::WebMediaStreamSource::ReadyStateLive
);
788 MediaStreamVideoSink::RemoveFromVideoTrack(&sink
, track
);
791 } // namespace content