Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / content / renderer / media / media_stream_video_source_unittest.cc
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.
4
5 #include <string>
6 #include <vector>
7
8 #include "base/bind.h"
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"
22
23 using ::testing::_;
24 using ::testing::DoAll;
25 using ::testing::SaveArg;
26
27 namespace content {
28
29 ACTION_P(RunClosure, closure) {
30   closure.Run();
31 }
32
33 class MediaStreamVideoSourceTest
34     : public ::testing::Test {
35  public:
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),
41         result_name_(""),
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_);
57   }
58
59   virtual void TearDown() {
60     webkit_source_.reset();
61     blink::WebHeap::collectAllGarbageForTesting();
62   }
63
64  protected:
65   // Create a track that's associated with |webkit_source_|.
66   blink::WebMediaStreamTrack CreateTrack(
67       const std::string& id,
68       const blink::WebMediaConstraints& constraints) {
69     bool enabled = true;
70     return MediaStreamVideoTrack::CreateVideoTrack(
71         mock_source_, constraints,
72         base::Bind(
73             &MediaStreamVideoSourceTest::OnConstraintsApplied,
74             base::Unretained(this)),
75         enabled);
76   }
77
78   blink::WebMediaStreamTrack CreateTrackAndStartSource(
79       const blink::WebMediaConstraints& constraints,
80       int expected_width,
81       int expected_height,
82       int expected_frame_rate) {
83     blink::WebMediaStreamTrack track = CreateTrack("123", constraints);
84
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);
90
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());
96     return track;
97   }
98
99   int NumberOfSuccessConstraintsCallbacks() const {
100     return number_of_successful_constraints_applied_;
101   }
102
103   int NumberOfFailedConstraintsCallbacks() const {
104     return number_of_failed_constraints_applied_;
105   }
106
107   content::MediaStreamRequestResult error_type() const { return result_; }
108   blink::WebString error_name() const { return result_name_; }
109
110   MockMediaStreamVideoSource* mock_source() { return mock_source_; }
111
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,
115                            int capture_height,
116                            const blink::WebMediaConstraints& constraints,
117                            int expected_width,
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,
122                                   30);
123
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());
129
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);
134   }
135
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);
145     run_loop.Run();
146   }
147
148   void DeliverVideoFrameAndWaitForTwoRenderers(
149       int width,
150       int height,
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);
161     run_loop.Run();
162   }
163
164   void TestTwoTracksWithDifferentConstraints(
165       const blink::WebMediaConstraints& constraints1,
166       const blink::WebMediaConstraints& constraints2,
167       int capture_width,
168       int capture_height,
169       int expected_width1,
170       int expected_height1,
171       int expected_width2,
172       int expected_height2) {
173     blink::WebMediaStreamTrack track1 =
174         CreateTrackAndStartSource(constraints1, capture_width, capture_height,
175                                   MediaStreamVideoSource::kDefaultFrameRate);
176
177     blink::WebMediaStreamTrack track2 =
178         CreateTrack("dummy", constraints2);
179
180     MockMediaStreamVideoSink sink1;
181     MediaStreamVideoSink::AddToVideoTrack(&sink1, sink1.GetDeliverFrameCB(),
182                                           track1);
183     EXPECT_EQ(0, sink1.number_of_frames());
184
185     MockMediaStreamVideoSink sink2;
186     MediaStreamVideoSink::AddToVideoTrack(&sink2, sink2.GetDeliverFrameCB(),
187                                           track2);
188     EXPECT_EQ(0, sink2.number_of_frames());
189
190     DeliverVideoFrameAndWaitForTwoRenderers(capture_width,
191                                             capture_height,
192                                             &sink1,
193                                             &sink2);
194
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());
198
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());
202
203     MediaStreamVideoSink::RemoveFromVideoTrack(&sink1, track1);
204     MediaStreamVideoSink::RemoveFromVideoTrack(&sink2, track2);
205   }
206
207   void SetSourceSupportedFormats(const media::VideoCaptureFormats& formats) {
208     mock_source_->SetSupportedFormats(formats);
209   }
210
211   void ReleaseTrackAndSourceOnAddTrackCallback(
212       const blink::WebMediaStreamTrack& track_to_release) {
213     track_to_release_ = track_to_release;
214   }
215
216  private:
217   void OnConstraintsApplied(MediaStreamSource* source,
218                             MediaStreamRequestResult result,
219                             const blink::WebString& result_name) {
220     ASSERT_EQ(source, webkit_source_.extraData());
221
222     if (result == MEDIA_DEVICE_OK) {
223       ++number_of_successful_constraints_applied_;
224     } else {
225       result_ = result;
226       result_name_ = result_name;
227       ++number_of_failed_constraints_applied_;
228     }
229
230     if (!track_to_release_.isNull()) {
231       mock_source_ = NULL;
232       webkit_source_.reset();
233       track_to_release_.reset();
234     }
235   }
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_;
246 };
247
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());
255 }
256
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());
266 }
267
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());
277 }
278
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());
286 }
287
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());
296 }
297
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);
305
306   CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), 352, 288, 5);
307 }
308
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,
317                       1280.0 / 720);
318
319   CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), 1280, 720, 30);
320 }
321
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,
330                        640.0 / 480);
331   factory.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
332
333   TestSourceCropFrame(1280, 720,
334                       factory.CreateWebMediaConstraints(), 960, 720);
335 }
336
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);
341
342   TestSourceCropFrame(MediaStreamVideoSource::kDefaultWidth,
343                       MediaStreamVideoSource::kDefaultHeight,
344                       factory.CreateWebMediaConstraints(), 640, 320);
345 }
346
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());
355 }
356
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());
364 }
365
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());
374 }
375
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());
384 }
385
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());
394 }
395
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;
400   {
401     blink::WebMediaStreamTrack track =
402         CreateTrack("123", factory.CreateWebMediaConstraints());
403     ReleaseTrackAndSourceOnAddTrackCallback(track);
404   }
405   mock_source()->CompleteGetSupportedFormats();
406   mock_source()->StartMockedSource();
407   EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
408 }
409
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);
415   {
416     blink::WebMediaStreamTrack track =
417         CreateTrack("123", factory.CreateWebMediaConstraints());
418     ReleaseTrackAndSourceOnAddTrackCallback(track);
419   }
420   mock_source()->CompleteGetSupportedFormats();
421   EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
422 }
423
424 // Test that the source ignores an optional aspect ratio that is higher than
425 // supported.
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();
432
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);
438 }
439
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);
450
451   blink::WebMediaConstraints constraints;
452   constraints.initialize();
453   CreateTrackAndStartSource(constraints,
454                             MediaStreamVideoSource::kDefaultWidth,
455                             MediaStreamVideoSource::kDefaultHeight,
456                             30);
457 }
458
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());
468 }
469
470 // Test that the source ignores an unknown optional constraint.
471 TEST_F(MediaStreamVideoSourceTest, InvalidOptionalConstraint) {
472   MockMediaConstraintFactory factory;
473   factory.AddOptional("weird key", 640);
474
475   CreateTrackAndStartSource(factory.CreateWebMediaConstraints(),
476                             MediaStreamVideoSource::kDefaultWidth,
477                             MediaStreamVideoSource::kDefaultHeight,
478                             30);
479 }
480
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);
491
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());
496 }
497
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);
507 }
508
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);
516 }
517
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);
523 }
524
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);
532 }
533
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);
541 }
542
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);
550 }
551
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(),
559                       1280, 720);
560 }
561
562 TEST_F(MediaStreamVideoSourceTest, TwoTracksWithVGAAndWVGA) {
563   MockMediaConstraintFactory factory1;
564   factory1.AddOptional(MediaStreamVideoSource::kMaxWidth, 640);
565   factory1.AddOptional(MediaStreamVideoSource::kMaxHeight, 480);
566
567   MockMediaConstraintFactory factory2;
568   factory2.AddOptional(MediaStreamVideoSource::kMaxHeight, 360);
569
570   TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
571                                         factory2.CreateWebMediaConstraints(),
572                                         640, 480,
573                                         640, 480,
574                                         640, 360);
575 }
576
577 TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndWVGA) {
578   MockMediaConstraintFactory factory1;
579   factory1.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
580   factory1.AddOptional(MediaStreamVideoSource::kMinHeight, 720);
581
582
583   MockMediaConstraintFactory factory2;
584   factory2.AddMandatory(MediaStreamVideoSource::kMaxWidth, 640);
585   factory2.AddMandatory(MediaStreamVideoSource::kMaxHeight, 360);
586
587   TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
588                                         factory2.CreateWebMediaConstraints(),
589                                         1280, 720,
590                                         1280, 720,
591                                         640, 360);
592 }
593
594 TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndW700H700) {
595   MockMediaConstraintFactory factory1;
596   factory1.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
597   factory1.AddOptional(MediaStreamVideoSource::kMinHeight, 720);
598
599   MockMediaConstraintFactory factory2;
600   factory2.AddMandatory(MediaStreamVideoSource::kMaxWidth, 700);
601   factory2.AddMandatory(MediaStreamVideoSource::kMaxHeight, 700);
602
603   TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
604                                         factory2.CreateWebMediaConstraints(),
605                                         1280, 720,
606                                         1280, 720,
607                                         700, 700);
608 }
609
610 TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndMaxAspectRatio4To3) {
611   MockMediaConstraintFactory factory1;
612   factory1.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
613   factory1.AddOptional(MediaStreamVideoSource::kMinHeight, 720);
614
615   MockMediaConstraintFactory factory2;
616   factory2.AddMandatory(MediaStreamVideoSource::kMaxAspectRatio, 640.0 / 480);
617
618   TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
619                                         factory2.CreateWebMediaConstraints(),
620                                         1280, 720,
621                                         1280, 720,
622                                         960, 720);
623 }
624
625 TEST_F(MediaStreamVideoSourceTest, TwoTracksWithVgaAndMinAspectRatio) {
626   MockMediaConstraintFactory factory1;
627   factory1.AddOptional(MediaStreamVideoSource::kMaxWidth, 640);
628   factory1.AddOptional(MediaStreamVideoSource::kMaxHeight, 480);
629
630   MockMediaConstraintFactory factory2;
631   factory2.AddMandatory(MediaStreamVideoSource::kMinAspectRatio, 640.0 / 360);
632
633   TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
634                                         factory2.CreateWebMediaConstraints(),
635                                         640, 480,
636                                         640, 480,
637                                         640, 360);
638 }
639
640 TEST_F(MediaStreamVideoSourceTest,
641        TwoTracksWithSecondTrackFrameRateHigherThanFirst) {
642   MockMediaConstraintFactory factory1;
643   factory1.AddMandatory(MediaStreamVideoSource::kMinFrameRate, 15);
644   factory1.AddMandatory(MediaStreamVideoSource::kMaxFrameRate, 15);
645
646   blink::WebMediaStreamTrack track1 =
647       CreateTrackAndStartSource(factory1.CreateWebMediaConstraints(),
648                                 MediaStreamVideoSource::kDefaultWidth,
649                                 MediaStreamVideoSource::kDefaultHeight,
650                                 15);
651
652   MockMediaConstraintFactory factory2;
653   factory2.AddMandatory(MediaStreamVideoSource::kMinFrameRate, 30);
654   blink::WebMediaStreamTrack track2 = CreateTrack(
655       "123", factory2.CreateWebMediaConstraints());
656   EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
657 }
658
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
661 // cropped.
662 TEST_F(MediaStreamVideoSourceTest, SourceChangeFrameSize) {
663   MockMediaConstraintFactory factory;
664   factory.AddOptional(MediaStreamVideoSource::kMaxWidth, 800);
665   factory.AddOptional(MediaStreamVideoSource::kMaxHeight, 700);
666
667   // Expect the source to start capture with the supported resolution.
668   blink::WebMediaStreamTrack track =
669       CreateTrackAndStartSource(factory.CreateWebMediaConstraints(),
670                                 640, 480, 30);
671
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
679   // max requested.
680   EXPECT_EQ(320, sink.frame_size().width());
681   EXPECT_EQ(240, sink.frame_size().height());
682
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
686   // max requested.
687   EXPECT_EQ(640, sink.frame_size().width());
688   EXPECT_EQ(480, sink.frame_size().height());
689
690   DeliverVideoFrameAndWaitForRenderer(1280, 720, &sink);
691
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());
696
697   MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
698 }
699
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));
717
718   EXPECT_FALSE(MediaStreamVideoSource::IsConstraintSupported(
719       "something unsupported"));
720 }
721
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);
730
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());
737
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
745   // max requested.
746   EXPECT_EQ(320, sink.frame_size().width());
747   EXPECT_EQ(240, sink.frame_size().height());
748   MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
749 }
750
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);
761
762   MockMediaConstraintFactory factory;
763   blink::WebMediaStreamTrack track =
764       CreateTrackAndStartSource(factory.CreateWebMediaConstraints(),
765                                 640, 480, 2000);
766   MockMediaStreamVideoSink sink;
767   MediaStreamVideoSink::AddToVideoTrack(&sink, sink.GetDeliverFrameCB(), track);
768   EXPECT_EQ(track.source().readyState(),
769             blink::WebMediaStreamSource::ReadyStateLive);
770
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)));
776   run_loop.Run();
777   EXPECT_EQ(muted_state, true);
778
779   EXPECT_EQ(track.source().readyState(),
780             blink::WebMediaStreamSource::ReadyStateMuted);
781
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);
787   run_loop2.Run();
788
789   EXPECT_EQ(muted_state, false);
790   EXPECT_EQ(track.source().readyState(),
791             blink::WebMediaStreamSource::ReadyStateLive);
792
793   MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
794 }
795
796 }  // namespace content