| 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/filters/skcanvas_video_renderer.h" | 5 #include "media/filters/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" |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 } | 139 } |
| 140 | 140 |
| 141 unsigned texture_id = | 141 unsigned texture_id = |
| 142 static_cast<unsigned>((bitmap->getTexture())->getTextureHandle()); | 142 static_cast<unsigned>((bitmap->getTexture())->getTextureHandle()); |
| 143 // If CopyVideoFrameTextureToGLTexture() changes the state of the | 143 // If CopyVideoFrameTextureToGLTexture() changes the state of the |
| 144 // |texture_id|, it's needed to invalidate the state cached in skia, | 144 // |texture_id|, it's needed to invalidate the state cached in skia, |
| 145 // but currently the state isn't changed. | 145 // but currently the state isn't changed. |
| 146 SkCanvasVideoRenderer::CopyVideoFrameTextureToGLTexture( | 146 SkCanvasVideoRenderer::CopyVideoFrameTextureToGLTexture( |
| 147 context_3d.gl, video_frame, texture_id, 0, GL_RGBA, GL_UNSIGNED_BYTE, | 147 context_3d.gl, video_frame, texture_id, 0, GL_RGBA, GL_UNSIGNED_BYTE, |
| 148 true, false); | 148 true, false); |
| 149 bitmap->notifyPixelsChanged(); |
| 149 return true; | 150 return true; |
| 150 } | 151 } |
| 151 | 152 |
| 152 class SyncPointClientImpl : public VideoFrame::SyncPointClient { | 153 class SyncPointClientImpl : public VideoFrame::SyncPointClient { |
| 153 public: | 154 public: |
| 154 explicit SyncPointClientImpl(gpu::gles2::GLES2Interface* gl) : gl_(gl) {} | 155 explicit SyncPointClientImpl(gpu::gles2::GLES2Interface* gl) : gl_(gl) {} |
| 155 ~SyncPointClientImpl() override {} | 156 ~SyncPointClientImpl() override {} |
| 156 uint32 InsertSyncPoint() override { return gl_->InsertSyncPointCHROMIUM(); } | 157 uint32 InsertSyncPoint() override { return gl_->InsertSyncPointCHROMIUM(); } |
| 157 void WaitSyncPoint(uint32 sync_point) override { | 158 void WaitSyncPoint(uint32 sync_point) override { |
| 158 gl_->WaitSyncPointCHROMIUM(sync_point); | 159 gl_->WaitSyncPointCHROMIUM(sync_point); |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 // Paint black rectangle if there isn't a frame available or the | 315 // Paint black rectangle if there isn't a frame available or the |
| 315 // frame has an unexpected format. | 316 // frame has an unexpected format. |
| 316 if (!video_frame.get() || video_frame->natural_size().IsEmpty() || | 317 if (!video_frame.get() || video_frame->natural_size().IsEmpty() || |
| 317 !IsYUVOrNative(video_frame->format())) { | 318 !IsYUVOrNative(video_frame->format())) { |
| 318 canvas->drawRect(dest, paint); | 319 canvas->drawRect(dest, paint); |
| 319 canvas->flush(); | 320 canvas->flush(); |
| 320 return; | 321 return; |
| 321 } | 322 } |
| 322 | 323 |
| 323 SkBitmap* target_frame = nullptr; | 324 SkBitmap* target_frame = nullptr; |
| 324 if (canvas->getGrContext()) { | 325 |
| 326 if (video_frame->format() == VideoFrame::NATIVE_TEXTURE) { |
| 327 // Draw HW Video on both SW and HW Canvas. |
| 328 // In SW Canvas case, rely on skia drawing Ganesh SkBitmap on SW SkCanvas. |
| 325 if (accelerated_last_frame_.isNull() || | 329 if (accelerated_last_frame_.isNull() || |
| 326 video_frame->timestamp() != accelerated_last_frame_timestamp_) { | 330 video_frame->timestamp() != accelerated_last_frame_timestamp_) { |
| 327 if (video_frame->format() == VideoFrame::NATIVE_TEXTURE) { | 331 DCHECK(context_3d.gl); |
| 328 // Draw HW Video on HW Canvas. | 332 DCHECK(context_3d.gr_context); |
| 329 DCHECK(context_3d.gl); | 333 if (accelerated_generator_) { |
| 330 DCHECK(context_3d.gr_context); | 334 // Reset SkBitmap used in SWVideo-to-HWCanvas path. |
| 331 if (accelerated_generator_) { | 335 accelerated_last_frame_.reset(); |
| 332 // Reset SkBitmap used in SWVideo-to-HWCanvas path. | 336 accelerated_generator_ = nullptr; |
| 333 accelerated_last_frame_.reset(); | 337 } |
| 334 accelerated_generator_ = nullptr; | 338 if (!CopyVideoFrameTextureToSkBitmapTexture( |
| 335 } | 339 video_frame.get(), &accelerated_last_frame_, context_3d)) { |
| 336 if (!CopyVideoFrameTextureToSkBitmapTexture( | 340 NOTREACHED(); |
| 337 video_frame.get(), &accelerated_last_frame_, context_3d)) { | 341 return; |
| 338 NOTREACHED(); | |
| 339 return; | |
| 340 } | |
| 341 } else { | |
| 342 // Draw SW Video on HW Canvas. | |
| 343 if (!accelerated_generator_ && !accelerated_last_frame_.isNull()) { | |
| 344 // Reset SkBitmap used in HWVideo-to-HWCanvas path. | |
| 345 accelerated_last_frame_.reset(); | |
| 346 } | |
| 347 accelerated_generator_ = new VideoImageGenerator(video_frame); | |
| 348 | |
| 349 // Note: This takes ownership of |accelerated_generator_|. | |
| 350 if (!SkInstallDiscardablePixelRef(accelerated_generator_, | |
| 351 &accelerated_last_frame_)) { | |
| 352 NOTREACHED(); | |
| 353 return; | |
| 354 } | |
| 355 } | 342 } |
| 356 DCHECK(video_frame->visible_rect().width() == | 343 DCHECK(video_frame->visible_rect().width() == |
| 357 accelerated_last_frame_.width() && | 344 accelerated_last_frame_.width() && |
| 345 video_frame->visible_rect().height() == |
| 346 accelerated_last_frame_.height()); |
| 347 |
| 348 accelerated_last_frame_timestamp_ = video_frame->timestamp(); |
| 349 } |
| 350 target_frame = &accelerated_last_frame_; |
| 351 accelerated_frame_deleting_timer_.Reset(); |
| 352 } else if (canvas->getGrContext()) { |
| 353 DCHECK(video_frame->format() != VideoFrame::NATIVE_TEXTURE); |
| 354 if (accelerated_last_frame_.isNull() || |
| 355 video_frame->timestamp() != accelerated_last_frame_timestamp_) { |
| 356 // Draw SW Video on HW Canvas. |
| 357 if (!accelerated_generator_ && !accelerated_last_frame_.isNull()) { |
| 358 // Reset SkBitmap used in HWVideo-to-HWCanvas path. |
| 359 accelerated_last_frame_.reset(); |
| 360 } |
| 361 accelerated_generator_ = new VideoImageGenerator(video_frame); |
| 362 |
| 363 // Note: This takes ownership of |accelerated_generator_|. |
| 364 if (!SkInstallDiscardablePixelRef(accelerated_generator_, |
| 365 &accelerated_last_frame_)) { |
| 366 NOTREACHED(); |
| 367 return; |
| 368 } |
| 369 DCHECK(video_frame->visible_rect().width() == |
| 370 accelerated_last_frame_.width() && |
| 358 video_frame->visible_rect().height() == | 371 video_frame->visible_rect().height() == |
| 359 accelerated_last_frame_.height()); | 372 accelerated_last_frame_.height()); |
| 360 | 373 |
| 361 accelerated_last_frame_timestamp_ = video_frame->timestamp(); | 374 accelerated_last_frame_timestamp_ = video_frame->timestamp(); |
| 362 } else if (accelerated_generator_) { | 375 } else if (accelerated_generator_) { |
| 363 accelerated_generator_->set_frame(video_frame); | 376 accelerated_generator_->set_frame(video_frame); |
| 364 } | 377 } |
| 365 target_frame = &accelerated_last_frame_; | 378 target_frame = &accelerated_last_frame_; |
| 366 accelerated_frame_deleting_timer_.Reset(); | 379 accelerated_frame_deleting_timer_.Reset(); |
| 367 } else { | 380 } else { |
| 368 // Draw both SW and HW Video on SW Canvas. | 381 // Draw SW Video on SW Canvas. |
| 382 DCHECK(video_frame->format() != VideoFrame::NATIVE_TEXTURE); |
| 369 if (last_frame_.isNull() || | 383 if (last_frame_.isNull() || |
| 370 video_frame->timestamp() != last_frame_timestamp_) { | 384 video_frame->timestamp() != last_frame_timestamp_) { |
| 371 // Check if |bitmap| needs to be (re)allocated. | 385 // Check if |bitmap| needs to be (re)allocated. |
| 372 if (last_frame_.isNull() || | 386 if (last_frame_.isNull() || |
| 373 last_frame_.width() != video_frame->visible_rect().width() || | 387 last_frame_.width() != video_frame->visible_rect().width() || |
| 374 last_frame_.height() != video_frame->visible_rect().height()) { | 388 last_frame_.height() != video_frame->visible_rect().height()) { |
| 375 last_frame_.allocN32Pixels(video_frame->visible_rect().width(), | 389 last_frame_.allocN32Pixels(video_frame->visible_rect().width(), |
| 376 video_frame->visible_rect().height()); | 390 video_frame->visible_rect().height()); |
| 377 last_frame_.setIsVolatile(true); | 391 last_frame_.setIsVolatile(true); |
| 378 } | 392 } |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 if (need_transform) | 445 if (need_transform) |
| 432 canvas->restore(); | 446 canvas->restore(); |
| 433 canvas->flush(); | 447 canvas->flush(); |
| 434 // SkCanvas::flush() causes the generator to generate SkImage, so delete | 448 // SkCanvas::flush() causes the generator to generate SkImage, so delete |
| 435 // |video_frame| not to be outlived. | 449 // |video_frame| not to be outlived. |
| 436 if (canvas->getGrContext() && accelerated_generator_) | 450 if (canvas->getGrContext() && accelerated_generator_) |
| 437 accelerated_generator_->set_frame(nullptr); | 451 accelerated_generator_->set_frame(nullptr); |
| 438 } | 452 } |
| 439 | 453 |
| 440 void SkCanvasVideoRenderer::Copy(const scoped_refptr<VideoFrame>& video_frame, | 454 void SkCanvasVideoRenderer::Copy(const scoped_refptr<VideoFrame>& video_frame, |
| 441 SkCanvas* canvas) { | 455 SkCanvas* canvas, |
| 456 const Context3D& context_3d) { |
| 442 Paint(video_frame, canvas, video_frame->visible_rect(), 0xff, | 457 Paint(video_frame, canvas, video_frame->visible_rect(), 0xff, |
| 443 SkXfermode::kSrc_Mode, media::VIDEO_ROTATION_0, Context3D()); | 458 SkXfermode::kSrc_Mode, media::VIDEO_ROTATION_0, context_3d); |
| 444 } | 459 } |
| 445 | 460 |
| 446 // static | 461 // static |
| 447 void SkCanvasVideoRenderer::ConvertVideoFrameToRGBPixels( | 462 void SkCanvasVideoRenderer::ConvertVideoFrameToRGBPixels( |
| 448 const scoped_refptr<media::VideoFrame>& video_frame, | 463 const scoped_refptr<media::VideoFrame>& video_frame, |
| 449 void* rgb_pixels, | 464 void* rgb_pixels, |
| 450 size_t row_bytes) { | 465 size_t row_bytes) { |
| 451 DCHECK(IsYUVOrNative(video_frame->format())) | 466 DCHECK(IsYUVOrNative(video_frame->format())) |
| 452 << video_frame->format(); | 467 << video_frame->format(); |
| 453 if (IsYUV(video_frame->format())) { | 468 if (IsYUV(video_frame->format())) { |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 SK_A32_SHIFT == 24 | 579 SK_A32_SHIFT == 24 |
| 565 libyuv::ARGBToABGR(static_cast<uint8*>(rgb_pixels), | 580 libyuv::ARGBToABGR(static_cast<uint8*>(rgb_pixels), |
| 566 row_bytes, | 581 row_bytes, |
| 567 static_cast<uint8*>(rgb_pixels), | 582 static_cast<uint8*>(rgb_pixels), |
| 568 row_bytes, | 583 row_bytes, |
| 569 video_frame->visible_rect().width(), | 584 video_frame->visible_rect().width(), |
| 570 video_frame->visible_rect().height()); | 585 video_frame->visible_rect().height()); |
| 571 #endif | 586 #endif |
| 572 break; | 587 break; |
| 573 | 588 |
| 574 case VideoFrame::NATIVE_TEXTURE: { | 589 case VideoFrame::NATIVE_TEXTURE: |
| 575 SkBitmap tmp; | 590 NOTREACHED(); |
| 576 tmp.installPixels( | |
| 577 SkImageInfo::MakeN32Premul(video_frame->visible_rect().width(), | |
| 578 video_frame->visible_rect().height()), | |
| 579 rgb_pixels, | |
| 580 row_bytes); | |
| 581 video_frame->ReadPixelsFromNativeTexture(tmp); | |
| 582 break; | 591 break; |
| 583 } | |
| 584 | |
| 585 #if defined(VIDEO_HOLE) | 592 #if defined(VIDEO_HOLE) |
| 586 case VideoFrame::HOLE: | 593 case VideoFrame::HOLE: |
| 587 #endif // defined(VIDEO_HOLE) | 594 #endif // defined(VIDEO_HOLE) |
| 588 case VideoFrame::ARGB: | 595 case VideoFrame::ARGB: |
| 589 case VideoFrame::UNKNOWN: | 596 case VideoFrame::UNKNOWN: |
| 590 case VideoFrame::NV12: | 597 case VideoFrame::NV12: |
| 591 NOTREACHED(); | 598 NOTREACHED(); |
| 592 } | 599 } |
| 593 } | 600 } |
| 594 | 601 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 637 last_frame_timestamp_ = media::kNoTimestamp(); | 644 last_frame_timestamp_ = media::kNoTimestamp(); |
| 638 } | 645 } |
| 639 | 646 |
| 640 void SkCanvasVideoRenderer::ResetAcceleratedLastFrame() { | 647 void SkCanvasVideoRenderer::ResetAcceleratedLastFrame() { |
| 641 accelerated_last_frame_.reset(); | 648 accelerated_last_frame_.reset(); |
| 642 accelerated_generator_ = nullptr; | 649 accelerated_generator_ = nullptr; |
| 643 accelerated_last_frame_timestamp_ = media::kNoTimestamp(); | 650 accelerated_last_frame_timestamp_ = media::kNoTimestamp(); |
| 644 } | 651 } |
| 645 | 652 |
| 646 } // namespace media | 653 } // namespace media |
| OLD | NEW |