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