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

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: scoping Y8 out. Created 4 years, 2 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 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 return img; 160 return img;
159 } 161 }
160 162
161 // Creates a SkImage from a |video_frame| backed by native resources. 163 // Creates a SkImage from a |video_frame| backed by native resources.
162 // The SkImage will take ownership of the underlying resource. 164 // The SkImage will take ownership of the underlying resource.
163 sk_sp<SkImage> NewSkImageFromVideoFrameNative(VideoFrame* video_frame, 165 sk_sp<SkImage> NewSkImageFromVideoFrameNative(VideoFrame* video_frame,
164 const Context3D& context_3d) { 166 const Context3D& context_3d) {
165 DCHECK(PIXEL_FORMAT_ARGB == video_frame->format() || 167 DCHECK(PIXEL_FORMAT_ARGB == video_frame->format() ||
166 PIXEL_FORMAT_XRGB == video_frame->format() || 168 PIXEL_FORMAT_XRGB == video_frame->format() ||
167 PIXEL_FORMAT_NV12 == video_frame->format() || 169 PIXEL_FORMAT_NV12 == video_frame->format() ||
168 PIXEL_FORMAT_UYVY == video_frame->format()); 170 PIXEL_FORMAT_UYVY == video_frame->format() ||
171 PIXEL_FORMAT_Y16 == video_frame->format());
169 172
170 const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(0); 173 const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(0);
171 DCHECK(mailbox_holder.texture_target == GL_TEXTURE_2D || 174 DCHECK(mailbox_holder.texture_target == GL_TEXTURE_2D ||
172 mailbox_holder.texture_target == GL_TEXTURE_RECTANGLE_ARB || 175 mailbox_holder.texture_target == GL_TEXTURE_RECTANGLE_ARB ||
173 mailbox_holder.texture_target == GL_TEXTURE_EXTERNAL_OES) 176 mailbox_holder.texture_target == GL_TEXTURE_EXTERNAL_OES)
174 << mailbox_holder.texture_target; 177 << mailbox_holder.texture_target;
175 178
176 gpu::gles2::GLES2Interface* gl = context_3d.gl; 179 gpu::gles2::GLES2Interface* gl = context_3d.gl;
177 unsigned source_texture = 0; 180 unsigned source_texture = 0;
178 if (mailbox_holder.texture_target != GL_TEXTURE_2D) { 181 if (mailbox_holder.texture_target != GL_TEXTURE_2D) {
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 return; 343 return;
341 } 344 }
342 345
343 SkRect dest; 346 SkRect dest;
344 dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom()); 347 dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom());
345 348
346 // Paint black rectangle if there isn't a frame available or the 349 // Paint black rectangle if there isn't a frame available or the
347 // frame has an unexpected format. 350 // frame has an unexpected format.
348 if (!video_frame.get() || video_frame->natural_size().IsEmpty() || 351 if (!video_frame.get() || video_frame->natural_size().IsEmpty() ||
349 !(media::IsYuvPlanar(video_frame->format()) || 352 !(media::IsYuvPlanar(video_frame->format()) ||
353 video_frame->format() == media::PIXEL_FORMAT_Y16 ||
350 video_frame->HasTextures())) { 354 video_frame->HasTextures())) {
351 SkPaint blackWithAlphaPaint; 355 SkPaint blackWithAlphaPaint;
352 blackWithAlphaPaint.setAlpha(paint.getAlpha()); 356 blackWithAlphaPaint.setAlpha(paint.getAlpha());
353 canvas->drawRect(dest, blackWithAlphaPaint); 357 canvas->drawRect(dest, blackWithAlphaPaint);
354 canvas->flush(); 358 canvas->flush();
355 return; 359 return;
356 } 360 }
357 361
358 gpu::gles2::GLES2Interface* gl = context_3d.gl; 362 gpu::gles2::GLES2Interface* gl = context_3d.gl;
359 if (!UpdateLastImage(video_frame, context_3d)) 363 if (!UpdateLastImage(video_frame, context_3d))
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 for (int row = 0; row < video_frame->rows(plane); row++) { 520 for (int row = 0; row < video_frame->rows(plane); row++) {
517 for (int x = 0; x < width; x++) { 521 for (int x = 0; x < width; x++) {
518 dst[x] = src[x] >> shift; 522 dst[x] = src[x] >> shift;
519 } 523 }
520 src += video_frame->stride(plane) / 2; 524 src += video_frame->stride(plane) / 2;
521 dst += ret->stride(plane); 525 dst += ret->stride(plane);
522 } 526 }
523 } 527 }
524 return ret; 528 return ret;
525 } 529 }
530
531 void ConvertY16ToARGB(const VideoFrame* video_frame,
532 void* argb_pixels,
533 size_t argb_row_bytes) {
534 const uint8_t* source =
535 reinterpret_cast<const uint8_t*>(video_frame->visible_data(0));
536 uint8_t* out = reinterpret_cast<uint8_t*>(argb_pixels);
537 const size_t stride = video_frame->stride(0);
538 for (int i = 0; i < video_frame->visible_rect().height(); ++i) {
539 const uint8_t* row = source;
540 uint32_t* rgba = reinterpret_cast<uint32_t*>(out);
541 for (const uint8_t* row_end = row + video_frame->row_bytes(0);
542 row < row_end; ++row) {
543 // We loose the precision here and take only upper 8 bits of 16 bit data.
544 // It is important not to render Y16 as RG_88. To get the full precision
545 // use float textures with WebGL1 and e.g. R16UI or R32F textures with
546 // WebGL2.
547 uint32_t green = *++row;
548 *rgba++ = SkColorSetARGB(0xFF, green, green, green);
549 }
550 out += argb_row_bytes;
551 source += stride;
552 }
553 }
554
555 void FlipAndConvertY16(const uint8_t* input,
556 uint8_t* output,
557 unsigned format,
558 unsigned type,
559 bool flip_y,
560 size_t row_bytes,
561 size_t stride,
562 size_t output_row_bytes,
563 size_t height) {
564 DCHECK(input != output);
565 for (size_t i = 0; i < height; ++i) {
566 const uint16_t* in = reinterpret_cast<const uint16_t*>(input + i * stride);
567 uint8_t* out = flip_y ? output + output_row_bytes * (height - i - 1)
568 : output + output_row_bytes * i;
569 if (type == GL_FLOAT) {
570 float* out_row = reinterpret_cast<float*>(out);
571 const uint16_t* in_end = in + row_bytes / 2;
572 if (format == GL_RGBA) {
573 while (in < in_end) {
574 float red = *in++ / 65536.f;
575 *out_row++ = red;
576 *out_row++ = red;
577 *out_row++ = red;
578 *out_row++ = 1.0f;
579 }
580 } else if (format == GL_RGB) {
581 while (in < in_end) {
582 float red = *in++ / 65536.f;
583 *out_row++ = red;
584 *out_row++ = red;
585 *out_row++ = red;
586 }
587 } else if (type == GL_RED) {
588 while (in < in_end)
589 *out_row++ = *in++ / 65536.f;
590 } else {
591 NOTREACHED();
592 }
593 } else if ((format == GL_RG && type == GL_UNSIGNED_BYTE) ||
594 (format == GL_RED_INTEGER && type == GL_UNSIGNED_SHORT)) {
595 memcpy(out, input + i * stride, row_bytes);
596 } else {
597 NOTREACHED();
598 }
599 }
600 }
526 } 601 }
527 602
528 // static 603 // static
529 void SkCanvasVideoRenderer::ConvertVideoFrameToRGBPixels( 604 void SkCanvasVideoRenderer::ConvertVideoFrameToRGBPixels(
530 const VideoFrame* video_frame, 605 const VideoFrame* video_frame,
531 void* rgb_pixels, 606 void* rgb_pixels,
532 size_t row_bytes) { 607 size_t row_bytes) {
533 if (!video_frame->IsMappable()) { 608 if (!video_frame->IsMappable()) {
534 NOTREACHED() << "Cannot extract pixels from non-CPU frame formats."; 609 NOTREACHED() << "Cannot extract pixels from non-CPU frame formats.";
535 return; 610 return;
536 } 611 }
537 if (!media::IsYuvPlanar(video_frame->format())) {
538 NOTREACHED() << "Non YUV formats are not supported";
539 return;
540 }
541 612
542 switch (video_frame->format()) { 613 switch (video_frame->format()) {
543 case PIXEL_FORMAT_YV12: 614 case PIXEL_FORMAT_YV12:
544 case PIXEL_FORMAT_I420: 615 case PIXEL_FORMAT_I420:
545 if (CheckColorSpace(video_frame, COLOR_SPACE_JPEG)) { 616 if (CheckColorSpace(video_frame, COLOR_SPACE_JPEG)) {
546 LIBYUV_J420_TO_ARGB(video_frame->visible_data(VideoFrame::kYPlane), 617 LIBYUV_J420_TO_ARGB(video_frame->visible_data(VideoFrame::kYPlane),
547 video_frame->stride(VideoFrame::kYPlane), 618 video_frame->stride(VideoFrame::kYPlane),
548 video_frame->visible_data(VideoFrame::kUPlane), 619 video_frame->visible_data(VideoFrame::kUPlane),
549 video_frame->stride(VideoFrame::kUPlane), 620 video_frame->stride(VideoFrame::kUPlane),
550 video_frame->visible_data(VideoFrame::kVPlane), 621 video_frame->visible_data(VideoFrame::kVPlane),
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 case PIXEL_FORMAT_YUV420P12: 694 case PIXEL_FORMAT_YUV420P12:
624 case PIXEL_FORMAT_YUV422P12: 695 case PIXEL_FORMAT_YUV422P12:
625 case PIXEL_FORMAT_YUV444P12: { 696 case PIXEL_FORMAT_YUV444P12: {
626 scoped_refptr<VideoFrame> temporary_frame = 697 scoped_refptr<VideoFrame> temporary_frame =
627 DownShiftHighbitVideoFrame(video_frame); 698 DownShiftHighbitVideoFrame(video_frame);
628 ConvertVideoFrameToRGBPixels(temporary_frame.get(), rgb_pixels, 699 ConvertVideoFrameToRGBPixels(temporary_frame.get(), rgb_pixels,
629 row_bytes); 700 row_bytes);
630 break; 701 break;
631 } 702 }
632 703
704 case PIXEL_FORMAT_Y16:
705 ConvertY16ToARGB(video_frame, rgb_pixels, row_bytes);
706 break;
707
633 case PIXEL_FORMAT_NV12: 708 case PIXEL_FORMAT_NV12:
634 case PIXEL_FORMAT_NV21: 709 case PIXEL_FORMAT_NV21:
635 case PIXEL_FORMAT_UYVY: 710 case PIXEL_FORMAT_UYVY:
636 case PIXEL_FORMAT_YUY2: 711 case PIXEL_FORMAT_YUY2:
637 case PIXEL_FORMAT_ARGB: 712 case PIXEL_FORMAT_ARGB:
638 case PIXEL_FORMAT_XRGB: 713 case PIXEL_FORMAT_XRGB:
639 case PIXEL_FORMAT_RGB24: 714 case PIXEL_FORMAT_RGB24:
640 case PIXEL_FORMAT_RGB32: 715 case PIXEL_FORMAT_RGB32:
641 case PIXEL_FORMAT_MJPEG: 716 case PIXEL_FORMAT_MJPEG:
642 case PIXEL_FORMAT_MT21: 717 case PIXEL_FORMAT_MT21:
643 // TODO(dshwang): Use either I400ToARGB or J400ToARGB depending if we want
644 // BT.601 constrained range of 16 to 240, or JPEG full range BT.601
645 // coefficients. Implement it when Y8/16 foramt is supported.
646 // crbug.com/624436
647 case PIXEL_FORMAT_Y8: 718 case PIXEL_FORMAT_Y8:
648 case PIXEL_FORMAT_Y16:
649 case PIXEL_FORMAT_UNKNOWN: 719 case PIXEL_FORMAT_UNKNOWN:
650 NOTREACHED(); 720 NOTREACHED() << "Only YUV formats and Y16 are supported.";
651 } 721 }
652 } 722 }
653 723
654 // static 724 // static
655 void SkCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture( 725 void SkCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture(
656 gpu::gles2::GLES2Interface* gl, 726 gpu::gles2::GLES2Interface* gl,
657 VideoFrame* video_frame, 727 VideoFrame* video_frame,
658 unsigned int texture, 728 unsigned int texture,
659 unsigned int internal_format, 729 unsigned int internal_format,
660 unsigned int type, 730 unsigned int type,
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
740 // canvas context. 810 // canvas context.
741 const GLuint64 dest_fence_sync = destination_gl->InsertFenceSyncCHROMIUM(); 811 const GLuint64 dest_fence_sync = destination_gl->InsertFenceSyncCHROMIUM();
742 destination_gl->ShallowFlushCHROMIUM(); 812 destination_gl->ShallowFlushCHROMIUM();
743 gpu::SyncToken dest_sync_token; 813 gpu::SyncToken dest_sync_token;
744 destination_gl->GenSyncTokenCHROMIUM(dest_fence_sync, 814 destination_gl->GenSyncTokenCHROMIUM(dest_fence_sync,
745 dest_sync_token.GetData()); 815 dest_sync_token.GetData());
746 canvas_gl->WaitSyncTokenCHROMIUM(dest_sync_token.GetConstData()); 816 canvas_gl->WaitSyncTokenCHROMIUM(dest_sync_token.GetConstData());
747 817
748 SyncTokenClientImpl client(canvas_gl); 818 SyncTokenClientImpl client(canvas_gl);
749 video_frame->UpdateReleaseSyncToken(&client); 819 video_frame->UpdateReleaseSyncToken(&client);
820 } else if (video_frame->format() == PIXEL_FORMAT_Y16) {
821 CopyRG8ToTexture(context_3d, destination_gl, video_frame.get(), texture,
822 internal_format, type, flip_y);
750 } else { 823 } else {
751 CopyVideoFrameSingleTextureToGLTexture(destination_gl, video_frame.get(), 824 CopyVideoFrameSingleTextureToGLTexture(destination_gl, video_frame.get(),
752 texture, internal_format, type, 825 texture, internal_format, type,
753 premultiply_alpha, flip_y); 826 premultiply_alpha, flip_y);
754 } 827 }
755
756 return true; 828 return true;
757 } 829 }
758 830
831 bool SkCanvasVideoRenderer::TexImageImpl(const char* functionID,
832 unsigned target,
833 gpu::gles2::GLES2Interface* gl,
834 VideoFrame* frame,
835 int level,
836 int internalformat,
837 unsigned format,
838 unsigned type,
839 int xoffset,
840 int yoffset,
841 int zoffset,
842 bool flip_y,
843 bool premultiplyAlpha) {
844 DCHECK(frame);
845 DCHECK(!frame->HasTextures());
846
847 bool has_alpha = false;
848 unsigned output_bytes_per_pixel;
849 switch (frame->format()) {
850 case PIXEL_FORMAT_Y16:
851 // Allow reinterpreting RG8 buffer here as R component in FLOAT.
852 switch (format) {
853 case GL_RGBA:
854 if (type == GL_FLOAT) {
855 output_bytes_per_pixel = 4 * sizeof(GLfloat);
856 break;
857 }
858 // Pass through.
859 case GL_RGB:
860 if (type == GL_FLOAT) {
861 output_bytes_per_pixel = 3 * sizeof(GLfloat);
862 break;
863 }
864 // Pass through.
865 default:
866 return false;
867 }
868 break;
869 default:
870 return false;
871 }
872 unsigned source_bytes_per_pixel =
873 VideoFrame::PlaneBitsPerPixel(frame->format(), 0) / 8;
874 DCHECK_EQ(VideoFrame::PlaneBitsPerPixel(frame->format(), 0) % 8, 0);
875
876 if (has_alpha && premultiplyAlpha) {
877 NOTREACHED() << "Premultiply alpha is not supported.";
878 return false;
879 }
880 if (xoffset || yoffset || zoffset) {
881 NOTREACHED() << "Offsets are not supported.";
882 return false;
883 }
884
885 uint8_t* data;
886 scoped_refptr<DataBuffer> temp_buffer;
887 size_t width = frame->visible_rect().width();
888 size_t height = frame->visible_rect().height();
889 size_t output_row_bytes =
890 frame->row_bytes(0) * output_bytes_per_pixel / source_bytes_per_pixel;
891 temp_buffer = new DataBuffer(output_row_bytes * height);
892 data = temp_buffer->writable_data();
893 DCHECK_EQ(frame->format(), PIXEL_FORMAT_Y16);
894 FlipAndConvertY16(frame->visible_data(0), data, format, type, flip_y,
895 frame->row_bytes(0), frame->stride(0), output_row_bytes,
896 height);
897
898 if (!strcmp(functionID, "texImage2D")) {
899 gl->TexImage2D(target, level, internalformat, width, height, 0, format,
900 type, data);
901 } else if (!strcmp(functionID, "texSubImage2D")) {
902 gl->TexSubImage2D(target, level, xoffset, yoffset, width, height, format,
903 type, data);
904 } else {
905 DCHECK(!strcmp(functionID, "texSubImage3D"));
906 gl->TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
907 1, format, type, data);
908 }
909 return true;
910 }
911
912 void SkCanvasVideoRenderer::CopyRG8ToTexture(
913 const Context3D& context_3d,
914 gpu::gles2::GLES2Interface* target_gl,
915 VideoFrame* frame,
916 unsigned texture,
917 unsigned internal_format,
918 unsigned type,
919 bool flip_y) {
920 // TODO(astojilj): After GLES 3.2, use glCopyImageSubData for RG8 to R16UI
921 // conversion. glCopyImageSubData is already available as extension on some of
922 // the Android devices (GL_EXT_COPY_IMAGE).
923 gpu::gles2::GLES2Interface* local_gl = context_3d.gl;
924
925 // Get source texture on local_gl.
926 unsigned source_texture;
927 {
928 const gpu::MailboxHolder& mailbox_holder = frame->mailbox_holder(0);
929 DCHECK(mailbox_holder.texture_target == GL_TEXTURE_2D)
930 << mailbox_holder.texture_target;
931
932 local_gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData());
933 source_texture = local_gl->CreateAndConsumeTextureCHROMIUM(
934 mailbox_holder.texture_target, mailbox_holder.mailbox.name);
935 }
936
937 // Reinterpret RG8 as 16 bit normalized and then to luminance in RGBA on
938 // local_gl. Later, do the copy on target_gl.
939 unsigned intermediate_texture;
940 local_gl->GenTextures(1, &intermediate_texture);
941 DoCopyRG8ToTexture(context_3d, source_texture, intermediate_texture, GL_RGBA,
942 GL_RGBA, GL_FLOAT, frame->visible_rect().width(),
943 frame->visible_rect().height(), flip_y);
944 local_gl->DeleteTextures(1, &source_texture);
945
946 // Get intermediate_texture to target_gl.
947 {
948 gpu::MailboxHolder mailbox_holder;
949 mailbox_holder.texture_target = GL_TEXTURE_2D;
950 local_gl->GenMailboxCHROMIUM(mailbox_holder.mailbox.name);
951 local_gl->ProduceTextureDirectCHROMIUM(intermediate_texture,
952 mailbox_holder.texture_target,
953 mailbox_holder.mailbox.name);
954 // Wait for mailbox creation on local context before consuming it and
955 // copying from it on the consumer context.
956 const GLuint64 fence_sync = local_gl->InsertFenceSyncCHROMIUM();
957 local_gl->ShallowFlushCHROMIUM();
958 local_gl->GenSyncTokenCHROMIUM(fence_sync,
959 mailbox_holder.sync_token.GetData());
960
961 target_gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData());
962 uint32_t target_intermediate_texture =
963 target_gl->CreateAndConsumeTextureCHROMIUM(
964 mailbox_holder.texture_target, mailbox_holder.mailbox.name);
965
966 local_gl->DeleteTextures(1, &intermediate_texture);
967 intermediate_texture = target_intermediate_texture;
968 }
969
970 // Copy intermediate_texture to texture.
971 target_gl->CopyTextureCHROMIUM(intermediate_texture, texture, internal_format,
972 type, false, false, false);
973 target_gl->DeleteTextures(1, &intermediate_texture);
974
975 // Undo gr_context state changes introduced in this function.
976 context_3d.gr_context->resetContext(
977 kMisc_GrGLBackendState | kBlend_GrGLBackendState |
978 kView_GrGLBackendState | kStencil_GrGLBackendState |
979 kVertex_GrGLBackendState | kProgram_GrGLBackendState |
980 kTextureBinding_GrGLBackendState);
981 SyncTokenClientImpl client(target_gl);
982 frame->UpdateReleaseSyncToken(&client);
983 }
984
985 void SkCanvasVideoRenderer::DoCopyRG8ToTexture(const Context3D& context_3d,
986 unsigned source_texture,
987 unsigned texture,
988 unsigned format,
989 unsigned internal_format,
990 unsigned type,
991 unsigned width,
992 unsigned height,
993 bool flip_y) {
994 gpu::gles2::GLES2Interface* gl = context_3d.gl;
995
996 if (cached_gl_resources_gr_context_id_ != context_3d.gr_context->uniqueID()) {
997 rg8_to_texture_program_ = 0;
998 rg8_to_texture_vertices_buffer_ = 0;
999 cached_gl_resources_gr_context_id_ = context_3d.gr_context->uniqueID();
1000 }
1001
1002 gl->EnableVertexAttribArray(0);
1003 if (!rg8_to_texture_vertices_buffer_) {
1004 gl->GenBuffers(1, &rg8_to_texture_vertices_buffer_);
1005 gl->BindBuffer(GL_ARRAY_BUFFER, rg8_to_texture_vertices_buffer_);
1006 const GLfloat vertices[] = {-1.f, -1.f, 1.f, -1.f, -1.0f, 1.f, 1.f, 1.f};
1007 gl->BufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
1008 gl->VertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
1009 }
1010
1011 if (!rg8_to_texture_program_) {
1012 rg8_to_texture_program_ = gl->CreateProgram();
1013 GLuint vertex_shader = gl->CreateShader(GL_VERTEX_SHADER);
1014 std::string source = std::string(
1015 "\
1016 #ifdef GL_ES\n\
1017 precision mediump float;\n\
1018 #define TexCoordPrecision mediump\n\
1019 #else\n\
1020 #define TexCoordPrecision\n\
1021 #endif\n\
1022 uniform vec2 coord_transform;\n\
1023 attribute vec2 a_pos;\n\
1024 varying TexCoordPrecision vec2 v_uv;\n\
1025 void main(void) {\n\
1026 gl_Position = vec4(a_pos, 0, 1.0);\n\
1027 v_uv = (a_pos * coord_transform) + 0.5;\n\
1028 }\n");
1029 const char* vertex_source = source.c_str();
1030 gl->ShaderSource(vertex_shader, 1, &vertex_source, 0);
1031 gl->CompileShader(vertex_shader);
1032 gl->AttachShader(rg8_to_texture_program_, vertex_shader);
1033
1034 GLuint fragment_shader = gl->CreateShader(GL_FRAGMENT_SHADER);
1035 source = std::string(
1036 "\
1037 #ifdef GL_ES\n\
1038 precision mediump float;\n\
1039 #define TexCoordPrecision mediump\n\
1040 #else\n\
1041 #define TexCoordPrecision\n\
1042 #endif\n\
1043 uniform sampler2D u_sampler;\n\
1044 varying TexCoordPrecision vec2 v_uv;\n\
1045 void main(void) {\n\
1046 vec4 color = texture2D(u_sampler, v_uv);\n\
1047 gl_FragColor.rgb = vec3((color.r * 0.00390625) + color.g);\n\
1048 }\n");
1049 const char* fragment_source = source.c_str();
1050 gl->ShaderSource(fragment_shader, 1, &fragment_source, 0);
1051 gl->CompileShader(fragment_shader);
1052
1053 gl->AttachShader(rg8_to_texture_program_, fragment_shader);
1054
1055 gl->BindAttribLocation(rg8_to_texture_program_, 0, "a_pos");
1056 gl->LinkProgram(rg8_to_texture_program_);
1057 }
1058
1059 gl->UseProgram(rg8_to_texture_program_);
1060 gl->Uniform1i(gl->GetUniformLocation(rg8_to_texture_program_, "u_sampler"),
1061 0);
1062 gl->Uniform2f(
1063 gl->GetUniformLocation(rg8_to_texture_program_, "coord_transform"), 0.5,
1064 flip_y ? -0.5 : 0.5);
1065
1066 GLuint fbo;
1067 gl->GenFramebuffers(1, &fbo);
1068 gl->ActiveTexture(GL_TEXTURE0);
1069 unsigned target = GL_TEXTURE_2D;
1070 gl->BindTexture(target, texture);
1071 gl->TexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, 0, format,
1072 type, 0);
1073
1074 gl->TexParameterf(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1075 gl->TexParameterf(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1076 gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1077 gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1078 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
1079 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target,
1080 texture, 0);
1081
1082 gl->BindTexture(target, source_texture);
1083 gl->TexParameterf(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1084 gl->TexParameterf(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1085 gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1086 gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1087
1088 gl->Disable(GL_DEPTH_TEST);
1089 gl->Disable(GL_STENCIL_TEST);
1090 gl->Disable(GL_CULL_FACE);
1091 gl->ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1092 gl->DepthMask(GL_FALSE);
1093 gl->Disable(GL_BLEND);
1094 gl->Disable(GL_SCISSOR_TEST);
1095 gl->Viewport(0, 0, width, height);
1096 gl->DrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1097 gl->Flush();
1098 gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
1099 gl->DeleteFramebuffers(1, &fbo);
1100 }
1101
759 void SkCanvasVideoRenderer::ResetCache() { 1102 void SkCanvasVideoRenderer::ResetCache() {
760 DCHECK(thread_checker_.CalledOnValidThread()); 1103 DCHECK(thread_checker_.CalledOnValidThread());
761 // Clear cached values. 1104 // Clear cached values.
762 last_image_ = nullptr; 1105 last_image_ = nullptr;
763 last_timestamp_ = kNoTimestamp; 1106 last_timestamp_ = kNoTimestamp;
764 } 1107 }
765 1108
766 bool SkCanvasVideoRenderer::UpdateLastImage( 1109 bool SkCanvasVideoRenderer::UpdateLastImage(
767 const scoped_refptr<VideoFrame>& video_frame, 1110 const scoped_refptr<VideoFrame>& video_frame,
768 const Context3D& context_3d) { 1111 const Context3D& context_3d) {
769 if (!last_image_ || video_frame->timestamp() != last_timestamp_) { 1112 if (!last_image_ || video_frame->timestamp() != last_timestamp_) {
770 ResetCache(); 1113 ResetCache();
771 // Generate a new image. 1114 // Generate a new image.
772 // Note: Skia will hold onto |video_frame| via |video_generator| only when 1115 // Note: Skia will hold onto |video_frame| via |video_generator| only when
773 // |video_frame| is software. 1116 // |video_frame| is software.
774 // Holding |video_frame| longer than this call when using GPUVideoDecoder 1117 // Holding |video_frame| longer than this call when using GPUVideoDecoder
775 // could cause problems since the pool of VideoFrames has a fixed size. 1118 // could cause problems since the pool of VideoFrames has a fixed size.
776 if (video_frame->HasTextures()) { 1119 if (video_frame->HasTextures()) {
777 DCHECK(context_3d.gr_context); 1120 DCHECK(context_3d.gr_context);
778 DCHECK(context_3d.gl); 1121 DCHECK(context_3d.gl);
779 if (media::VideoFrame::NumPlanes(video_frame->format()) > 1) { 1122 if (media::VideoFrame::NumPlanes(video_frame->format()) > 1) {
780 last_image_ = 1123 last_image_ =
781 NewSkImageFromVideoFrameYUVTextures(video_frame.get(), context_3d); 1124 NewSkImageFromVideoFrameYUVTextures(video_frame.get(), context_3d);
782 } else { 1125 } else {
1126 // TODO(astojilj): For Y16 on RG textures we don't want to paint 16 bit
1127 // split to 8 bit R & G. Implement using CopyRG8ToTexture.
783 last_image_ = 1128 last_image_ =
784 NewSkImageFromVideoFrameNative(video_frame.get(), context_3d); 1129 NewSkImageFromVideoFrameNative(video_frame.get(), context_3d);
785 } 1130 }
786 } else { 1131 } else {
787 auto* video_generator = new VideoImageGenerator(video_frame); 1132 auto* video_generator = new VideoImageGenerator(video_frame);
788 last_image_ = SkImage::MakeFromGenerator(video_generator); 1133 last_image_ = SkImage::MakeFromGenerator(video_generator);
789 } 1134 }
790 if (!last_image_) // Couldn't create the SkImage. 1135 if (!last_image_) // Couldn't create the SkImage.
791 return false; 1136 return false;
792 last_timestamp_ = video_frame->timestamp(); 1137 last_timestamp_ = video_frame->timestamp();
793 } 1138 }
794 last_image_deleting_timer_.Reset(); 1139 last_image_deleting_timer_.Reset();
795 DCHECK(!!last_image_); 1140 DCHECK(!!last_image_);
796 return true; 1141 return true;
797 } 1142 }
798 1143
799 } // namespace media 1144 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698