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

Side by Side Diff: content/renderer/media/android/webmediaplayer_android.cc

Issue 445013002: media: Optimize HW Video to 2D Canvas copy. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase to ToT. Address nits Created 6 years, 2 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 "content/renderer/media/android/webmediaplayer_android.h" 5 #include "content/renderer/media/android/webmediaplayer_android.h"
6 6
7 #include <limits> 7 #include <limits>
8 8
9 #include "base/android/build_info.h" 9 #include "base/android/build_info.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 25 matching lines...) Expand all
36 #include "media/base/android/media_player_android.h" 36 #include "media/base/android/media_player_android.h"
37 #include "media/base/bind_to_current_loop.h" 37 #include "media/base/bind_to_current_loop.h"
38 // TODO(xhwang): Remove when we remove prefixed EME implementation. 38 // TODO(xhwang): Remove when we remove prefixed EME implementation.
39 #include "media/base/media_keys.h" 39 #include "media/base/media_keys.h"
40 #include "media/base/media_log.h" 40 #include "media/base/media_log.h"
41 #include "media/base/media_switches.h" 41 #include "media/base/media_switches.h"
42 #include "media/base/video_frame.h" 42 #include "media/base/video_frame.h"
43 #include "media/blink/webmediaplayer_delegate.h" 43 #include "media/blink/webmediaplayer_delegate.h"
44 #include "media/blink/webmediaplayer_util.h" 44 #include "media/blink/webmediaplayer_util.h"
45 #include "net/base/mime_util.h" 45 #include "net/base/mime_util.h"
46 #include "third_party/WebKit/public/platform/Platform.h"
47 #include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h" 46 #include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h"
48 #include "third_party/WebKit/public/platform/WebGraphicsContext3DProvider.h" 47 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
49 #include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" 48 #include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
50 #include "third_party/WebKit/public/platform/WebString.h" 49 #include "third_party/WebKit/public/platform/WebString.h"
51 #include "third_party/WebKit/public/platform/WebURL.h" 50 #include "third_party/WebKit/public/platform/WebURL.h"
52 #include "third_party/WebKit/public/web/WebDocument.h" 51 #include "third_party/WebKit/public/web/WebDocument.h"
53 #include "third_party/WebKit/public/web/WebFrame.h" 52 #include "third_party/WebKit/public/web/WebFrame.h"
54 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h" 53 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
55 #include "third_party/WebKit/public/web/WebSecurityOrigin.h" 54 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
56 #include "third_party/WebKit/public/web/WebView.h" 55 #include "third_party/WebKit/public/web/WebView.h"
56 #include "third_party/skia/include/core/SkBitmap.h"
57 #include "third_party/skia/include/core/SkCanvas.h" 57 #include "third_party/skia/include/core/SkCanvas.h"
58 #include "third_party/skia/include/core/SkPaint.h"
59 #include "third_party/skia/include/core/SkTypeface.h" 58 #include "third_party/skia/include/core/SkTypeface.h"
60 #include "ui/gfx/image/image.h" 59 #include "ui/gfx/image/image.h"
60 #include "webkit/common/gpu/context_provider_web_context.h"
61 #include "webkit/common/gpu/webgraphicscontext3d_impl.h"
61 62
62 static const uint32 kGLTextureExternalOES = 0x8D65; 63 static const uint32 kGLTextureExternalOES = 0x8D65;
63 static const int kSDKVersionToSupportSecurityOriginCheck = 20; 64 static const int kSDKVersionToSupportSecurityOriginCheck = 20;
64 65
65 using blink::WebMediaPlayer; 66 using blink::WebMediaPlayer;
66 using blink::WebSize; 67 using blink::WebSize;
67 using blink::WebString; 68 using blink::WebString;
68 using blink::WebURL; 69 using blink::WebURL;
69 using gpu::gles2::GLES2Interface; 70 using gpu::gles2::GLES2Interface;
70 using media::MediaPlayerAndroid; 71 using media::MediaPlayerAndroid;
71 using media::VideoFrame; 72 using media::VideoFrame;
72 73
73 namespace { 74 namespace {
74 // Prefix for histograms related to Encrypted Media Extensions. 75 // Prefix for histograms related to Encrypted Media Extensions.
75 const char* kMediaEme = "Media.EME."; 76 const char* kMediaEme = "Media.EME.";
76 77
77 // File-static function is to allow it to run even after WMPA is deleted. 78 // File-static function is to allow it to run even after WMPA is deleted.
78 void OnReleaseTexture( 79 void OnReleaseTexture(
79 const scoped_refptr<content::StreamTextureFactory>& factories, 80 const scoped_refptr<content::StreamTextureFactory>& factories,
80 uint32 texture_id, 81 uint32 texture_id,
81 uint32 release_sync_point) { 82 uint32 release_sync_point) {
82 GLES2Interface* gl = factories->ContextGL(); 83 GLES2Interface* gl = factories->ContextGL();
83 gl->WaitSyncPointCHROMIUM(release_sync_point); 84 gl->WaitSyncPointCHROMIUM(release_sync_point);
84 gl->DeleteTextures(1, &texture_id); 85 gl->DeleteTextures(1, &texture_id);
85 } 86 }
86 87
87 class SyncPointClientImpl : public media::VideoFrame::SyncPointClient {
88 public:
89 explicit SyncPointClientImpl(
90 blink::WebGraphicsContext3D* web_graphics_context)
91 : web_graphics_context_(web_graphics_context) {}
92 virtual ~SyncPointClientImpl() {}
93 virtual uint32 InsertSyncPoint() override {
94 return web_graphics_context_->insertSyncPoint();
95 }
96 virtual void WaitSyncPoint(uint32 sync_point) override {
97 web_graphics_context_->waitSyncPoint(sync_point);
98 }
99
100 private:
101 blink::WebGraphicsContext3D* web_graphics_context_;
102 };
103
104 // Used for calls to decryptor_ready_cb_ where the result can be ignored. 88 // Used for calls to decryptor_ready_cb_ where the result can be ignored.
105 void DoNothing(bool) { 89 void DoNothing(bool) {
106 } 90 }
107 91
108 } // namespace 92 } // namespace
109 93
110 namespace content { 94 namespace content {
111 95
112 WebMediaPlayerAndroid::WebMediaPlayerAndroid( 96 WebMediaPlayerAndroid::WebMediaPlayerAndroid(
113 blink::WebFrame* frame, 97 blink::WebFrame* frame,
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 blink::WebTimeRange seekable_range(0.0, seekable_end); 518 blink::WebTimeRange seekable_range(0.0, seekable_end);
535 return blink::WebTimeRanges(&seekable_range, 1); 519 return blink::WebTimeRanges(&seekable_range, 1);
536 } 520 }
537 521
538 bool WebMediaPlayerAndroid::didLoadingProgress() { 522 bool WebMediaPlayerAndroid::didLoadingProgress() {
539 bool ret = did_loading_progress_; 523 bool ret = did_loading_progress_;
540 did_loading_progress_ = false; 524 did_loading_progress_ = false;
541 return ret; 525 return ret;
542 } 526 }
543 527
544 bool WebMediaPlayerAndroid::EnsureTextureBackedSkBitmap(GrContext* gr,
545 SkBitmap& bitmap,
546 const WebSize& size,
547 GrSurfaceOrigin origin,
548 GrPixelConfig config) {
549 DCHECK(main_thread_checker_.CalledOnValidThread());
550 if (!bitmap.getTexture() || bitmap.width() != size.width
551 || bitmap.height() != size.height) {
552 if (!gr)
553 return false;
554 GrTextureDesc desc;
555 desc.fConfig = config;
556 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
557 desc.fSampleCnt = 0;
558 desc.fOrigin = origin;
559 desc.fWidth = size.width;
560 desc.fHeight = size.height;
561 skia::RefPtr<GrTexture> texture;
562 texture = skia::AdoptRef(gr->createUncachedTexture(desc, 0, 0));
563 if (!texture.get())
564 return false;
565
566 SkImageInfo info = SkImageInfo::MakeN32Premul(desc.fWidth, desc.fHeight);
567 SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (info, texture.get()));
568 if (!pixelRef)
569 return false;
570 bitmap.setInfo(info);
571 bitmap.setPixelRef(pixelRef)->unref();
572 }
573
574 return true;
575 }
576
577 void WebMediaPlayerAndroid::paint(blink::WebCanvas* canvas, 528 void WebMediaPlayerAndroid::paint(blink::WebCanvas* canvas,
578 const blink::WebRect& rect, 529 const blink::WebRect& rect,
579 unsigned char alpha) { 530 unsigned char alpha) {
580 paint(canvas, rect, alpha, SkXfermode::kSrcOver_Mode); 531 paint(canvas, rect, alpha, SkXfermode::kSrcOver_Mode);
581 } 532 }
582 533
583 void WebMediaPlayerAndroid::paint(blink::WebCanvas* canvas, 534 void WebMediaPlayerAndroid::paint(blink::WebCanvas* canvas,
584 const blink::WebRect& rect, 535 const blink::WebRect& rect,
585 unsigned char alpha, 536 unsigned char alpha,
586 SkXfermode::Mode mode) { 537 SkXfermode::Mode mode) {
587 DCHECK(main_thread_checker_.CalledOnValidThread()); 538 DCHECK(main_thread_checker_.CalledOnValidThread());
588 scoped_ptr<blink::WebGraphicsContext3DProvider> provider = 539 // Don't allow clients to copy an encrypted video frame.
589 scoped_ptr<blink::WebGraphicsContext3DProvider>(blink::Platform::current( 540 if (needs_external_surface_)
590 )->createSharedOffscreenGraphicsContext3DProvider());
591 if (!provider)
592 return;
593 blink::WebGraphicsContext3D* context3D = provider->context3d();
594 if (!context3D)
595 return; 541 return;
596 542
597 // Copy video texture into a RGBA texture based bitmap first as video texture 543 scoped_refptr<VideoFrame> video_frame;
598 // on Android is GL_TEXTURE_EXTERNAL_OES which is not supported by Skia yet. 544 {
599 // The bitmap's size needs to be the same as the video and use naturalSize() 545 base::AutoLock auto_lock(current_frame_lock_);
600 // here. Check if we could reuse existing texture based bitmap. 546 video_frame = current_frame_;
601 // Otherwise, release existing texture based bitmap and allocate
602 // a new one based on video size.
603 if (!EnsureTextureBackedSkBitmap(provider->grContext(), bitmap_,
604 naturalSize(), kTopLeft_GrSurfaceOrigin, kSkia8888_GrPixelConfig)) {
605 return;
606 } 547 }
607 548
608 unsigned textureId = static_cast<unsigned>( 549 gfx::Rect gfx_rect(rect);
609 (bitmap_.getTexture())->getTextureHandle()); 550 scoped_refptr<cc::ContextProvider> context_provider =
610 if (!copyVideoTextureToPlatformTexture(context3D, textureId, 0, 551 RenderThreadImpl::current()->SharedMainThreadContextProvider();
611 GL_RGBA, GL_UNSIGNED_BYTE, true, false)) { 552 media::SkCanvasVideoRenderer::Context3DProvider provider{
612 return; 553 context_provider->ContextGL(), context_provider->GrContext()};
613 } 554 skcanvas_video_renderer_.Paint(video_frame.get(),
614 555 canvas,
615 // Draw the texture based bitmap onto the Canvas. If the canvas is 556 gfx_rect,
616 // hardware based, this will do a GPU-GPU texture copy. 557 alpha,
617 // If the canvas is software based, the texture based bitmap will be 558 mode,
618 // readbacked to system memory then draw onto the canvas. 559 media::VIDEO_ROTATION_0,
619 SkRect dest; 560 &provider);
620 dest.set(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);
621 SkPaint paint;
622 paint.setAlpha(alpha);
623 paint.setXfermodeMode(mode);
624 // It is not necessary to pass the dest into the drawBitmap call since all
625 // the context have been set up before calling paintCurrentFrameInContext.
626 canvas->drawBitmapRect(bitmap_, 0, dest, &paint);
627 } 561 }
628 562
629 bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture( 563 bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture(
630 blink::WebGraphicsContext3D* web_graphics_context, 564 blink::WebGraphicsContext3D* web_graphics_context,
631 unsigned int texture, 565 unsigned int texture,
632 unsigned int level, 566 unsigned int level,
633 unsigned int internal_format, 567 unsigned int internal_format,
634 unsigned int type, 568 unsigned int type,
635 bool premultiply_alpha, 569 bool premultiply_alpha,
636 bool flip_y) { 570 bool flip_y) {
637 DCHECK(main_thread_checker_.CalledOnValidThread()); 571 DCHECK(main_thread_checker_.CalledOnValidThread());
638 // Don't allow clients to copy an encrypted video frame. 572 // Don't allow clients to copy an encrypted video frame.
639 if (needs_external_surface_) 573 if (needs_external_surface_)
640 return false; 574 return false;
641 575
642 scoped_refptr<VideoFrame> video_frame; 576 scoped_refptr<VideoFrame> video_frame;
643 { 577 {
644 base::AutoLock auto_lock(current_frame_lock_); 578 base::AutoLock auto_lock(current_frame_lock_);
645 video_frame = current_frame_; 579 video_frame = current_frame_;
646 } 580 }
647 581
648 if (!video_frame.get() || 582 if (!video_frame.get() ||
649 video_frame->format() != media::VideoFrame::NATIVE_TEXTURE) 583 video_frame->format() != media::VideoFrame::NATIVE_TEXTURE)
650 return false; 584 return false;
585
586 #if DCHECK_IS_ON
651 const gpu::MailboxHolder* mailbox_holder = video_frame->mailbox_holder(); 587 const gpu::MailboxHolder* mailbox_holder = video_frame->mailbox_holder();
652 DCHECK((!is_remote_ && 588 DCHECK((!is_remote_ &&
653 mailbox_holder->texture_target == GL_TEXTURE_EXTERNAL_OES) || 589 mailbox_holder->texture_target == GL_TEXTURE_EXTERNAL_OES) ||
654 (is_remote_ && mailbox_holder->texture_target == GL_TEXTURE_2D)); 590 (is_remote_ && mailbox_holder->texture_target == GL_TEXTURE_2D));
591 #endif
655 592
656 web_graphics_context->waitSyncPoint(mailbox_holder->sync_point); 593 // TODO(dshwang): need more elegant way to convert WebGraphicsContext3D to
657 594 // GLES2Interface.
658 // Ensure the target of texture is set before copyTextureCHROMIUM, otherwise 595 gpu::gles2::GLES2Interface* gl =
659 // an invalid texture target may be used for copy texture. 596 static_cast<webkit::gpu::WebGraphicsContext3DImpl*>(web_graphics_context)
660 uint32 src_texture = web_graphics_context->createAndConsumeTextureCHROMIUM( 597 ->GetGLInterface();
661 mailbox_holder->texture_target, mailbox_holder->mailbox.name); 598 skcanvas_video_renderer_.CopyVideoFrameToTexture(gl,
scherkus (not reviewing) 2014/10/15 17:10:23 use SkCanvasVideoRenderer:: instead of the object
662 599 video_frame.get(),
663 // The video is stored in an unmultiplied format, so premultiply if 600 texture,
664 // necessary. 601 level,
665 web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, 602 internal_format,
666 premultiply_alpha); 603 type,
667 604 premultiply_alpha,
668 // Application itself needs to take care of setting the right flip_y 605 flip_y);
669 // value down to get the expected result.
670 // flip_y==true means to reverse the video orientation while
671 // flip_y==false means to keep the intrinsic orientation.
672 web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, flip_y);
673 web_graphics_context->copyTextureCHROMIUM(GL_TEXTURE_2D, src_texture,
674 texture, level, internal_format,
675 type);
676 web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, false);
677 web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM,
678 false);
679
680 web_graphics_context->deleteTexture(src_texture);
681 web_graphics_context->flush();
682
683 SyncPointClientImpl client(web_graphics_context);
684 video_frame->UpdateReleaseSyncPoint(&client);
685 return true; 606 return true;
686 } 607 }
687 608
688 bool WebMediaPlayerAndroid::hasSingleSecurityOrigin() const { 609 bool WebMediaPlayerAndroid::hasSingleSecurityOrigin() const {
689 DCHECK(main_thread_checker_.CalledOnValidThread()); 610 DCHECK(main_thread_checker_.CalledOnValidThread());
690 if (player_type_ != MEDIA_PLAYER_TYPE_URL) 611 if (player_type_ != MEDIA_PLAYER_TYPE_URL)
691 return true; 612 return true;
692 613
693 if (!info_loader_ || !info_loader_->HasSingleOrigin()) 614 if (!info_loader_ || !info_loader_->HasSingleOrigin())
694 return false; 615 return false;
(...skipping 1135 matching lines...) Expand 10 before | Expand all | Expand 10 after
1830 1751
1831 bool WebMediaPlayerAndroid::IsHLSStream() const { 1752 bool WebMediaPlayerAndroid::IsHLSStream() const {
1832 std::string mime; 1753 std::string mime;
1833 GURL url = redirected_url_.is_empty() ? url_ : redirected_url_; 1754 GURL url = redirected_url_.is_empty() ? url_ : redirected_url_;
1834 if (!net::GetMimeTypeFromFile(base::FilePath(url.path()), &mime)) 1755 if (!net::GetMimeTypeFromFile(base::FilePath(url.path()), &mime))
1835 return false; 1756 return false;
1836 return !mime.compare("application/x-mpegurl"); 1757 return !mime.compare("application/x-mpegurl");
1837 } 1758 }
1838 1759
1839 } // namespace content 1760 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698