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

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

Issue 2121043002: 16 bpp video stream capture, render and WebGL usage - Realsense R200 & SR300 support. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: WebGL video to texture support and readPixels from R16UI for CPU access Created 4 years, 4 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/renderers/skcanvas_video_renderer.h" 5 #include "media/renderers/skcanvas_video_renderer.h"
6 6
7 #include <GLES3/gl3.h>
7 #include <limits> 8 #include <limits>
8 9
9 #include "base/macros.h" 10 #include "base/macros.h"
10 #include "gpu/GLES2/gl2extchromium.h" 11 #include "gpu/GLES2/gl2extchromium.h"
11 #include "gpu/command_buffer/client/gles2_interface.h" 12 #include "gpu/command_buffer/client/gles2_interface.h"
12 #include "gpu/command_buffer/common/mailbox_holder.h" 13 #include "gpu/command_buffer/common/mailbox_holder.h"
14 #include "media/base/data_buffer.h"
13 #include "media/base/video_frame.h" 15 #include "media/base/video_frame.h"
14 #include "media/base/yuv_convert.h" 16 #include "media/base/yuv_convert.h"
15 #include "skia/ext/texture_handle.h" 17 #include "skia/ext/texture_handle.h"
16 #include "third_party/libyuv/include/libyuv.h" 18 #include "third_party/libyuv/include/libyuv.h"
17 #include "third_party/skia/include/core/SkCanvas.h" 19 #include "third_party/skia/include/core/SkCanvas.h"
18 #include "third_party/skia/include/core/SkImage.h" 20 #include "third_party/skia/include/core/SkImage.h"
19 #include "third_party/skia/include/core/SkImageGenerator.h" 21 #include "third_party/skia/include/core/SkImageGenerator.h"
20 #include "third_party/skia/include/gpu/GrContext.h" 22 #include "third_party/skia/include/gpu/GrContext.h"
21 #include "third_party/skia/include/gpu/GrPaint.h" 23 #include "third_party/skia/include/gpu/GrPaint.h"
22 #include "third_party/skia/include/gpu/GrTexture.h" 24 #include "third_party/skia/include/gpu/GrTexture.h"
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 desc.fTextureHandle = 204 desc.fTextureHandle =
203 skia::GrGLTextureInfoToGrBackendObject(source_texture_info); 205 skia::GrGLTextureInfoToGrBackendObject(source_texture_info);
204 return SkImage::MakeFromAdoptedTexture(context_3d.gr_context, desc); 206 return SkImage::MakeFromAdoptedTexture(context_3d.gr_context, desc);
205 } 207 }
206 208
207 } // anonymous namespace 209 } // anonymous namespace
208 210
209 // Generates an RGB image from a VideoFrame. Convert YUV to RGB plain on GPU. 211 // Generates an RGB image from a VideoFrame. Convert YUV to RGB plain on GPU.
210 class VideoImageGenerator : public SkImageGenerator { 212 class VideoImageGenerator : public SkImageGenerator {
211 public: 213 public:
212 VideoImageGenerator(const scoped_refptr<VideoFrame>& frame) 214 VideoImageGenerator(const scoped_refptr<VideoFrame>& frame, SkColorType type)
213 : SkImageGenerator( 215 : SkImageGenerator(SkImageInfo::Make(frame->visible_rect().width(),
214 SkImageInfo::MakeN32Premul(frame->visible_rect().width(), 216 frame->visible_rect().height(),
215 frame->visible_rect().height())), 217 type,
218 kPremul_SkAlphaType)),
216 frame_(frame) { 219 frame_(frame) {
217 DCHECK(!frame_->HasTextures()); 220 DCHECK(!frame_->HasTextures());
218 } 221 }
219 ~VideoImageGenerator() override {} 222 ~VideoImageGenerator() override {}
220 223
221 protected: 224 protected:
222 bool onGetPixels(const SkImageInfo& info, 225 bool onGetPixels(const SkImageInfo& info,
223 void* pixels, 226 void* pixels,
224 size_t row_bytes, 227 size_t row_bytes,
225 SkPMColor ctable[], 228 SkPMColor ctable[],
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 346
344 SkRect dest; 347 SkRect dest;
345 dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom()); 348 dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom());
346 349
347 SkPaint paint; 350 SkPaint paint;
348 paint.setAlpha(alpha); 351 paint.setAlpha(alpha);
349 352
350 // Paint black rectangle if there isn't a frame available or the 353 // Paint black rectangle if there isn't a frame available or the
351 // frame has an unexpected format. 354 // frame has an unexpected format.
352 if (!video_frame.get() || video_frame->natural_size().IsEmpty() || 355 if (!video_frame.get() || video_frame->natural_size().IsEmpty() ||
353 !(media::IsYuvPlanar(video_frame->format()) || 356 !((media::IsYuvPlanar(video_frame->format()) ||
357 video_frame->format() == media::PIXEL_FORMAT_Y16) ||
354 video_frame->HasTextures())) { 358 video_frame->HasTextures())) {
355 canvas->drawRect(dest, paint); 359 canvas->drawRect(dest, paint);
356 canvas->flush(); 360 canvas->flush();
357 return; 361 return;
358 } 362 }
359 363
360 gpu::gles2::GLES2Interface* gl = context_3d.gl; 364 gpu::gles2::GLES2Interface* gl = context_3d.gl;
361 365
362 if (!last_image_ || video_frame->timestamp() != last_timestamp_) { 366 if (!last_image_ || video_frame->timestamp() != last_timestamp_) {
363 ResetCache(); 367 ResetCache();
364 // Generate a new image. 368 // Generate a new image.
365 // Note: Skia will hold onto |video_frame| via |video_generator| only when 369 // Note: Skia will hold onto |video_frame| via |video_generator| only when
366 // |video_frame| is software. 370 // |video_frame| is software.
367 // Holding |video_frame| longer than this call when using GPUVideoDecoder 371 // Holding |video_frame| longer than this call when using GPUVideoDecoder
368 // could cause problems since the pool of VideoFrames has a fixed size. 372 // could cause problems since the pool of VideoFrames has a fixed size.
369 if (video_frame->HasTextures()) { 373 if (video_frame->HasTextures()) {
370 DCHECK(context_3d.gr_context); 374 DCHECK(context_3d.gr_context);
371 DCHECK(gl); 375 DCHECK(gl);
372 if (media::VideoFrame::NumPlanes(video_frame->format()) > 1) { 376 if (media::VideoFrame::NumPlanes(video_frame->format()) > 1) {
373 last_image_ = 377 last_image_ =
374 NewSkImageFromVideoFrameYUVTextures(video_frame.get(), context_3d); 378 NewSkImageFromVideoFrameYUVTextures(video_frame.get(), context_3d);
375 } else { 379 } else {
376 last_image_ = 380 last_image_ =
377 NewSkImageFromVideoFrameNative(video_frame.get(), context_3d); 381 NewSkImageFromVideoFrameNative(video_frame.get(), context_3d);
378 } 382 }
379 } else { 383 } else {
380 auto* video_generator = new VideoImageGenerator(video_frame); 384 auto* video_generator = new VideoImageGenerator(
385 video_frame, (video_frame->format() == media::PIXEL_FORMAT_Y16)
386 ? kRGBA_8888_SkColorType
387 : kN32_SkColorType);
381 last_image_ = SkImage::MakeFromGenerator(video_generator); 388 last_image_ = SkImage::MakeFromGenerator(video_generator);
382 } 389 }
383 if (!last_image_) // Couldn't create the SkImage. 390 if (!last_image_) // Couldn't create the SkImage.
384 return; 391 return;
385 last_timestamp_ = video_frame->timestamp(); 392 last_timestamp_ = video_frame->timestamp();
386 } 393 }
387 last_image_deleting_timer_.Reset(); 394 last_image_deleting_timer_.Reset();
388 395
389 paint.setXfermodeMode(mode); 396 paint.setXfermodeMode(mode);
390 paint.setFilterQuality(kLow_SkFilterQuality); 397 paint.setFilterQuality(kLow_SkFilterQuality);
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 for (int row = 0; row < video_frame->rows(plane); row++) { 522 for (int row = 0; row < video_frame->rows(plane); row++) {
516 for (int x = 0; x < width; x++) { 523 for (int x = 0; x < width; x++) {
517 dst[x] = src[x] >> shift; 524 dst[x] = src[x] >> shift;
518 } 525 }
519 src += video_frame->stride(plane) / 2; 526 src += video_frame->stride(plane) / 2;
520 dst += ret->stride(plane); 527 dst += ret->stride(plane);
521 } 528 }
522 } 529 }
523 return ret; 530 return ret;
524 } 531 }
532
533 void ConvertY16ToABGR(const VideoFrame* video_frame,
534 void* argb_pixels,
535 size_t argb_row_bytes) {
536 const uint8_t* source =
537 reinterpret_cast<const uint8_t*>(video_frame->visible_data(0));
538 uint8_t* out = reinterpret_cast<uint8_t*>(argb_pixels);
539 const size_t stride = video_frame->stride(0);
540 for (int i = 0; i < video_frame->visible_rect().height(); ++i) {
541 const uint16_t* row = reinterpret_cast<const uint16_t*>(source);
542 uint32_t* argb = reinterpret_cast<uint32_t*>(out);
543 for (const uint16_t* row_end = row + video_frame->visible_rect().width();
544 row < row_end;)
545 *argb++ = ((*row++) >> 8) | 0xFF000000;
546 out += argb_row_bytes;
547 source += stride;
548 }
549 }
550
551 void FlipAndMultiply(const uint8_t* input,
552 uint8_t* output,
553 unsigned format,
554 unsigned type,
555 bool flipY,
556 bool premultiplyAlpha,
557 size_t row_bytes,
558 size_t stride,
559 size_t height) {
560 // Premultiply alpha is not set for formats that this method supports.
561 DCHECK(!premultiplyAlpha);
562 DCHECK(flipY || premultiplyAlpha);
563 DCHECK(input != output);
564 for (int i = 0; i < height; ++i)
565 memcpy(output + stride * (height - i - 1), input + i * stride, row_bytes);
566 }
525 } 567 }
526 568
527 // static 569 // static
528 void SkCanvasVideoRenderer::ConvertVideoFrameToRGBPixels( 570 void SkCanvasVideoRenderer::ConvertVideoFrameToRGBPixels(
529 const VideoFrame* video_frame, 571 const VideoFrame* video_frame,
530 void* rgb_pixels, 572 void* rgb_pixels,
531 size_t row_bytes) { 573 size_t row_bytes) {
532 if (!video_frame->IsMappable()) { 574 if (!video_frame->IsMappable()) {
533 NOTREACHED() << "Cannot extract pixels from non-CPU frame formats."; 575 NOTREACHED() << "Cannot extract pixels from non-CPU frame formats.";
534 return; 576 return;
535 } 577 }
536 if (!media::IsYuvPlanar(video_frame->format())) {
537 NOTREACHED() << "Non YUV formats are not supported";
538 return;
539 }
540 578
541 switch (video_frame->format()) { 579 switch (video_frame->format()) {
542 case PIXEL_FORMAT_YV12: 580 case PIXEL_FORMAT_YV12:
543 case PIXEL_FORMAT_I420: 581 case PIXEL_FORMAT_I420:
544 if (CheckColorSpace(video_frame, COLOR_SPACE_JPEG)) { 582 if (CheckColorSpace(video_frame, COLOR_SPACE_JPEG)) {
545 LIBYUV_J420_TO_ARGB(video_frame->visible_data(VideoFrame::kYPlane), 583 LIBYUV_J420_TO_ARGB(video_frame->visible_data(VideoFrame::kYPlane),
546 video_frame->stride(VideoFrame::kYPlane), 584 video_frame->stride(VideoFrame::kYPlane),
547 video_frame->visible_data(VideoFrame::kUPlane), 585 video_frame->visible_data(VideoFrame::kUPlane),
548 video_frame->stride(VideoFrame::kUPlane), 586 video_frame->stride(VideoFrame::kUPlane),
549 video_frame->visible_data(VideoFrame::kVPlane), 587 video_frame->visible_data(VideoFrame::kVPlane),
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 case PIXEL_FORMAT_YUV420P10: 657 case PIXEL_FORMAT_YUV420P10:
620 case PIXEL_FORMAT_YUV422P10: 658 case PIXEL_FORMAT_YUV422P10:
621 case PIXEL_FORMAT_YUV444P10: { 659 case PIXEL_FORMAT_YUV444P10: {
622 scoped_refptr<VideoFrame> temporary_frame = 660 scoped_refptr<VideoFrame> temporary_frame =
623 DownShiftHighbitVideoFrame(video_frame); 661 DownShiftHighbitVideoFrame(video_frame);
624 ConvertVideoFrameToRGBPixels(temporary_frame.get(), rgb_pixels, 662 ConvertVideoFrameToRGBPixels(temporary_frame.get(), rgb_pixels,
625 row_bytes); 663 row_bytes);
626 break; 664 break;
627 } 665 }
628 666
667 case PIXEL_FORMAT_Y16:
668 ConvertY16ToABGR(video_frame, rgb_pixels, row_bytes);
669 break;
670
629 case PIXEL_FORMAT_NV12: 671 case PIXEL_FORMAT_NV12:
630 case PIXEL_FORMAT_NV21: 672 case PIXEL_FORMAT_NV21:
631 case PIXEL_FORMAT_UYVY: 673 case PIXEL_FORMAT_UYVY:
632 case PIXEL_FORMAT_YUY2: 674 case PIXEL_FORMAT_YUY2:
633 case PIXEL_FORMAT_ARGB: 675 case PIXEL_FORMAT_ARGB:
634 case PIXEL_FORMAT_XRGB: 676 case PIXEL_FORMAT_XRGB:
635 case PIXEL_FORMAT_RGB24: 677 case PIXEL_FORMAT_RGB24:
636 case PIXEL_FORMAT_RGB32: 678 case PIXEL_FORMAT_RGB32:
637 case PIXEL_FORMAT_MJPEG: 679 case PIXEL_FORMAT_MJPEG:
638 case PIXEL_FORMAT_MT21: 680 case PIXEL_FORMAT_MT21:
681 case PIXEL_FORMAT_Y8:
639 case PIXEL_FORMAT_UNKNOWN: 682 case PIXEL_FORMAT_UNKNOWN:
640 NOTREACHED(); 683 NOTREACHED() << "Only YUV formats and Y16 are supported.";
641 } 684 }
642 } 685 }
643 686
644 // static 687 // static
645 void SkCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture( 688 void SkCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture(
646 gpu::gles2::GLES2Interface* gl, 689 gpu::gles2::GLES2Interface* gl,
647 VideoFrame* video_frame, 690 VideoFrame* video_frame,
648 unsigned int texture, 691 unsigned int texture,
649 unsigned int internal_format, 692 unsigned int internal_format,
650 unsigned int type, 693 unsigned int type,
(...skipping 20 matching lines...) Expand all
671 // "flip_y == false" means to keep the intrinsic orientation. 714 // "flip_y == false" means to keep the intrinsic orientation.
672 gl->CopyTextureCHROMIUM(source_texture, texture, internal_format, type, 715 gl->CopyTextureCHROMIUM(source_texture, texture, internal_format, type,
673 flip_y, premultiply_alpha, false); 716 flip_y, premultiply_alpha, false);
674 gl->DeleteTextures(1, &source_texture); 717 gl->DeleteTextures(1, &source_texture);
675 gl->Flush(); 718 gl->Flush();
676 719
677 SyncTokenClientImpl client(gl); 720 SyncTokenClientImpl client(gl);
678 video_frame->UpdateReleaseSyncToken(&client); 721 video_frame->UpdateReleaseSyncToken(&client);
679 } 722 }
680 723
724 bool SkCanvasVideoRenderer::TexImageImpl(const char* functionID,
725 unsigned target,
726 gpu::gles2::GLES2Interface* gl,
727 VideoFrame* frame,
728 int level,
729 int internalformat,
730 unsigned format,
731 unsigned type,
732 int xoffset,
733 int yoffset,
734 int zoffset,
735 bool flipY,
736 bool premultiplyAlpha) {
737 DCHECK(frame);
738
739 bool hasAlpha = false;
740 switch (frame->format()) {
741 case PIXEL_FORMAT_Y16:
742 // Allow reinterpreting R16 buffer here as RG8.
743 if ((format != GL_RED_INTEGER || type != GL_UNSIGNED_SHORT) &&
744 (format != GL_RG || type != GL_UNSIGNED_BYTE))
745 return false;
746 break;
747 case PIXEL_FORMAT_Y8:
748 if (format != GL_RED || type != GL_UNSIGNED_BYTE)
749 return false;
750 break;
751 // TODO(astojilj): ARGB, XRGB....v
752 default:
753 return false;
754 }
755
756 size_t width = frame->visible_rect().width();
757 size_t height = frame->visible_rect().height();
758 if (hasAlpha && premultiplyAlpha) {
759 NOTREACHED() << "Premultiply alpha is not supported.";
760 return false;
761 }
762 if (xoffset || yoffset || zoffset) {
763 NOTREACHED() << "Offsets are not supported.";
764 return false;
765 }
766
767 uint8_t* data;
768 scoped_refptr<DataBuffer> temp_buffer;
769 if (flipY) {
770 temp_buffer = new DataBuffer(frame->stride(0) * height);
771 data = temp_buffer->writable_data();
772 FlipAndMultiply(frame->visible_data(0), data, format, type, flipY, false,
773 frame->row_bytes(0), frame->stride(0), height);
774 } else {
775 data = frame->visible_data(0);
Ken Russell (switch to Gerrit) 2016/08/16 00:22:27 Is there ever a situation where the video frame's
aleksandar.stojiljkovic 2016/08/16 12:02:31 Of course. In this case VideoFrame::storage_type()
Ken Russell (switch to Gerrit) 2016/08/16 18:27:37 OK. Do you plan to add this code path? If this co
aleksandar.stojiljkovic 2016/09/20 12:22:55 Done. Reinterpreting RG8 to R32F when storage is G
776 }
777
778 if (!strcmp(functionID, "texImage2D")) {
779 gl->TexImage2D(target, level, internalformat, width, height, 0, format,
780 type, data);
781 } else if (!strcmp(functionID, "texSubImage2D")) {
782 gl->TexSubImage2D(target, level, xoffset, yoffset, width, height, format,
783 type, data);
784 } else {
785 DCHECK(!strcmp(functionID, "texSubImage3D"));
786 gl->TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
787 1, format, type, data);
788 }
789 return true;
790 }
791
681 void SkCanvasVideoRenderer::ResetCache() { 792 void SkCanvasVideoRenderer::ResetCache() {
682 DCHECK(thread_checker_.CalledOnValidThread()); 793 DCHECK(thread_checker_.CalledOnValidThread());
683 // Clear cached values. 794 // Clear cached values.
684 last_image_ = nullptr; 795 last_image_ = nullptr;
685 last_timestamp_ = kNoTimestamp(); 796 last_timestamp_ = kNoTimestamp();
686 } 797 }
687 798
688 } // namespace media 799 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698