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 |