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

Side by Side Diff: media/filters/skcanvas_video_renderer.cc

Issue 818853004: Revert of media: Optimize HW Video to 2D Canvas copy. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 11 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 (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/filters/skcanvas_video_renderer.h" 5 #include "media/filters/skcanvas_video_renderer.h"
6 6
7 #include "gpu/GLES2/gl2extchromium.h" 7 #include "base/logging.h"
8 #include "gpu/command_buffer/client/gles2_interface.h"
9 #include "gpu/command_buffer/common/mailbox_holder.h"
10 #include "media/base/video_frame.h" 8 #include "media/base/video_frame.h"
11 #include "media/base/yuv_convert.h" 9 #include "media/base/yuv_convert.h"
12 #include "skia/ext/refptr.h"
13 #include "third_party/libyuv/include/libyuv.h" 10 #include "third_party/libyuv/include/libyuv.h"
14 #include "third_party/skia/include/core/SkCanvas.h" 11 #include "third_party/skia/include/core/SkCanvas.h"
15 #include "third_party/skia/include/core/SkImageGenerator.h" 12 #include "third_party/skia/include/core/SkImageGenerator.h"
16 #include "third_party/skia/include/gpu/GrContext.h" 13 #include "third_party/skia/include/gpu/GrContext.h"
17 #include "third_party/skia/include/gpu/SkGrPixelRef.h"
18 #include "ui/gfx/skbitmap_operations.h" 14 #include "ui/gfx/skbitmap_operations.h"
19 15
20 // Skia internal format depends on a platform. On Android it is ABGR, on others 16 // Skia internal format depends on a platform. On Android it is ABGR, on others
21 // it is ARGB. 17 // it is ARGB.
22 #if SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && \ 18 #if SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && \
23 SK_A32_SHIFT == 24 19 SK_A32_SHIFT == 24
24 #define LIBYUV_I420_TO_ARGB libyuv::I420ToARGB 20 #define LIBYUV_I420_TO_ARGB libyuv::I420ToARGB
25 #define LIBYUV_I422_TO_ARGB libyuv::I422ToARGB 21 #define LIBYUV_I422_TO_ARGB libyuv::I422ToARGB
26 #elif SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \ 22 #elif SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \
27 SK_A32_SHIFT == 24 23 SK_A32_SHIFT == 24
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 row_bytes); 207 row_bytes);
212 video_frame->ReadPixelsFromNativeTexture(tmp); 208 video_frame->ReadPixelsFromNativeTexture(tmp);
213 break; 209 break;
214 } 210 }
215 default: 211 default:
216 NOTREACHED(); 212 NOTREACHED();
217 break; 213 break;
218 } 214 }
219 } 215 }
220 216
221 bool IsSkBitmapProperlySizedTexture(const SkBitmap* bitmap,
222 const gfx::Size& size) {
223 return bitmap->getTexture() && bitmap->width() == size.width() &&
224 bitmap->height() == size.height();
225 }
226
227 bool AllocateSkBitmapTexture(GrContext* gr,
228 SkBitmap* bitmap,
229 const gfx::Size& size) {
230 DCHECK(gr);
231 GrTextureDesc desc;
232 // Use kRGBA_8888_GrPixelConfig, not kSkia8888_GrPixelConfig, to avoid
233 // RGBA to BGRA conversion.
234 desc.fConfig = kRGBA_8888_GrPixelConfig;
235 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
236 desc.fSampleCnt = 0;
237 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
238 desc.fWidth = size.width();
239 desc.fHeight = size.height();
240 skia::RefPtr<GrTexture> texture = skia::AdoptRef(
241 gr->refScratchTexture(desc, GrContext::kExact_ScratchTexMatch));
242 if (!texture.get())
243 return false;
244
245 SkImageInfo info = SkImageInfo::MakeN32Premul(desc.fWidth, desc.fHeight);
246 SkGrPixelRef* pixel_ref = SkNEW_ARGS(SkGrPixelRef, (info, texture.get()));
247 if (!pixel_ref)
248 return false;
249 bitmap->setInfo(info);
250 bitmap->setPixelRef(pixel_ref)->unref();
251 return true;
252 }
253
254 bool CopyVideoFrameTextureToSkBitmapTexture(VideoFrame* video_frame,
255 SkBitmap* bitmap,
256 const Context3D& context_3d) {
257 // Check if we could reuse existing texture based bitmap.
258 // Otherwise, release existing texture based bitmap and allocate
259 // a new one based on video size.
260 if (!IsSkBitmapProperlySizedTexture(bitmap,
261 video_frame->visible_rect().size())) {
262 if (!AllocateSkBitmapTexture(context_3d.gr_context, bitmap,
263 video_frame->visible_rect().size())) {
264 return false;
265 }
266 }
267
268 unsigned texture_id =
269 static_cast<unsigned>((bitmap->getTexture())->getTextureHandle());
270 // If CopyVideoFrameTextureToGLTexture() changes the state of the
271 // |texture_id|, it's needed to invalidate the state cached in skia,
272 // but currently the state isn't changed.
273 SkCanvasVideoRenderer::CopyVideoFrameTextureToGLTexture(
274 context_3d.gl, video_frame, texture_id, 0, GL_RGBA, GL_UNSIGNED_BYTE,
275 true, false);
276 return true;
277 }
278
279 class SyncPointClientImpl : public VideoFrame::SyncPointClient {
280 public:
281 explicit SyncPointClientImpl(gpu::gles2::GLES2Interface* gl) : gl_(gl) {}
282 ~SyncPointClientImpl() override {}
283 uint32 InsertSyncPoint() override { return gl_->InsertSyncPointCHROMIUM(); }
284 void WaitSyncPoint(uint32 sync_point) override {
285 gl_->WaitSyncPointCHROMIUM(sync_point);
286 }
287
288 private:
289 gpu::gles2::GLES2Interface* gl_;
290
291 DISALLOW_IMPLICIT_CONSTRUCTORS(SyncPointClientImpl);
292 };
293
294 } // anonymous namespace 217 } // anonymous namespace
295 218
296 // Generates an RGB image from a VideoFrame. Convert YUV to RGB plain on GPU. 219 // Generates an RGB image from a VideoFrame. Convert YUV to RGB plain on GPU.
297 class VideoImageGenerator : public SkImageGenerator { 220 class VideoImageGenerator : public SkImageGenerator {
298 public: 221 public:
299 VideoImageGenerator(const scoped_refptr<VideoFrame>& frame) : frame_(frame) { 222 VideoImageGenerator(const scoped_refptr<VideoFrame>& frame) : frame_(frame) {
300 DCHECK(frame_.get()); 223 DCHECK(frame_.get());
301 } 224 }
302 ~VideoImageGenerator() override {} 225 ~VideoImageGenerator() override {}
303 226
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 DISALLOW_IMPLICIT_CONSTRUCTORS(VideoImageGenerator); 299 DISALLOW_IMPLICIT_CONSTRUCTORS(VideoImageGenerator);
377 }; 300 };
378 301
379 SkCanvasVideoRenderer::SkCanvasVideoRenderer() 302 SkCanvasVideoRenderer::SkCanvasVideoRenderer()
380 : last_frame_timestamp_(media::kNoTimestamp()), 303 : last_frame_timestamp_(media::kNoTimestamp()),
381 frame_deleting_timer_( 304 frame_deleting_timer_(
382 FROM_HERE, 305 FROM_HERE,
383 base::TimeDelta::FromSeconds(kTemporaryResourceDeletionDelay), 306 base::TimeDelta::FromSeconds(kTemporaryResourceDeletionDelay),
384 this, 307 this,
385 &SkCanvasVideoRenderer::ResetLastFrame), 308 &SkCanvasVideoRenderer::ResetLastFrame),
386 accelerated_generator_(nullptr), 309 accelerated_generator_(NULL),
387 accelerated_last_frame_timestamp_(media::kNoTimestamp()), 310 accelerated_last_frame_timestamp_(media::kNoTimestamp()),
388 accelerated_frame_deleting_timer_( 311 accelerated_frame_deleting_timer_(
389 FROM_HERE, 312 FROM_HERE,
390 base::TimeDelta::FromSeconds(kTemporaryResourceDeletionDelay), 313 base::TimeDelta::FromSeconds(kTemporaryResourceDeletionDelay),
391 this, 314 this,
392 &SkCanvasVideoRenderer::ResetAcceleratedLastFrame) { 315 &SkCanvasVideoRenderer::ResetAcceleratedLastFrame) {
393 last_frame_.setIsVolatile(true); 316 last_frame_.setIsVolatile(true);
394 } 317 }
395 318
396 SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {} 319 SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {}
397 320
398 void SkCanvasVideoRenderer::Paint(const scoped_refptr<VideoFrame>& video_frame, 321 void SkCanvasVideoRenderer::Paint(const scoped_refptr<VideoFrame>& video_frame,
399 SkCanvas* canvas, 322 SkCanvas* canvas,
400 const gfx::RectF& dest_rect, 323 const gfx::RectF& dest_rect,
401 uint8 alpha, 324 uint8 alpha,
402 SkXfermode::Mode mode, 325 SkXfermode::Mode mode,
403 VideoRotation video_rotation, 326 VideoRotation video_rotation) {
404 const Context3D& context_3d) {
405 if (alpha == 0) { 327 if (alpha == 0) {
406 return; 328 return;
407 } 329 }
408 330
409 SkRect dest; 331 SkRect dest;
410 dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom()); 332 dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom());
411 333
412 SkPaint paint; 334 SkPaint paint;
413 paint.setAlpha(alpha); 335 paint.setAlpha(alpha);
414 336
415 // Paint black rectangle if there isn't a frame available or the 337 // Paint black rectangle if there isn't a frame available or the
416 // frame has an unexpected format. 338 // frame has an unexpected format.
417 if (!video_frame.get() || video_frame->natural_size().IsEmpty() || 339 if (!video_frame.get() || video_frame->natural_size().IsEmpty() ||
418 !IsYUVOrNative(video_frame->format())) { 340 !IsYUVOrNative(video_frame->format())) {
419 canvas->drawRect(dest, paint); 341 canvas->drawRect(dest, paint);
420 canvas->flush(); 342 canvas->flush();
421 return; 343 return;
422 } 344 }
423 345
424 SkBitmap* target_frame = nullptr; 346 SkBitmap* target_frame = NULL;
425 if (canvas->getGrContext()) { 347 if (canvas->getGrContext()) {
426 if (accelerated_last_frame_.isNull() || 348 if (accelerated_last_frame_.isNull() ||
427 video_frame->timestamp() != accelerated_last_frame_timestamp_) { 349 video_frame->timestamp() != accelerated_last_frame_timestamp_) {
428 if (video_frame->format() == VideoFrame::NATIVE_TEXTURE) { 350 accelerated_generator_ = new VideoImageGenerator(video_frame);
429 DCHECK(context_3d.gl);
430 DCHECK(context_3d.gr_context);
431 // Draw HW Video on HW Canvas.
432 DCHECK(!accelerated_generator_);
433 if (!CopyVideoFrameTextureToSkBitmapTexture(
434 video_frame.get(), &accelerated_last_frame_, context_3d)) {
435 NOTREACHED();
436 return;
437 }
438 } else {
439 // Draw SW Video on HW Canvas.
440 accelerated_generator_ = new VideoImageGenerator(video_frame);
441 351
442 // Note: This takes ownership of |accelerated_generator_|. 352 // Note: This takes ownership of |accelerated_generator_|.
443 if (!SkInstallDiscardablePixelRef(accelerated_generator_, 353 if (!SkInstallDiscardablePixelRef(accelerated_generator_,
444 &accelerated_last_frame_)) { 354 &accelerated_last_frame_)) {
445 NOTREACHED(); 355 NOTREACHED();
446 return;
447 }
448 } 356 }
449 DCHECK(video_frame->visible_rect().width() == 357 DCHECK(video_frame->visible_rect().width() ==
450 accelerated_last_frame_.width() && 358 accelerated_last_frame_.width() &&
451 video_frame->visible_rect().height() == 359 video_frame->visible_rect().height() ==
452 accelerated_last_frame_.height()); 360 accelerated_last_frame_.height());
453 361
454 accelerated_last_frame_timestamp_ = video_frame->timestamp(); 362 accelerated_last_frame_timestamp_ = video_frame->timestamp();
455 } else if (accelerated_generator_) { 363 } else {
456 accelerated_generator_->set_frame(video_frame); 364 accelerated_generator_->set_frame(video_frame);
457 } 365 }
458 target_frame = &accelerated_last_frame_; 366 target_frame = &accelerated_last_frame_;
459 accelerated_frame_deleting_timer_.Reset(); 367 accelerated_frame_deleting_timer_.Reset();
460 } else { 368 } else {
461 // Draw both SW and HW Video on SW Canvas. 369 // Check if we should convert and update |last_frame_|.
462 if (last_frame_.isNull() || 370 if (last_frame_.isNull() ||
463 video_frame->timestamp() != last_frame_timestamp_) { 371 video_frame->timestamp() != last_frame_timestamp_) {
464 // Check if |bitmap| needs to be (re)allocated. 372 // Check if |bitmap| needs to be (re)allocated.
465 if (last_frame_.isNull() || 373 if (last_frame_.isNull() ||
466 last_frame_.width() != video_frame->visible_rect().width() || 374 last_frame_.width() != video_frame->visible_rect().width() ||
467 last_frame_.height() != video_frame->visible_rect().height()) { 375 last_frame_.height() != video_frame->visible_rect().height()) {
468 last_frame_.allocN32Pixels(video_frame->visible_rect().width(), 376 last_frame_.allocN32Pixels(video_frame->visible_rect().width(),
469 video_frame->visible_rect().height()); 377 video_frame->visible_rect().height());
470 last_frame_.setIsVolatile(true); 378 last_frame_.setIsVolatile(true);
471 } 379 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 SkFloatToScalar(rotated_dest_size.height() / target_frame->height())); 427 SkFloatToScalar(rotated_dest_size.height() / target_frame->height()));
520 canvas->translate(-SkFloatToScalar(target_frame->width() * 0.5f), 428 canvas->translate(-SkFloatToScalar(target_frame->width() * 0.5f),
521 -SkFloatToScalar(target_frame->height() * 0.5f)); 429 -SkFloatToScalar(target_frame->height() * 0.5f));
522 } 430 }
523 canvas->drawBitmap(*target_frame, 0, 0, &paint); 431 canvas->drawBitmap(*target_frame, 0, 0, &paint);
524 if (need_transform) 432 if (need_transform)
525 canvas->restore(); 433 canvas->restore();
526 canvas->flush(); 434 canvas->flush();
527 // SkCanvas::flush() causes the generator to generate SkImage, so delete 435 // SkCanvas::flush() causes the generator to generate SkImage, so delete
528 // |video_frame| not to be outlived. 436 // |video_frame| not to be outlived.
529 if (canvas->getGrContext() && accelerated_generator_) 437 if (canvas->getGrContext())
530 accelerated_generator_->set_frame(nullptr); 438 accelerated_generator_->set_frame(NULL);
531 } 439 }
532 440
533 void SkCanvasVideoRenderer::Copy(const scoped_refptr<VideoFrame>& video_frame, 441 void SkCanvasVideoRenderer::Copy(const scoped_refptr<VideoFrame>& video_frame,
534 SkCanvas* canvas) { 442 SkCanvas* canvas) {
535 Paint(video_frame, canvas, video_frame->visible_rect(), 0xff, 443 Paint(video_frame,
536 SkXfermode::kSrc_Mode, media::VIDEO_ROTATION_0, Context3D()); 444 canvas,
537 } 445 video_frame->visible_rect(),
538 446 0xff,
539 // static 447 SkXfermode::kSrc_Mode,
540 void SkCanvasVideoRenderer::CopyVideoFrameTextureToGLTexture( 448 media::VIDEO_ROTATION_0);
541 gpu::gles2::GLES2Interface* gl,
542 VideoFrame* video_frame,
543 unsigned int texture,
544 unsigned int level,
545 unsigned int internal_format,
546 unsigned int type,
547 bool premultiply_alpha,
548 bool flip_y) {
549 DCHECK(video_frame && video_frame->format() == VideoFrame::NATIVE_TEXTURE);
550 const gpu::MailboxHolder* mailbox_holder = video_frame->mailbox_holder();
551 DCHECK(mailbox_holder->texture_target == GL_TEXTURE_2D ||
552 mailbox_holder->texture_target == GL_TEXTURE_EXTERNAL_OES);
553
554 gl->WaitSyncPointCHROMIUM(mailbox_holder->sync_point);
555 uint32 source_texture = gl->CreateAndConsumeTextureCHROMIUM(
556 mailbox_holder->texture_target, mailbox_holder->mailbox.name);
557
558 // The video is stored in a unmultiplied format, so premultiply
559 // if necessary.
560 gl->PixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, premultiply_alpha);
561 // Application itself needs to take care of setting the right |flip_y|
562 // value down to get the expected result.
563 // "flip_y == true" means to reverse the video orientation while
564 // "flip_y == false" means to keep the intrinsic orientation.
565 gl->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, flip_y);
566 gl->CopyTextureCHROMIUM(GL_TEXTURE_2D, source_texture, texture, level,
567 internal_format, type);
568 gl->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, false);
569 gl->PixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, false);
570
571 gl->DeleteTextures(1, &source_texture);
572 gl->Flush();
573
574 SyncPointClientImpl client(gl);
575 video_frame->UpdateReleaseSyncPoint(&client);
576 } 449 }
577 450
578 void SkCanvasVideoRenderer::ResetLastFrame() { 451 void SkCanvasVideoRenderer::ResetLastFrame() {
579 last_frame_.reset(); 452 last_frame_.reset();
580 last_frame_timestamp_ = media::kNoTimestamp(); 453 last_frame_timestamp_ = media::kNoTimestamp();
581 } 454 }
582 455
583 void SkCanvasVideoRenderer::ResetAcceleratedLastFrame() { 456 void SkCanvasVideoRenderer::ResetAcceleratedLastFrame() {
584 accelerated_last_frame_.reset(); 457 accelerated_last_frame_.reset();
585 accelerated_generator_ = nullptr; 458 accelerated_generator_ = nullptr;
586 accelerated_last_frame_timestamp_ = media::kNoTimestamp(); 459 accelerated_last_frame_timestamp_ = media::kNoTimestamp();
587 } 460 }
588 461
589 } // namespace media 462 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/skcanvas_video_renderer.h ('k') | media/filters/skcanvas_video_renderer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698