OLD | NEW |
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 <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <limits> | 9 #include <limits> |
10 | 10 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 #include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" | 58 #include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" |
59 #include "third_party/WebKit/public/platform/WebMediaPlayerEncryptedMediaClient.
h" | 59 #include "third_party/WebKit/public/platform/WebMediaPlayerEncryptedMediaClient.
h" |
60 #include "third_party/WebKit/public/platform/WebMediaPlayerSource.h" | 60 #include "third_party/WebKit/public/platform/WebMediaPlayerSource.h" |
61 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h" | 61 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h" |
62 #include "third_party/WebKit/public/platform/WebString.h" | 62 #include "third_party/WebKit/public/platform/WebString.h" |
63 #include "third_party/WebKit/public/platform/WebURL.h" | 63 #include "third_party/WebKit/public/platform/WebURL.h" |
64 #include "third_party/WebKit/public/web/WebDocument.h" | 64 #include "third_party/WebKit/public/web/WebDocument.h" |
65 #include "third_party/WebKit/public/web/WebFrame.h" | 65 #include "third_party/WebKit/public/web/WebFrame.h" |
66 #include "third_party/WebKit/public/web/WebView.h" | 66 #include "third_party/WebKit/public/web/WebView.h" |
67 #include "third_party/skia/include/core/SkCanvas.h" | 67 #include "third_party/skia/include/core/SkCanvas.h" |
| 68 #include "third_party/skia/include/core/SkImage.h" |
68 #include "third_party/skia/include/core/SkPaint.h" | 69 #include "third_party/skia/include/core/SkPaint.h" |
69 #include "third_party/skia/include/core/SkTypeface.h" | 70 #include "third_party/skia/include/core/SkTypeface.h" |
70 #include "third_party/skia/include/gpu/GrContext.h" | |
71 #include "third_party/skia/include/gpu/SkGrPixelRef.h" | |
72 #include "ui/gfx/image/image.h" | 71 #include "ui/gfx/image/image.h" |
73 | 72 |
74 static const uint32_t kGLTextureExternalOES = 0x8D65; | 73 static const uint32_t kGLTextureExternalOES = 0x8D65; |
75 static const int kSDKVersionToSupportSecurityOriginCheck = 20; | 74 static const int kSDKVersionToSupportSecurityOriginCheck = 20; |
76 | 75 |
77 using blink::WebMediaPlayer; | 76 using blink::WebMediaPlayer; |
78 using blink::WebSize; | 77 using blink::WebSize; |
79 using blink::WebString; | 78 using blink::WebString; |
80 using blink::WebURL; | 79 using blink::WebURL; |
81 using gpu::gles2::GLES2Interface; | 80 using gpu::gles2::GLES2Interface; |
(...skipping 20 matching lines...) Expand all Loading... |
102 const scoped_refptr<content::StreamTextureFactory>& factories, | 101 const scoped_refptr<content::StreamTextureFactory>& factories, |
103 uint32_t texture_id, | 102 uint32_t texture_id, |
104 const gpu::SyncToken& sync_token) { | 103 const gpu::SyncToken& sync_token) { |
105 GLES2Interface* gl = factories->ContextGL(); | 104 GLES2Interface* gl = factories->ContextGL(); |
106 gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); | 105 gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); |
107 gl->DeleteTextures(1, &texture_id); | 106 gl->DeleteTextures(1, &texture_id); |
108 // Flush to ensure that the stream texture gets deleted in a timely fashion. | 107 // Flush to ensure that the stream texture gets deleted in a timely fashion. |
109 gl->ShallowFlushCHROMIUM(); | 108 gl->ShallowFlushCHROMIUM(); |
110 } | 109 } |
111 | 110 |
112 bool IsSkBitmapProperlySizedTexture(const SkBitmap* bitmap, | |
113 const gfx::Size& size) { | |
114 return bitmap->getTexture() && bitmap->width() == size.width() && | |
115 bitmap->height() == size.height(); | |
116 } | |
117 | |
118 bool AllocateSkBitmapTexture(GrContext* gr, | |
119 SkBitmap* bitmap, | |
120 const gfx::Size& size) { | |
121 DCHECK(gr); | |
122 GrTextureDesc desc; | |
123 // Use kRGBA_8888_GrPixelConfig, not kSkia8888_GrPixelConfig, to avoid | |
124 // RGBA to BGRA conversion. | |
125 desc.fConfig = kRGBA_8888_GrPixelConfig; | |
126 // kRenderTarget_GrTextureFlagBit avoids a copy before readback in skia. | |
127 desc.fFlags = kRenderTarget_GrSurfaceFlag; | |
128 desc.fSampleCnt = 0; | |
129 desc.fOrigin = kTopLeft_GrSurfaceOrigin; | |
130 desc.fWidth = size.width(); | |
131 desc.fHeight = size.height(); | |
132 sk_sp<GrTexture> texture(gr->textureProvider()->refScratchTexture( | |
133 desc, GrTextureProvider::kExact_ScratchTexMatch)); | |
134 if (!texture.get()) | |
135 return false; | |
136 | |
137 SkImageInfo info = SkImageInfo::MakeN32Premul(desc.fWidth, desc.fHeight); | |
138 SkGrPixelRef* pixel_ref = new SkGrPixelRef(info, texture.get()); | |
139 if (!pixel_ref) | |
140 return false; | |
141 bitmap->setInfo(info); | |
142 bitmap->setPixelRef(pixel_ref)->unref(); | |
143 return true; | |
144 } | |
145 | |
146 class SyncTokenClientImpl : public media::VideoFrame::SyncTokenClient { | 111 class SyncTokenClientImpl : public media::VideoFrame::SyncTokenClient { |
147 public: | 112 public: |
148 explicit SyncTokenClientImpl(gpu::gles2::GLES2Interface* gl) : gl_(gl) {} | 113 explicit SyncTokenClientImpl(gpu::gles2::GLES2Interface* gl) : gl_(gl) {} |
149 ~SyncTokenClientImpl() override {} | 114 ~SyncTokenClientImpl() override {} |
150 void GenerateSyncToken(gpu::SyncToken* sync_token) override { | 115 void GenerateSyncToken(gpu::SyncToken* sync_token) override { |
151 const GLuint64 fence_sync = gl_->InsertFenceSyncCHROMIUM(); | 116 const GLuint64 fence_sync = gl_->InsertFenceSyncCHROMIUM(); |
152 gl_->ShallowFlushCHROMIUM(); | 117 gl_->ShallowFlushCHROMIUM(); |
153 gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token->GetData()); | 118 gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token->GetData()); |
154 } | 119 } |
155 void WaitSyncToken(const gpu::SyncToken& sync_token) override { | 120 void WaitSyncToken(const gpu::SyncToken& sync_token) override { |
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
652 unsigned char alpha, | 617 unsigned char alpha, |
653 SkXfermode::Mode mode) { | 618 SkXfermode::Mode mode) { |
654 DCHECK(main_thread_checker_.CalledOnValidThread()); | 619 DCHECK(main_thread_checker_.CalledOnValidThread()); |
655 std::unique_ptr<blink::WebGraphicsContext3DProvider> provider( | 620 std::unique_ptr<blink::WebGraphicsContext3DProvider> provider( |
656 blink::Platform::current() | 621 blink::Platform::current() |
657 ->createSharedOffscreenGraphicsContext3DProvider()); | 622 ->createSharedOffscreenGraphicsContext3DProvider()); |
658 if (!provider) | 623 if (!provider) |
659 return; | 624 return; |
660 gpu::gles2::GLES2Interface* gl = provider->contextGL(); | 625 gpu::gles2::GLES2Interface* gl = provider->contextGL(); |
661 | 626 |
662 // Copy video texture into a RGBA texture based bitmap first as video texture | 627 scoped_refptr<VideoFrame> video_frame; |
663 // on Android is GL_TEXTURE_EXTERNAL_OES which is not supported by Skia yet. | 628 { |
664 // The bitmap's size needs to be the same as the video and use naturalSize() | 629 base::AutoLock auto_lock(current_frame_lock_); |
665 // here. Check if we could reuse existing texture based bitmap. | 630 video_frame = current_frame_; |
666 // Otherwise, release existing texture based bitmap and allocate | |
667 // a new one based on video size. | |
668 if (!IsSkBitmapProperlySizedTexture(&bitmap_, naturalSize())) { | |
669 if (!AllocateSkBitmapTexture(provider->grContext(), &bitmap_, | |
670 naturalSize())) { | |
671 return; | |
672 } | |
673 } | 631 } |
674 | 632 |
675 unsigned textureId = skia::GrBackendObjectToGrGLTextureInfo( | 633 if (!video_frame.get() || !video_frame->HasTextures()) |
676 (bitmap_.getTexture())->getTextureHandle()) | |
677 ->fID; | |
678 if (!copyVideoTextureToPlatformTexture(gl, textureId, GL_RGBA, | |
679 GL_UNSIGNED_BYTE, true, false)) { | |
680 return; | 634 return; |
681 } | 635 DCHECK_EQ(1u, media::VideoFrame::NumPlanes(video_frame->format())); |
| 636 const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(0); |
682 | 637 |
683 // Ensure SkBitmap to make the latest change by external source visible. | 638 gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData()); |
684 bitmap_.notifyPixelsChanged(); | |
685 | 639 |
686 // Draw the texture based bitmap onto the Canvas. If the canvas is | 640 uint32_t src_texture = gl->CreateAndConsumeTextureCHROMIUM( |
| 641 mailbox_holder.texture_target, mailbox_holder.mailbox.name); |
| 642 |
| 643 GrGLTextureInfo texture_info; |
| 644 texture_info.fID = src_texture; |
| 645 texture_info.fTarget = mailbox_holder.texture_target; |
| 646 |
| 647 GrBackendTextureDesc desc; |
| 648 desc.fWidth = naturalSize().width; |
| 649 desc.fHeight = naturalSize().height; |
| 650 desc.fOrigin = kTopLeft_GrSurfaceOrigin; |
| 651 desc.fConfig = kRGBA_8888_GrPixelConfig; |
| 652 desc.fSampleCnt = 0; |
| 653 desc.fTextureHandle = skia::GrGLTextureInfoToGrBackendObject(texture_info); |
| 654 |
| 655 sk_sp<SkImage> image(SkImage::MakeFromTexture(provider->grContext(), desc, |
| 656 kOpaque_SkAlphaType)); |
| 657 if (!image) |
| 658 return; |
| 659 |
| 660 // Draw the texture based image onto the Canvas. If the canvas is |
687 // hardware based, this will do a GPU-GPU texture copy. | 661 // hardware based, this will do a GPU-GPU texture copy. |
688 // If the canvas is software based, the texture based bitmap will be | 662 // If the canvas is software based, the texture based bitmap will be |
689 // readbacked to system memory then draw onto the canvas. | 663 // readbacked to system memory then draw onto the canvas. |
690 SkRect dest; | 664 SkRect dest; |
691 dest.set(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height); | 665 dest.set(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height); |
692 SkPaint paint; | 666 SkPaint paint; |
693 paint.setAlpha(alpha); | 667 paint.setAlpha(alpha); |
694 paint.setXfermodeMode(mode); | 668 paint.setXfermodeMode(mode); |
695 // It is not necessary to pass the dest into the drawBitmap call since all | 669 // It is not necessary to pass the dest into the drawBitmap call since all |
696 // the context have been set up before calling paintCurrentFrameInContext. | 670 // the context have been set up before calling paintCurrentFrameInContext. |
697 canvas->drawBitmapRect(bitmap_, dest, &paint); | 671 canvas->drawImageRect(image, dest, &paint); |
| 672 |
| 673 // Ensure the Skia draw of the GL texture is flushed to GL, delete the |
| 674 // mailboxed texture from this context, and then signal that we're done with |
| 675 // the video frame. |
698 canvas->flush(); | 676 canvas->flush(); |
| 677 gl->DeleteTextures(1, &src_texture); |
| 678 gl->Flush(); |
| 679 SyncTokenClientImpl client(gl); |
| 680 video_frame->UpdateReleaseSyncToken(&client); |
699 } | 681 } |
700 | 682 |
701 bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture( | 683 bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture( |
702 gpu::gles2::GLES2Interface* gl, | 684 gpu::gles2::GLES2Interface* gl, |
703 unsigned int texture, | 685 unsigned int texture, |
704 unsigned int internal_format, | 686 unsigned int internal_format, |
705 unsigned int type, | 687 unsigned int type, |
706 bool premultiply_alpha, | 688 bool premultiply_alpha, |
707 bool flip_y) { | 689 bool flip_y) { |
708 DCHECK(main_thread_checker_.CalledOnValidThread()); | 690 DCHECK(main_thread_checker_.CalledOnValidThread()); |
(...skipping 971 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1680 result = PREDICTION_RESULT_PATH_BASED_WAS_BETTER; | 1662 result = PREDICTION_RESULT_PATH_BASED_WAS_BETTER; |
1681 } else if (is_hls_url == is_hls) { | 1663 } else if (is_hls_url == is_hls) { |
1682 result = PREDICTION_RESULT_URL_BASED_WAS_BETTER; | 1664 result = PREDICTION_RESULT_URL_BASED_WAS_BETTER; |
1683 } | 1665 } |
1684 UMA_HISTOGRAM_ENUMERATION( | 1666 UMA_HISTOGRAM_ENUMERATION( |
1685 "Media.Android.IsHttpLiveStreamingMediaPredictionResult", | 1667 "Media.Android.IsHttpLiveStreamingMediaPredictionResult", |
1686 result, PREDICTION_RESULT_MAX); | 1668 result, PREDICTION_RESULT_MAX); |
1687 } | 1669 } |
1688 | 1670 |
1689 } // namespace content | 1671 } // namespace content |
OLD | NEW |