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