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 
     22 namespace content {
     23 
     24 ACTION_P(RunClosure, closure) {
     25   closure.Run();
     26 }
     27 
     28 class MediaStreamVideoSourceTest
     29     : public ::testing::Test {
     30  public:
     31   MediaStreamVideoSourceTest()
     32       : child_process_(new ChildProcess()),
     33         number_of_successful_constraints_applied_(0),
     34         number_of_failed_constraints_applied_(0),
     35         mock_source_(new MockMediaStreamVideoSource(true)) {
     36     media::VideoCaptureFormats formats;
     37     formats.push_back(media::VideoCaptureFormat(
     38         gfx::Size(1280, 720), 30, media::PIXEL_FORMAT_I420));
     39     formats.push_back(media::VideoCaptureFormat(
     40         gfx::Size(640, 480), 30, media::PIXEL_FORMAT_I420));
     41     formats.push_back(media::VideoCaptureFormat(
     42         gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420));
     43     formats.push_back(media::VideoCaptureFormat(
     44         gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420));
     45     mock_source_->SetSupportedFormats(formats);
     46     webkit_source_.initialize(base::UTF8ToUTF16("dummy_source_id"),
     47                               blink::WebMediaStreamSource::TypeVideo,
     48                               base::UTF8ToUTF16("dummy_source_name"));
     49     webkit_source_.setExtraData(mock_source_);
     50   }
     51 
     52  protected:
     53   // Create a track that's associated with |webkit_source_|.
     54   blink::WebMediaStreamTrack CreateTrack(
     55       const std::string& id,
     56       const blink::WebMediaConstraints& constraints) {
     57     bool enabled = true;
     58     return MediaStreamVideoTrack::CreateVideoTrack(
     59         mock_source_, constraints,
     60         base::Bind(
     61             &MediaStreamVideoSourceTest::OnConstraintsApplied,
     62             base::Unretained(this)),
     63         enabled);
     64   }
     65 
     66   blink::WebMediaStreamTrack CreateTrackAndStartSource(
     67       const blink::WebMediaConstraints& constraints,
     68       int expected_width,
     69       int expected_height,
     70       int expected_frame_rate) {
     71     blink::WebMediaStreamTrack track = CreateTrack("123", constraints);
     72 
     73     mock_source_->CompleteGetSupportedFormats();
     74     const media::VideoCaptureParams& format = mock_source()->start_params();
     75     EXPECT_EQ(expected_width, format.requested_format.frame_size.width());
     76     EXPECT_EQ(expected_height, format.requested_format.frame_size.height());
     77     EXPECT_EQ(expected_frame_rate, format.requested_format.frame_rate);
     78 
     79     EXPECT_EQ(0, NumberOfSuccessConstraintsCallbacks());
     80     mock_source_->StartMockedSource();
     81     // Once the source has started successfully we expect that the
     82     // ConstraintsCallback in MediaStreamSource::AddTrack completes.
     83     EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
     84     return track;
     85   }
     86 
     87   int NumberOfSuccessConstraintsCallbacks() const {
     88     return number_of_successful_constraints_applied_;
     89   }
     90 
     91   int NumberOfFailedConstraintsCallbacks() const {
     92     return number_of_failed_constraints_applied_;
     93   }
     94 
     95   MockMediaStreamVideoSource* mock_source() { return mock_source_; }
     96 
     97   // Test that the source crops/scales to the requested width and
     98   // height even though the camera delivers a larger frame.
     99   void TestSourceCropFrame(int capture_width,
    100                            int capture_height,
    101                            const blink::WebMediaConstraints& constraints,
    102                            int expected_width,
    103                            int expected_height) {
    104     // Expect the source to start capture with the supported resolution.
    105     blink::WebMediaStreamTrack track =
    106         CreateTrackAndStartSource(constraints, capture_width, capture_height,
    107                                   30);
    108 
    109     MockMediaStreamVideoSink sink;
    110     MediaStreamVideoSink::AddToVideoTrack(
    111         &sink, sink.GetDeliverFrameCB(), track);
    112     DeliverVideoFrameAndWaitForRenderer(capture_width, capture_height, &sink);
    113     EXPECT_EQ(1, sink.number_of_frames());
    114 
    115     // Expect the delivered frame to be cropped.
    116     EXPECT_EQ(expected_height, sink.frame_size().height());
    117     EXPECT_EQ(expected_width, sink.frame_size().width());
    118     MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
    119   }
    120 
    121   void DeliverVideoFrameAndWaitForRenderer(int width, int height,
    122                                            MockMediaStreamVideoSink* sink) {
    123     base::RunLoop run_loop;
    124     base::Closure quit_closure = run_loop.QuitClosure();
    125     EXPECT_CALL(*sink, OnVideoFrame()).WillOnce(
    126         RunClosure(quit_closure));
    127     scoped_refptr<media::VideoFrame> frame =
    128               media::VideoFrame::CreateBlackFrame(gfx::Size(width, height));
    129     mock_source()->DeliverVideoFrame(frame);
    130     run_loop.Run();
    131   }
    132 
    133   void DeliverVideoFrameAndWaitForTwoRenderers(
    134       int width,
    135       int height,
    136       MockMediaStreamVideoSink* sink1,
    137       MockMediaStreamVideoSink* sink2) {
    138     base::RunLoop run_loop;
    139     base::Closure quit_closure = run_loop.QuitClosure();
    140     EXPECT_CALL(*sink1, OnVideoFrame());
    141     EXPECT_CALL(*sink2, OnVideoFrame()).WillOnce(
    142         RunClosure(quit_closure));
    143     scoped_refptr<media::VideoFrame> frame =
    144         media::VideoFrame::CreateBlackFrame(gfx::Size(width, height));
    145     mock_source()->DeliverVideoFrame(frame);
    146     run_loop.Run();
    147   }
    148 
    149   void TestTwoTracksWithDifferentConstraints(
    150       const blink::WebMediaConstraints& constraints1,
    151       const blink::WebMediaConstraints& constraints2,
    152       int capture_width,
    153       int capture_height,
    154       int expected_width1,
    155       int expected_height1,
    156       int expected_width2,
    157       int expected_height2) {
    158     blink::WebMediaStreamTrack track1 =
    159         CreateTrackAndStartSource(constraints1, capture_width, capture_height,
    160                                   MediaStreamVideoSource::kDefaultFrameRate);
    161 
    162     blink::WebMediaStreamTrack track2 =
    163         CreateTrack("dummy", constraints2);
    164 
    165     MockMediaStreamVideoSink sink1;
    166     MediaStreamVideoSink::AddToVideoTrack(&sink1, sink1.GetDeliverFrameCB(),
    167                                           track1);
    168     EXPECT_EQ(0, sink1.number_of_frames());
    169 
    170     MockMediaStreamVideoSink sink2;
    171     MediaStreamVideoSink::AddToVideoTrack(&sink2, sink2.GetDeliverFrameCB(),
    172                                           track2);
    173     EXPECT_EQ(0, sink2.number_of_frames());
    174 
    175     DeliverVideoFrameAndWaitForTwoRenderers(capture_width,
    176                                             capture_height,
    177                                             &sink1,
    178                                             &sink2);
    179 
    180     EXPECT_EQ(1, sink1.number_of_frames());
    181     EXPECT_EQ(expected_width1, sink1.frame_size().width());
    182     EXPECT_EQ(expected_height1, sink1.frame_size().height());
    183 
    184     EXPECT_EQ(1, sink2.number_of_frames());
    185     EXPECT_EQ(expected_width2, sink2.frame_size().width());
    186     EXPECT_EQ(expected_height2, sink2.frame_size().height());
    187 
    188     MediaStreamVideoSink::RemoveFromVideoTrack(&sink1, track1);
    189     MediaStreamVideoSink::RemoveFromVideoTrack(&sink2, track2);
    190   }
    191 
    192   void ReleaseTrackAndSourceOnAddTrackCallback(
    193       const blink::WebMediaStreamTrack& track_to_release) {
    194     track_to_release_ = track_to_release;
    195   }
    196 
    197  private:
    198   void OnConstraintsApplied(MediaStreamSource* source, bool success) {
    199     ASSERT_EQ(source, webkit_source_.extraData());
    200 
    201     if (success)
    202       ++number_of_successful_constraints_applied_;
    203     else
    204       ++number_of_failed_constraints_applied_;
    205 
    206     if (!track_to_release_.isNull()) {
    207       mock_source_ = NULL;
    208       webkit_source_.reset();
    209       track_to_release_.reset();
    210     }
    211   }
    212   base::MessageLoopForUI message_loop_;
    213   scoped_ptr<ChildProcess> child_process_;
    214   blink::WebMediaStreamTrack track_to_release_;
    215   int number_of_successful_constraints_applied_;
    216   int number_of_failed_constraints_applied_;
    217   blink::WebMediaStreamSource webkit_source_;
    218   // |mock_source_| is owned by |webkit_source_|.
    219   MockMediaStreamVideoSource* mock_source_;
    220 };
    221 
    222 TEST_F(MediaStreamVideoSourceTest, AddTrackAndStartSource) {
    223   blink::WebMediaConstraints constraints;
    224   constraints.initialize();
    225   blink::WebMediaStreamTrack track = CreateTrack("123", constraints);
    226   mock_source()->CompleteGetSupportedFormats();
    227   mock_source()->StartMockedSource();
    228   EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
    229 }
    230 
    231 TEST_F(MediaStreamVideoSourceTest, AddTwoTracksBeforeSourceStarts) {
    232   blink::WebMediaConstraints constraints;
    233   constraints.initialize();
    234   blink::WebMediaStreamTrack track1 = CreateTrack("123", constraints);
    235   mock_source()->CompleteGetSupportedFormats();
    236   blink::WebMediaStreamTrack track2 = CreateTrack("123", constraints);
    237   EXPECT_EQ(0, NumberOfSuccessConstraintsCallbacks());
    238   mock_source()->StartMockedSource();
    239   EXPECT_EQ(2, NumberOfSuccessConstraintsCallbacks());
    240 }
    241 
    242 TEST_F(MediaStreamVideoSourceTest, AddTrackAfterSourceStarts) {
    243   blink::WebMediaConstraints constraints;
    244   constraints.initialize();
    245   blink::WebMediaStreamTrack track1 = CreateTrack("123", constraints);
    246   mock_source()->CompleteGetSupportedFormats();
    247   mock_source()->StartMockedSource();
    248   EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
    249   blink::WebMediaStreamTrack track2 = CreateTrack("123", constraints);
    250   EXPECT_EQ(2, NumberOfSuccessConstraintsCallbacks());
    251 }
    252 
    253 TEST_F(MediaStreamVideoSourceTest, AddTrackAndFailToStartSource) {
    254   blink::WebMediaConstraints constraints;
    255   constraints.initialize();
    256   blink::WebMediaStreamTrack track = CreateTrack("123", constraints);
    257   mock_source()->CompleteGetSupportedFormats();
    258   mock_source()->FailToStartMockedSource();
    259   EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
    260 }
    261 
    262 TEST_F(MediaStreamVideoSourceTest, AddTwoTracksBeforeGetSupportedFormats) {
    263   blink::WebMediaConstraints constraints;
    264   constraints.initialize();
    265   blink::WebMediaStreamTrack track1 = CreateTrack("123", constraints);
    266   blink::WebMediaStreamTrack track2 = CreateTrack("123", constraints);
    267   mock_source()->CompleteGetSupportedFormats();
    268   mock_source()->StartMockedSource();
    269   EXPECT_EQ(2, NumberOfSuccessConstraintsCallbacks());
    270 }
    271 
    272 // Test that the capture output is CIF if we set max constraints to CIF.
    273 // and the capture device support CIF.
    274 TEST_F(MediaStreamVideoSourceTest, MandatoryConstraintCif5Fps) {
    275   MockMediaConstraintFactory factory;
    276   factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 352);
    277   factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 288);
    278   factory.AddMandatory(MediaStreamVideoSource::kMaxFrameRate, 5);
    279 
    280   CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), 352, 288, 5);
    281 }
    282 
    283 // Test that the capture output is 720P if the camera support it and the
    284 // optional constraint is set to 720P.
    285 TEST_F(MediaStreamVideoSourceTest, MandatoryMinVgaOptional720P) {
    286   MockMediaConstraintFactory factory;
    287   factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 640);
    288   factory.AddMandatory(MediaStreamVideoSource::kMinHeight, 480);
    289   factory.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
    290   factory.AddOptional(MediaStreamVideoSource::kMinAspectRatio,
    291                       1280.0 / 720);
    292 
    293   CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), 1280, 720, 30);
    294 }
    295 
    296 // Test that the capture output have aspect ratio 4:3 if a mandatory constraint
    297 // require it even if an optional constraint request a higher resolution
    298 // that don't have this aspect ratio.
    299 TEST_F(MediaStreamVideoSourceTest, MandatoryAspectRatio4To3) {
    300   MockMediaConstraintFactory factory;
    301   factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 640);
    302   factory.AddMandatory(MediaStreamVideoSource::kMinHeight, 480);
    303   factory.AddMandatory(MediaStreamVideoSource::kMaxAspectRatio,
    304                        640.0 / 480);
    305   factory.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
    306 
    307   TestSourceCropFrame(1280, 720,
    308                       factory.CreateWebMediaConstraints(), 960, 720);
    309 }
    310 
    311 // Test that AddTrack succeeds if the mandatory min aspect ratio it set to 2.
    312 TEST_F(MediaStreamVideoSourceTest, MandatoryAspectRatio2) {
    313   MockMediaConstraintFactory factory;
    314   factory.AddMandatory(MediaStreamVideoSource::kMinAspectRatio, 2);
    315 
    316   TestSourceCropFrame(MediaStreamVideoSource::kDefaultWidth,
    317                       MediaStreamVideoSource::kDefaultHeight,
    318                       factory.CreateWebMediaConstraints(), 640, 320);
    319 }
    320 
    321 TEST_F(MediaStreamVideoSourceTest, MinAspectRatioLargerThanMaxAspectRatio) {
    322   MockMediaConstraintFactory factory;
    323   factory.AddMandatory(MediaStreamVideoSource::kMinAspectRatio, 2);
    324   factory.AddMandatory(MediaStreamVideoSource::kMaxAspectRatio, 1);
    325   blink::WebMediaStreamTrack track = CreateTrack(
    326       "123", factory.CreateWebMediaConstraints());
    327   mock_source()->CompleteGetSupportedFormats();
    328   EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
    329 }
    330 
    331 TEST_F(MediaStreamVideoSourceTest, MaxAspectRatioZero) {
    332   MockMediaConstraintFactory factory;
    333   factory.AddOptional(MediaStreamVideoSource::kMaxAspectRatio, 0);
    334   blink::WebMediaStreamTrack track = CreateTrack(
    335       "123", factory.CreateWebMediaConstraints());
    336   mock_source()->CompleteGetSupportedFormats();
    337   EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
    338 }
    339 
    340 TEST_F(MediaStreamVideoSourceTest, MinWidthLargerThanMaxWidth) {
    341   MockMediaConstraintFactory factory;
    342   factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 640);
    343   factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 320);
    344   blink::WebMediaStreamTrack track = CreateTrack(
    345       "123", factory.CreateWebMediaConstraints());
    346   mock_source()->CompleteGetSupportedFormats();
    347   EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
    348 }
    349 
    350 TEST_F(MediaStreamVideoSourceTest, MinHeightLargerThanMaxHeight) {
    351   MockMediaConstraintFactory factory;
    352   factory.AddMandatory(MediaStreamVideoSource::kMinHeight, 480);
    353   factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 360);
    354   blink::WebMediaStreamTrack track = CreateTrack(
    355       "123", factory.CreateWebMediaConstraints());
    356   mock_source()->CompleteGetSupportedFormats();
    357   EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
    358 }
    359 
    360 // Test that its safe to release the last reference of a blink track and the
    361 // source during the callback if adding a track succeeds.
    362 TEST_F(MediaStreamVideoSourceTest, ReleaseTrackAndSourceOnSuccessCallBack) {
    363   MockMediaConstraintFactory factory;
    364   {
    365     blink::WebMediaStreamTrack track =
    366         CreateTrack("123", factory.CreateWebMediaConstraints());
    367     ReleaseTrackAndSourceOnAddTrackCallback(track);
    368   }
    369   mock_source()->CompleteGetSupportedFormats();
    370   mock_source()->StartMockedSource();
    371   EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
    372 }
    373 
    374 // Test that its safe to release the last reference of a blink track and the
    375 // source during the callback if adding a track fails.
    376 TEST_F(MediaStreamVideoSourceTest, ReleaseTrackAndSourceOnFailureCallBack) {
    377   MockMediaConstraintFactory factory;
    378   factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 99999);
    379   {
    380     blink::WebMediaStreamTrack track =
    381         CreateTrack("123", factory.CreateWebMediaConstraints());
    382     ReleaseTrackAndSourceOnAddTrackCallback(track);
    383   }
    384   mock_source()->CompleteGetSupportedFormats();
    385   EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
    386 }
    387 
    388 // Test that the source ignores an optional aspect ratio that is higher than
    389 // supported.
    390 TEST_F(MediaStreamVideoSourceTest, OptionalAspectRatioTooHigh) {
    391   MockMediaConstraintFactory factory;
    392   factory.AddOptional(MediaStreamVideoSource::kMinAspectRatio, 2);
    393   blink::WebMediaStreamTrack track = CreateTrack(
    394       "123", factory.CreateWebMediaConstraints());
    395   mock_source()->CompleteGetSupportedFormats();
    396 
    397   const media::VideoCaptureParams& params = mock_source()->start_params();
    398   double aspect_ratio =
    399       static_cast<double>(params.requested_format.frame_size.width()) /
    400       params.requested_format.frame_size.height();
    401   EXPECT_LT(aspect_ratio, 2);
    402 }
    403 
    404 // Test that the source starts video with the default resolution if the
    405 // that is the only supported.
    406 TEST_F(MediaStreamVideoSourceTest, DefaultCapability) {
    407   media::VideoCaptureFormats formats;
    408   formats.push_back(media::VideoCaptureFormat(
    409       gfx::Size(MediaStreamVideoSource::kDefaultWidth,
    410                 MediaStreamVideoSource::kDefaultHeight),
    411       MediaStreamVideoSource::kDefaultFrameRate,
    412       media::PIXEL_FORMAT_I420));
    413   mock_source()->SetSupportedFormats(formats);
    414 
    415   blink::WebMediaConstraints constraints;
    416   constraints.initialize();
    417   CreateTrackAndStartSource(constraints,
    418                             MediaStreamVideoSource::kDefaultWidth,
    419                             MediaStreamVideoSource::kDefaultHeight,
    420                             30);
    421 }
    422 
    423 TEST_F(MediaStreamVideoSourceTest, InvalidMandatoryConstraint) {
    424   MockMediaConstraintFactory factory;
    425   factory.AddMandatory("weird key", 640);
    426   blink::WebMediaStreamTrack track = CreateTrack(
    427       "123", factory.CreateWebMediaConstraints());
    428   mock_source()->CompleteGetSupportedFormats();
    429   EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
    430 }
    431 
    432 // Test that the source ignores an unknown optional constraint.
    433 TEST_F(MediaStreamVideoSourceTest, InvalidOptionalConstraint) {
    434   MockMediaConstraintFactory factory;
    435   factory.AddOptional("weird key", 640);
    436 
    437   CreateTrackAndStartSource(factory.CreateWebMediaConstraints(),
    438                             MediaStreamVideoSource::kDefaultWidth,
    439                             MediaStreamVideoSource::kDefaultHeight,
    440                             30);
    441 }
    442 
    443 // Tests that the source starts video with the max width and height set by
    444 // constraints for screencast.
    445 TEST_F(MediaStreamVideoSourceTest, ScreencastResolutionWithConstraint) {
    446   media::VideoCaptureFormats formats;
    447       formats.push_back(media::VideoCaptureFormat(
    448           gfx::Size(480, 270), 30, media::PIXEL_FORMAT_I420));
    449   mock_source()->SetSupportedFormats(formats);
    450   MockMediaConstraintFactory factory;
    451   factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 480);
    452   factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 270);
    453 
    454   blink::WebMediaStreamTrack track = CreateTrackAndStartSource(
    455       factory.CreateWebMediaConstraints(), 480, 270, 30);
    456   EXPECT_EQ(480, mock_source()->max_requested_height());
    457   EXPECT_EQ(270, mock_source()->max_requested_width());
    458 }
    459 
    460 // Test that optional constraints are applied in order.
    461 TEST_F(MediaStreamVideoSourceTest, OptionalConstraints) {
    462   MockMediaConstraintFactory factory;
    463   // Min width of 2056 pixels can not be fulfilled.
    464   factory.AddOptional(MediaStreamVideoSource::kMinWidth, 2056);
    465   factory.AddOptional(MediaStreamVideoSource::kMinWidth, 641);
    466   // Since min width is set to 641 pixels, max width 640 can not be fulfilled.
    467   factory.AddOptional(MediaStreamVideoSource::kMaxWidth, 640);
    468   CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), 1280, 720, 30);
    469 }
    470 
    471 // Test that the source crops to the requested max width and
    472 // height even though the camera delivers a larger frame.
    473 TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrameOptional640360) {
    474   MockMediaConstraintFactory factory;
    475   factory.AddOptional(MediaStreamVideoSource::kMaxWidth, 640);
    476   factory.AddOptional(MediaStreamVideoSource::kMaxHeight, 360);
    477   TestSourceCropFrame(640, 480, factory.CreateWebMediaConstraints(), 640, 360);
    478 }
    479 
    480 TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrameMandatory640360) {
    481   MockMediaConstraintFactory factory;
    482   factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 640);
    483   factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 360);
    484   TestSourceCropFrame(640, 480, factory.CreateWebMediaConstraints(), 640, 360);
    485 }
    486 
    487 TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrameMandatory732489) {
    488   MockMediaConstraintFactory factory;
    489   factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 732);
    490   factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 489);
    491   factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 732);
    492   factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 489);
    493   TestSourceCropFrame(1280, 720, factory.CreateWebMediaConstraints(), 732, 489);
    494 }
    495 
    496 // Test that the source crops to the requested max width and
    497 // height even though the requested frame has odd size.
    498 TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrame637359) {
    499   MockMediaConstraintFactory factory;
    500   factory.AddOptional(MediaStreamVideoSource::kMaxWidth, 637);
    501   factory.AddOptional(MediaStreamVideoSource::kMaxHeight, 359);
    502   TestSourceCropFrame(640, 480, factory.CreateWebMediaConstraints(), 637, 359);
    503 }
    504 
    505 TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrame320320) {
    506   MockMediaConstraintFactory factory;
    507   factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 320);
    508   factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 320);
    509   factory.AddMandatory(MediaStreamVideoSource::kMinHeight, 320);
    510   factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 320);
    511   TestSourceCropFrame(640, 480, factory.CreateWebMediaConstraints(), 320, 320);
    512 }
    513 
    514 TEST_F(MediaStreamVideoSourceTest, DeliverSmallerSizeWhenTooLargeMax) {
    515   MockMediaConstraintFactory factory;
    516   factory.AddOptional(MediaStreamVideoSource::kMaxWidth, 1920);
    517   factory.AddOptional(MediaStreamVideoSource::kMaxHeight, 1080);
    518   factory.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
    519   factory.AddOptional(MediaStreamVideoSource::kMinHeight, 720);
    520   TestSourceCropFrame(1280, 720, factory.CreateWebMediaConstraints(),
    521                       1280, 720);
    522 }
    523 
    524 TEST_F(MediaStreamVideoSourceTest, TwoTracksWithVGAAndWVGA) {
    525   MockMediaConstraintFactory factory1;
    526   factory1.AddOptional(MediaStreamVideoSource::kMaxWidth, 640);
    527   factory1.AddOptional(MediaStreamVideoSource::kMaxHeight, 480);
    528 
    529   MockMediaConstraintFactory factory2;
    530   factory2.AddOptional(MediaStreamVideoSource::kMaxHeight, 360);
    531 
    532   TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
    533                                         factory2.CreateWebMediaConstraints(),
    534                                         640, 480,
    535                                         640, 480,
    536                                         640, 360);
    537 }
    538 
    539 TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndWVGA) {
    540   MockMediaConstraintFactory factory1;
    541   factory1.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
    542   factory1.AddOptional(MediaStreamVideoSource::kMinHeight, 720);
    543 
    544 
    545   MockMediaConstraintFactory factory2;
    546   factory2.AddMandatory(MediaStreamVideoSource::kMaxWidth, 640);
    547   factory2.AddMandatory(MediaStreamVideoSource::kMaxHeight, 360);
    548 
    549   TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
    550                                         factory2.CreateWebMediaConstraints(),
    551                                         1280, 720,
    552                                         1280, 720,
    553                                         640, 360);
    554 }
    555 
    556 TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndW700H700) {
    557   MockMediaConstraintFactory factory1;
    558   factory1.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
    559   factory1.AddOptional(MediaStreamVideoSource::kMinHeight, 720);
    560 
    561   MockMediaConstraintFactory factory2;
    562   factory2.AddMandatory(MediaStreamVideoSource::kMaxWidth, 700);
    563   factory2.AddMandatory(MediaStreamVideoSource::kMaxHeight, 700);
    564 
    565   TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
    566                                         factory2.CreateWebMediaConstraints(),
    567                                         1280, 720,
    568                                         1280, 720,
    569                                         700, 700);
    570 }
    571 
    572 TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndMaxAspectRatio4To3) {
    573   MockMediaConstraintFactory factory1;
    574   factory1.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
    575   factory1.AddOptional(MediaStreamVideoSource::kMinHeight, 720);
    576 
    577   MockMediaConstraintFactory factory2;
    578   factory2.AddMandatory(MediaStreamVideoSource::kMaxAspectRatio, 640.0 / 480);
    579 
    580   TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
    581                                         factory2.CreateWebMediaConstraints(),
    582                                         1280, 720,
    583                                         1280, 720,
    584                                         960, 720);
    585 }
    586 
    587 TEST_F(MediaStreamVideoSourceTest, TwoTracksWithVgaAndMinAspectRatio) {
    588   MockMediaConstraintFactory factory1;
    589   factory1.AddOptional(MediaStreamVideoSource::kMaxWidth, 640);
    590   factory1.AddOptional(MediaStreamVideoSource::kMaxHeight, 480);
    591 
    592   MockMediaConstraintFactory factory2;
    593   factory2.AddMandatory(MediaStreamVideoSource::kMinAspectRatio, 640.0 / 360);
    594 
    595   TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
    596                                         factory2.CreateWebMediaConstraints(),
    597                                         640, 480,
    598                                         640, 480,
    599                                         640, 360);
    600 }
    601 
    602 // Test that a source can change the frame resolution on the fly and that
    603 // tracks sinks get the new frame size unless constraints force the frame to be
    604 // cropped.
    605 TEST_F(MediaStreamVideoSourceTest, SourceChangeFrameSize) {
    606   MockMediaConstraintFactory factory;
    607   factory.AddOptional(MediaStreamVideoSource::kMaxWidth, 800);
    608   factory.AddOptional(MediaStreamVideoSource::kMaxHeight, 700);
    609 
    610   // Expect the source to start capture with the supported resolution.
    611   blink::WebMediaStreamTrack track =
    612       CreateTrackAndStartSource(factory.CreateWebMediaConstraints(),
    613                                 640, 480, 30);
    614 
    615   MockMediaStreamVideoSink sink;
    616   MediaStreamVideoSink::AddToVideoTrack(
    617       &sink, sink.GetDeliverFrameCB(), track);
    618   EXPECT_EQ(0, sink.number_of_frames());
    619   DeliverVideoFrameAndWaitForRenderer(320, 240, &sink);
    620   EXPECT_EQ(1, sink.number_of_frames());
    621   // Expect the delivered frame to be passed unchanged since its smaller than
    622   // max requested.
    623   EXPECT_EQ(320, sink.frame_size().width());
    624   EXPECT_EQ(240, sink.frame_size().height());
    625 
    626   DeliverVideoFrameAndWaitForRenderer(640, 480, &sink);
    627   EXPECT_EQ(2, sink.number_of_frames());
    628   // Expect the delivered frame to be passed unchanged since its smaller than
    629   // max requested.
    630   EXPECT_EQ(640, sink.frame_size().width());
    631   EXPECT_EQ(480, sink.frame_size().height());
    632 
    633   DeliverVideoFrameAndWaitForRenderer(1280, 720, &sink);
    634 
    635   EXPECT_EQ(3, sink.number_of_frames());
    636   // Expect a frame to be cropped since its larger than max requested.
    637   EXPECT_EQ(800, sink.frame_size().width());
    638   EXPECT_EQ(700, sink.frame_size().height());
    639 
    640   MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
    641 }
    642 
    643 TEST_F(MediaStreamVideoSourceTest, IsConstraintSupported) {
    644   EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
    645           MediaStreamVideoSource::kMaxFrameRate));
    646   EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
    647         MediaStreamVideoSource::kMinFrameRate));
    648   EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
    649       MediaStreamVideoSource::kMaxWidth));
    650   EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
    651         MediaStreamVideoSource::kMinWidth));
    652   EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
    653         MediaStreamVideoSource::kMaxHeight));
    654   EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
    655       MediaStreamVideoSource::kMinHeight));
    656   EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
    657         MediaStreamVideoSource::kMaxAspectRatio));
    658   EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
    659       MediaStreamVideoSource::kMinAspectRatio));
    660 
    661   EXPECT_FALSE(MediaStreamVideoSource::IsConstraintSupported(
    662       "something unsupported"));
    663 }
    664 
    665 // Test that the constraint negotiation can handle 0.0 fps as frame rate.
    666 TEST_F(MediaStreamVideoSourceTest, Use0FpsSupportedFormat) {
    667   media::VideoCaptureFormats formats;
    668   formats.push_back(media::VideoCaptureFormat(
    669       gfx::Size(640, 480), 0.0f, media::PIXEL_FORMAT_I420));
    670   formats.push_back(media::VideoCaptureFormat(
    671       gfx::Size(320, 240), 0.0f, media::PIXEL_FORMAT_I420));
    672   mock_source()->SetSupportedFormats(formats);
    673 
    674   blink::WebMediaConstraints constraints;
    675   constraints.initialize();
    676   blink::WebMediaStreamTrack track = CreateTrack("123", constraints);
    677   mock_source()->CompleteGetSupportedFormats();
    678   mock_source()->StartMockedSource();
    679   EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
    680 
    681   MockMediaStreamVideoSink sink;
    682   MediaStreamVideoSink::AddToVideoTrack(
    683       &sink, sink.GetDeliverFrameCB(), track);
    684   EXPECT_EQ(0, sink.number_of_frames());
    685   DeliverVideoFrameAndWaitForRenderer(320, 240, &sink);
    686   EXPECT_EQ(1, sink.number_of_frames());
    687   // Expect the delivered frame to be passed unchanged since its smaller than
    688   // max requested.
    689   EXPECT_EQ(320, sink.frame_size().width());
    690   EXPECT_EQ(240, sink.frame_size().height());
    691   MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
    692 }
    693 
    694 }  // namespace content
    695