Home | History | Annotate | Download | only in media
      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
    797