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/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 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 196 SK_A32_SHIFT == 24 | 196 SK_A32_SHIFT == 24 |
| 197 libyuv::ARGBToABGR(static_cast<uint8*>(rgb_pixels), | 197 libyuv::ARGBToABGR(static_cast<uint8*>(rgb_pixels), |
| 198 row_bytes, | 198 row_bytes, |
| 199 static_cast<uint8*>(rgb_pixels), | 199 static_cast<uint8*>(rgb_pixels), |
| 200 row_bytes, | 200 row_bytes, |
| 201 video_frame->visible_rect().width(), | 201 video_frame->visible_rect().width(), |
| 202 video_frame->visible_rect().height()); | 202 video_frame->visible_rect().height()); |
| 203 #endif | 203 #endif |
| 204 break; | 204 break; |
| 205 | 205 |
| 206 case media::VideoFrame::NATIVE_TEXTURE: { | 206 case media::VideoFrame::NATIVE_TEXTURE: |
| 207 SkBitmap tmp; | 207 NOTREACHED(); |
| 208 tmp.installPixels( | |
| 209 SkImageInfo::MakeN32Premul(video_frame->visible_rect().width(), | |
| 210 video_frame->visible_rect().height()), | |
| 211 rgb_pixels, | |
| 212 row_bytes); | |
| 213 video_frame->ReadPixelsFromNativeTexture(tmp); | |
|
dshwang
2015/01/14 20:32:13
Remove this complicated ReadPixel callback impleme
| |
| 214 break; | 208 break; |
| 215 } | |
| 216 | |
| 217 case media::VideoFrame::ARGB: | 209 case media::VideoFrame::ARGB: |
| 218 default: | 210 default: |
| 219 NOTREACHED(); | 211 NOTREACHED(); |
| 220 break; | 212 break; |
| 221 } | 213 } |
| 222 } | 214 } |
| 223 | 215 |
| 224 bool IsSkBitmapProperlySizedTexture(const SkBitmap* bitmap, | 216 bool IsSkBitmapProperlySizedTexture(const SkBitmap* bitmap, |
| 225 const gfx::Size& size) { | 217 const gfx::Size& size) { |
| 226 return bitmap->getTexture() && bitmap->width() == size.width() && | 218 return bitmap->getTexture() && bitmap->width() == size.width() && |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 269 } | 261 } |
| 270 | 262 |
| 271 unsigned texture_id = | 263 unsigned texture_id = |
| 272 static_cast<unsigned>((bitmap->getTexture())->getTextureHandle()); | 264 static_cast<unsigned>((bitmap->getTexture())->getTextureHandle()); |
| 273 // If CopyVideoFrameTextureToGLTexture() changes the state of the | 265 // If CopyVideoFrameTextureToGLTexture() changes the state of the |
| 274 // |texture_id|, it's needed to invalidate the state cached in skia, | 266 // |texture_id|, it's needed to invalidate the state cached in skia, |
| 275 // but currently the state isn't changed. | 267 // but currently the state isn't changed. |
| 276 SkCanvasVideoRenderer::CopyVideoFrameTextureToGLTexture( | 268 SkCanvasVideoRenderer::CopyVideoFrameTextureToGLTexture( |
| 277 context_3d.gl, video_frame, texture_id, 0, GL_RGBA, GL_UNSIGNED_BYTE, | 269 context_3d.gl, video_frame, texture_id, 0, GL_RGBA, GL_UNSIGNED_BYTE, |
| 278 true, false); | 270 true, false); |
| 271 bitmap->notifyPixelsChanged(); | |
| 279 return true; | 272 return true; |
| 280 } | 273 } |
| 281 | 274 |
| 282 class SyncPointClientImpl : public VideoFrame::SyncPointClient { | 275 class SyncPointClientImpl : public VideoFrame::SyncPointClient { |
| 283 public: | 276 public: |
| 284 explicit SyncPointClientImpl(gpu::gles2::GLES2Interface* gl) : gl_(gl) {} | 277 explicit SyncPointClientImpl(gpu::gles2::GLES2Interface* gl) : gl_(gl) {} |
| 285 ~SyncPointClientImpl() override {} | 278 ~SyncPointClientImpl() override {} |
| 286 uint32 InsertSyncPoint() override { return gl_->InsertSyncPointCHROMIUM(); } | 279 uint32 InsertSyncPoint() override { return gl_->InsertSyncPointCHROMIUM(); } |
| 287 void WaitSyncPoint(uint32 sync_point) override { | 280 void WaitSyncPoint(uint32 sync_point) override { |
| 288 gl_->WaitSyncPointCHROMIUM(sync_point); | 281 gl_->WaitSyncPointCHROMIUM(sync_point); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 418 // Paint black rectangle if there isn't a frame available or the | 411 // Paint black rectangle if there isn't a frame available or the |
| 419 // frame has an unexpected format. | 412 // frame has an unexpected format. |
| 420 if (!video_frame.get() || video_frame->natural_size().IsEmpty() || | 413 if (!video_frame.get() || video_frame->natural_size().IsEmpty() || |
| 421 !IsYUVOrNative(video_frame->format())) { | 414 !IsYUVOrNative(video_frame->format())) { |
| 422 canvas->drawRect(dest, paint); | 415 canvas->drawRect(dest, paint); |
| 423 canvas->flush(); | 416 canvas->flush(); |
| 424 return; | 417 return; |
| 425 } | 418 } |
| 426 | 419 |
| 427 SkBitmap* target_frame = nullptr; | 420 SkBitmap* target_frame = nullptr; |
| 428 if (canvas->getGrContext()) { | 421 |
| 422 if (video_frame->format() == VideoFrame::NATIVE_TEXTURE) { | |
| 423 // Draw HW Video on both SW and HW Canvas. | |
| 424 // In SW Canvas case, rely on skia drawing Ganesh SkBitmap on SW SkCanvas. | |
|
dshwang
2015/01/14 20:32:13
As comment mentions, drawing ganesh SkBitmap on Sw
| |
| 429 if (accelerated_last_frame_.isNull() || | 425 if (accelerated_last_frame_.isNull() || |
| 430 video_frame->timestamp() != accelerated_last_frame_timestamp_) { | 426 video_frame->timestamp() != accelerated_last_frame_timestamp_) { |
| 431 if (video_frame->format() == VideoFrame::NATIVE_TEXTURE) { | 427 DCHECK(context_3d.gl); |
| 432 // Draw HW Video on HW Canvas. | 428 DCHECK(context_3d.gr_context); |
| 433 DCHECK(context_3d.gl); | 429 if (accelerated_generator_) { |
| 434 DCHECK(context_3d.gr_context); | 430 // Reset SkBitmap used in SWVideo-to-HWCanvas path. |
| 435 if (accelerated_generator_) { | 431 accelerated_last_frame_.reset(); |
| 436 // Reset SkBitmap used in SWVideo-to-HWCanvas path. | 432 accelerated_generator_ = nullptr; |
| 437 accelerated_last_frame_.reset(); | 433 } |
| 438 accelerated_generator_ = nullptr; | 434 if (!CopyVideoFrameTextureToSkBitmapTexture( |
| 439 } | 435 video_frame.get(), &accelerated_last_frame_, context_3d)) { |
| 440 if (!CopyVideoFrameTextureToSkBitmapTexture( | 436 NOTREACHED(); |
| 441 video_frame.get(), &accelerated_last_frame_, context_3d)) { | 437 return; |
| 442 NOTREACHED(); | 438 } |
| 443 return; | 439 DCHECK(video_frame->visible_rect().width() == |
| 444 } | 440 accelerated_last_frame_.width() && |
| 445 } else { | 441 video_frame->visible_rect().height() == |
| 442 accelerated_last_frame_.height()); | |
| 443 | |
| 444 accelerated_last_frame_timestamp_ = video_frame->timestamp(); | |
| 445 } | |
| 446 target_frame = &accelerated_last_frame_; | |
| 447 accelerated_frame_deleting_timer_.Reset(); | |
| 448 } else if (canvas->getGrContext()) { | |
| 449 DCHECK(video_frame->format() != VideoFrame::NATIVE_TEXTURE); | |
| 450 if (accelerated_last_frame_.isNull() || | |
| 451 video_frame->timestamp() != accelerated_last_frame_timestamp_) { | |
| 452 { | |
| 446 // Draw SW Video on HW Canvas. | 453 // Draw SW Video on HW Canvas. |
| 447 if (!accelerated_generator_ && !accelerated_last_frame_.isNull()) { | 454 if (!accelerated_generator_ && !accelerated_last_frame_.isNull()) { |
| 448 // Reset SkBitmap used in HWVideo-to-HWCanvas path. | 455 // Reset SkBitmap used in HWVideo-to-HWCanvas path. |
| 449 accelerated_last_frame_.reset(); | 456 accelerated_last_frame_.reset(); |
| 450 } | 457 } |
| 451 accelerated_generator_ = new VideoImageGenerator(video_frame); | 458 accelerated_generator_ = new VideoImageGenerator(video_frame); |
| 452 | 459 |
| 453 // Note: This takes ownership of |accelerated_generator_|. | 460 // Note: This takes ownership of |accelerated_generator_|. |
| 454 if (!SkInstallDiscardablePixelRef(accelerated_generator_, | 461 if (!SkInstallDiscardablePixelRef(accelerated_generator_, |
| 455 &accelerated_last_frame_)) { | 462 &accelerated_last_frame_)) { |
| 456 NOTREACHED(); | 463 NOTREACHED(); |
| 457 return; | 464 return; |
| 458 } | 465 } |
| 459 } | 466 } |
| 460 DCHECK(video_frame->visible_rect().width() == | 467 DCHECK(video_frame->visible_rect().width() == |
| 461 accelerated_last_frame_.width() && | 468 accelerated_last_frame_.width() && |
| 462 video_frame->visible_rect().height() == | 469 video_frame->visible_rect().height() == |
| 463 accelerated_last_frame_.height()); | 470 accelerated_last_frame_.height()); |
| 464 | 471 |
| 465 accelerated_last_frame_timestamp_ = video_frame->timestamp(); | 472 accelerated_last_frame_timestamp_ = video_frame->timestamp(); |
| 466 } else if (accelerated_generator_) { | 473 } else if (accelerated_generator_) { |
| 467 accelerated_generator_->set_frame(video_frame); | 474 accelerated_generator_->set_frame(video_frame); |
| 468 } | 475 } |
| 469 target_frame = &accelerated_last_frame_; | 476 target_frame = &accelerated_last_frame_; |
| 470 accelerated_frame_deleting_timer_.Reset(); | 477 accelerated_frame_deleting_timer_.Reset(); |
| 471 } else { | 478 } else { |
| 472 // Draw both SW and HW Video on SW Canvas. | 479 // Draw SW Video on SW Canvas. |
| 480 DCHECK(video_frame->format() != VideoFrame::NATIVE_TEXTURE); | |
| 473 if (last_frame_.isNull() || | 481 if (last_frame_.isNull() || |
| 474 video_frame->timestamp() != last_frame_timestamp_) { | 482 video_frame->timestamp() != last_frame_timestamp_) { |
| 475 // Check if |bitmap| needs to be (re)allocated. | 483 // Check if |bitmap| needs to be (re)allocated. |
| 476 if (last_frame_.isNull() || | 484 if (last_frame_.isNull() || |
| 477 last_frame_.width() != video_frame->visible_rect().width() || | 485 last_frame_.width() != video_frame->visible_rect().width() || |
| 478 last_frame_.height() != video_frame->visible_rect().height()) { | 486 last_frame_.height() != video_frame->visible_rect().height()) { |
| 479 last_frame_.allocN32Pixels(video_frame->visible_rect().width(), | 487 last_frame_.allocN32Pixels(video_frame->visible_rect().width(), |
| 480 video_frame->visible_rect().height()); | 488 video_frame->visible_rect().height()); |
| 481 last_frame_.setIsVolatile(true); | 489 last_frame_.setIsVolatile(true); |
| 482 } | 490 } |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 535 if (need_transform) | 543 if (need_transform) |
| 536 canvas->restore(); | 544 canvas->restore(); |
| 537 canvas->flush(); | 545 canvas->flush(); |
| 538 // SkCanvas::flush() causes the generator to generate SkImage, so delete | 546 // SkCanvas::flush() causes the generator to generate SkImage, so delete |
| 539 // |video_frame| not to be outlived. | 547 // |video_frame| not to be outlived. |
| 540 if (canvas->getGrContext() && accelerated_generator_) | 548 if (canvas->getGrContext() && accelerated_generator_) |
| 541 accelerated_generator_->set_frame(nullptr); | 549 accelerated_generator_->set_frame(nullptr); |
| 542 } | 550 } |
| 543 | 551 |
| 544 void SkCanvasVideoRenderer::Copy(const scoped_refptr<VideoFrame>& video_frame, | 552 void SkCanvasVideoRenderer::Copy(const scoped_refptr<VideoFrame>& video_frame, |
| 545 SkCanvas* canvas) { | 553 SkCanvas* canvas, |
| 554 const Context3D& context_3d) { | |
| 546 Paint(video_frame, canvas, video_frame->visible_rect(), 0xff, | 555 Paint(video_frame, canvas, video_frame->visible_rect(), 0xff, |
| 547 SkXfermode::kSrc_Mode, media::VIDEO_ROTATION_0, Context3D()); | 556 SkXfermode::kSrc_Mode, media::VIDEO_ROTATION_0, context_3d); |
| 548 } | 557 } |
| 549 | 558 |
| 550 // static | 559 // static |
| 551 void SkCanvasVideoRenderer::CopyVideoFrameTextureToGLTexture( | 560 void SkCanvasVideoRenderer::CopyVideoFrameTextureToGLTexture( |
| 552 gpu::gles2::GLES2Interface* gl, | 561 gpu::gles2::GLES2Interface* gl, |
| 553 VideoFrame* video_frame, | 562 VideoFrame* video_frame, |
| 554 unsigned int texture, | 563 unsigned int texture, |
| 555 unsigned int level, | 564 unsigned int level, |
| 556 unsigned int internal_format, | 565 unsigned int internal_format, |
| 557 unsigned int type, | 566 unsigned int type, |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 591 last_frame_timestamp_ = media::kNoTimestamp(); | 600 last_frame_timestamp_ = media::kNoTimestamp(); |
| 592 } | 601 } |
| 593 | 602 |
| 594 void SkCanvasVideoRenderer::ResetAcceleratedLastFrame() { | 603 void SkCanvasVideoRenderer::ResetAcceleratedLastFrame() { |
| 595 accelerated_last_frame_.reset(); | 604 accelerated_last_frame_.reset(); |
| 596 accelerated_generator_ = nullptr; | 605 accelerated_generator_ = nullptr; |
| 597 accelerated_last_frame_timestamp_ = media::kNoTimestamp(); | 606 accelerated_last_frame_timestamp_ = media::kNoTimestamp(); |
| 598 } | 607 } |
| 599 | 608 |
| 600 } // namespace media | 609 } // namespace media |
| OLD | NEW |