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

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: Don't move SkCanvasVideoRenderer Created 6 years, 4 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/bind.h" 9 #include "base/bind.h"
10 #include "base/callback_helpers.h" 10 #include "base/callback_helpers.h"
(...skipping 21 matching lines...) Expand all
32 #include "gpu/GLES2/gl2extchromium.h" 32 #include "gpu/GLES2/gl2extchromium.h"
33 #include "gpu/command_buffer/client/gles2_interface.h" 33 #include "gpu/command_buffer/client/gles2_interface.h"
34 #include "gpu/command_buffer/common/mailbox_holder.h" 34 #include "gpu/command_buffer/common/mailbox_holder.h"
35 #include "media/base/android/media_player_android.h" 35 #include "media/base/android/media_player_android.h"
36 #include "media/base/bind_to_current_loop.h" 36 #include "media/base/bind_to_current_loop.h"
37 // TODO(xhwang): Remove when we remove prefixed EME implementation. 37 // TODO(xhwang): Remove when we remove prefixed EME implementation.
38 #include "media/base/media_keys.h" 38 #include "media/base/media_keys.h"
39 #include "media/base/media_switches.h" 39 #include "media/base/media_switches.h"
40 #include "media/base/video_frame.h" 40 #include "media/base/video_frame.h"
41 #include "net/base/mime_util.h" 41 #include "net/base/mime_util.h"
42 #include "third_party/WebKit/public/platform/Platform.h" 42 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
43 #include "third_party/WebKit/public/platform/WebGraphicsContext3DProvider.h"
44 #include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" 43 #include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
45 #include "third_party/WebKit/public/platform/WebString.h" 44 #include "third_party/WebKit/public/platform/WebString.h"
46 #include "third_party/WebKit/public/platform/WebURL.h" 45 #include "third_party/WebKit/public/platform/WebURL.h"
47 #include "third_party/WebKit/public/web/WebDocument.h" 46 #include "third_party/WebKit/public/web/WebDocument.h"
48 #include "third_party/WebKit/public/web/WebFrame.h" 47 #include "third_party/WebKit/public/web/WebFrame.h"
49 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h" 48 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
50 #include "third_party/WebKit/public/web/WebSecurityOrigin.h" 49 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
51 #include "third_party/WebKit/public/web/WebView.h" 50 #include "third_party/WebKit/public/web/WebView.h"
51 #include "third_party/skia/include/core/SkBitmap.h"
52 #include "third_party/skia/include/core/SkCanvas.h" 52 #include "third_party/skia/include/core/SkCanvas.h"
53 #include "third_party/skia/include/core/SkPaint.h"
54 #include "third_party/skia/include/core/SkTypeface.h" 53 #include "third_party/skia/include/core/SkTypeface.h"
55 #include "ui/gfx/image/image.h" 54 #include "ui/gfx/image/image.h"
55 #include "webkit/common/gpu/context_provider_web_context.h"
56 #include "webkit/common/gpu/webgraphicscontext3d_impl.h"
56 57
57 static const uint32 kGLTextureExternalOES = 0x8D65; 58 static const uint32 kGLTextureExternalOES = 0x8D65;
58 59
59 using blink::WebMediaPlayer; 60 using blink::WebMediaPlayer;
60 using blink::WebSize; 61 using blink::WebSize;
61 using blink::WebString; 62 using blink::WebString;
62 using blink::WebTimeRanges; 63 using blink::WebTimeRanges;
63 using blink::WebURL; 64 using blink::WebURL;
64 using gpu::gles2::GLES2Interface; 65 using gpu::gles2::GLES2Interface;
65 using media::MediaPlayerAndroid; 66 using media::MediaPlayerAndroid;
66 using media::VideoFrame; 67 using media::VideoFrame;
67 68
68 namespace { 69 namespace {
69 // Prefix for histograms related to Encrypted Media Extensions. 70 // Prefix for histograms related to Encrypted Media Extensions.
70 const char* kMediaEme = "Media.EME."; 71 const char* kMediaEme = "Media.EME.";
71 72
72 // File-static function is to allow it to run even after WMPA is deleted. 73 // File-static function is to allow it to run even after WMPA is deleted.
73 void OnReleaseTexture( 74 void OnReleaseTexture(
74 const scoped_refptr<content::StreamTextureFactory>& factories, 75 const scoped_refptr<content::StreamTextureFactory>& factories,
75 uint32 texture_id, 76 uint32 texture_id,
76 uint32 release_sync_point) { 77 uint32 release_sync_point) {
77 GLES2Interface* gl = factories->ContextGL(); 78 GLES2Interface* gl = factories->ContextGL();
78 gl->WaitSyncPointCHROMIUM(release_sync_point); 79 gl->WaitSyncPointCHROMIUM(release_sync_point);
79 gl->DeleteTextures(1, &texture_id); 80 gl->DeleteTextures(1, &texture_id);
80 } 81 }
81 82
82 class SyncPointClientImpl : public media::VideoFrame::SyncPointClient {
83 public:
84 explicit SyncPointClientImpl(
85 blink::WebGraphicsContext3D* web_graphics_context)
86 : web_graphics_context_(web_graphics_context) {}
87 virtual ~SyncPointClientImpl() {}
88 virtual uint32 InsertSyncPoint() OVERRIDE {
89 return web_graphics_context_->insertSyncPoint();
90 }
91 virtual void WaitSyncPoint(uint32 sync_point) OVERRIDE {
92 web_graphics_context_->waitSyncPoint(sync_point);
93 }
94
95 private:
96 blink::WebGraphicsContext3D* web_graphics_context_;
97 };
98
99 } // namespace 83 } // namespace
100 84
101 namespace content { 85 namespace content {
102 86
103 WebMediaPlayerAndroid::WebMediaPlayerAndroid( 87 WebMediaPlayerAndroid::WebMediaPlayerAndroid(
104 blink::WebFrame* frame, 88 blink::WebFrame* frame,
105 blink::WebMediaPlayerClient* client, 89 blink::WebMediaPlayerClient* client,
106 base::WeakPtr<WebMediaPlayerDelegate> delegate, 90 base::WeakPtr<WebMediaPlayerDelegate> delegate,
107 RendererMediaPlayerManager* player_manager, 91 RendererMediaPlayerManager* player_manager,
108 RendererCdmManager* cdm_manager, 92 RendererCdmManager* cdm_manager,
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 438
455 return duration(); 439 return duration();
456 } 440 }
457 441
458 bool WebMediaPlayerAndroid::didLoadingProgress() { 442 bool WebMediaPlayerAndroid::didLoadingProgress() {
459 bool ret = did_loading_progress_; 443 bool ret = did_loading_progress_;
460 did_loading_progress_ = false; 444 did_loading_progress_ = false;
461 return ret; 445 return ret;
462 } 446 }
463 447
464 bool WebMediaPlayerAndroid::EnsureTextureBackedSkBitmap(GrContext* gr,
465 SkBitmap& bitmap,
466 const WebSize& size,
467 GrSurfaceOrigin origin,
468 GrPixelConfig config) {
469 if (!bitmap.getTexture() || bitmap.width() != size.width
470 || bitmap.height() != size.height) {
471 if (!gr)
472 return false;
473 GrTextureDesc desc;
474 desc.fConfig = config;
475 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
476 desc.fSampleCnt = 0;
477 desc.fOrigin = origin;
478 desc.fWidth = size.width;
479 desc.fHeight = size.height;
480 skia::RefPtr<GrTexture> texture;
481 texture = skia::AdoptRef(gr->createUncachedTexture(desc, 0, 0));
482 if (!texture.get())
483 return false;
484
485 SkImageInfo info = SkImageInfo::MakeN32Premul(desc.fWidth, desc.fHeight);
486 SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (info, texture.get()));
487 if (!pixelRef)
488 return false;
489 bitmap.setInfo(info);
490 bitmap.setPixelRef(pixelRef)->unref();
491 }
492
493 return true;
494 }
495
496 void WebMediaPlayerAndroid::paint(blink::WebCanvas* canvas, 448 void WebMediaPlayerAndroid::paint(blink::WebCanvas* canvas,
497 const blink::WebRect& rect, 449 const blink::WebRect& rect,
498 unsigned char alpha) { 450 unsigned char alpha) {
499 scoped_ptr<blink::WebGraphicsContext3DProvider> provider = 451 // Don't allow clients to copy an encrypted video frame.
500 scoped_ptr<blink::WebGraphicsContext3DProvider>(blink::Platform::current( 452 if (needs_external_surface_)
501 )->createSharedOffscreenGraphicsContext3DProvider());
502 if (!provider)
503 return;
504 blink::WebGraphicsContext3D* context3D = provider->context3d();
505 if (!context3D || !context3D->makeContextCurrent())
506 return; 453 return;
507 454
508 // Copy video texture into a RGBA texture based bitmap first as video texture 455 scoped_refptr<VideoFrame> video_frame;
509 // on Android is GL_TEXTURE_EXTERNAL_OES which is not supported by Skia yet. 456 {
510 // The bitmap's size needs to be the same as the video and use naturalSize() 457 base::AutoLock auto_lock(current_frame_lock_);
511 // here. Check if we could reuse existing texture based bitmap. 458 video_frame = current_frame_;
512 // Otherwise, release existing texture based bitmap and allocate
513 // a new one based on video size.
514 if (!EnsureTextureBackedSkBitmap(provider->grContext(), bitmap_,
515 naturalSize(), kTopLeft_GrSurfaceOrigin, kSkia8888_GrPixelConfig)) {
516 return;
517 } 459 }
518 460
519 unsigned textureId = static_cast<unsigned>( 461 gfx::Rect gfx_rect(rect);
520 (bitmap_.getTexture())->getTextureHandle()); 462 scoped_refptr<cc::ContextProvider> context_provider =
521 if (!copyVideoTextureToPlatformTexture(context3D, textureId, 0, 463 RenderThreadImpl::current()->SharedMainThreadContextProvider();
522 GL_RGBA, GL_UNSIGNED_BYTE, true, false)) { 464 media::SkCanvasVideoRenderer::ContextProvider provider{
523 return; 465 context_provider->ContextGL(), context_provider->GrContext()};
524 } 466 skcanvas_video_renderer_.Paint(
525 467 video_frame.get(), canvas, gfx_rect, alpha, &provider);
526 // Draw the texture based bitmap onto the Canvas. If the canvas is
527 // hardware based, this will do a GPU-GPU texture copy.
528 // If the canvas is software based, the texture based bitmap will be
529 // readbacked to system memory then draw onto the canvas.
530 SkRect dest;
531 dest.set(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);
532 SkPaint paint;
533 paint.setAlpha(alpha);
534 // It is not necessary to pass the dest into the drawBitmap call since all
535 // the context have been set up before calling paintCurrentFrameInContext.
536 canvas->drawBitmapRect(bitmap_, 0, dest, &paint);
537 } 468 }
538 469
539 bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture( 470 bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture(
540 blink::WebGraphicsContext3D* web_graphics_context, 471 blink::WebGraphicsContext3D* web_graphics_context,
541 unsigned int texture, 472 unsigned int texture,
542 unsigned int level, 473 unsigned int level,
543 unsigned int internal_format, 474 unsigned int internal_format,
544 unsigned int type, 475 unsigned int type,
545 bool premultiply_alpha, 476 bool premultiply_alpha,
546 bool flip_y) { 477 bool flip_y) {
547 // Don't allow clients to copy an encrypted video frame. 478 // Don't allow clients to copy an encrypted video frame.
548 if (needs_external_surface_) 479 if (needs_external_surface_)
549 return false; 480 return false;
550 481
551 scoped_refptr<VideoFrame> video_frame; 482 scoped_refptr<VideoFrame> video_frame;
552 { 483 {
553 base::AutoLock auto_lock(current_frame_lock_); 484 base::AutoLock auto_lock(current_frame_lock_);
554 video_frame = current_frame_; 485 video_frame = current_frame_;
555 } 486 }
556 487
557 if (!video_frame || 488 if (!video_frame ||
558 video_frame->format() != media::VideoFrame::NATIVE_TEXTURE) 489 video_frame->format() != media::VideoFrame::NATIVE_TEXTURE)
559 return false; 490 return false;
491
492 #if DCHECK_IS_ON
560 const gpu::MailboxHolder* mailbox_holder = video_frame->mailbox_holder(); 493 const gpu::MailboxHolder* mailbox_holder = video_frame->mailbox_holder();
561 DCHECK((!is_remote_ && 494 DCHECK((!is_remote_ &&
562 mailbox_holder->texture_target == GL_TEXTURE_EXTERNAL_OES) || 495 mailbox_holder->texture_target == GL_TEXTURE_EXTERNAL_OES) ||
563 (is_remote_ && mailbox_holder->texture_target == GL_TEXTURE_2D)); 496 (is_remote_ && mailbox_holder->texture_target == GL_TEXTURE_2D));
497 #endif
564 498
565 // For hidden video element (with style "display:none"), ensure the texture 499 // For hidden video element (with style "display:none"), ensure the texture
566 // size is set. 500 // size is set.
567 if (!is_remote_ && 501 if (!is_remote_ &&
568 (cached_stream_texture_size_.width != natural_size_.width || 502 (cached_stream_texture_size_.width != natural_size_.width ||
569 cached_stream_texture_size_.height != natural_size_.height)) { 503 cached_stream_texture_size_.height != natural_size_.height)) {
570 stream_texture_factory_->SetStreamTextureSize( 504 stream_texture_factory_->SetStreamTextureSize(
571 stream_id_, gfx::Size(natural_size_.width, natural_size_.height)); 505 stream_id_, gfx::Size(natural_size_.width, natural_size_.height));
572 cached_stream_texture_size_ = natural_size_; 506 cached_stream_texture_size_ = natural_size_;
573 } 507 }
574 508
575 web_graphics_context->waitSyncPoint(mailbox_holder->sync_point); 509 // TODO(dshwang): need more elegant way to convert WebGraphicsContext3D to
576 510 // GLES2Interface.
577 // Ensure the target of texture is set before copyTextureCHROMIUM, otherwise 511 gpu::gles2::GLES2Interface* gl =
578 // an invalid texture target may be used for copy texture. 512 static_cast<webkit::gpu::WebGraphicsContext3DImpl*>(web_graphics_context)
579 uint32 src_texture = web_graphics_context->createAndConsumeTextureCHROMIUM( 513 ->GetGLInterface();
580 mailbox_holder->texture_target, mailbox_holder->mailbox.name); 514 skcanvas_video_renderer_.CopyVideoFrameToTexture(gl,
581 515 video_frame.get(),
582 // The video is stored in an unmultiplied format, so premultiply if 516 texture,
583 // necessary. 517 level,
584 web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, 518 internal_format,
585 premultiply_alpha); 519 type,
586 520 premultiply_alpha,
587 // Application itself needs to take care of setting the right flip_y 521 flip_y);
588 // value down to get the expected result.
589 // flip_y==true means to reverse the video orientation while
590 // flip_y==false means to keep the intrinsic orientation.
591 web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, flip_y);
592 web_graphics_context->copyTextureCHROMIUM(GL_TEXTURE_2D, src_texture,
593 texture, level, internal_format,
594 type);
595 web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, false);
596 web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM,
597 false);
598
599 web_graphics_context->deleteTexture(src_texture);
600 web_graphics_context->flush();
601
602 SyncPointClientImpl client(web_graphics_context);
603 video_frame->UpdateReleaseSyncPoint(&client);
604 return true; 522 return true;
605 } 523 }
606 524
607 bool WebMediaPlayerAndroid::hasSingleSecurityOrigin() const { 525 bool WebMediaPlayerAndroid::hasSingleSecurityOrigin() const {
608 if (info_loader_) 526 if (info_loader_)
609 return info_loader_->HasSingleOrigin(); 527 return info_loader_->HasSingleOrigin();
610 // The info loader may have failed. 528 // The info loader may have failed.
611 if (player_type_ == MEDIA_PLAYER_TYPE_URL) 529 if (player_type_ == MEDIA_PLAYER_TYPE_URL)
612 return false; 530 return false;
613 return true; 531 return true;
(...skipping 988 matching lines...) Expand 10 before | Expand all | Expand 10 after
1602 player_manager_->EnterFullscreen(player_id_, frame_); 1520 player_manager_->EnterFullscreen(player_id_, frame_);
1603 SetNeedsEstablishPeer(false); 1521 SetNeedsEstablishPeer(false);
1604 } 1522 }
1605 } 1523 }
1606 1524
1607 bool WebMediaPlayerAndroid::canEnterFullscreen() const { 1525 bool WebMediaPlayerAndroid::canEnterFullscreen() const {
1608 return player_manager_->CanEnterFullscreen(frame_); 1526 return player_manager_->CanEnterFullscreen(frame_);
1609 } 1527 }
1610 1528
1611 } // namespace content 1529 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698