| 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 |