Chromium Code Reviews| 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 UpdateLastImage(video_frame, context_3d); |
| 362 if (!last_image_ || video_frame->timestamp() != last_timestamp_) { | 362 if (!last_image_) |
| 363 ResetCache(); | 363 return; |
| 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 | 364 |
| 389 paint.setXfermodeMode(mode); | 365 paint.setXfermodeMode(mode); |
| 390 paint.setFilterQuality(kLow_SkFilterQuality); | 366 paint.setFilterQuality(kLow_SkFilterQuality); |
| 391 | 367 |
| 392 const bool need_rotation = video_rotation != VIDEO_ROTATION_0; | 368 const bool need_rotation = video_rotation != VIDEO_ROTATION_0; |
| 393 const bool need_scaling = | 369 const bool need_scaling = |
| 394 dest_rect.size() != | 370 dest_rect.size() != |
| 395 gfx::SizeF(gfx::SkISizeToSize(last_image_->dimensions())); | 371 gfx::SizeF(gfx::SkISizeToSize(last_image_->dimensions())); |
| 396 const bool need_translation = !dest_rect.origin().IsOrigin(); | 372 const bool need_translation = !dest_rect.origin().IsOrigin(); |
| 397 bool need_transform = need_rotation || need_scaling || need_translation; | 373 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. | 647 // "flip_y == false" means to keep the intrinsic orientation. |
| 672 gl->CopyTextureCHROMIUM(source_texture, texture, internal_format, type, | 648 gl->CopyTextureCHROMIUM(source_texture, texture, internal_format, type, |
| 673 flip_y, premultiply_alpha, false); | 649 flip_y, premultiply_alpha, false); |
| 674 gl->DeleteTextures(1, &source_texture); | 650 gl->DeleteTextures(1, &source_texture); |
| 675 gl->Flush(); | 651 gl->Flush(); |
| 676 | 652 |
| 677 SyncTokenClientImpl client(gl); | 653 SyncTokenClientImpl client(gl); |
| 678 video_frame->UpdateReleaseSyncToken(&client); | 654 video_frame->UpdateReleaseSyncToken(&client); |
| 679 } | 655 } |
| 680 | 656 |
| 657 bool SkCanvasVideoRenderer::CopyVideoFrameTexturesToGLTexture( | |
| 658 const Context3D& context_3d, | |
| 659 gpu::gles2::GLES2Interface* destination_gl, | |
| 660 const scoped_refptr<VideoFrame>& video_frame, | |
| 661 unsigned int texture, | |
| 662 unsigned int internal_format, | |
| 663 unsigned int type, | |
| 664 bool premultiply_alpha, | |
| 665 bool flip_y) { | |
| 666 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 667 DCHECK(video_frame); | |
| 668 DCHECK(video_frame->HasTextures()); | |
| 669 if (media::VideoFrame::NumPlanes(video_frame->format()) > 1) { | |
| 670 if (!context_3d.gr_context) | |
| 671 return false; | |
| 672 UpdateLastImage(video_frame, context_3d); | |
| 673 if (!last_image_) | |
|
sandersd (OOO until July 31)
2016/07/18 23:46:57
Given this pattern is used by both call sites, per
| |
| 674 return false; | |
| 675 | |
| 676 const GrGLTextureInfo* texture_info = | |
| 677 skia::GrBackendObjectToGrGLTextureInfo( | |
| 678 last_image_->getTextureHandle(true)); | |
| 679 | |
| 680 gpu::gles2::GLES2Interface* canvas_gl = context_3d.gl; | |
| 681 gpu::MailboxHolder mailbox_holder; | |
| 682 mailbox_holder.texture_target = texture_info->fTarget; | |
| 683 canvas_gl->GenMailboxCHROMIUM(mailbox_holder.mailbox.name); | |
| 684 canvas_gl->ProduceTextureDirectCHROMIUM(texture_info->fID, | |
| 685 mailbox_holder.texture_target, | |
| 686 mailbox_holder.mailbox.name); | |
| 687 | |
| 688 // Wait for mailbox creation on canvas context before consuming it and | |
| 689 // copying from it on the consumer context. | |
| 690 const GLuint64 fence_sync = canvas_gl->InsertFenceSyncCHROMIUM(); | |
| 691 canvas_gl->ShallowFlushCHROMIUM(); | |
| 692 canvas_gl->GenSyncTokenCHROMIUM(fence_sync, | |
| 693 mailbox_holder.sync_token.GetData()); | |
| 694 | |
| 695 destination_gl->WaitSyncTokenCHROMIUM( | |
| 696 mailbox_holder.sync_token.GetConstData()); | |
| 697 uint32_t source_texture2 = destination_gl->CreateAndConsumeTextureCHROMIUM( | |
|
Daniele Castagna
2016/07/13 20:51:01
nit: why 2?
| |
| 698 mailbox_holder.texture_target, mailbox_holder.mailbox.name); | |
| 699 | |
| 700 destination_gl->CopyTextureCHROMIUM(source_texture2, texture, | |
| 701 internal_format, type, flip_y, | |
| 702 premultiply_alpha, false); | |
| 703 destination_gl->DeleteTextures(1, &source_texture2); | |
| 704 | |
| 705 // Wait for copy to complete before source texture destruction. | |
|
Daniele Castagna
2016/07/13 20:51:01
By source texture you mean texture_info->fID, not
| |
| 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 void 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; | |
| 757 last_timestamp_ = video_frame->timestamp(); | |
| 758 } | |
| 759 last_image_deleting_timer_.Reset(); | |
| 760 } | |
| 761 | |
| 688 } // namespace media | 762 } // namespace media |
| OLD | NEW |