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" |
11 #include "gpu/command_buffer/client/gles2_interface.h" | 11 #include "gpu/command_buffer/client/gles2_interface.h" |
12 #include "gpu/command_buffer/common/mailbox_holder.h" | 12 #include "gpu/command_buffer/common/mailbox_holder.h" |
13 #include "media/base/video_frame.h" | 13 #include "media/base/video_frame.h" |
14 #include "media/base/yuv_convert.h" | 14 #include "media/base/yuv_convert.h" |
15 #include "skia/ext/refptr.h" | 15 #include "skia/ext/refptr.h" |
| 16 #include "skia/ext/texture_handle.h" |
16 #include "third_party/libyuv/include/libyuv.h" | 17 #include "third_party/libyuv/include/libyuv.h" |
17 #include "third_party/skia/include/core/SkCanvas.h" | 18 #include "third_party/skia/include/core/SkCanvas.h" |
18 #include "third_party/skia/include/core/SkImage.h" | 19 #include "third_party/skia/include/core/SkImage.h" |
19 #include "third_party/skia/include/core/SkImageGenerator.h" | 20 #include "third_party/skia/include/core/SkImageGenerator.h" |
20 #include "third_party/skia/include/gpu/GrContext.h" | 21 #include "third_party/skia/include/gpu/GrContext.h" |
21 #include "third_party/skia/include/gpu/GrPaint.h" | 22 #include "third_party/skia/include/gpu/GrPaint.h" |
22 #include "third_party/skia/include/gpu/GrTexture.h" | 23 #include "third_party/skia/include/gpu/GrTexture.h" |
23 #include "third_party/skia/include/gpu/GrTextureProvider.h" | 24 #include "third_party/skia/include/gpu/GrTextureProvider.h" |
24 #include "third_party/skia/include/gpu/SkGr.h" | 25 #include "third_party/skia/include/gpu/SkGr.h" |
| 26 #include "third_party/skia/include/gpu/gl/GrGLTypes.h" |
25 #include "ui/gfx/geometry/rect_f.h" | 27 #include "ui/gfx/geometry/rect_f.h" |
26 #include "ui/gfx/skia_util.h" | 28 #include "ui/gfx/skia_util.h" |
27 | 29 |
28 // Skia internal format depends on a platform. On Android it is ABGR, on others | 30 // Skia internal format depends on a platform. On Android it is ABGR, on others |
29 // it is ARGB. | 31 // it is ARGB. |
30 #if SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && \ | 32 #if SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && \ |
31 SK_A32_SHIFT == 24 | 33 SK_A32_SHIFT == 24 |
32 #define LIBYUV_I420_TO_ARGB libyuv::I420ToARGB | 34 #define LIBYUV_I420_TO_ARGB libyuv::I420ToARGB |
33 #define LIBYUV_I422_TO_ARGB libyuv::I422ToARGB | 35 #define LIBYUV_I422_TO_ARGB libyuv::I422ToARGB |
34 #define LIBYUV_I444_TO_ARGB libyuv::I444ToARGB | 36 #define LIBYUV_I444_TO_ARGB libyuv::I444ToARGB |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 DCHECK(video_frame->HasTextures()); | 90 DCHECK(video_frame->HasTextures()); |
89 DCHECK_EQ(media::PIXEL_FORMAT_I420, video_frame->format()); | 91 DCHECK_EQ(media::PIXEL_FORMAT_I420, video_frame->format()); |
90 DCHECK_EQ(3u, media::VideoFrame::NumPlanes(video_frame->format())); | 92 DCHECK_EQ(3u, media::VideoFrame::NumPlanes(video_frame->format())); |
91 | 93 |
92 gpu::gles2::GLES2Interface* gl = context_3d.gl; | 94 gpu::gles2::GLES2Interface* gl = context_3d.gl; |
93 DCHECK(gl); | 95 DCHECK(gl); |
94 gfx::Size ya_tex_size = video_frame->coded_size(); | 96 gfx::Size ya_tex_size = video_frame->coded_size(); |
95 gfx::Size uv_tex_size((ya_tex_size.width() + 1) / 2, | 97 gfx::Size uv_tex_size((ya_tex_size.width() + 1) / 2, |
96 (ya_tex_size.height() + 1) / 2); | 98 (ya_tex_size.height() + 1) / 2); |
97 | 99 |
98 unsigned source_textures[3] = {0}; | 100 GrGLTextureInfo source_textures[] = {{0, 0}, {0, 0}, {0, 0}}; |
99 for (size_t i = 0; i < media::VideoFrame::NumPlanes(video_frame->format()); | 101 for (size_t i = 0; i < media::VideoFrame::NumPlanes(video_frame->format()); |
100 ++i) { | 102 ++i) { |
101 // Get the texture from the mailbox and wrap it in a GrTexture. | 103 // Get the texture from the mailbox and wrap it in a GrTexture. |
102 const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(i); | 104 const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(i); |
103 DCHECK(mailbox_holder.texture_target == GL_TEXTURE_2D || | 105 DCHECK(mailbox_holder.texture_target == GL_TEXTURE_2D || |
104 mailbox_holder.texture_target == GL_TEXTURE_EXTERNAL_OES || | 106 mailbox_holder.texture_target == GL_TEXTURE_EXTERNAL_OES || |
105 mailbox_holder.texture_target == GL_TEXTURE_RECTANGLE_ARB); | 107 mailbox_holder.texture_target == GL_TEXTURE_RECTANGLE_ARB); |
106 gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData()); | 108 gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData()); |
107 source_textures[i] = gl->CreateAndConsumeTextureCHROMIUM( | 109 source_textures[i].fID = gl->CreateAndConsumeTextureCHROMIUM( |
108 mailbox_holder.texture_target, mailbox_holder.mailbox.name); | 110 mailbox_holder.texture_target, mailbox_holder.mailbox.name); |
109 | 111 |
110 // TODO(dcastagna): avoid this copy once Skia supports native textures | 112 // TODO(dcastagna): avoid this copy once Skia supports native textures |
111 // with a texture target different than TEXTURE_2D. | 113 // with a texture target different than TEXTURE_2D. |
112 // crbug.com/505026 | 114 // crbug.com/505026 |
113 if (mailbox_holder.texture_target != GL_TEXTURE_2D) { | 115 if (mailbox_holder.texture_target != GL_TEXTURE_2D) { |
114 unsigned texture_copy = 0; | 116 unsigned texture_copy = 0; |
115 gl->GenTextures(1, &texture_copy); | 117 gl->GenTextures(1, &texture_copy); |
116 DCHECK(texture_copy); | 118 DCHECK(texture_copy); |
117 gl->BindTexture(GL_TEXTURE_2D, texture_copy); | 119 gl->BindTexture(GL_TEXTURE_2D, texture_copy); |
118 gl->CopyTextureCHROMIUM(source_textures[i], texture_copy, GL_RGB, | 120 gl->CopyTextureCHROMIUM(source_textures[i].fID, texture_copy, GL_RGB, |
119 GL_UNSIGNED_BYTE, false, true, false); | 121 GL_UNSIGNED_BYTE, false, true, false); |
120 | 122 |
121 gl->DeleteTextures(1, &source_textures[i]); | 123 gl->DeleteTextures(1, &source_textures[i].fID); |
122 source_textures[i] = texture_copy; | 124 source_textures[i].fID = texture_copy; |
| 125 source_textures[i].fTarget = GL_TEXTURE_2D; |
123 } | 126 } |
124 } | 127 } |
125 DCHECK_LE(source_textures[0], | 128 GrBackendObject handles[3] = { |
126 static_cast<unsigned>(std::numeric_limits<int>::max())); | 129 skia::GrGLTextureInfoToGrBackendObject(source_textures[0]), |
127 DCHECK_LE(source_textures[1], | 130 skia::GrGLTextureInfoToGrBackendObject(source_textures[1]), |
128 static_cast<unsigned>(std::numeric_limits<int>::max())); | 131 skia::GrGLTextureInfoToGrBackendObject(source_textures[2])}; |
129 DCHECK_LE(source_textures[2], | |
130 static_cast<unsigned>(std::numeric_limits<int>::max())); | |
131 GrBackendObject handles[3] = {static_cast<int>(source_textures[0]), | |
132 static_cast<int>(source_textures[1]), | |
133 static_cast<int>(source_textures[2])}; | |
134 | 132 |
135 SkISize yuvSizes[] = { | 133 SkISize yuvSizes[] = { |
136 {ya_tex_size.width(), ya_tex_size.height()}, | 134 {ya_tex_size.width(), ya_tex_size.height()}, |
137 {uv_tex_size.width(), uv_tex_size.height()}, | 135 {uv_tex_size.width(), uv_tex_size.height()}, |
138 {uv_tex_size.width(), uv_tex_size.height()}, | 136 {uv_tex_size.width(), uv_tex_size.height()}, |
139 }; | 137 }; |
140 | 138 |
141 SkYUVColorSpace color_space = kRec601_SkYUVColorSpace; | 139 SkYUVColorSpace color_space = kRec601_SkYUVColorSpace; |
142 if (CheckColorSpace(video_frame, media::COLOR_SPACE_JPEG)) | 140 if (CheckColorSpace(video_frame, media::COLOR_SPACE_JPEG)) |
143 color_space = kJPEG_SkYUVColorSpace; | 141 color_space = kJPEG_SkYUVColorSpace; |
144 else if (CheckColorSpace(video_frame, media::COLOR_SPACE_HD_REC709)) | 142 else if (CheckColorSpace(video_frame, media::COLOR_SPACE_HD_REC709)) |
145 color_space = kRec709_SkYUVColorSpace; | 143 color_space = kRec709_SkYUVColorSpace; |
146 | 144 |
147 SkImage* img = SkImage::NewFromYUVTexturesCopy(context_3d.gr_context, | 145 SkImage* img = SkImage::NewFromYUVTexturesCopy(context_3d.gr_context, |
148 color_space, handles, yuvSizes, | 146 color_space, handles, yuvSizes, |
149 kTopLeft_GrSurfaceOrigin); | 147 kTopLeft_GrSurfaceOrigin); |
150 gl->DeleteTextures(3, source_textures); | 148 for (size_t i = 0; i < media::VideoFrame::NumPlanes(video_frame->format()); |
| 149 ++i) { |
| 150 gl->DeleteTextures(1, &source_textures[i].fID); |
| 151 } |
151 return skia::AdoptRef(img); | 152 return skia::AdoptRef(img); |
152 } | 153 } |
153 | 154 |
154 // Creates a SkImage from a |video_frame| backed by native resources. | 155 // Creates a SkImage from a |video_frame| backed by native resources. |
155 // The SkImage will take ownership of the underlying resource. | 156 // The SkImage will take ownership of the underlying resource. |
156 skia::RefPtr<SkImage> NewSkImageFromVideoFrameNative( | 157 skia::RefPtr<SkImage> NewSkImageFromVideoFrameNative( |
157 VideoFrame* video_frame, | 158 VideoFrame* video_frame, |
158 const Context3D& context_3d) { | 159 const Context3D& context_3d) { |
159 DCHECK(PIXEL_FORMAT_ARGB == video_frame->format() || | 160 DCHECK(PIXEL_FORMAT_ARGB == video_frame->format() || |
160 PIXEL_FORMAT_XRGB == video_frame->format() || | 161 PIXEL_FORMAT_XRGB == video_frame->format() || |
(...skipping 22 matching lines...) Expand all Loading... |
183 gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData()); | 184 gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData()); |
184 source_texture = gl->CreateAndConsumeTextureCHROMIUM( | 185 source_texture = gl->CreateAndConsumeTextureCHROMIUM( |
185 mailbox_holder.texture_target, mailbox_holder.mailbox.name); | 186 mailbox_holder.texture_target, mailbox_holder.mailbox.name); |
186 } | 187 } |
187 GrBackendTextureDesc desc; | 188 GrBackendTextureDesc desc; |
188 desc.fFlags = kRenderTarget_GrBackendTextureFlag; | 189 desc.fFlags = kRenderTarget_GrBackendTextureFlag; |
189 desc.fOrigin = kTopLeft_GrSurfaceOrigin; | 190 desc.fOrigin = kTopLeft_GrSurfaceOrigin; |
190 desc.fWidth = video_frame->coded_size().width(); | 191 desc.fWidth = video_frame->coded_size().width(); |
191 desc.fHeight = video_frame->coded_size().height(); | 192 desc.fHeight = video_frame->coded_size().height(); |
192 desc.fConfig = kRGBA_8888_GrPixelConfig; | 193 desc.fConfig = kRGBA_8888_GrPixelConfig; |
193 DCHECK_LE(source_texture, | 194 GrGLTextureInfo source_texture_info; |
194 static_cast<unsigned>(std::numeric_limits<int>::max())); | 195 source_texture_info.fID = source_texture; |
195 desc.fTextureHandle = static_cast<int>(source_texture); | 196 source_texture_info.fTarget = GL_TEXTURE_2D; |
| 197 desc.fTextureHandle = |
| 198 skia::GrGLTextureInfoToGrBackendObject(source_texture_info); |
196 return skia::AdoptRef( | 199 return skia::AdoptRef( |
197 SkImage::NewFromAdoptedTexture(context_3d.gr_context, desc)); | 200 SkImage::NewFromAdoptedTexture(context_3d.gr_context, desc)); |
198 } | 201 } |
199 | 202 |
200 } // anonymous namespace | 203 } // anonymous namespace |
201 | 204 |
202 // Generates an RGB image from a VideoFrame. Convert YUV to RGB plain on GPU. | 205 // Generates an RGB image from a VideoFrame. Convert YUV to RGB plain on GPU. |
203 class VideoImageGenerator : public SkImageGenerator { | 206 class VideoImageGenerator : public SkImageGenerator { |
204 public: | 207 public: |
205 VideoImageGenerator(const scoped_refptr<VideoFrame>& frame) | 208 VideoImageGenerator(const scoped_refptr<VideoFrame>& frame) |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
659 } | 662 } |
660 | 663 |
661 void SkCanvasVideoRenderer::ResetCache() { | 664 void SkCanvasVideoRenderer::ResetCache() { |
662 DCHECK(thread_checker_.CalledOnValidThread()); | 665 DCHECK(thread_checker_.CalledOnValidThread()); |
663 // Clear cached values. | 666 // Clear cached values. |
664 last_image_ = nullptr; | 667 last_image_ = nullptr; |
665 last_timestamp_ = kNoTimestamp(); | 668 last_timestamp_ = kNoTimestamp(); |
666 } | 669 } |
667 | 670 |
668 } // namespace media | 671 } // namespace media |
OLD | NEW |