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