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

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

Powered by Google App Engine
This is Rietveld 408576698