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/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 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 515 for (int x = 0; x < width; x++) { | 517 for (int x = 0; x < width; x++) { |
| 516 dst[x] = src[x] >> shift; | 518 dst[x] = src[x] >> shift; |
| 517 } | 519 } |
| 518 src += video_frame->stride(plane) / 2; | 520 src += video_frame->stride(plane) / 2; |
| 519 dst += ret->stride(plane); | 521 dst += ret->stride(plane); |
| 520 } | 522 } |
| 521 } | 523 } |
| 522 return ret; | 524 return ret; |
| 523 } | 525 } |
| 524 | 526 |
| 525 // We take the upper 8 bits of 16-bit data and convert it as luminance to ARGB. | 527 void FlipAndConvertY16(const VideoFrame* video_frame, |
|
hubbe
2016/11/07 22:16:55
Add comment.
aleksandar.stojiljkovic
2016/11/16 20:01:24
Done.
| |
| 526 // We loose the precision here, but it is important not to render Y16 as RG_88. | 528 uint8_t* out, |
| 527 // To get the full precision use float textures with WebGL1 and e.g. R16UI or | 529 unsigned format, |
| 528 // R32F textures with WebGL2. | 530 unsigned type, |
| 529 void ConvertY16ToARGB(const VideoFrame* video_frame, | 531 bool flip_y, |
| 530 void* argb_pixels, | 532 size_t output_row_bytes) { |
| 531 size_t argb_row_bytes) { | |
| 532 const uint8_t* row_head = video_frame->visible_data(0); | 533 const uint8_t* row_head = video_frame->visible_data(0); |
| 533 uint8_t* out = static_cast<uint8_t*>(argb_pixels); | |
| 534 const size_t stride = video_frame->stride(0); | 534 const size_t stride = video_frame->stride(0); |
| 535 for (int i = 0; i < video_frame->visible_rect().height(); ++i) { | 535 const int height = video_frame->visible_rect().height(); |
| 536 uint32_t* rgba = reinterpret_cast<uint32_t*>(out); | 536 for (int i = 0; i < height; ++i) { |
| 537 const uint8_t* row_end = row_head + video_frame->visible_rect().width() * 2; | 537 uint8_t* out_row_head = flip_y ? out + output_row_bytes * (height - i - 1) |
| 538 for (const uint8_t* row = row_head; row < row_end; ++row) { | 538 : out + output_row_bytes * i; |
| 539 uint32_t gray_value = *++row; | 539 const uint16_t* row = reinterpret_cast<const uint16_t*>(row_head); |
| 540 *rgba++ = SkColorSetRGB(gray_value, gray_value, gray_value); | 540 const uint16_t* row_end = row + video_frame->visible_rect().width(); |
| 541 if (type == GL_FLOAT && format == GL_RGBA) { | |
| 542 float* out_row = reinterpret_cast<float*>(out_row_head); | |
| 543 while (row < row_end) { | |
| 544 float gray_value = *row++ / 65535.f; | |
| 545 *out_row++ = gray_value; | |
| 546 *out_row++ = gray_value; | |
| 547 *out_row++ = gray_value; | |
| 548 *out_row++ = 1.0f; | |
| 549 } | |
| 550 } else if (type == GL_UNSIGNED_BYTE) { | |
| 551 // We take the upper 8 bits of 16-bit data and convert it as luminance to | |
| 552 // ARGB. We loose the precision here, but it is important not to render | |
| 553 // Y16 as RG_88. To get the full precision use float textures with WebGL1 | |
| 554 // and e.g. R16UI or R32F textures with WebGL2. | |
| 555 DCHECK(format == GL_RGBA) << "Unsupported Y16 conversion for format: 0x" | |
| 556 << std::hex << format << " and type: 0x" | |
| 557 << std::hex << type; | |
| 558 uint32_t* rgba = reinterpret_cast<uint32_t*>(out_row_head); | |
| 559 while (row < row_end) { | |
| 560 uint32_t gray_value = *row++ >> 8; | |
| 561 *rgba++ = SkColorSetRGB(gray_value, gray_value, gray_value); | |
| 562 } | |
| 563 } else { | |
| 564 NOTREACHED() << "Unsupported Y16 conversion for format: 0x" << std::hex | |
| 565 << format << " and type: 0x" << std::hex << type; | |
| 541 } | 566 } |
| 542 out += argb_row_bytes; | |
| 543 row_head += stride; | 567 row_head += stride; |
| 544 } | 568 } |
| 545 } | 569 } |
| 546 | 570 |
| 547 } // anonymous namespace | 571 } // anonymous namespace |
| 548 | 572 |
| 549 // static | 573 // static |
| 550 void SkCanvasVideoRenderer::ConvertVideoFrameToRGBPixels( | 574 void SkCanvasVideoRenderer::ConvertVideoFrameToRGBPixels( |
| 551 const VideoFrame* video_frame, | 575 const VideoFrame* video_frame, |
| 552 void* rgb_pixels, | 576 void* rgb_pixels, |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 641 case PIXEL_FORMAT_YUV422P12: | 665 case PIXEL_FORMAT_YUV422P12: |
| 642 case PIXEL_FORMAT_YUV444P12: { | 666 case PIXEL_FORMAT_YUV444P12: { |
| 643 scoped_refptr<VideoFrame> temporary_frame = | 667 scoped_refptr<VideoFrame> temporary_frame = |
| 644 DownShiftHighbitVideoFrame(video_frame); | 668 DownShiftHighbitVideoFrame(video_frame); |
| 645 ConvertVideoFrameToRGBPixels(temporary_frame.get(), rgb_pixels, | 669 ConvertVideoFrameToRGBPixels(temporary_frame.get(), rgb_pixels, |
| 646 row_bytes); | 670 row_bytes); |
| 647 break; | 671 break; |
| 648 } | 672 } |
| 649 | 673 |
| 650 case PIXEL_FORMAT_Y16: | 674 case PIXEL_FORMAT_Y16: |
| 651 ConvertY16ToARGB(video_frame, rgb_pixels, row_bytes); | 675 // Since it is grayscale conversion, we disregard SK_PMCOLOR_BYTE_ORDER |
| 676 // and always use GL_RGBA. | |
| 677 FlipAndConvertY16(video_frame, static_cast<uint8_t*>(rgb_pixels), GL_RGBA, | |
| 678 GL_UNSIGNED_BYTE, false /*flip_y*/, row_bytes); | |
| 652 break; | 679 break; |
| 653 | 680 |
| 654 case PIXEL_FORMAT_NV12: | 681 case PIXEL_FORMAT_NV12: |
| 655 case PIXEL_FORMAT_NV21: | 682 case PIXEL_FORMAT_NV21: |
| 656 case PIXEL_FORMAT_UYVY: | 683 case PIXEL_FORMAT_UYVY: |
| 657 case PIXEL_FORMAT_YUY2: | 684 case PIXEL_FORMAT_YUY2: |
| 658 case PIXEL_FORMAT_ARGB: | 685 case PIXEL_FORMAT_ARGB: |
| 659 case PIXEL_FORMAT_XRGB: | 686 case PIXEL_FORMAT_XRGB: |
| 660 case PIXEL_FORMAT_RGB24: | 687 case PIXEL_FORMAT_RGB24: |
| 661 case PIXEL_FORMAT_RGB32: | 688 case PIXEL_FORMAT_RGB32: |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 765 video_frame->UpdateReleaseSyncToken(&client); | 792 video_frame->UpdateReleaseSyncToken(&client); |
| 766 } else { | 793 } else { |
| 767 CopyVideoFrameSingleTextureToGLTexture(destination_gl, video_frame.get(), | 794 CopyVideoFrameSingleTextureToGLTexture(destination_gl, video_frame.get(), |
| 768 texture, internal_format, type, | 795 texture, internal_format, type, |
| 769 premultiply_alpha, flip_y); | 796 premultiply_alpha, flip_y); |
| 770 } | 797 } |
| 771 | 798 |
| 772 return true; | 799 return true; |
| 773 } | 800 } |
| 774 | 801 |
| 802 bool SkCanvasVideoRenderer::TexImageImpl(const char* functionID, | |
| 803 unsigned target, | |
| 804 gpu::gles2::GLES2Interface* gl, | |
| 805 VideoFrame* frame, | |
| 806 int level, | |
| 807 int internalformat, | |
| 808 unsigned format, | |
| 809 unsigned type, | |
| 810 int xoffset, | |
| 811 int yoffset, | |
| 812 int zoffset, | |
| 813 bool flip_y, | |
| 814 bool premultiplyAlpha) { | |
| 815 DCHECK(frame); | |
| 816 DCHECK(!frame->HasTextures()); | |
| 817 | |
| 818 bool has_alpha = false; | |
| 819 unsigned output_bytes_per_pixel; | |
|
hubbe
2016/11/07 22:16:55
Please initialize to something.
aleksandar.stojiljkovic
2016/11/16 20:01:24
Done.
| |
| 820 switch (frame->format()) { | |
| 821 case PIXEL_FORMAT_Y16: | |
| 822 // Converting single component unsigned short here to FLOAT luminance. | |
| 823 switch (format) { | |
| 824 case GL_RGBA: | |
| 825 if (type == GL_FLOAT) { | |
| 826 output_bytes_per_pixel = 4 * sizeof(GLfloat); | |
| 827 break; | |
| 828 } | |
| 829 // Pass through. | |
| 830 default: | |
| 831 return false; | |
| 832 } | |
| 833 break; | |
| 834 default: | |
| 835 return false; | |
| 836 } | |
| 837 | |
| 838 if (has_alpha && premultiplyAlpha) { | |
| 839 NOTREACHED() << "Premultiply alpha is not supported."; | |
| 840 return false; | |
| 841 } | |
| 842 if (xoffset || yoffset || zoffset) { | |
| 843 NOTREACHED() << "Offsets are not supported."; | |
|
hubbe
2016/11/07 22:16:55
If they are not supported, why even have those arg
aleksandar.stojiljkovic
2016/11/16 20:01:24
Done. Split the method and now supported in texSub
| |
| 844 return false; | |
| 845 } | |
| 846 | |
| 847 const size_t width = frame->visible_rect().width(); | |
| 848 const size_t height = frame->visible_rect().height(); | |
| 849 size_t output_row_bytes = width * output_bytes_per_pixel; | |
| 850 scoped_refptr<DataBuffer> temp_buffer = | |
| 851 new DataBuffer(output_row_bytes * height); | |
| 852 uint8_t* data = temp_buffer->writable_data(); | |
| 853 | |
| 854 FlipAndConvertY16(frame, data, format, type, flip_y, output_row_bytes); | |
| 855 | |
| 856 if (!strcmp(functionID, "texImage2D")) { | |
| 857 gl->TexImage2D(target, level, internalformat, width, height, 0, format, | |
| 858 type, data); | |
| 859 } else if (!strcmp(functionID, "texSubImage2D")) { | |
| 860 gl->TexSubImage2D(target, level, xoffset, yoffset, width, height, format, | |
| 861 type, data); | |
| 862 } else { | |
| 863 DCHECK(false) << functionID << " isn't implemented for format: " | |
| 864 << VideoPixelFormatToString(frame->format()); | |
| 865 } | |
| 866 return true; | |
| 867 } | |
| 868 | |
| 775 void SkCanvasVideoRenderer::ResetCache() { | 869 void SkCanvasVideoRenderer::ResetCache() { |
| 776 DCHECK(thread_checker_.CalledOnValidThread()); | 870 DCHECK(thread_checker_.CalledOnValidThread()); |
| 777 // Clear cached values. | 871 // Clear cached values. |
| 778 last_image_ = nullptr; | 872 last_image_ = nullptr; |
| 779 last_timestamp_ = kNoTimestamp; | 873 last_timestamp_ = kNoTimestamp; |
| 780 } | 874 } |
| 781 | 875 |
| 782 bool SkCanvasVideoRenderer::UpdateLastImage( | 876 bool SkCanvasVideoRenderer::UpdateLastImage( |
| 783 const scoped_refptr<VideoFrame>& video_frame, | 877 const scoped_refptr<VideoFrame>& video_frame, |
| 784 const Context3D& context_3d) { | 878 const Context3D& context_3d) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 822 last_image_->bounds().contains(visible_rect)) { | 916 last_image_->bounds().contains(visible_rect)) { |
| 823 last_image_ = last_image_->makeSubset(visible_rect); | 917 last_image_ = last_image_->makeSubset(visible_rect); |
| 824 } | 918 } |
| 825 } | 919 } |
| 826 | 920 |
| 827 SkISize SkCanvasVideoRenderer::LastImageDimensionsForTesting() { | 921 SkISize SkCanvasVideoRenderer::LastImageDimensionsForTesting() { |
| 828 return last_image_dimensions_for_testing_; | 922 return last_image_dimensions_for_testing_; |
| 829 } | 923 } |
| 830 | 924 |
| 831 } // namespace media | 925 } // namespace media |
| OLD | NEW |