| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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 "media/renderers/skcanvas_video_renderer.h" | 5 #include "media/renderers/skcanvas_video_renderer.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "gpu/GLES2/gl2extchromium.h" | 10 #include "gpu/GLES2/gl2extchromium.h" |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 // frame has an unexpected format. | 351 // frame has an unexpected format. |
| 352 if (!video_frame.get() || video_frame->natural_size().IsEmpty() || | 352 if (!video_frame.get() || video_frame->natural_size().IsEmpty() || |
| 353 !(media::IsYuvPlanar(video_frame->format()) || | 353 !(media::IsYuvPlanar(video_frame->format()) || |
| 354 video_frame->HasTextures())) { | 354 video_frame->HasTextures())) { |
| 355 canvas->drawRect(dest, paint); | 355 canvas->drawRect(dest, paint); |
| 356 canvas->flush(); | 356 canvas->flush(); |
| 357 return; | 357 return; |
| 358 } | 358 } |
| 359 | 359 |
| 360 gpu::gles2::GLES2Interface* gl = context_3d.gl; | 360 gpu::gles2::GLES2Interface* gl = context_3d.gl; |
| 361 | 361 if (!UpdateLastImage(video_frame, context_3d)) |
| 362 if (!last_image_ || video_frame->timestamp() != last_timestamp_) { | 362 return; |
| 363 ResetCache(); | |
| 364 // Generate a new image. | |
| 365 // Note: Skia will hold onto |video_frame| via |video_generator| only when | |
| 366 // |video_frame| is software. | |
| 367 // Holding |video_frame| longer than this call when using GPUVideoDecoder | |
| 368 // could cause problems since the pool of VideoFrames has a fixed size. | |
| 369 if (video_frame->HasTextures()) { | |
| 370 DCHECK(context_3d.gr_context); | |
| 371 DCHECK(gl); | |
| 372 if (media::VideoFrame::NumPlanes(video_frame->format()) > 1) { | |
| 373 last_image_ = | |
| 374 NewSkImageFromVideoFrameYUVTextures(video_frame.get(), context_3d); | |
| 375 } else { | |
| 376 last_image_ = | |
| 377 NewSkImageFromVideoFrameNative(video_frame.get(), context_3d); | |
| 378 } | |
| 379 } else { | |
| 380 auto* video_generator = new VideoImageGenerator(video_frame); | |
| 381 last_image_ = SkImage::MakeFromGenerator(video_generator); | |
| 382 } | |
| 383 if (!last_image_) // Couldn't create the SkImage. | |
| 384 return; | |
| 385 last_timestamp_ = video_frame->timestamp(); | |
| 386 } | |
| 387 last_image_deleting_timer_.Reset(); | |
| 388 | 363 |
| 389 paint.setXfermodeMode(mode); | 364 paint.setXfermodeMode(mode); |
| 390 paint.setFilterQuality(kLow_SkFilterQuality); | 365 paint.setFilterQuality(kLow_SkFilterQuality); |
| 391 | 366 |
| 392 const bool need_rotation = video_rotation != VIDEO_ROTATION_0; | 367 const bool need_rotation = video_rotation != VIDEO_ROTATION_0; |
| 393 const bool need_scaling = | 368 const bool need_scaling = |
| 394 dest_rect.size() != | 369 dest_rect.size() != |
| 395 gfx::SizeF(gfx::SkISizeToSize(last_image_->dimensions())); | 370 gfx::SizeF(gfx::SkISizeToSize(last_image_->dimensions())); |
| 396 const bool need_translation = !dest_rect.origin().IsOrigin(); | 371 const bool need_translation = !dest_rect.origin().IsOrigin(); |
| 397 bool need_transform = need_rotation || need_scaling || need_translation; | 372 bool need_transform = need_rotation || need_scaling || need_translation; |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 // "flip_y == false" means to keep the intrinsic orientation. | 646 // "flip_y == false" means to keep the intrinsic orientation. |
| 672 gl->CopyTextureCHROMIUM(source_texture, texture, internal_format, type, | 647 gl->CopyTextureCHROMIUM(source_texture, texture, internal_format, type, |
| 673 flip_y, premultiply_alpha, false); | 648 flip_y, premultiply_alpha, false); |
| 674 gl->DeleteTextures(1, &source_texture); | 649 gl->DeleteTextures(1, &source_texture); |
| 675 gl->Flush(); | 650 gl->Flush(); |
| 676 | 651 |
| 677 SyncTokenClientImpl client(gl); | 652 SyncTokenClientImpl client(gl); |
| 678 video_frame->UpdateReleaseSyncToken(&client); | 653 video_frame->UpdateReleaseSyncToken(&client); |
| 679 } | 654 } |
| 680 | 655 |
| 656 bool SkCanvasVideoRenderer::CopyVideoFrameTexturesToGLTexture( |
| 657 const Context3D& context_3d, |
| 658 gpu::gles2::GLES2Interface* destination_gl, |
| 659 const scoped_refptr<VideoFrame>& video_frame, |
| 660 unsigned int texture, |
| 661 unsigned int internal_format, |
| 662 unsigned int type, |
| 663 bool premultiply_alpha, |
| 664 bool flip_y) { |
| 665 DCHECK(thread_checker_.CalledOnValidThread()); |
| 666 DCHECK(video_frame); |
| 667 DCHECK(video_frame->HasTextures()); |
| 668 if (media::VideoFrame::NumPlanes(video_frame->format()) > 1) { |
| 669 if (!context_3d.gr_context) |
| 670 return false; |
| 671 if (!UpdateLastImage(video_frame, context_3d)) |
| 672 return false; |
| 673 |
| 674 const GrGLTextureInfo* texture_info = |
| 675 skia::GrBackendObjectToGrGLTextureInfo( |
| 676 last_image_->getTextureHandle(true)); |
| 677 |
| 678 gpu::gles2::GLES2Interface* canvas_gl = context_3d.gl; |
| 679 gpu::MailboxHolder mailbox_holder; |
| 680 mailbox_holder.texture_target = texture_info->fTarget; |
| 681 canvas_gl->GenMailboxCHROMIUM(mailbox_holder.mailbox.name); |
| 682 canvas_gl->ProduceTextureDirectCHROMIUM(texture_info->fID, |
| 683 mailbox_holder.texture_target, |
| 684 mailbox_holder.mailbox.name); |
| 685 |
| 686 // Wait for mailbox creation on canvas context before consuming it and |
| 687 // copying from it on the consumer context. |
| 688 const GLuint64 fence_sync = canvas_gl->InsertFenceSyncCHROMIUM(); |
| 689 canvas_gl->ShallowFlushCHROMIUM(); |
| 690 canvas_gl->GenSyncTokenCHROMIUM(fence_sync, |
| 691 mailbox_holder.sync_token.GetData()); |
| 692 |
| 693 destination_gl->WaitSyncTokenCHROMIUM( |
| 694 mailbox_holder.sync_token.GetConstData()); |
| 695 uint32_t intermediate_texture = |
| 696 destination_gl->CreateAndConsumeTextureCHROMIUM( |
| 697 mailbox_holder.texture_target, mailbox_holder.mailbox.name); |
| 698 |
| 699 destination_gl->CopyTextureCHROMIUM(intermediate_texture, texture, |
| 700 internal_format, type, flip_y, |
| 701 premultiply_alpha, false); |
| 702 destination_gl->DeleteTextures(1, &intermediate_texture); |
| 703 |
| 704 // Wait for destination context to consume mailbox before deleting it in |
| 705 // canvas context. |
| 706 const GLuint64 dest_fence_sync = destination_gl->InsertFenceSyncCHROMIUM(); |
| 707 destination_gl->ShallowFlushCHROMIUM(); |
| 708 gpu::SyncToken dest_sync_token; |
| 709 destination_gl->GenSyncTokenCHROMIUM(dest_fence_sync, |
| 710 dest_sync_token.GetData()); |
| 711 canvas_gl->WaitSyncTokenCHROMIUM(dest_sync_token.GetConstData()); |
| 712 |
| 713 SyncTokenClientImpl client(canvas_gl); |
| 714 video_frame->UpdateReleaseSyncToken(&client); |
| 715 } else { |
| 716 CopyVideoFrameSingleTextureToGLTexture(destination_gl, video_frame.get(), |
| 717 texture, internal_format, type, |
| 718 premultiply_alpha, flip_y); |
| 719 } |
| 720 |
| 721 return true; |
| 722 } |
| 723 |
| 681 void SkCanvasVideoRenderer::ResetCache() { | 724 void SkCanvasVideoRenderer::ResetCache() { |
| 682 DCHECK(thread_checker_.CalledOnValidThread()); | 725 DCHECK(thread_checker_.CalledOnValidThread()); |
| 683 // Clear cached values. | 726 // Clear cached values. |
| 684 last_image_ = nullptr; | 727 last_image_ = nullptr; |
| 685 last_timestamp_ = kNoTimestamp(); | 728 last_timestamp_ = kNoTimestamp(); |
| 686 } | 729 } |
| 687 | 730 |
| 731 bool SkCanvasVideoRenderer::UpdateLastImage( |
| 732 const scoped_refptr<VideoFrame>& video_frame, |
| 733 const Context3D& context_3d) { |
| 734 if (!last_image_ || video_frame->timestamp() != last_timestamp_) { |
| 735 ResetCache(); |
| 736 // Generate a new image. |
| 737 // Note: Skia will hold onto |video_frame| via |video_generator| only when |
| 738 // |video_frame| is software. |
| 739 // Holding |video_frame| longer than this call when using GPUVideoDecoder |
| 740 // could cause problems since the pool of VideoFrames has a fixed size. |
| 741 if (video_frame->HasTextures()) { |
| 742 DCHECK(context_3d.gr_context); |
| 743 DCHECK(context_3d.gl); |
| 744 if (media::VideoFrame::NumPlanes(video_frame->format()) > 1) { |
| 745 last_image_ = |
| 746 NewSkImageFromVideoFrameYUVTextures(video_frame.get(), context_3d); |
| 747 } else { |
| 748 last_image_ = |
| 749 NewSkImageFromVideoFrameNative(video_frame.get(), context_3d); |
| 750 } |
| 751 } else { |
| 752 auto* video_generator = new VideoImageGenerator(video_frame); |
| 753 last_image_ = SkImage::MakeFromGenerator(video_generator); |
| 754 } |
| 755 if (!last_image_) // Couldn't create the SkImage. |
| 756 return false; |
| 757 last_timestamp_ = video_frame->timestamp(); |
| 758 } |
| 759 last_image_deleting_timer_.Reset(); |
| 760 DCHECK(!!last_image_); |
| 761 return true; |
| 762 } |
| 763 |
| 688 } // namespace media | 764 } // namespace media |
| OLD | NEW |