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/blink/skcanvas_video_renderer.h" | 5 #include "media/blink/skcanvas_video_renderer.h" |
6 | 6 |
7 #include "gpu/GLES2/gl2extchromium.h" | 7 #include "gpu/GLES2/gl2extchromium.h" |
8 #include "gpu/command_buffer/client/gles2_interface.h" | 8 #include "gpu/command_buffer/client/gles2_interface.h" |
9 #include "gpu/command_buffer/common/mailbox_holder.h" | 9 #include "gpu/command_buffer/common/mailbox_holder.h" |
10 #include "media/base/video_frame.h" | 10 #include "media/base/video_frame.h" |
11 #include "media/base/yuv_convert.h" | 11 #include "media/base/yuv_convert.h" |
12 #include "skia/ext/refptr.h" | 12 #include "skia/ext/refptr.h" |
13 #include "third_party/libyuv/include/libyuv.h" | 13 #include "third_party/libyuv/include/libyuv.h" |
14 #include "third_party/skia/include/core/SkCanvas.h" | 14 #include "third_party/skia/include/core/SkCanvas.h" |
15 #include "third_party/skia/include/core/SkImage.h" | |
15 #include "third_party/skia/include/core/SkImageGenerator.h" | 16 #include "third_party/skia/include/core/SkImageGenerator.h" |
16 #include "third_party/skia/include/gpu/GrContext.h" | 17 #include "third_party/skia/include/gpu/GrContext.h" |
18 #include "third_party/skia/include/gpu/GrPaint.h" | |
19 #include "third_party/skia/include/gpu/GrTexture.h" | |
17 #include "third_party/skia/include/gpu/GrTextureProvider.h" | 20 #include "third_party/skia/include/gpu/GrTextureProvider.h" |
21 #include "third_party/skia/include/gpu/SkGr.h" | |
18 #include "third_party/skia/include/gpu/SkGrPixelRef.h" | 22 #include "third_party/skia/include/gpu/SkGrPixelRef.h" |
19 #include "ui/gfx/skbitmap_operations.h" | 23 #include "ui/gfx/skbitmap_operations.h" |
20 | 24 |
21 // Skia internal format depends on a platform. On Android it is ABGR, on others | 25 // Skia internal format depends on a platform. On Android it is ABGR, on others |
22 // it is ARGB. | 26 // it is ARGB. |
23 #if SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && \ | 27 #if SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && \ |
24 SK_A32_SHIFT == 24 | 28 SK_A32_SHIFT == 24 |
25 #define LIBYUV_I420_TO_ARGB libyuv::I420ToARGB | 29 #define LIBYUV_I420_TO_ARGB libyuv::I420ToARGB |
26 #define LIBYUV_I422_TO_ARGB libyuv::I422ToARGB | 30 #define LIBYUV_I422_TO_ARGB libyuv::I422ToARGB |
27 #elif SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \ | 31 #elif SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \ |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
77 | 81 |
78 SkImageInfo info = SkImageInfo::MakeN32Premul(desc.fWidth, desc.fHeight); | 82 SkImageInfo info = SkImageInfo::MakeN32Premul(desc.fWidth, desc.fHeight); |
79 SkGrPixelRef* pixel_ref = SkNEW_ARGS(SkGrPixelRef, (info, texture.get())); | 83 SkGrPixelRef* pixel_ref = SkNEW_ARGS(SkGrPixelRef, (info, texture.get())); |
80 if (!pixel_ref) | 84 if (!pixel_ref) |
81 return false; | 85 return false; |
82 bitmap->setInfo(info); | 86 bitmap->setInfo(info); |
83 bitmap->setPixelRef(pixel_ref)->unref(); | 87 bitmap->setPixelRef(pixel_ref)->unref(); |
84 return true; | 88 return true; |
85 } | 89 } |
86 | 90 |
87 bool CopyVideoFrameTextureToSkBitmapTexture(VideoFrame* video_frame, | 91 scoped_ptr<SkImage> CreateSkImageFromVideoFrameNativeTextures( |
88 SkBitmap* bitmap, | 92 VideoFrame* video_frame, |
89 const Context3D& context_3d) { | 93 const Context3D& context_3d) { |
94 // Support only TEXTURE_YUV_420. | |
95 DCHECK(video_frame->storage_type() == VideoFrame::STORAGE_TEXTURE); | |
96 DCHECK_EQ(media::VideoFrame::I420, video_frame->format()); | |
97 DCHECK_EQ(3u, media::VideoFrame::NumPlanes(video_frame->format())); | |
98 | |
99 gpu::gles2::GLES2Interface* gl = context_3d.gl; | |
100 gfx::Size ya_tex_size = video_frame->coded_size(); | |
101 gfx::Size uv_tex_size((ya_tex_size.width() + 1) / 2, | |
102 (ya_tex_size.height() + 1) / 2); | |
103 | |
104 unsigned source_textures[3] = {0}; | |
105 for (size_t i = 0; i < media::VideoFrame::NumPlanes(video_frame->format()); | |
106 ++i) { | |
107 // Get the texture from the mailbox and wrap it in a GrTexture. | |
108 const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(i); | |
109 DCHECK(mailbox_holder.texture_target == GL_TEXTURE_2D || | |
110 mailbox_holder.texture_target == GL_TEXTURE_RECTANGLE_ARB); | |
dshwang
2015/06/10 07:26:37
TEXTURE_EXTERNAL_OES?
Daniele Castagna
2015/06/10 14:22:54
Done.
| |
111 gl->WaitSyncPointCHROMIUM(mailbox_holder.sync_point); | |
112 source_textures[i] = gl->CreateAndConsumeTextureCHROMIUM( | |
113 mailbox_holder.texture_target, mailbox_holder.mailbox.name); | |
dshwang
2015/06/10 07:26:38
how these textures are deleted?
Daniele Castagna
2015/06/10 14:22:54
Added glDeleteTextures.
| |
114 } | |
115 GrBackendObject handles[3] = { | |
116 source_textures[0], source_textures[1], source_textures[2]}; | |
117 | |
118 SkISize yuvSizes[] = { | |
119 {ya_tex_size.width(), ya_tex_size.height()}, | |
120 {uv_tex_size.width(), uv_tex_size.height()}, | |
121 {uv_tex_size.width(), uv_tex_size.height()}, | |
122 }; | |
123 SkImage* img = SkImage::NewFromYUVTexturesCopy( | |
124 context_3d.gr_context, kRec601_SkYUVColorSpace, handles, yuvSizes, | |
125 kTopLeft_GrSurfaceOrigin); | |
dshwang
2015/06/10 07:26:38
need to insert sync point here
Daniele Castagna
2015/06/10 14:22:54
Done.
| |
126 DCHECK(img); | |
127 return make_scoped_ptr(img); | |
128 } | |
129 | |
130 bool CopyVideoFrameSingleTextureToSkBitmap(VideoFrame* video_frame, | |
131 SkBitmap* bitmap, | |
132 const Context3D& context_3d) { | |
90 // Check if we could reuse existing texture based bitmap. | 133 // Check if we could reuse existing texture based bitmap. |
91 // Otherwise, release existing texture based bitmap and allocate | 134 // Otherwise, release existing texture based bitmap and allocate |
92 // a new one based on video size. | 135 // a new one based on video size. |
93 if (!IsSkBitmapProperlySizedTexture(bitmap, | 136 if (!IsSkBitmapProperlySizedTexture(bitmap, |
94 video_frame->visible_rect().size())) { | 137 video_frame->visible_rect().size())) { |
95 if (!AllocateSkBitmapTexture(context_3d.gr_context, bitmap, | 138 if (!AllocateSkBitmapTexture(context_3d.gr_context, bitmap, |
96 video_frame->visible_rect().size())) { | 139 video_frame->visible_rect().size())) { |
97 return false; | 140 return false; |
98 } | 141 } |
99 } | 142 } |
100 | 143 |
101 unsigned texture_id = | 144 unsigned texture_id = |
102 static_cast<unsigned>((bitmap->getTexture())->getTextureHandle()); | 145 static_cast<unsigned>((bitmap->getTexture())->getTextureHandle()); |
103 // If CopyVideoFrameTextureToGLTexture() changes the state of the | 146 // If CopyVideoFrameSingleTextureToGLTexture() changes the state of the |
104 // |texture_id|, it's needed to invalidate the state cached in skia, | 147 // |texture_id|, it's needed to invalidate the state cached in skia, |
105 // but currently the state isn't changed. | 148 // but currently the state isn't changed. |
106 SkCanvasVideoRenderer::CopyVideoFrameTextureToGLTexture( | 149 |
150 SkCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture( | |
107 context_3d.gl, video_frame, texture_id, GL_RGBA, GL_UNSIGNED_BYTE, true, | 151 context_3d.gl, video_frame, texture_id, GL_RGBA, GL_UNSIGNED_BYTE, true, |
108 false); | 152 false); |
109 bitmap->notifyPixelsChanged(); | 153 bitmap->notifyPixelsChanged(); |
110 return true; | 154 return true; |
111 } | 155 } |
112 | 156 |
113 class SyncPointClientImpl : public VideoFrame::SyncPointClient { | 157 class SyncPointClientImpl : public VideoFrame::SyncPointClient { |
114 public: | 158 public: |
115 explicit SyncPointClientImpl(gpu::gles2::GLES2Interface* gl) : gl_(gl) {} | 159 explicit SyncPointClientImpl(gpu::gles2::GLES2Interface* gl) : gl_(gl) {} |
116 ~SyncPointClientImpl() override {} | 160 ~SyncPointClientImpl() override {} |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
283 // In SW Canvas case, rely on skia drawing Ganesh SkBitmap on SW SkCanvas. | 327 // In SW Canvas case, rely on skia drawing Ganesh SkBitmap on SW SkCanvas. |
284 if (accelerated_last_frame_.isNull() || | 328 if (accelerated_last_frame_.isNull() || |
285 video_frame->timestamp() != accelerated_last_frame_timestamp_) { | 329 video_frame->timestamp() != accelerated_last_frame_timestamp_) { |
286 DCHECK(context_3d.gl); | 330 DCHECK(context_3d.gl); |
287 DCHECK(context_3d.gr_context); | 331 DCHECK(context_3d.gr_context); |
288 if (accelerated_generator_) { | 332 if (accelerated_generator_) { |
289 // Reset SkBitmap used in SWVideo-to-HWCanvas path. | 333 // Reset SkBitmap used in SWVideo-to-HWCanvas path. |
290 accelerated_last_frame_.reset(); | 334 accelerated_last_frame_.reset(); |
291 accelerated_generator_ = nullptr; | 335 accelerated_generator_ = nullptr; |
292 } | 336 } |
293 if (!CopyVideoFrameTextureToSkBitmapTexture( | 337 |
294 video_frame.get(), &accelerated_last_frame_, context_3d)) { | 338 if (media::VideoFrame::NumPlanes(video_frame->format()) == 1) { |
295 NOTREACHED(); | 339 accelerated_last_image_.reset(); |
296 return; | 340 if (!CopyVideoFrameSingleTextureToSkBitmap( |
341 video_frame.get(), &accelerated_last_frame_, context_3d)) { | |
342 NOTREACHED(); | |
343 return; | |
344 } | |
345 DCHECK(video_frame->visible_rect().width() == | |
346 accelerated_last_frame_.width() && | |
347 video_frame->visible_rect().height() == | |
348 accelerated_last_frame_.height()); | |
349 } else { | |
350 accelerated_last_image_ = CreateSkImageFromVideoFrameNativeTextures( | |
351 video_frame.get(), context_3d); | |
352 DCHECK(accelerated_last_image_); | |
297 } | 353 } |
298 DCHECK(video_frame->visible_rect().width() == | |
299 accelerated_last_frame_.width() && | |
300 video_frame->visible_rect().height() == | |
301 accelerated_last_frame_.height()); | |
302 | |
303 accelerated_last_frame_timestamp_ = video_frame->timestamp(); | 354 accelerated_last_frame_timestamp_ = video_frame->timestamp(); |
304 } | 355 } |
305 target_frame = &accelerated_last_frame_; | 356 target_frame = &accelerated_last_frame_; |
306 accelerated_frame_deleting_timer_.Reset(); | 357 accelerated_frame_deleting_timer_.Reset(); |
307 } else if (canvas->getGrContext()) { | 358 } else if (canvas->getGrContext()) { |
308 if (accelerated_last_frame_.isNull() || | 359 if (accelerated_last_frame_.isNull() || |
309 video_frame->timestamp() != accelerated_last_frame_timestamp_) { | 360 video_frame->timestamp() != accelerated_last_frame_timestamp_) { |
310 // Draw SW Video on HW Canvas. | 361 // Draw SW Video on HW Canvas. |
311 if (!accelerated_generator_ && !accelerated_last_frame_.isNull()) { | 362 if (!accelerated_generator_ && !accelerated_last_frame_.isNull()) { |
312 // Reset SkBitmap used in HWVideo-to-HWCanvas path. | 363 // Reset SkBitmap used in HWVideo-to-HWCanvas path. |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
388 video_rotation == VIDEO_ROTATION_270) { | 439 video_rotation == VIDEO_ROTATION_270) { |
389 rotated_dest_size = | 440 rotated_dest_size = |
390 gfx::SizeF(rotated_dest_size.height(), rotated_dest_size.width()); | 441 gfx::SizeF(rotated_dest_size.height(), rotated_dest_size.width()); |
391 } | 442 } |
392 canvas->scale( | 443 canvas->scale( |
393 SkFloatToScalar(rotated_dest_size.width() / target_frame->width()), | 444 SkFloatToScalar(rotated_dest_size.width() / target_frame->width()), |
394 SkFloatToScalar(rotated_dest_size.height() / target_frame->height())); | 445 SkFloatToScalar(rotated_dest_size.height() / target_frame->height())); |
395 canvas->translate(-SkFloatToScalar(target_frame->width() * 0.5f), | 446 canvas->translate(-SkFloatToScalar(target_frame->width() * 0.5f), |
396 -SkFloatToScalar(target_frame->height() * 0.5f)); | 447 -SkFloatToScalar(target_frame->height() * 0.5f)); |
397 } | 448 } |
398 canvas->drawBitmap(*target_frame, 0, 0, &paint); | 449 if (accelerated_last_image_) { |
450 canvas->drawImage(accelerated_last_image_.get(), 0, 0, &paint); | |
451 } else { | |
452 canvas->drawBitmap(*target_frame, 0, 0, &paint); | |
453 } | |
399 if (need_transform) | 454 if (need_transform) |
400 canvas->restore(); | 455 canvas->restore(); |
401 canvas->flush(); | 456 canvas->flush(); |
402 // SkCanvas::flush() causes the generator to generate SkImage, so delete | 457 // SkCanvas::flush() causes the generator to generate SkImage, so delete |
403 // |video_frame| not to be outlived. | 458 // |video_frame| not to be outlived. |
404 if (canvas->getGrContext() && accelerated_generator_) | 459 if (canvas->getGrContext() && accelerated_generator_) |
405 accelerated_generator_->set_frame(nullptr); | 460 accelerated_generator_->set_frame(nullptr); |
406 } | 461 } |
407 | 462 |
408 void SkCanvasVideoRenderer::Copy(const scoped_refptr<VideoFrame>& video_frame, | 463 void SkCanvasVideoRenderer::Copy(const scoped_refptr<VideoFrame>& video_frame, |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
541 case VideoFrame::NV12: | 596 case VideoFrame::NV12: |
542 #endif | 597 #endif |
543 case VideoFrame::ARGB: | 598 case VideoFrame::ARGB: |
544 case VideoFrame::XRGB: | 599 case VideoFrame::XRGB: |
545 case VideoFrame::UNKNOWN: | 600 case VideoFrame::UNKNOWN: |
546 NOTREACHED(); | 601 NOTREACHED(); |
547 } | 602 } |
548 } | 603 } |
549 | 604 |
550 // static | 605 // static |
551 void SkCanvasVideoRenderer::CopyVideoFrameTextureToGLTexture( | 606 void SkCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture( |
552 gpu::gles2::GLES2Interface* gl, | 607 gpu::gles2::GLES2Interface* gl, |
553 VideoFrame* video_frame, | 608 VideoFrame* video_frame, |
554 unsigned int texture, | 609 unsigned int texture, |
555 unsigned int internal_format, | 610 unsigned int internal_format, |
556 unsigned int type, | 611 unsigned int type, |
557 bool premultiply_alpha, | 612 bool premultiply_alpha, |
558 bool flip_y) { | 613 bool flip_y) { |
559 DCHECK(video_frame); | 614 DCHECK(video_frame); |
560 DCHECK_EQ(video_frame->storage_type(), VideoFrame::STORAGE_TEXTURE); | 615 DCHECK_EQ(video_frame->storage_type(), VideoFrame::STORAGE_TEXTURE); |
561 DCHECK_EQ(1u, VideoFrame::NumPlanes(video_frame->format())); | 616 DCHECK_EQ(1u, VideoFrame::NumPlanes(video_frame->format())); |
(...skipping 26 matching lines...) Expand all Loading... | |
588 SyncPointClientImpl client(gl); | 643 SyncPointClientImpl client(gl); |
589 video_frame->UpdateReleaseSyncPoint(&client); | 644 video_frame->UpdateReleaseSyncPoint(&client); |
590 } | 645 } |
591 | 646 |
592 void SkCanvasVideoRenderer::ResetLastFrame() { | 647 void SkCanvasVideoRenderer::ResetLastFrame() { |
593 last_frame_.reset(); | 648 last_frame_.reset(); |
594 last_frame_timestamp_ = media::kNoTimestamp(); | 649 last_frame_timestamp_ = media::kNoTimestamp(); |
595 } | 650 } |
596 | 651 |
597 void SkCanvasVideoRenderer::ResetAcceleratedLastFrame() { | 652 void SkCanvasVideoRenderer::ResetAcceleratedLastFrame() { |
653 accelerated_last_image_.reset(); | |
598 accelerated_last_frame_.reset(); | 654 accelerated_last_frame_.reset(); |
599 accelerated_generator_ = nullptr; | 655 accelerated_generator_ = nullptr; |
600 accelerated_last_frame_timestamp_ = media::kNoTimestamp(); | 656 accelerated_last_frame_timestamp_ = media::kNoTimestamp(); |
601 } | 657 } |
602 | 658 |
603 } // namespace media | 659 } // namespace media |
OLD | NEW |