Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(458)

Side by Side Diff: cc/resources/video_resource_updater.cc

Issue 2738713003: color: Ensure that VideoResourceUpdater give consistent colors (Closed)
Patch Set: Rebase Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "cc/resources/video_resource_updater.h" 5 #include "cc/resources/video_resource_updater.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 ResourceFormat output_resource_format; 439 ResourceFormat output_resource_format;
440 if (input_frame_format == media::PIXEL_FORMAT_Y16) { 440 if (input_frame_format == media::PIXEL_FORMAT_Y16) {
441 // Unable to display directly as yuv planes so convert it to RGBA for 441 // Unable to display directly as yuv planes so convert it to RGBA for
442 // compositing. 442 // compositing.
443 output_resource_format = RGBA_8888; 443 output_resource_format = RGBA_8888;
444 } else { 444 } else {
445 // Can be composited directly from yuv planes. 445 // Can be composited directly from yuv planes.
446 output_resource_format = 446 output_resource_format =
447 resource_provider_->YuvResourceFormat(bits_per_channel); 447 resource_provider_->YuvResourceFormat(bits_per_channel);
448 } 448 }
449 gfx::ColorSpace output_color_space = video_frame->ColorSpace();
449 450
450 // If GPU compositing is enabled, but the output resource format 451 // If GPU compositing is enabled, but the output resource format
451 // returned by the resource provider is RGBA_8888, then a GPU driver 452 // returned by the resource provider is RGBA_8888, then a GPU driver
452 // bug workaround requires that YUV frames must be converted to RGB 453 // bug workaround requires that YUV frames must be converted to RGB
453 // before texture upload. 454 // before texture upload.
454 bool texture_needs_rgb_conversion = 455 bool texture_needs_rgb_conversion =
455 !software_compositor && 456 !software_compositor &&
456 output_resource_format == ResourceFormat::RGBA_8888; 457 output_resource_format == ResourceFormat::RGBA_8888;
457 size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format); 458 size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format);
458 459
459 // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB 460 // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB
460 // conversion here. That involves an extra copy of each frame to a bitmap. 461 // conversion here. That involves an extra copy of each frame to a bitmap.
461 // Obviously, this is suboptimal and should be addressed once ubercompositor 462 // Obviously, this is suboptimal and should be addressed once ubercompositor
462 // starts shaping up. 463 // starts shaping up.
463 if (software_compositor || texture_needs_rgb_conversion) { 464 if (software_compositor || texture_needs_rgb_conversion) {
465 output_color_space = output_color_space.GetAsFullRangeRGB();
464 output_resource_format = kRGBResourceFormat; 466 output_resource_format = kRGBResourceFormat;
465 output_plane_count = 1; 467 output_plane_count = 1;
466 bits_per_channel = 8; 468 bits_per_channel = 8;
467 } 469 }
468 470
469 // Drop recycled resources that are the wrong format. 471 // Drop recycled resources that are the wrong format.
470 for (auto it = all_resources_.begin(); it != all_resources_.end();) { 472 for (auto it = all_resources_.begin(); it != all_resources_.end();) {
471 if (!it->has_refs() && it->resource_format() != output_resource_format) 473 if (!it->has_refs() && it->resource_format() != output_resource_format)
472 DeleteResource(it++); 474 DeleteResource(it++);
473 else 475 else
(...skipping 10 matching lines...) Expand all
484 output_plane_resource_size.height() > max_resource_size) { 486 output_plane_resource_size.height() > max_resource_size) {
485 // This output plane has invalid geometry. Clean up and return an empty 487 // This output plane has invalid geometry. Clean up and return an empty
486 // external resources. 488 // external resources.
487 for (ResourceList::iterator resource_it : plane_resources) 489 for (ResourceList::iterator resource_it : plane_resources)
488 resource_it->remove_ref(); 490 resource_it->remove_ref();
489 return VideoFrameExternalResources(); 491 return VideoFrameExternalResources();
490 } 492 }
491 493
492 const bool is_immutable = true; 494 const bool is_immutable = true;
493 ResourceList::iterator resource_it = RecycleOrAllocateResource( 495 ResourceList::iterator resource_it = RecycleOrAllocateResource(
494 output_plane_resource_size, output_resource_format, 496 output_plane_resource_size, output_resource_format, output_color_space,
495 video_frame->ColorSpace(), software_compositor, is_immutable, 497 software_compositor, is_immutable, video_frame->unique_id(), i);
496 video_frame->unique_id(), i);
497 498
498 resource_it->add_ref(); 499 resource_it->add_ref();
499 plane_resources.push_back(resource_it); 500 plane_resources.push_back(resource_it);
500 } 501 }
501 502
502 VideoFrameExternalResources external_resources; 503 VideoFrameExternalResources external_resources;
503 504
504 external_resources.bits_per_channel = bits_per_channel; 505 external_resources.bits_per_channel = bits_per_channel;
505 506
506 if (software_compositor || texture_needs_rgb_conversion) { 507 if (software_compositor || texture_needs_rgb_conversion) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 plane_resource.resource_id()); 544 plane_resource.resource_id());
544 external_resources.software_release_callback = base::Bind( 545 external_resources.software_release_callback = base::Bind(
545 &RecycleResource, AsWeakPtr(), plane_resource.resource_id()); 546 &RecycleResource, AsWeakPtr(), plane_resource.resource_id());
546 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; 547 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE;
547 } else { 548 } else {
548 // VideoResourceUpdater shares a context with the compositor so 549 // VideoResourceUpdater shares a context with the compositor so
549 // a sync token is not required. 550 // a sync token is not required.
550 TextureMailbox mailbox(plane_resource.mailbox(), gpu::SyncToken(), 551 TextureMailbox mailbox(plane_resource.mailbox(), gpu::SyncToken(),
551 resource_provider_->GetResourceTextureTarget( 552 resource_provider_->GetResourceTextureTarget(
552 plane_resource.resource_id())); 553 plane_resource.resource_id()));
553 mailbox.set_color_space(video_frame->ColorSpace()); 554 mailbox.set_color_space(output_color_space);
554 external_resources.mailboxes.push_back(mailbox); 555 external_resources.mailboxes.push_back(mailbox);
555 external_resources.release_callbacks.push_back(base::Bind( 556 external_resources.release_callbacks.push_back(base::Bind(
556 &RecycleResource, AsWeakPtr(), plane_resource.resource_id())); 557 &RecycleResource, AsWeakPtr(), plane_resource.resource_id()));
557 external_resources.type = VideoFrameExternalResources::RGBA_RESOURCE; 558 external_resources.type = VideoFrameExternalResources::RGBA_RESOURCE;
558 } 559 }
559 return external_resources; 560 return external_resources;
560 } 561 }
561 562
562 std::unique_ptr<HalfFloatMaker> half_float_maker; 563 std::unique_ptr<HalfFloatMaker> half_float_maker;
563 if (resource_provider_->YuvResourceFormat(bits_per_channel) == 564 if (resource_provider_->YuvResourceFormat(bits_per_channel) ==
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
645 resource_provider_->CopyToResource(plane_resource.resource_id(), pixels, 646 resource_provider_->CopyToResource(plane_resource.resource_id(), pixels,
646 resource_size_pixels); 647 resource_size_pixels);
647 plane_resource.SetUniqueId(video_frame->unique_id(), i); 648 plane_resource.SetUniqueId(video_frame->unique_id(), i);
648 } 649 }
649 650
650 // VideoResourceUpdater shares a context with the compositor so a 651 // VideoResourceUpdater shares a context with the compositor so a
651 // sync token is not required. 652 // sync token is not required.
652 TextureMailbox mailbox(plane_resource.mailbox(), gpu::SyncToken(), 653 TextureMailbox mailbox(plane_resource.mailbox(), gpu::SyncToken(),
653 resource_provider_->GetResourceTextureTarget( 654 resource_provider_->GetResourceTextureTarget(
654 plane_resource.resource_id())); 655 plane_resource.resource_id()));
655 mailbox.set_color_space(video_frame->ColorSpace()); 656 mailbox.set_color_space(output_color_space);
656 external_resources.mailboxes.push_back(mailbox); 657 external_resources.mailboxes.push_back(mailbox);
657 external_resources.release_callbacks.push_back(base::Bind( 658 external_resources.release_callbacks.push_back(base::Bind(
658 &RecycleResource, AsWeakPtr(), plane_resource.resource_id())); 659 &RecycleResource, AsWeakPtr(), plane_resource.resource_id()));
659 } 660 }
660 661
661 external_resources.type = VideoFrameExternalResources::YUV_RESOURCE; 662 external_resources.type = VideoFrameExternalResources::YUV_RESOURCE;
662 return external_resources; 663 return external_resources;
663 } 664 }
664 665
665 // static 666 // static
(...skipping 12 matching lines...) Expand all
678 // |video_frame|'s previous sync point using the current GL context. 679 // |video_frame|'s previous sync point using the current GL context.
679 SyncTokenClientImpl client(updater->context_provider_->ContextGL(), 680 SyncTokenClientImpl client(updater->context_provider_->ContextGL(),
680 sync_token); 681 sync_token);
681 video_frame->UpdateReleaseSyncToken(&client); 682 video_frame->UpdateReleaseSyncToken(&client);
682 } 683 }
683 684
684 // Create a copy of a texture-backed source video frame in a new GL_TEXTURE_2D 685 // Create a copy of a texture-backed source video frame in a new GL_TEXTURE_2D
685 // texture. 686 // texture.
686 void VideoResourceUpdater::CopyPlaneTexture( 687 void VideoResourceUpdater::CopyPlaneTexture(
687 media::VideoFrame* video_frame, 688 media::VideoFrame* video_frame,
689 const gfx::ColorSpace& resource_color_space,
688 const gpu::MailboxHolder& mailbox_holder, 690 const gpu::MailboxHolder& mailbox_holder,
689 VideoFrameExternalResources* external_resources) { 691 VideoFrameExternalResources* external_resources) {
690 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 692 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
691 SyncTokenClientImpl client(gl, mailbox_holder.sync_token); 693 SyncTokenClientImpl client(gl, mailbox_holder.sync_token);
692 694
693 const gfx::Size output_plane_resource_size = video_frame->coded_size(); 695 const gfx::Size output_plane_resource_size = video_frame->coded_size();
694 // The copy needs to be a direct transfer of pixel data, so we use an RGBA8 696 // The copy needs to be a direct transfer of pixel data, so we use an RGBA8
695 // target to avoid loss of precision or dropping any alpha component. 697 // target to avoid loss of precision or dropping any alpha component.
696 const ResourceFormat copy_target_format = ResourceFormat::RGBA_8888; 698 const ResourceFormat copy_target_format = ResourceFormat::RGBA_8888;
697 699
698 const bool is_immutable = false; 700 const bool is_immutable = false;
699 const int no_unique_id = 0; 701 const int no_unique_id = 0;
700 const int no_plane_index = -1; // Do not recycle referenced textures. 702 const int no_plane_index = -1; // Do not recycle referenced textures.
701 VideoResourceUpdater::ResourceList::iterator resource = 703 VideoResourceUpdater::ResourceList::iterator resource =
702 RecycleOrAllocateResource(output_plane_resource_size, copy_target_format, 704 RecycleOrAllocateResource(output_plane_resource_size, copy_target_format,
703 video_frame->ColorSpace(), false, is_immutable, 705 resource_color_space, false, is_immutable,
704 no_unique_id, no_plane_index); 706 no_unique_id, no_plane_index);
705 resource->add_ref(); 707 resource->add_ref();
706 708
707 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, 709 ResourceProvider::ScopedWriteLockGL lock(resource_provider_,
708 resource->resource_id(), false); 710 resource->resource_id(), false);
709 DCHECK_EQ( 711 DCHECK_EQ(
710 resource_provider_->GetResourceTextureTarget(resource->resource_id()), 712 resource_provider_->GetResourceTextureTarget(resource->resource_id()),
711 (GLenum)GL_TEXTURE_2D); 713 (GLenum)GL_TEXTURE_2D);
712 714
713 gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData()); 715 gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData());
714 uint32_t src_texture_id = gl->CreateAndConsumeTextureCHROMIUM( 716 uint32_t src_texture_id = gl->CreateAndConsumeTextureCHROMIUM(
715 mailbox_holder.texture_target, mailbox_holder.mailbox.name); 717 mailbox_holder.texture_target, mailbox_holder.mailbox.name);
716 gl->CopySubTextureCHROMIUM( 718 gl->CopySubTextureCHROMIUM(
717 src_texture_id, 0, GL_TEXTURE_2D, lock.texture_id(), 0, 0, 0, 0, 0, 719 src_texture_id, 0, GL_TEXTURE_2D, lock.texture_id(), 0, 0, 0, 0, 0,
718 output_plane_resource_size.width(), output_plane_resource_size.height(), 720 output_plane_resource_size.width(), output_plane_resource_size.height(),
719 false, false, false); 721 false, false, false);
720 gl->DeleteTextures(1, &src_texture_id); 722 gl->DeleteTextures(1, &src_texture_id);
721 723
722 // Done with the source video frame texture at this point. 724 // Done with the source video frame texture at this point.
723 video_frame->UpdateReleaseSyncToken(&client); 725 video_frame->UpdateReleaseSyncToken(&client);
724 726
725 // VideoResourceUpdater shares a context with the compositor so a 727 // VideoResourceUpdater shares a context with the compositor so a
726 // sync token is not required. 728 // sync token is not required.
727 TextureMailbox mailbox(resource->mailbox(), gpu::SyncToken(), GL_TEXTURE_2D, 729 TextureMailbox mailbox(resource->mailbox(), gpu::SyncToken(), GL_TEXTURE_2D,
728 video_frame->coded_size(), false, false); 730 video_frame->coded_size(), false, false);
729 mailbox.set_color_space(video_frame->ColorSpace()); 731 mailbox.set_color_space(resource_color_space);
730 external_resources->mailboxes.push_back(mailbox); 732 external_resources->mailboxes.push_back(mailbox);
731 733
732 external_resources->release_callbacks.push_back( 734 external_resources->release_callbacks.push_back(
733 base::Bind(&RecycleResource, AsWeakPtr(), resource->resource_id())); 735 base::Bind(&RecycleResource, AsWeakPtr(), resource->resource_id()));
734 } 736 }
735 737
736 VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes( 738 VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes(
737 scoped_refptr<media::VideoFrame> video_frame) { 739 scoped_refptr<media::VideoFrame> video_frame) {
738 TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForHardwarePlanes"); 740 TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForHardwarePlanes");
739 DCHECK(video_frame->HasTextures()); 741 DCHECK(video_frame->HasTextures());
740 if (!context_provider_) 742 if (!context_provider_)
741 return VideoFrameExternalResources(); 743 return VideoFrameExternalResources();
742 744
743 VideoFrameExternalResources external_resources; 745 VideoFrameExternalResources external_resources;
744 if (video_frame->metadata()->IsTrue( 746 if (video_frame->metadata()->IsTrue(
745 media::VideoFrameMetadata::READ_LOCK_FENCES_ENABLED)) { 747 media::VideoFrameMetadata::READ_LOCK_FENCES_ENABLED)) {
746 external_resources.read_lock_fences_enabled = true; 748 external_resources.read_lock_fences_enabled = true;
747 } 749 }
750 gfx::ColorSpace resource_color_space = video_frame->ColorSpace();
748 751
749 external_resources.type = ResourceTypeForVideoFrame(video_frame.get()); 752 external_resources.type = ResourceTypeForVideoFrame(video_frame.get());
750 if (external_resources.type == VideoFrameExternalResources::NONE) { 753 if (external_resources.type == VideoFrameExternalResources::NONE) {
751 DLOG(ERROR) << "Unsupported Texture format" 754 DLOG(ERROR) << "Unsupported Texture format"
752 << media::VideoPixelFormatToString(video_frame->format()); 755 << media::VideoPixelFormatToString(video_frame->format());
753 return external_resources; 756 return external_resources;
754 } 757 }
758 if (external_resources.type == VideoFrameExternalResources::YUV_RESOURCE)
759 resource_color_space = resource_color_space.GetAsFullRangeRGB();
hubbe 2017/03/13 17:53:45 If the YUV->RGB matrix applied by the hardware doe
ccameron 2017/03/13 22:16:55 Yes, hardware-performed YUV->RGB at sample time wi
755 760
756 const size_t num_planes = media::VideoFrame::NumPlanes(video_frame->format()); 761 const size_t num_planes = media::VideoFrame::NumPlanes(video_frame->format());
757 for (size_t i = 0; i < num_planes; ++i) { 762 for (size_t i = 0; i < num_planes; ++i) {
758 const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(i); 763 const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(i);
759 if (mailbox_holder.mailbox.IsZero()) 764 if (mailbox_holder.mailbox.IsZero())
760 break; 765 break;
761 766
762 if (video_frame->metadata()->IsTrue( 767 if (video_frame->metadata()->IsTrue(
763 media::VideoFrameMetadata::COPY_REQUIRED)) { 768 media::VideoFrameMetadata::COPY_REQUIRED)) {
764 CopyPlaneTexture(video_frame.get(), mailbox_holder, &external_resources); 769 CopyPlaneTexture(video_frame.get(), resource_color_space, mailbox_holder,
770 &external_resources);
765 } else { 771 } else {
766 TextureMailbox mailbox(mailbox_holder.mailbox, mailbox_holder.sync_token, 772 TextureMailbox mailbox(mailbox_holder.mailbox, mailbox_holder.sync_token,
767 mailbox_holder.texture_target, 773 mailbox_holder.texture_target,
768 video_frame->coded_size(), 774 video_frame->coded_size(),
769 video_frame->metadata()->IsTrue( 775 video_frame->metadata()->IsTrue(
770 media::VideoFrameMetadata::ALLOW_OVERLAY), 776 media::VideoFrameMetadata::ALLOW_OVERLAY),
771 false); 777 false);
772 mailbox.set_color_space(video_frame->ColorSpace()); 778 mailbox.set_color_space(resource_color_space);
773 #if defined(OS_ANDROID) 779 #if defined(OS_ANDROID)
774 mailbox.set_is_backed_by_surface_texture(video_frame->metadata()->IsTrue( 780 mailbox.set_is_backed_by_surface_texture(video_frame->metadata()->IsTrue(
775 media::VideoFrameMetadata::SURFACE_TEXTURE)); 781 media::VideoFrameMetadata::SURFACE_TEXTURE));
776 mailbox.set_wants_promotion_hint(video_frame->metadata()->IsTrue( 782 mailbox.set_wants_promotion_hint(video_frame->metadata()->IsTrue(
777 media::VideoFrameMetadata::WANTS_PROMOTION_HINT)); 783 media::VideoFrameMetadata::WANTS_PROMOTION_HINT));
778 #endif 784 #endif
779 external_resources.mailboxes.push_back(mailbox); 785 external_resources.mailboxes.push_back(mailbox);
780 external_resources.release_callbacks.push_back( 786 external_resources.release_callbacks.push_back(
781 base::Bind(&ReturnTexture, AsWeakPtr(), video_frame)); 787 base::Bind(&ReturnTexture, AsWeakPtr(), video_frame));
782 } 788 }
(...skipping 29 matching lines...) Expand all
812 if (lost_resource) { 818 if (lost_resource) {
813 resource_it->clear_refs(); 819 resource_it->clear_refs();
814 updater->DeleteResource(resource_it); 820 updater->DeleteResource(resource_it);
815 return; 821 return;
816 } 822 }
817 823
818 resource_it->remove_ref(); 824 resource_it->remove_ref();
819 } 825 }
820 826
821 } // namespace cc 827 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698