OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/message_loop/message_loop.h" | 5 #include "base/message_loop/message_loop.h" |
6 #include "cc/layers/append_quads_data.h" | 6 #include "cc/layers/append_quads_data.h" |
7 #include "cc/output/gl_renderer.h" | 7 #include "cc/output/gl_renderer.h" |
8 #include "cc/quads/draw_quad.h" | 8 #include "cc/quads/draw_quad.h" |
9 #include "cc/quads/picture_draw_quad.h" | 9 #include "cc/quads/picture_draw_quad.h" |
10 #include "cc/quads/texture_draw_quad.h" | 10 #include "cc/quads/texture_draw_quad.h" |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 uint8_t* u_row = video_frame->data(media::VideoFrame::kUPlane) + | 416 uint8_t* u_row = video_frame->data(media::VideoFrame::kUPlane) + |
417 video_frame->stride(media::VideoFrame::kUPlane) * i; | 417 video_frame->stride(media::VideoFrame::kUPlane) * i; |
418 uint8_t* v_row = video_frame->data(media::VideoFrame::kVPlane) + | 418 uint8_t* v_row = video_frame->data(media::VideoFrame::kVPlane) + |
419 video_frame->stride(media::VideoFrame::kVPlane) * i; | 419 video_frame->stride(media::VideoFrame::kVPlane) * i; |
420 for (int j = 0; j < video_frame->row_bytes(media::VideoFrame::kUPlane); | 420 for (int j = 0; j < video_frame->row_bytes(media::VideoFrame::kUPlane); |
421 ++j) { | 421 ++j) { |
422 u_row[j] = (u_value += 3); | 422 u_row[j] = (u_value += 3); |
423 v_row[j] = (v_value += 5); | 423 v_row[j] = (v_value += 5); |
424 } | 424 } |
425 } | 425 } |
| 426 uint8 alpha_value = is_transparent ? 0 : 128; |
426 CreateTestYUVVideoDrawQuad_FromVideoFrame( | 427 CreateTestYUVVideoDrawQuad_FromVideoFrame( |
427 shared_state, video_frame, is_transparent, tex_coord_rect, render_pass); | 428 shared_state, video_frame, alpha_value, tex_coord_rect, render_pass); |
428 } | 429 } |
429 | 430 |
430 void CreateTestYUVVideoDrawQuad_Solid(const SharedQuadState* shared_state, | 431 void CreateTestYUVVideoDrawQuad_Solid(const SharedQuadState* shared_state, |
431 media::VideoFrame::Format format, | 432 media::VideoFrame::Format format, |
432 bool is_transparent, | 433 bool is_transparent, |
433 const gfx::RectF& tex_coord_rect, | 434 const gfx::RectF& tex_coord_rect, |
434 uint8 y, | 435 uint8 y, |
435 uint8 u, | 436 uint8 u, |
436 uint8 v, | 437 uint8 v, |
437 RenderPass* render_pass) { | 438 RenderPass* render_pass) { |
(...skipping 11 matching lines...) Expand all Loading... |
449 video_frame->rows(media::VideoFrame::kYPlane)); | 450 video_frame->rows(media::VideoFrame::kYPlane)); |
450 memset(video_frame->data(media::VideoFrame::kUPlane), | 451 memset(video_frame->data(media::VideoFrame::kUPlane), |
451 u, | 452 u, |
452 video_frame->stride(media::VideoFrame::kUPlane) * | 453 video_frame->stride(media::VideoFrame::kUPlane) * |
453 video_frame->rows(media::VideoFrame::kUPlane)); | 454 video_frame->rows(media::VideoFrame::kUPlane)); |
454 memset(video_frame->data(media::VideoFrame::kVPlane), | 455 memset(video_frame->data(media::VideoFrame::kVPlane), |
455 v, | 456 v, |
456 video_frame->stride(media::VideoFrame::kVPlane) * | 457 video_frame->stride(media::VideoFrame::kVPlane) * |
457 video_frame->rows(media::VideoFrame::kVPlane)); | 458 video_frame->rows(media::VideoFrame::kVPlane)); |
458 | 459 |
| 460 uint8 alpha_value = is_transparent ? 0 : 128; |
459 CreateTestYUVVideoDrawQuad_FromVideoFrame( | 461 CreateTestYUVVideoDrawQuad_FromVideoFrame( |
460 shared_state, video_frame, is_transparent, tex_coord_rect, render_pass); | 462 shared_state, video_frame, alpha_value, tex_coord_rect, render_pass); |
| 463 } |
| 464 |
| 465 void CreateEdgeBleedPass(media::VideoFrame::Format format, |
| 466 RenderPassList* pass_list) { |
| 467 gfx::Rect rect(200, 200); |
| 468 |
| 469 RenderPassId id(1, 1); |
| 470 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect); |
| 471 |
| 472 // Scale the video up so that bilinear filtering kicks in to sample more |
| 473 // than just nearest neighbor would. |
| 474 gfx::Transform scale_by_2; |
| 475 scale_by_2.Scale(2.f, 2.f); |
| 476 gfx::Rect half_rect(100, 100); |
| 477 SharedQuadState* shared_state = |
| 478 CreateTestSharedQuadState(scale_by_2, half_rect, pass.get()); |
| 479 |
| 480 gfx::Size background_size(200, 200); |
| 481 gfx::Rect green_rect(16, 20, 100, 100); |
| 482 gfx::RectF tex_coord_rect( |
| 483 static_cast<float>(green_rect.x()) / background_size.width(), |
| 484 static_cast<float>(green_rect.y()) / background_size.height(), |
| 485 static_cast<float>(green_rect.width()) / background_size.width(), |
| 486 static_cast<float>(green_rect.height()) / background_size.height()); |
| 487 |
| 488 // YUV of (149,43,21) should be green (0,255,0) in RGB. |
| 489 // Create a video frame that has a non-green background rect, with a |
| 490 // green sub-rectangle that should be the only thing displayed in |
| 491 // the final image. Bleeding will appear on all four sides of the video |
| 492 // if the tex coords are not clamped. |
| 493 CreateTestYUVVideoDrawQuad_TwoColor(shared_state, format, false, |
| 494 tex_coord_rect, background_size, 0, 0, |
| 495 0, green_rect, 149, 43, 21, pass.get()); |
| 496 pass_list->push_back(pass.Pass()); |
| 497 } |
| 498 |
| 499 // Creates a video frame of size background_size filled with yuv_background, |
| 500 // and then draws a foreground rectangle in a different color on top of |
| 501 // that. The foreground rectangle must have coordinates that are divisible |
| 502 // by 2 because YUV is a block format. |
| 503 void CreateTestYUVVideoDrawQuad_TwoColor(const SharedQuadState* shared_state, |
| 504 media::VideoFrame::Format format, |
| 505 bool is_transparent, |
| 506 const gfx::RectF& tex_coord_rect, |
| 507 const gfx::Size& background_size, |
| 508 uint8 y_background, |
| 509 uint8 u_background, |
| 510 uint8 v_background, |
| 511 const gfx::Rect& foreground_rect, |
| 512 uint8 y_foreground, |
| 513 uint8 u_foreground, |
| 514 uint8 v_foreground, |
| 515 RenderPass* render_pass) { |
| 516 const gfx::Rect rect(background_size); |
| 517 |
| 518 scoped_refptr<media::VideoFrame> video_frame = |
| 519 media::VideoFrame::CreateFrame(format, background_size, foreground_rect, |
| 520 foreground_rect.size(), |
| 521 base::TimeDelta()); |
| 522 |
| 523 int planes[] = {media::VideoFrame::kYPlane, |
| 524 media::VideoFrame::kUPlane, |
| 525 media::VideoFrame::kVPlane}; |
| 526 uint8 yuv_background[] = {y_background, u_background, v_background}; |
| 527 uint8 yuv_foreground[] = {y_foreground, u_foreground, v_foreground}; |
| 528 int sample_size[] = {1, 2, 2}; |
| 529 |
| 530 for (int i = 0; i < 3; ++i) { |
| 531 memset(video_frame->data(planes[i]), yuv_background[i], |
| 532 video_frame->stride(planes[i]) * video_frame->rows(planes[i])); |
| 533 } |
| 534 |
| 535 for (int i = 0; i < 3; ++i) { |
| 536 // Since yuv encoding uses block encoding, widths have to be divisible |
| 537 // by the sample size in order for this function to behave properly. |
| 538 DCHECK_EQ(foreground_rect.x() % sample_size[i], 0); |
| 539 DCHECK_EQ(foreground_rect.y() % sample_size[i], 0); |
| 540 DCHECK_EQ(foreground_rect.width() % sample_size[i], 0); |
| 541 DCHECK_EQ(foreground_rect.height() % sample_size[i], 0); |
| 542 |
| 543 gfx::Rect sample_rect(foreground_rect.x() / sample_size[i], |
| 544 foreground_rect.y() / sample_size[i], |
| 545 foreground_rect.width() / sample_size[i], |
| 546 foreground_rect.height() / sample_size[i]); |
| 547 for (int y = sample_rect.y(); y < sample_rect.bottom(); ++y) { |
| 548 for (int x = sample_rect.x(); x < sample_rect.right(); ++x) { |
| 549 size_t offset = y * video_frame->stride(planes[i]) + x; |
| 550 video_frame->data(planes[i])[offset] = yuv_foreground[i]; |
| 551 } |
| 552 } |
| 553 } |
| 554 |
| 555 uint8 alpha_value = 255; |
| 556 CreateTestYUVVideoDrawQuad_FromVideoFrame( |
| 557 shared_state, video_frame, alpha_value, tex_coord_rect, render_pass); |
461 } | 558 } |
462 | 559 |
463 void CreateTestYUVVideoDrawQuad_FromVideoFrame( | 560 void CreateTestYUVVideoDrawQuad_FromVideoFrame( |
464 const SharedQuadState* shared_state, | 561 const SharedQuadState* shared_state, |
465 scoped_refptr<media::VideoFrame> video_frame, | 562 scoped_refptr<media::VideoFrame> video_frame, |
466 bool is_transparent, | 563 uint8 alpha_value, |
467 const gfx::RectF& tex_coord_rect, | 564 const gfx::RectF& tex_coord_rect, |
468 RenderPass* render_pass) { | 565 RenderPass* render_pass) { |
469 const bool with_alpha = (video_frame->format() == media::VideoFrame::YV12A); | 566 const bool with_alpha = (video_frame->format() == media::VideoFrame::YV12A); |
470 const YUVVideoDrawQuad::ColorSpace color_space = | 567 const YUVVideoDrawQuad::ColorSpace color_space = |
471 (video_frame->format() == media::VideoFrame::YV12J | 568 (video_frame->format() == media::VideoFrame::YV12J |
472 ? YUVVideoDrawQuad::REC_601_JPEG | 569 ? YUVVideoDrawQuad::REC_601_JPEG |
473 : YUVVideoDrawQuad::REC_601); | 570 : YUVVideoDrawQuad::REC_601); |
474 const gfx::Rect rect(this->device_viewport_size_); | 571 const gfx::Rect rect(shared_state->content_bounds); |
475 const gfx::Rect opaque_rect(0, 0, 0, 0); | 572 const gfx::Rect opaque_rect(0, 0, 0, 0); |
476 | 573 |
477 if (with_alpha) | 574 if (with_alpha) |
478 memset(video_frame->data(media::VideoFrame::kAPlane), | 575 memset(video_frame->data(media::VideoFrame::kAPlane), alpha_value, |
479 is_transparent ? 0 : 128, | |
480 video_frame->stride(media::VideoFrame::kAPlane) * | 576 video_frame->stride(media::VideoFrame::kAPlane) * |
481 video_frame->rows(media::VideoFrame::kAPlane)); | 577 video_frame->rows(media::VideoFrame::kAPlane)); |
482 | 578 |
483 VideoFrameExternalResources resources = | 579 VideoFrameExternalResources resources = |
484 video_resource_updater_->CreateExternalResourcesFromVideoFrame( | 580 video_resource_updater_->CreateExternalResourcesFromVideoFrame( |
485 video_frame); | 581 video_frame); |
486 | 582 |
487 EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type); | 583 EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type); |
488 EXPECT_EQ(media::VideoFrame::NumPlanes(video_frame->format()), | 584 EXPECT_EQ(media::VideoFrame::NumPlanes(video_frame->format()), |
489 resources.mailboxes.size()); | 585 resources.mailboxes.size()); |
(...skipping 18 matching lines...) Expand all Loading... |
508 ResourceProvider::ResourceId a_resource = 0; | 604 ResourceProvider::ResourceId a_resource = 0; |
509 if (with_alpha) { | 605 if (with_alpha) { |
510 a_resource = resource_provider_->CreateResourceFromTextureMailbox( | 606 a_resource = resource_provider_->CreateResourceFromTextureMailbox( |
511 resources.mailboxes[media::VideoFrame::kAPlane], | 607 resources.mailboxes[media::VideoFrame::kAPlane], |
512 SingleReleaseCallbackImpl::Create( | 608 SingleReleaseCallbackImpl::Create( |
513 resources.release_callbacks[media::VideoFrame::kAPlane])); | 609 resources.release_callbacks[media::VideoFrame::kAPlane])); |
514 } | 610 } |
515 | 611 |
516 YUVVideoDrawQuad* yuv_quad = | 612 YUVVideoDrawQuad* yuv_quad = |
517 render_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>(); | 613 render_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>(); |
518 yuv_quad->SetNew(shared_state, | 614 yuv_quad->SetNew(shared_state, rect, opaque_rect, rect, tex_coord_rect, |
519 rect, | 615 video_frame->coded_size(), y_resource, u_resource, |
520 opaque_rect, | 616 v_resource, a_resource, color_space); |
521 rect, | |
522 tex_coord_rect, | |
523 y_resource, | |
524 u_resource, | |
525 v_resource, | |
526 a_resource, | |
527 color_space); | |
528 } | 617 } |
529 | 618 |
530 void SetUp() override { | 619 void SetUp() override { |
531 GLRendererPixelTest::SetUp(); | 620 GLRendererPixelTest::SetUp(); |
532 video_resource_updater_.reset(new VideoResourceUpdater( | 621 video_resource_updater_.reset(new VideoResourceUpdater( |
533 output_surface_->context_provider(), resource_provider_.get())); | 622 output_surface_->context_provider(), resource_provider_.get())); |
534 } | 623 } |
535 | 624 |
536 private: | 625 private: |
537 scoped_ptr<VideoResourceUpdater> video_resource_updater_; | 626 scoped_ptr<VideoResourceUpdater> video_resource_updater_; |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
635 pass.get()); | 724 pass.get()); |
636 | 725 |
637 RenderPassList pass_list; | 726 RenderPassList pass_list; |
638 pass_list.push_back(pass.Pass()); | 727 pass_list.push_back(pass.Pass()); |
639 | 728 |
640 EXPECT_TRUE(this->RunPixelTest(&pass_list, | 729 EXPECT_TRUE(this->RunPixelTest(&pass_list, |
641 base::FilePath(FILE_PATH_LITERAL("green.png")), | 730 base::FilePath(FILE_PATH_LITERAL("green.png")), |
642 FuzzyPixelOffByOneComparator(true))); | 731 FuzzyPixelOffByOneComparator(true))); |
643 } | 732 } |
644 | 733 |
| 734 // Test that a YUV video doesn't bleed outside of its tex coords when the |
| 735 // tex coord rect is only a partial subrectangle of the coded contents. |
| 736 TEST_F(VideoGLRendererPixelTest, YUVEdgeBleed) { |
| 737 RenderPassList pass_list; |
| 738 CreateEdgeBleedPass(media::VideoFrame::YV12J, &pass_list); |
| 739 EXPECT_TRUE(this->RunPixelTest(&pass_list, |
| 740 base::FilePath(FILE_PATH_LITERAL("green.png")), |
| 741 FuzzyPixelOffByOneComparator(true))); |
| 742 } |
| 743 |
| 744 TEST_F(VideoGLRendererPixelTest, YUVAEdgeBleed) { |
| 745 RenderPassList pass_list; |
| 746 CreateEdgeBleedPass(media::VideoFrame::YV12A, &pass_list); |
| 747 EXPECT_TRUE(this->RunPixelTest(&pass_list, |
| 748 base::FilePath(FILE_PATH_LITERAL("green.png")), |
| 749 FuzzyPixelOffByOneComparator(true))); |
| 750 } |
| 751 |
645 TEST_F(VideoGLRendererPixelTest, SimpleYUVJRectGrey) { | 752 TEST_F(VideoGLRendererPixelTest, SimpleYUVJRectGrey) { |
646 gfx::Rect rect(this->device_viewport_size_); | 753 gfx::Rect rect(this->device_viewport_size_); |
647 | 754 |
648 RenderPassId id(1, 1); | 755 RenderPassId id(1, 1); |
649 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect); | 756 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect); |
650 | 757 |
651 SharedQuadState* shared_state = | 758 SharedQuadState* shared_state = |
652 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get()); | 759 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get()); |
653 | 760 |
654 // Dark grey in JPEG color range (in MPEG, this is black). | 761 // Dark grey in JPEG color range (in MPEG, this is black). |
(...skipping 1764 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2419 EXPECT_TRUE(this->RunPixelTest( | 2526 EXPECT_TRUE(this->RunPixelTest( |
2420 &pass_list, | 2527 &pass_list, |
2421 base::FilePath(FILE_PATH_LITERAL("wrap_mode_repeat.png")), | 2528 base::FilePath(FILE_PATH_LITERAL("wrap_mode_repeat.png")), |
2422 FuzzyPixelOffByOneComparator(true))); | 2529 FuzzyPixelOffByOneComparator(true))); |
2423 } | 2530 } |
2424 | 2531 |
2425 #endif // !defined(OS_ANDROID) | 2532 #endif // !defined(OS_ANDROID) |
2426 | 2533 |
2427 } // namespace | 2534 } // namespace |
2428 } // namespace cc | 2535 } // namespace cc |
OLD | NEW |